ui: avoid full renders when worker threads return StartupChecks

Now listings only re-render when their folder gets a StartupCheck event,
account menu always re-renders to update new mail counts

closes #76
embed
Manos Pitsidianakis 2019-03-30 13:41:32 +02:00
parent d19bda8977
commit 551db51b00
Signed by: Manos Pitsidianakis
GPG Key ID: 73627C2F690DF710
9 changed files with 38 additions and 50 deletions

View File

@ -121,7 +121,7 @@ impl RefreshEventConsumer {
}
}
pub struct NotifyFn(Box<Fn() -> ()>);
pub struct NotifyFn(Box<Fn(FolderHash) -> ()>);
unsafe impl Send for NotifyFn {}
unsafe impl Sync for NotifyFn {}
@ -131,18 +131,18 @@ impl fmt::Debug for NotifyFn {
}
}
impl From<Box<Fn() -> ()>> for NotifyFn {
fn from(kind: Box<Fn() -> ()>) -> Self {
impl From<Box<Fn(FolderHash) -> ()>> for NotifyFn {
fn from(kind: Box<Fn(FolderHash) -> ()>) -> Self {
NotifyFn(kind)
}
}
impl NotifyFn {
pub fn new(b: Box<Fn() -> ()>) -> Self {
pub fn new(b: Box<Fn(FolderHash) -> ()>) -> Self {
NotifyFn(b)
}
pub fn notify(&self) {
self.0();
pub fn notify(&self, f: FolderHash) {
self.0(f);
}
}
pub trait MailBackend: ::std::fmt::Debug {

View File

@ -171,24 +171,6 @@ fn main() {
break 'inner; // `goto` 'reap loop, and wait on child.
}
}
ThreadEvent::UIEvent(UIEventType::StartupCheck) => {
let mut render_flag = false;
for idx_a in 0..state.context.accounts.len() {
let len = state.context.accounts[idx_a].len();
for idx_m in 0..len {
match state.context.account_status(idx_a, idx_m) {
Ok(_) => {
render_flag = true;
},
Err(_) => {}
}
}
}
if render_flag {
state.render();
}
}
ThreadEvent::UIEvent(e) => {
state.rcv_event(UIEvent { id: 0, event_type: e});
state.render();

View File

@ -247,9 +247,7 @@ impl Component for AccountMenu {
}
clear_area(grid, area);
let upper_left = upper_left!(area);
let x = get_x(upper_left);
let bottom_right = bottom_right!(area);
let x_max = get_x(bottom_right);
self.dirty = false;
let mut y = get_y(upper_left);
for a in &self.accounts {
@ -275,6 +273,9 @@ impl Component for AccountMenu {
self.visible = !self.visible;
self.dirty = true;
}
UIEventType::StartupCheck(_) => {
self.dirty = true;
}
_ => {}
}
false

View File

@ -479,11 +479,13 @@ impl Component for CompactListing {
self.view = None;
self.dirty = true;
}
UIEventType::MailboxUpdate((ref idxa, ref idxf)) => {
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 {
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::MailboxUpdate((ref idxa, ref idxf)) if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 => {
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::StartupCheck(ref f) if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) => {
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::ChangeMode(UIMode::Normal) => {
self.dirty = true;

View File

@ -512,11 +512,13 @@ impl Component for PlainListing {
self.dirty = true;
self.view = None;
}
UIEventType::MailboxUpdate((ref idxa, ref idxf)) => {
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 {
self.dirty = true;
self.refresh_mailbox(context);
}
UIEventType::MailboxUpdate((ref idxa, ref idxf)) if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 => {
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::StartupCheck(ref f) if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) => {
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::ChangeMode(UIMode::Normal) => {
self.dirty = true;

View File

@ -651,14 +651,13 @@ impl Component for ThreadListing {
self.dirty = true;
self.view = None;
}
UIEventType::MailboxUpdate((ref idxa, ref idxf)) => {
if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 {
self.dirty = true;
self.refresh_mailbox(context);
if cfg!(feature = "debug_log") {
eprintln!("mailboxupdate");
}
}
UIEventType::MailboxUpdate((ref idxa, ref idxf)) if *idxa == self.new_cursor_pos.0 && *idxf == self.new_cursor_pos.1 => {
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::StartupCheck(ref f) if context.mailbox_hashes[f] == (self.new_cursor_pos.0, self.new_cursor_pos.1) => {
self.refresh_mailbox(context);
self.set_dirty();
}
UIEventType::ChangeMode(UIMode::Normal) => {
self.dirty = true;

View File

@ -140,9 +140,10 @@ impl Account {
work.compute();
handle.join();
let envelopes = handle.extract();
let hash = folder.hash();
let ret = Mailbox::new(folder, envelopes);
tx.send(AsyncStatus::Payload(ret));
notify_fn.notify();
notify_fn.notify(hash);
})))
}
pub fn reload(&mut self, event: RefreshEvent, idx: usize) -> Option<UIEventType> {

View File

@ -75,7 +75,7 @@ impl InputHandler {
/// A context container for loaded settings, accounts, UI changes, etc.
pub struct Context {
pub accounts: Vec<Account>,
mailbox_hashes: FnvHashMap<FolderHash, (usize, usize)>,
pub mailbox_hashes: FnvHashMap<FolderHash, (usize, usize)>,
pub settings: Settings,
pub runtime_settings: Settings,
@ -185,8 +185,8 @@ impl State {
n.to_string(),
a_s.clone(),
&backends,
NotifyFn::new(Box::new(move || {
sender.send(ThreadEvent::UIEvent(UIEventType::StartupCheck))
NotifyFn::new(Box::new(move |f: FolderHash| {
sender.send(ThreadEvent::UIEvent(UIEventType::StartupCheck(f)))
})),
)
})
@ -279,7 +279,7 @@ impl State {
if let Some(notification) = self.context.accounts[idxa].reload(event, idxm) {
self.context
.sender
.send(ThreadEvent::UIEvent(UIEventType::StartupCheck));
.send(ThreadEvent::UIEvent(UIEventType::StartupCheck(hash)));
self.context.replies.push_back(UIEvent {
id: 0,
event_type: notification,

View File

@ -27,6 +27,7 @@ use super::execute::Action;
use super::terminal::*;
use melib::RefreshEvent;
use melib::backends::FolderHash;
use std;
use std::fmt;
use std::thread;
@ -83,7 +84,7 @@ pub enum UIEventType {
StatusEvent(StatusEvent),
MailboxUpdate((usize, usize)), // (account_idx, mailbox_idx)
EntityKill(Uuid),
StartupCheck,
StartupCheck(FolderHash),
RefreshEvent(Box<RefreshEvent>),
}