ui: refactor watch thread spawning procedure
- Remove unnecessary parameters from watch(), reload() - Add NewThread event that adds new threads in work_controller.static_threads hashmap - removed obsolete field State.threads - silence watch thread error notificationsasync
parent
7732b851e6
commit
59f7f03d64
|
@ -373,8 +373,8 @@ fn run_app() -> Result<()> {
|
||||||
state.check_accounts();
|
state.check_accounts();
|
||||||
state.redraw();
|
state.redraw();
|
||||||
},
|
},
|
||||||
ThreadEvent::ThreadJoin(id) => {
|
ThreadEvent::NewThread(id, name) => {
|
||||||
state.join(id);
|
state.new_thread(id, name);
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -38,7 +38,7 @@ use melib::StackVec;
|
||||||
use text_processing::GlobMatch;
|
use text_processing::GlobMatch;
|
||||||
|
|
||||||
use crate::types::UIEvent::{self, EnvelopeRemove, EnvelopeRename, EnvelopeUpdate, Notification};
|
use crate::types::UIEvent::{self, EnvelopeRemove, EnvelopeRename, EnvelopeUpdate, Notification};
|
||||||
use crate::{workers::WorkController, StatusEvent, ThreadEvent};
|
use crate::{StatusEvent, ThreadEvent};
|
||||||
use crossbeam::Sender;
|
use crossbeam::Sender;
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
@ -162,6 +162,7 @@ pub struct Account {
|
||||||
pub(crate) runtime_settings: AccountConf,
|
pub(crate) runtime_settings: AccountConf,
|
||||||
pub(crate) backend: Arc<RwLock<Box<dyn MailBackend>>>,
|
pub(crate) backend: Arc<RwLock<Box<dyn MailBackend>>>,
|
||||||
|
|
||||||
|
sender: Sender<ThreadEvent>,
|
||||||
event_queue: VecDeque<(FolderHash, RefreshEvent)>,
|
event_queue: VecDeque<(FolderHash, RefreshEvent)>,
|
||||||
notify_fn: Arc<NotifyFn>,
|
notify_fn: Arc<NotifyFn>,
|
||||||
}
|
}
|
||||||
|
@ -245,6 +246,7 @@ impl Account {
|
||||||
mut settings: AccountConf,
|
mut settings: AccountConf,
|
||||||
map: &Backends,
|
map: &Backends,
|
||||||
work_context: WorkContext,
|
work_context: WorkContext,
|
||||||
|
sender: Sender<ThreadEvent>,
|
||||||
notify_fn: NotifyFn,
|
notify_fn: NotifyFn,
|
||||||
) -> Result<Self> {
|
) -> Result<Self> {
|
||||||
let s = settings.clone();
|
let s = settings.clone();
|
||||||
|
@ -300,6 +302,7 @@ impl Account {
|
||||||
settings,
|
settings,
|
||||||
backend: Arc::new(RwLock::new(backend)),
|
backend: Arc::new(RwLock::new(backend)),
|
||||||
notify_fn,
|
notify_fn,
|
||||||
|
sender,
|
||||||
|
|
||||||
event_queue: VecDeque::with_capacity(8),
|
event_queue: VecDeque::with_capacity(8),
|
||||||
})
|
})
|
||||||
|
@ -514,16 +517,7 @@ impl Account {
|
||||||
}
|
}
|
||||||
Some(w)
|
Some(w)
|
||||||
}
|
}
|
||||||
pub fn reload(
|
pub fn reload(&mut self, event: RefreshEvent, folder_hash: FolderHash) -> Option<UIEvent> {
|
||||||
&mut self,
|
|
||||||
event: RefreshEvent,
|
|
||||||
folder_hash: FolderHash,
|
|
||||||
context: (
|
|
||||||
&mut WorkController,
|
|
||||||
&Sender<ThreadEvent>,
|
|
||||||
&mut VecDeque<UIEvent>,
|
|
||||||
),
|
|
||||||
) -> Option<UIEvent> {
|
|
||||||
if !self.folders[&folder_hash].is_available() {
|
if !self.folders[&folder_hash].is_available() {
|
||||||
self.event_queue.push_back((folder_hash, event));
|
self.event_queue.push_back((folder_hash, event));
|
||||||
return None;
|
return None;
|
||||||
|
@ -683,6 +677,7 @@ impl Account {
|
||||||
}
|
}
|
||||||
RefreshEventKind::Failure(e) => {
|
RefreshEventKind::Failure(e) => {
|
||||||
debug!("RefreshEvent Failure: {}", e.to_string());
|
debug!("RefreshEvent Failure: {}", e.to_string());
|
||||||
|
/*
|
||||||
context
|
context
|
||||||
.1
|
.1
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::Notification(
|
.send(ThreadEvent::UIEvent(UIEvent::Notification(
|
||||||
|
@ -691,43 +686,39 @@ impl Account {
|
||||||
Some(crate::types::NotificationType::ERROR),
|
Some(crate::types::NotificationType::ERROR),
|
||||||
)))
|
)))
|
||||||
.expect("Could not send event on main channel");
|
.expect("Could not send event on main channel");
|
||||||
self.watch(context);
|
*/
|
||||||
|
self.watch();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
pub fn watch(
|
pub fn watch(&self) {
|
||||||
&self,
|
let sender_ = self.sender.clone();
|
||||||
context: (
|
|
||||||
&mut WorkController,
|
|
||||||
&Sender<ThreadEvent>,
|
|
||||||
&mut VecDeque<UIEvent>,
|
|
||||||
),
|
|
||||||
) {
|
|
||||||
let (work_controller, sender, replies) = context;
|
|
||||||
let sender = sender.clone();
|
|
||||||
let r = RefreshEventConsumer::new(Box::new(move |r| {
|
let r = RefreshEventConsumer::new(Box::new(move |r| {
|
||||||
sender.send(ThreadEvent::from(r)).unwrap();
|
sender_.send(ThreadEvent::from(r)).unwrap();
|
||||||
}));
|
}));
|
||||||
match self
|
match self
|
||||||
.backend
|
.backend
|
||||||
.read()
|
.read()
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.watch(r, work_controller.get_context())
|
.watch(r, self.work_context.clone())
|
||||||
{
|
{
|
||||||
Ok(id) => {
|
Ok(id) => {
|
||||||
work_controller
|
self.sender
|
||||||
.static_threads
|
.send(ThreadEvent::NewThread(
|
||||||
.lock()
|
id,
|
||||||
.unwrap()
|
format!("watching {}", self.name()).into(),
|
||||||
.insert(id, format!("watching {}", self.name()).into());
|
))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
replies.push_back(UIEvent::StatusEvent(StatusEvent::DisplayMessage(
|
self.sender
|
||||||
e.to_string(),
|
.send(ThreadEvent::UIEvent(UIEvent::StatusEvent(
|
||||||
)));
|
StatusEvent::DisplayMessage(e.to_string()),
|
||||||
|
)))
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,9 +137,6 @@ impl Context {
|
||||||
|
|
||||||
pub fn is_online(&mut self, account_pos: usize) -> bool {
|
pub fn is_online(&mut self, account_pos: usize) -> bool {
|
||||||
let Context {
|
let Context {
|
||||||
ref mut work_controller,
|
|
||||||
ref sender,
|
|
||||||
ref mut replies,
|
|
||||||
ref mut accounts,
|
ref mut accounts,
|
||||||
ref mut mailbox_hashes,
|
ref mut mailbox_hashes,
|
||||||
..
|
..
|
||||||
|
@ -158,7 +155,7 @@ impl Context {
|
||||||
* inform the main binary that refresh events arrived
|
* inform the main binary that refresh events arrived
|
||||||
* - replies to report any failures to the user
|
* - replies to report any failures to the user
|
||||||
*/
|
*/
|
||||||
accounts[account_pos].watch((work_controller, sender, replies));
|
accounts[account_pos].watch();
|
||||||
}
|
}
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
|
@ -184,7 +181,6 @@ pub struct State {
|
||||||
components: Vec<Box<dyn Component>>,
|
components: Vec<Box<dyn Component>>,
|
||||||
pub context: Context,
|
pub context: Context,
|
||||||
timer: thread::JoinHandle<()>,
|
timer: thread::JoinHandle<()>,
|
||||||
threads: FnvHashMap<thread::ThreadId, (Sender<bool>, thread::JoinHandle<()>)>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for State {
|
impl Drop for State {
|
||||||
|
@ -232,6 +228,7 @@ impl State {
|
||||||
a_s.clone(),
|
a_s.clone(),
|
||||||
&backends,
|
&backends,
|
||||||
work_controller.get_context(),
|
work_controller.get_context(),
|
||||||
|
sender.clone(),
|
||||||
NotifyFn::new(Box::new(move |f: FolderHash| {
|
NotifyFn::new(Box::new(move |f: FolderHash| {
|
||||||
sender
|
sender
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::StartupCheck(f)))
|
.send(ThreadEvent::UIEvent(UIEvent::StartupCheck(f)))
|
||||||
|
@ -286,7 +283,6 @@ impl State {
|
||||||
tx: input_thread.0,
|
tx: input_thread.0,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
threads: FnvHashMap::with_capacity_and_hasher(1, Default::default()),
|
|
||||||
};
|
};
|
||||||
if s.context.settings.terminal.ascii_drawing {
|
if s.context.settings.terminal.ascii_drawing {
|
||||||
s.grid.set_ascii_drawing(true);
|
s.grid.set_ascii_drawing(true);
|
||||||
|
@ -319,41 +315,29 @@ impl State {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let Context {
|
let Context {
|
||||||
ref mut work_controller,
|
ref mut accounts, ..
|
||||||
ref sender,
|
|
||||||
ref mut replies,
|
|
||||||
ref mut accounts,
|
|
||||||
..
|
|
||||||
} = &mut self.context;
|
} = &mut self.context;
|
||||||
|
|
||||||
if let Some(notification) =
|
if let Some(notification) = accounts[idxa].reload(event, hash) {
|
||||||
accounts[idxa].reload(event, hash, (work_controller, sender, replies))
|
|
||||||
{
|
|
||||||
if let UIEvent::Notification(_, _, _) = notification {
|
if let UIEvent::Notification(_, _, _) = notification {
|
||||||
self.rcv_event(UIEvent::MailboxUpdate((idxa, hash)));
|
self.rcv_event(UIEvent::MailboxUpdate((idxa, hash)));
|
||||||
}
|
}
|
||||||
self.rcv_event(notification);
|
self.rcv_event(notification);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if let melib::backends::RefreshEventKind::Failure(e) = event.kind() {
|
if let melib::backends::RefreshEventKind::Failure(err) = event.kind() {
|
||||||
self.context
|
debug!(err);
|
||||||
.sender
|
|
||||||
.send(ThreadEvent::UIEvent(UIEvent::Notification(
|
|
||||||
Some("watcher thread exited with error".to_string()),
|
|
||||||
e.to_string(),
|
|
||||||
Some(crate::types::NotificationType::ERROR),
|
|
||||||
)))
|
|
||||||
.expect("Could not send event on main channel");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// If an owned thread returns a `ThreadEvent::ThreadJoin` event to `State` then it must remove
|
pub fn new_thread(&mut self, id: thread::ThreadId, name: String) {
|
||||||
/// the thread from its list and `join` it.
|
self.context
|
||||||
pub fn join(&mut self, id: thread::ThreadId) {
|
.work_controller
|
||||||
let (tx, handle) = self.threads.remove(&id).unwrap();
|
.static_threads
|
||||||
tx.send(true).unwrap();
|
.lock()
|
||||||
handle.join().unwrap();
|
.unwrap()
|
||||||
|
.insert(id, name.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Switch back to the terminal's main screen (The command line the user sees before opening
|
/// Switch back to the terminal's main screen (The command line the user sees before opening
|
||||||
|
|
|
@ -46,7 +46,7 @@ pub enum StatusEvent {
|
||||||
/// to the main process.
|
/// to the main process.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum ThreadEvent {
|
pub enum ThreadEvent {
|
||||||
ThreadJoin(thread::ThreadId),
|
NewThread(thread::ThreadId, String),
|
||||||
/// User input.
|
/// User input.
|
||||||
Input(Key),
|
Input(Key),
|
||||||
/// User input and input as raw bytes.
|
/// User input and input as raw bytes.
|
||||||
|
|
Loading…
Reference in New Issue