make heavy operation async

This commit is contained in:
yggverse 2025-03-14 00:00:31 +02:00
parent 4002c94a4a
commit c3f63dfbdc
3 changed files with 73 additions and 45 deletions

View file

@ -155,32 +155,51 @@ impl Suggestion {
pub fn update(&self, limit: Option<usize>) { pub fn update(&self, limit: Option<usize>) {
use gtk::prelude::EditableExt; use gtk::prelude::EditableExt;
use itertools::Itertools; use itertools::Itertools;
self.popover.popdown();
if self.request.text_length() > 0 { if self.request.text_length() > 0 {
self.list_store.remove_all(); self.list_store.remove_all();
let query = self.request.text(); let query = self.request.text();
let items = self.profile.history.contains_request(&query, limit); let popover = self.popover.clone();
if !items.is_empty() { let list_store = self.list_store.clone();
for item in items
.into_iter() let history = self.profile.history.memory.clone(); // @TODO
.sorted_by(|a, b| Ord::cmp(&b.opened.count, &a.opened.count)) let bookmark = self.profile.bookmark.memory.clone(); // @TODO
{
let subtitle = highlight(&item.request, &query); gtk::glib::spawn_future_local(async move {
let title = match item.title { let list_items = gtk::gio::spawn_blocking(move || {
Some(title) => highlight(&title, &query), let result = history
None => subtitle.clone(), .read()
}; .unwrap()
self.list_store.append(&Item::build( .contains_request(&query, limit)
title, .into_iter()
subtitle, .sorted_by(|a, b| Ord::cmp(&b.opened.count, &a.opened.count));
self.profile.bookmark.is_match_request(&item.request), let mut list_items = Vec::with_capacity(result.len());
item.request, for item in result {
)); let subtitle = highlight(&item.request, &query);
let title = match item.title {
Some(title) => highlight(&title, &query),
None => subtitle.clone(),
};
list_items.push((
title,
subtitle,
bookmark.read().unwrap().is_match_request(&item.request),
item.request,
))
}
list_items
})
.await
.unwrap();
if !list_items.is_empty() {
for (title, subtitle, has_bookmark, request) in list_items {
list_store.append(&Item::build(title, subtitle, has_bookmark, request));
} // @TODO take a while
popover.popup()
} }
self.popover.popup(); });
return;
}
} }
self.hide();
} }
pub fn hide(&self) { pub fn hide(&self) {

View file

@ -8,12 +8,15 @@ use gtk::glib::DateTime;
use item::Item; use item::Item;
use memory::Memory; use memory::Memory;
use sqlite::{Connection, Transaction}; use sqlite::{Connection, Transaction};
use std::{cell::RefCell, rc::Rc, sync::RwLock}; use std::{
rc::Rc,
sync::{Arc, RwLock},
};
pub struct Bookmark { pub struct Bookmark {
database: Database, // permanent storage database: Database, // permanent storage
memory: RefCell<Memory>, // fast search index pub memory: Arc<RwLock<Memory>>, // fast search index
} } // @TODO close memory member, Arc entire profile instead
impl Bookmark { impl Bookmark {
// Constructors // Constructors
@ -22,11 +25,11 @@ impl Bookmark {
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Result<Self> { pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Result<Self> {
// Init children components // Init children components
let database = Database::new(connection, profile_id); let database = Database::new(connection, profile_id);
let memory = RefCell::new(Memory::new()); let memory = Arc::new(RwLock::new(Memory::new()));
// Build initial index // Build initial index
{ {
let mut memory = memory.borrow_mut(); let mut memory = memory.write().unwrap();
for item in database.records(None, None)? { for item in database.records(None, None)? {
memory.add(item); memory.add(item);
} }
@ -41,7 +44,7 @@ impl Bookmark {
/// Toggle bookmark in `database` and `memory` index /// Toggle bookmark in `database` and `memory` index
/// * return `true` on bookmark create, `false` on delete /// * return `true` on bookmark create, `false` on delete
pub fn toggle(&self, request: &str, title: Option<&str>) -> Result<bool> { pub fn toggle(&self, request: &str, title: Option<&str>) -> Result<bool> {
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.write().unwrap();
Ok(match memory.delete_by_request(request) { Ok(match memory.delete_by_request(request) {
Some(item) => { Some(item) => {
self.database.delete(item.id)?; self.database.delete(item.id)?;
@ -62,17 +65,20 @@ impl Bookmark {
/// Check `request` exists in the memory index /// Check `request` exists in the memory index
pub fn is_match_request(&self, request: &str) -> bool { pub fn is_match_request(&self, request: &str) -> bool {
self.memory.borrow_mut().is_match_request(request) self.memory.write().unwrap().is_match_request(request)
} }
/// Find Items match `request` /// Find Items match `request`
pub fn contains_request(&self, request: &str, limit: Option<usize>) -> Vec<Item> { pub fn contains_request(&self, request: &str, limit: Option<usize>) -> Vec<Item> {
self.memory.borrow_mut().contains_request(request, limit) self.memory
.write()
.unwrap()
.contains_request(request, limit)
} }
/// Get recent Items vector from `memory`, sorted by `ID` DESC /// Get recent Items vector from `memory`, sorted by `ID` DESC
pub fn recent(&self, limit: Option<usize>) -> Vec<Item> { pub fn recent(&self, limit: Option<usize>) -> Vec<Item> {
self.memory.borrow().recent(limit) self.memory.read().unwrap().recent(limit)
} }
} }

View file

@ -8,12 +8,15 @@ use gtk::glib::GString;
use item::{Event, Item}; use item::{Event, Item};
use memory::Memory; use memory::Memory;
use sqlite::{Connection, Transaction}; use sqlite::{Connection, Transaction};
use std::{cell::RefCell, rc::Rc, sync::RwLock}; use std::{
rc::Rc,
sync::{Arc, RwLock},
};
pub struct History { pub struct History {
database: Database, // permanent storage database: Database, // permanent storage
memory: RefCell<Memory>, // fast search index pub memory: Arc<RwLock<Memory>>, // fast search index
} } // @TODO close memory member, Arc entire profile instead
impl History { impl History {
// Constructors // Constructors
@ -22,10 +25,10 @@ impl History {
pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Result<Self> { pub fn build(connection: &Rc<RwLock<Connection>>, profile_id: i64) -> Result<Self> {
// Init children components // Init children components
let database = Database::build(connection, profile_id); let database = Database::build(connection, profile_id);
let memory = RefCell::new(Memory::new()); let memory = Arc::new(RwLock::new(Memory::new()));
for item in database.records(None, None)? { for item in database.records(None, None)? {
memory.borrow_mut().add(item) memory.write().unwrap().add(item)
} }
// Return new `Self` // Return new `Self`
@ -35,7 +38,7 @@ impl History {
// Actions // Actions
pub fn save(&self) -> Result<()> { pub fn save(&self) -> Result<()> {
for item in self.memory.borrow().items() { for item in self.memory.read().unwrap().items() {
if !item.is_saved { if !item.is_saved {
match item.id { match item.id {
Some(_) => { Some(_) => {
@ -54,7 +57,7 @@ impl History {
/// Create new history record /// Create new history record
pub fn open(&self, request: GString, title: Option<GString>) { pub fn open(&self, request: GString, title: Option<GString>) {
let mut memory = self.memory.borrow_mut(); let mut memory = self.memory.write().unwrap();
if !memory.open(&request) { if !memory.open(&request) {
memory.add(Item { memory.add(Item {
id: None, id: None,
@ -69,25 +72,25 @@ impl History {
/// Close existing history record /// Close existing history record
pub fn close(&self, request: &str) { pub fn close(&self, request: &str) {
self.memory.borrow_mut().close(request) self.memory.write().unwrap().close(request)
} }
// Getters // Getters
/// Get recently `opened` Items vector from the memory index, sorted by ASC /// Get recently `opened` Items vector from the memory index, sorted by ASC
pub fn recently_opened(&self, limit: Option<usize>) -> Vec<Item> { pub fn recently_opened(&self, limit: Option<usize>) -> Vec<Item> {
self.memory.borrow().recently_opened(limit) self.memory.read().unwrap().recently_opened(limit)
} }
/// Get recently `closed` Items vector from the memory index, sorted by ASC /// Get recently `closed` Items vector from the memory index, sorted by ASC
pub fn recently_closed(&self, limit: Option<usize>) -> Vec<Item> { pub fn recently_closed(&self, limit: Option<usize>) -> Vec<Item> {
self.memory.borrow().recently_closed(limit) self.memory.read().unwrap().recently_closed(limit)
} }
/// Get unordered Items vector contains `request` /// Get unordered Items vector that contains given `request`
pub fn contains_request(&self, request: &str, limit: Option<usize>) -> Vec<Item> { pub fn contains_request(&self, request: &str, limit: Option<usize>) -> Vec<Item> {
self.memory.borrow().contains_request(request, limit) self.memory.read().unwrap().contains_request(request, limit)
} } // @TODO close memory member
} }
// Tools // Tools