Loading

i hate rust

  1. // search_provider.rs
  2. //
  3. // Copyright 2019 Felix H├Ącker <haeckerfelix@gnome.org>
  4. //
  5. // This program is free software: you can redistribute it and/or modify
  6. // it under the terms of the GNU General Public License as published by
  7. // the Free Software Foundation, either version 3 of the License, or
  8. // (at your option) any later version.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17. //
  18. // SPDX-License-Identifier: GPL-3.0-or-later
  19.  
  20. use crossbeam_channel::Sender;
  21. use gtk::prelude::*;
  22. use podcasts_data::dbqueries;
  23. use search_provider::{ResultMetadata, SearchProvider as SP};
  24.  
  25. use std::str::FromStr;
  26. use std::sync::Arc;
  27.  
  28. use crate::app::Action;
  29. use crate::config::APP_ID;
  30.  
  31. #[derive(Debug, Clone)]
  32. pub(crate) struct SearchProvider {
  33.     search_provider: Arc<SP>,
  34.     window: gtk::ApplicationWindow,
  35.     sender: Sender<Action>,
  36. }
  37.  
  38. impl SearchProvider {
  39.     pub(crate) fn new(window: gtk::ApplicationWindow, sender: Sender<Action>) -> SearchProvider {
  40.         let search_provider = SP::new(
  41.             APP_ID.to_string(),
  42.             "/org/gnome/Podcasts/SearchProvider".to_string(),
  43.         );
  44.  
  45.         let sp = SearchProvider {
  46.             search_provider,
  47.             window,
  48.             sender,
  49.         };
  50.  
  51.         sp.setup_callbacks();
  52.         sp
  53.     }
  54.  
  55.     fn setup_callbacks(&self) {
  56.         let window = self.window.clone();
  57.         let sender = self.sender.clone();
  58.         self.search_provider
  59.             .connect_activate_result(move |sp_id, _, timestamp| {
  60.                 // Show window
  61.                 window.present_with_time(timestamp);
  62.                 window.show_all();
  63.                 window.present();
  64.  
  65.                 // Get episode
  66.                 let mut id = sp_id.clone().split("_").collect::<Vec<&str>>();
  67.                 let title: &str = id.pop().unwrap();
  68.                 let show_id: i32 = std::str::FromStr::from_str(id.pop().unwrap()).unwrap();
  69.                 let episode = dbqueries::get_episode_from_pk(title, show_id).unwrap();
  70.  
  71.                 // Play episode
  72.                 sender
  73.                     .send(Action::InitEpisode(episode.rowid()))
  74.                     .expect("Action channel blew up somehow");
  75.                 // TODO: Sometimes it's necessary to download the episode first. Otherwise it cannot be played.
  76.                 // TODO: Greyout title state doesn't get applied.
  77.             });
  78.  
  79.         self.search_provider
  80.             .connect_get_initial_result_set(|terms| {
  81.                 let term = terms.join("");
  82.                 Self::search(term)
  83.             });
  84.  
  85.         self.search_provider
  86.             .connect_get_subsearch_result_set(|_, terms| {
  87.                 let term = terms.join("");
  88.                 Self::search(term)
  89.             });
  90.  
  91.         self.search_provider.connect_get_result_metas(|sp_ids| {
  92.             let mut metas = Vec::new();
  93.             for sp_id in sp_ids {
  94.                 let id = sp_id.clone().split("_").collect::<Vec<&str>>();
  95.                 let show_id: i32 = FromStr::from_str(id[0]).unwrap();
  96.  
  97.                 let episode = dbqueries::get_episode_from_pk(id[1], show_id).unwrap();
  98.  
  99.                 // TODO: this.
  100.                 let image_uri = dbqueries::get_podcast_cover_from_id(show_id).map(|cover| cover.image_uri().clone().unwrap_or("image-x-generic-symbolic").clone()).unwrap_or("image-x-generic-symbolic");
  101.  
  102.                 let meta = ResultMetadata::new(
  103.                     sp_id,
  104.                     episode.title(),
  105.                     image_uri,
  106.                     episode.description().unwrap_or(""),
  107.                 );
  108.                 metas.insert(0, meta);
  109.             }
  110.             metas
  111.         });
  112.     }
  113.  
  114.     fn search(term: String) -> Vec<String> {
  115.         let episodes = dbqueries::search_episodes(&term)
  116.             .expect("Could not search for episodes (search provider)");
  117.  
  118.         let mut sp_ids = Vec::new();
  119.         for episode in episodes {
  120.             let sp_id = format!("{}_{}", episode.show_id(), episode.title());
  121.             sp_ids.insert(0, sp_id);
  122.         }
  123.         sp_ids
  124.     }
  125. }