listing: add BackgroundSearch struct WIP

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
jump_to
Manos Pitsidianakis 1 month ago
parent 8a16cf6db4
commit e7e33b7a85
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

@ -39,6 +39,7 @@ use super::*;
use crate::{
accounts::{JobRequest, MailboxStatus},
components::ExtendShortcutsMaps,
jobs::{JobId, JoinHandle},
};
pub const DEFAULT_ATTACHMENT_FLAG: &str = concat!("📎", emoji_text_presentation_selector!());
@ -1006,6 +1007,37 @@ pub trait ListingTrait: Component {
}
}
#[derive(Debug)]
pub struct BackgroundSearch {
pub text: String,
pub timestamp: std::time::Instant,
pub handle: JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>,
}
impl From<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)> for BackgroundSearch {
fn from((text, handle): (String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)) -> Self {
Self {
text,
handle,
timestamp: std::time::Instant::now(),
}
}
}
#[derive(Default, Debug)]
struct BackgroundJobs {
pub search_job: Option<BackgroundSearch>,
pub select_job: Option<BackgroundSearch>,
}
impl BackgroundJobs {
pub fn is_match(&self, job_id: &JobId) -> bool {
[&self.search_job, &self.select_job].iter().any(
|bg| matches!(bg, Some(BackgroundSearch { handle, .. }) if handle.job_id == *job_id),
)
}
}
#[derive(Debug)]
pub enum ListingComponent {
Compact(Box<CompactListing>),

@ -142,10 +142,7 @@ pub struct CompactListing {
rows_drawn: SegmentTree,
rows: RowsState<(ThreadHash, EnvelopeHash)>,
#[allow(clippy::type_complexity)]
search_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
#[allow(clippy::type_complexity)]
select_job: Option<(String, JoinHandle<Result<SmallVec<[EnvelopeHash; 512]>>>)>,
bg_jobs: BackgroundJobs,
filter_term: String,
filtered_selection: Vec<ThreadHash>,
filtered_order: HashMap<ThreadHash, usize>,
@ -213,6 +210,7 @@ impl MailListingTrait for CompactListing {
fn refresh_mailbox(&mut self, context: &mut Context, force: bool) {
self.set_dirty(true);
self.rows.clear();
self.bg_jobs = BackgroundJobs::default();
let old_cursor_pos = self.cursor_pos;
if !(self.cursor_pos.0 == self.new_cursor_pos.0
&& self.cursor_pos.1 == self.new_cursor_pos.1)
@ -556,6 +554,7 @@ impl ListingTrait for CompactListing {
fn set_coordinates(&mut self, coordinates: (AccountHash, MailboxHash)) {
self.new_cursor_pos = (coordinates.0, coordinates.1, 0);
self.focus = Focus::None;
self.bg_jobs = BackgroundJobs::default();
self.filtered_selection.clear();
self.filtered_order.clear();
self.filter_term.clear();
@ -873,8 +872,7 @@ impl CompactListing {
sort: (Default::default(), Default::default()),
sortcmd: false,
subsort: (SortField::Date, SortOrder::Desc),
search_job: None,
select_job: None,
bg_jobs: BackgroundJobs::default(),
filter_term: String::new(),
filtered_selection: Vec::new(),
filtered_order: HashMap::default(),
@ -1524,9 +1522,9 @@ impl CompactListing {
log::error!("{}", message);
context.replies.push_back(UIEvent::Notification {
title: Some("Could not perform search".into()),
source: None,
body: message.into(),
kind: Some(crate::types::NotificationType::Error(err.kind)),
source: Some(err),
});
}
}
@ -2030,14 +2028,14 @@ impl Component for CompactListing {
.main_loop_handler
.job_executor
.spawn_specialized("search".into(), job);
self.search_job = Some((filter_term.to_string(), handle));
self.bg_jobs.search_job = Some((filter_term.to_string(), handle).into());
}
Err(err) => {
context.replies.push_back(UIEvent::Notification {
title: Some("Could not perform search".into()),
source: None,
body: err.to_string().into(),
kind: Some(crate::types::NotificationType::Error(err.kind)),
source: Some(err),
});
}
};
@ -2058,15 +2056,16 @@ impl Component for CompactListing {
if let Ok(Some(search_result)) = try_recv_timeout!(&mut handle.chan) {
self.select(search_term, search_result, context);
} else {
self.select_job = Some((search_term.to_string(), handle));
self.bg_jobs.select_job =
Some((search_term.to_string(), handle).into());
}
}
Err(err) => {
context.replies.push_back(UIEvent::Notification {
title: Some("Could not perform search".into()),
source: None,
body: err.to_string().into(),
kind: Some(crate::types::NotificationType::Error(err.kind)),
source: Some(err),
});
}
};
@ -2074,42 +2073,56 @@ impl Component for CompactListing {
return true;
}
UIEvent::StatusEvent(StatusEvent::JobFinished(ref job_id))
if self
.search_job
.as_ref()
.map(|(_, j)| j == job_id)
.unwrap_or(false) =>
if self.bg_jobs.is_match(job_id) =>
{
let (filter_term, mut handle) = self.search_job.take().unwrap();
match handle.chan.try_recv() {
Err(_) => { /* search was canceled */ }
Ok(None) => { /* something happened, perhaps a worker thread panicked */ }
Ok(Some(Ok(results))) => self.filter(filter_term, results, context),
Ok(Some(Err(err))) => {
context.replies.push_back(UIEvent::Notification {
title: Some("Could not perform search".into()),
source: None,
body: err.to_string().into(),
kind: Some(crate::types::NotificationType::Error(err.kind)),
});
let job = self.bg_jobs.search_job.take();
if job
.as_ref()
.map(|bg| bg.handle.job_id == *job_id)
.unwrap_or(false)
{
let BackgroundSearch {
text: filter_term,
mut handle,
..
} = job.unwrap();
match handle.chan.try_recv() {
Err(_) => { /* search was canceled */ }
Ok(None) => { /* something happened, perhaps a worker thread panicked */ }
Ok(Some(Ok(results))) => self.filter(filter_term, results, context),
Ok(Some(Err(err))) => {
context.replies.push_back(UIEvent::Notification {
title: Some("Could not perform search".into()),
body: err.to_string().into(),
kind: Some(crate::types::NotificationType::Error(err.kind)),
source: Some(err),
});
}
}
self.set_dirty(true);
return false;
}
self.set_dirty(true);
}
UIEvent::StatusEvent(StatusEvent::JobFinished(ref job_id))
if self
.select_job
self.bg_jobs.search_job = job;
let job = self.bg_jobs.select_job.take();
if job
.as_ref()
.map(|(_, j)| j == job_id)
.unwrap_or(false) =>
{
let (search_term, mut handle) = self.select_job.take().unwrap();
match handle.chan.try_recv() {
Err(_) => { /* search was canceled */ }
Ok(None) => { /* something happened, perhaps a worker thread panicked */ }
Ok(Some(results)) => self.select(&search_term, results, context),
.map(|bg| bg.handle.job_id == *job_id)
.unwrap_or(false)
{
let BackgroundSearch {
text: search_term,
mut handle,
..
} = job.unwrap();
match handle.chan.try_recv() {
Err(_) => { /* search was canceled */ }
Ok(None) => { /* something happened, perhaps a worker thread panicked */ }
Ok(Some(results)) => self.select(&search_term, results, context),
}
self.set_dirty(true);
return false;
}
self.set_dirty(true);
self.bg_jobs.select_job = job;
}
_ => {}
}

Loading…
Cancel
Save