mod database; mod item; mod memory; use anyhow::Result; use database::Database; use gtk::glib::DateTime; use item::Item; use memory::Memory; use sqlite::{Connection, Transaction}; use std::{ rc::Rc, sync::{Arc, RwLock}, }; pub struct Bookmark { database: Database, // permanent storage pub memory: Arc>, // fast search index } // @TODO close memory member, Arc entire profile instead impl Bookmark { // Constructors /// Create new `Self` pub fn build(connection: &Rc>, profile_id: i64) -> Result { // Init children components let database = Database::new(connection, profile_id); let memory = Arc::new(RwLock::new(Memory::new())); // Build initial index { let mut memory = memory.write().unwrap(); for item in database.records(None, None)? { memory.add(item); } } // Return new `Self` Ok(Self { database, memory }) } // Actions /// Toggle bookmark in `database` and `memory` index /// * return `true` on bookmark create, `false` on delete pub fn toggle(&self, request: &str, title: Option<&str>) -> Result { let mut memory = self.memory.write().unwrap(); Ok(match memory.delete_by_request(request) { Some(item) => { self.database.delete(item.id)?; false } None => { memory.add(Item { id: self.database.add(DateTime::now_local()?, request, title)?, request: request.into(), title: title.map(|t| t.to_string()), }); true } }) } // Getters /// Check `request` exists in the memory index pub fn is_match_request(&self, request: &str) -> bool { self.memory.write().unwrap().is_match_request(request) } /// Find Items match `request` pub fn contains_request(&self, request: &str, limit: Option) -> Vec { self.memory .write() .unwrap() .contains_request(request, limit) } /// Get recent Items vector from `memory`, sorted by `ID` DESC pub fn recent(&self, limit: Option) -> Vec { self.memory.read().unwrap().recent(limit) } } // Tools pub fn migrate(tx: &Transaction) -> Result<()> { // Migrate self components database::init(tx)?; // Delegate migration to childs // nothing yet.. // Success Ok(()) }