mod content; mod database; mod input; mod navigation; mod search; use super::{Action as ItemAction, BrowserAction, Profile, TabAction, WindowAction}; use adw::TabPage; use anyhow::Result; use content::Content; use input::Input; use navigation::Navigation; use search::Search; use sqlite::Transaction; use std::{rc::Rc, sync::Arc}; pub struct Page { pub profile: Arc, // Actions pub browser_action: Rc, pub item_action: Rc, pub window_action: Rc, // Components pub content: Rc, pub input: Rc, pub navigation: Rc, pub search: Rc, // System /// Reference to [TabPage](https://gnome.pages.gitlab.gnome.org/libadwaita/doc/main/class.TabPage.html) /// wanted to update title, loading status and other features related with page. /// * this member sensitively dependent of parental HashMap index,\ /// as connection drivers interact with `Page` API,\ /// let's keep it private to isolate direct access and prevent their implementation errors tab_page: TabPage, } impl Page { // Constructors pub fn build( profile: &Arc, (browser_action, window_action, tab_action, item_action): ( &Rc, &Rc, &Rc, &Rc, ), tab_page: &TabPage, ) -> Self { // Init components let content = Rc::new(Content::build((window_action, tab_action, item_action))); let search = Rc::new(Search::new()); let navigation = Rc::new(Navigation::build( profile, (window_action, tab_action, item_action), )); let input = Rc::new(Input::new()); // Done Self { profile: profile.clone(), tab_page: tab_page.clone(), // Actions browser_action: browser_action.clone(), item_action: item_action.clone(), window_action: window_action.clone(), // Components content, input, navigation, search, } } // Actions /// Toggle bookmark for current navigation request pub fn bookmark(&self) { self.profile .bookmark .toggle(&self.navigation.request(), Some(&self.title())) .unwrap(); // @TODO } /// Request `Escape` action for all page components pub fn escape(&self) { self.search.hide(); self.navigation.escape(); } /// Toggle `Find` widget pub fn find(&self) { self.search.show() } /// Make new history record in related components pub fn snap_history(&self) { self.item_action .history .add(self.navigation.request(), true); self.profile .history .open(self.navigation.request(), Some(self.title())) } /// Cleanup session for `Self` pub fn clean( &self, transaction: &Transaction, app_browser_window_tab_item_id: i64, ) -> Result<()> { for record in database::select(transaction, app_browser_window_tab_item_id)? { database::delete(transaction, record.id)?; // Delegate clean action to the item childs self.navigation.clean(transaction, &record.id)?; } Ok(()) } /// Restore `Self` session from database pub fn restore( &self, transaction: &Transaction, app_browser_window_tab_item_id: i64, ) -> Result<()> { // Begin page restore for record in database::select(transaction, app_browser_window_tab_item_id)? { // Restore `Self` if let Some(title) = record.title { self.set_title(title.as_str()); } self.set_needs_attention(record.is_needs_attention); // Restore child components self.navigation.restore(transaction, &record.id)?; // Make initial page history snap self.profile .history .open(self.navigation.request(), Some(self.title())); } Ok(()) } /// Save `Self` session to database pub fn save( &self, transaction: &Transaction, app_browser_window_tab_item_id: i64, ) -> Result<()> { // Keep value in memory until operation complete let title = self.tab_page.title(); let id = database::insert( transaction, app_browser_window_tab_item_id, self.tab_page.needs_attention(), match title.is_empty() { true => None, false => Some(title.as_str()), }, )?; // Delegate save action to childs self.navigation.save(transaction, &id)?; Ok(()) } // Setters /// Set title for `Self` /// * this method allows to keep `tab_page` isolated from driver implementation pub fn set_title(&self, title: &str) { self.tab_page.set_title(title) } pub fn set_needs_attention(&self, is_needs_attention: bool) { self.tab_page.set_needs_attention(is_needs_attention) } pub fn set_progress(&self, progress_fraction: f64) { self.navigation.set_progress_fraction(progress_fraction); self.tab_page.set_loading(progress_fraction > 0.0) } // Getters pub fn title(&self) -> gtk::glib::GString { self.tab_page.title() } } // Tools pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components database::init(tx)?; // Delegate migration to childs navigation::migrate(tx)?; // Success Ok(()) }