Move search provider stuff into own file; A bit code cleanup

This commit is contained in:
Felix Häcker 2019-04-28 19:43:08 +02:00 committed by Felix Häcker
parent 75156a1b41
commit dc3bd094b2
4 changed files with 128 additions and 0 deletions

View File

@ -87,6 +87,7 @@ mod headerbar;
mod window; mod window;
mod manager; mod manager;
mod search_provider;
mod settings; mod settings;
mod static_resource; mod static_resource;
mod utils; mod utils;

View File

@ -53,6 +53,7 @@ podcasts_sources = files(
'i18n.rs', 'i18n.rs',
'main.rs', 'main.rs',
'manager.rs', 'manager.rs',
'search_provider.rs',
'settings.rs', 'settings.rs',
'utils.rs' 'utils.rs'
) )

View File

@ -0,0 +1,122 @@
// search_provider.rs
//
// Copyright 2019 Felix Häcker <haeckerfelix@gnome.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// SPDX-License-Identifier: GPL-3.0-or-later
use crossbeam_channel::Sender;
use gtk::prelude::*;
use podcasts_data::dbqueries;
use search_provider::{ResultMetadata, SearchProvider as SP};
use std::str::FromStr;
use std::sync::Arc;
use crate::app::Action;
use crate::config::APP_ID;
#[derive(Debug, Clone)]
pub(crate) struct SearchProvider {
search_provider: Arc<SP>,
window: gtk::ApplicationWindow,
sender: Sender<Action>,
}
impl SearchProvider {
pub(crate) fn new(window: gtk::ApplicationWindow, sender: Sender<Action>) -> SearchProvider {
let search_provider = SP::new(
APP_ID.to_string(),
"/org/gnome/Podcasts/SearchProvider".to_string(),
);
let sp = SearchProvider {
search_provider,
window,
sender,
};
sp.setup_callbacks();
sp
}
fn setup_callbacks(&self) {
let window = self.window.clone();
let sender = self.sender.clone();
self.search_provider
.connect_activate_result(move |sp_id, _, timestamp| {
// Show window
window.present_with_time(timestamp);
window.show_all();
window.present();
// Get episode
let mut id = sp_id.clone().split("_").collect::<Vec<&str>>();
let title: &str = id.pop().unwrap();
let show_id: i32 = std::str::FromStr::from_str(id.pop().unwrap()).unwrap();
let episode = dbqueries::get_episode_from_pk(title, show_id).unwrap();
// Play episode
sender
.send(Action::InitEpisode(episode.rowid()))
.expect("Action channel blew up somehow");
// TODO: Sometimes it's necessary to download the episode first. Otherwise it cannot be played.
// TODO: Greyout title state doesn't get applied.
});
self.search_provider
.connect_get_initial_result_set(|terms| {
let term = terms.join("");
Self::search(term)
});
self.search_provider
.connect_get_subsearch_result_set(|_, terms| {
let term = terms.join("");
Self::search(term)
});
self.search_provider.connect_get_result_metas(|sp_ids| {
let mut metas = Vec::new();
for sp_id in sp_ids {
let id = sp_id.clone().split("_").collect::<Vec<&str>>();
let show_id: i32 = FromStr::from_str(id[0]).unwrap();
let episode = dbqueries::get_episode_from_pk(id[1], show_id).unwrap();
let meta = ResultMetadata::new(
sp_id,
episode.title(),
"folder-documents-symbolic",
episode.description().unwrap_or(""),
);
metas.insert(0, meta);
}
metas
});
}
fn search(term: String) -> Vec<String> {
let episodes = dbqueries::search_episodes(&term)
.expect("Could not search for episodes (search provider)");
let mut sp_ids = Vec::new();
for episode in episodes {
let sp_id = format!("{}_{}", episode.show_id(), episode.title());
sp_ids.insert(0, sp_id);
}
sp_ids
}
}

View File

@ -29,6 +29,7 @@ use crossbeam_channel::{unbounded, Receiver, Sender};
use crate::app::{Action, PdApplication}; use crate::app::{Action, PdApplication};
use crate::headerbar::Header; use crate::headerbar::Header;
use crate::search_provider::SearchProvider;
use crate::settings::{self, WindowGeometry}; use crate::settings::{self, WindowGeometry};
use crate::stacks::Content; use crate::stacks::Content;
use crate::utils; use crate::utils;
@ -149,6 +150,9 @@ impl MainWindow {
glib::Continue(true) glib::Continue(true)
}); });
// Setup GNOME Shell search provider integration
let search_provider = SearchProvider::new(window.clone(), sender.clone());
Self { Self {
app: app.clone(), app: app.clone(),
window, window,