diff --git a/melib/src/backends/maildir/backend.rs b/melib/src/backends/maildir/backend.rs index a3004f57..e51eec32 100644 --- a/melib/src/backends/maildir/backend.rs +++ b/melib/src/backends/maildir/backend.rs @@ -839,7 +839,7 @@ fn add_path_to_index( let hash = get_file_hash(path); { let mut map = hash_index.lock().unwrap(); - let map = map.entry(folder_hash).or_default();; + let map = map.entry(folder_hash).or_default(); map.insert(hash, path.to_path_buf().into()); debug!( "inserted {} in {} map, len={}", diff --git a/melib/src/email/address.rs b/melib/src/email/address.rs index 4845d328..d5807e44 100644 --- a/melib/src/email/address.rs +++ b/melib/src/email/address.rs @@ -68,11 +68,10 @@ impl Address { pub fn get_tags(&self, separator: char) -> Vec { let mut ret = Vec::new(); - if let email = self.get_email() { - let at_pos = email.as_bytes().iter().position(|&b| b == b'@').unwrap(); - let email: &str = email[..at_pos].into(); - ret.extend(email.split(separator).skip(1).map(str::to_string)); - } + let email = self.get_email(); + let at_pos = email.as_bytes().iter().position(|&b| b == b'@').unwrap(); + let email: &str = email[..at_pos].into(); + ret.extend(email.split(separator).skip(1).map(str::to_string)); ret } } diff --git a/ui/src/components.rs b/ui/src/components.rs index bc56f14a..583c8e9c 100644 --- a/ui/src/components.rs +++ b/ui/src/components.rs @@ -86,9 +86,7 @@ pub type ShortcutMaps = FnvHashMap; pub trait Component: Display + Debug + Send { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context); fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool; - fn is_dirty(&self) -> bool { - true - } + fn is_dirty(&self) -> bool; fn is_visible(&self) -> bool { true } diff --git a/ui/src/components/mail/view.rs b/ui/src/components/mail/view.rs index 154bd01a..315970aa 100644 --- a/ui/src/components/mail/view.rs +++ b/ui/src/components/mail/view.rs @@ -341,6 +341,7 @@ impl Component for MailView { if !account.contains_key(self.coordinates.2) { /* The envelope has been renamed or removed, so wait for the appropriate event to * arrive */ + self.dirty = false; return; } let (hash, is_seen) = { @@ -638,7 +639,6 @@ impl Component for MailView { self.subview = None; } }; - self.dirty = false; } match self.mode { ViewMode::Subview if self.subview.is_some() => { @@ -656,6 +656,7 @@ impl Component for MailView { } } } + self.dirty = false; } fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { diff --git a/ui/src/components/mail/view/thread.rs b/ui/src/components/mail/view/thread.rs index b3cf3e27..f84ad207 100644 --- a/ui/src/components/mail/view/thread.rs +++ b/ui/src/components/mail/view/thread.rs @@ -414,11 +414,14 @@ impl ThreadView { let bottom_right = bottom_right!(area); let (width, height) = self.content.size(); if height == 0 { - clear_area(grid, area); context.dirty_areas.push_back(area); return; } let rows = (get_y(bottom_right) - get_y(upper_left)).wrapping_div(2); + if rows == 0 { + context.dirty_areas.push_back(area); + return; + } if let Some(mvm) = self.movement.take() { match mvm { PageMovement::PageUp => { @@ -751,7 +754,10 @@ impl ThreadView { let upper_left = upper_left!(area); let bottom_right = bottom_right!(area); - let rows = (get_y(bottom_right) - get_y(upper_left) + 1) / 2; + let rows = (get_y(bottom_right).saturating_sub(get_y(upper_left) + 1)) / 2; + if rows == 0 { + return; + } let page_no = (self.new_cursor_pos).wrapping_div(rows); let top_idx = page_no * rows; @@ -765,7 +771,10 @@ impl ThreadView { let area = (set_y(upper_left, y), bottom_right); let upper_left = upper_left!(area); - let rows = (get_y(bottom_right) - get_y(upper_left) + 1) / 2; + let rows = (get_y(bottom_right).saturating_sub(get_y(upper_left) + 1)) / 2; + if rows == 0 { + return; + } let page_no = (self.new_cursor_pos).wrapping_div(rows); let top_idx = page_no * rows; copy_area( @@ -875,6 +884,7 @@ impl Component for ThreadView { fn draw(&mut self, grid: &mut CellBuffer, area: Area, context: &mut Context) { let total_cols = width!(area); if self.entries.is_empty() { + self.dirty = false; return; } @@ -891,6 +901,7 @@ impl Component for ThreadView { if self.entries.len() == 1 { self.mailview.draw(grid, area, context); + self.dirty = false; return; } @@ -899,6 +910,7 @@ impl Component for ThreadView { } else { self.draw_horz(grid, area, context); } + self.dirty = false; } fn process_event(&mut self, event: &mut UIEvent, context: &mut Context) -> bool { match event { @@ -959,6 +971,7 @@ impl Component for ThreadView { UIEvent::Input(Key::Up) => { if self.cursor_pos > 0 { self.new_cursor_pos = self.new_cursor_pos.saturating_sub(1); + self.dirty = true; } return true; } @@ -966,24 +979,25 @@ impl Component for ThreadView { let height = self.visible_entries.iter().flat_map(|v| v.iter()).count(); if height > 0 && self.new_cursor_pos + 1 < height { self.new_cursor_pos += 1; + self.dirty = true; } return true; } UIEvent::Input(ref key) if *key == shortcuts["prev_page"] => { self.movement = Some(PageMovement::PageUp); - self.set_dirty(); + self.dirty = true; } UIEvent::Input(ref key) if *key == shortcuts["next_page"] => { self.movement = Some(PageMovement::PageDown); - self.set_dirty(); + self.dirty = true; } UIEvent::Input(ref key) if *key == Key::Home => { self.movement = Some(PageMovement::Home); - self.set_dirty(); + self.dirty = true; } UIEvent::Input(ref key) if *key == Key::End => { self.movement = Some(PageMovement::End); - self.set_dirty(); + self.dirty = true; } UIEvent::Input(Key::Char('\n')) => { if self.entries.len() < 2 { @@ -1066,9 +1080,7 @@ impl Component for ThreadView { false } fn is_dirty(&self) -> bool { - (self.cursor_pos != self.new_cursor_pos) - || self.dirty - || (self.show_mailview && self.mailview.is_dirty()) + self.dirty || (self.show_mailview && self.mailview.is_dirty()) } fn set_dirty(&mut self) { self.dirty = true; diff --git a/ui/src/components/notifications.rs b/ui/src/components/notifications.rs index 8f9b11c1..5b0acf17 100644 --- a/ui/src/components/notifications.rs +++ b/ui/src/components/notifications.rs @@ -73,6 +73,9 @@ impl Component for XDGNotifications { false } fn set_dirty(&mut self) {} + fn is_dirty(&self) -> bool { + false + } fn id(&self) -> ComponentId { ComponentId::nil() @@ -174,6 +177,9 @@ impl Component for NotificationFilter { fn id(&self) -> ComponentId { ComponentId::nil() } + fn is_dirty(&self) -> bool { + false + } fn set_dirty(&mut self) {} fn set_id(&mut self, _id: ComponentId) {} } diff --git a/ui/src/components/utilities.rs b/ui/src/components/utilities.rs index 626c10c6..db8c54f6 100644 --- a/ui/src/components/utilities.rs +++ b/ui/src/components/utilities.rs @@ -554,7 +554,7 @@ impl Component for Pager { "Pager text piped to '{}{}{}'", &bin, if args.is_empty() { "" } else { " " }, - args.join(", ") + args.join(" ") )))); return true; } @@ -1121,6 +1121,9 @@ impl Component for Progress { false } fn set_dirty(&mut self) {} + fn is_dirty(&self) -> bool { + false + } fn id(&self) -> ComponentId { self.id diff --git a/ui/src/components/utilities/widgets.rs b/ui/src/components/utilities/widgets.rs index 387fd906..749e63fa 100644 --- a/ui/src/components/utilities/widgets.rs +++ b/ui/src/components/utilities/widgets.rs @@ -195,7 +195,7 @@ impl Component for Field { true } fn is_dirty(&self) -> bool { - true + false } fn set_dirty(&mut self) {} @@ -477,6 +477,7 @@ where result: Option, cursor: usize, + dirty: bool, id: ComponentId, } @@ -499,6 +500,7 @@ where buttons: vec![init_val].into_iter().collect(), result: None, cursor: 0, + dirty: true, id: ComponentId::new_v4(), } } @@ -518,28 +520,31 @@ where T: std::fmt::Debug + Default + Send, { fn draw(&mut self, grid: &mut CellBuffer, area: Area, _context: &mut Context) { - let upper_left = upper_left!(area); + if self.dirty { + let upper_left = upper_left!(area); - let mut len = 0; - for (i, k) in self.layout.iter().enumerate() { - let cur_len = k.len(); - write_string_to_grid( - k.as_str(), - grid, - Color::Default, - if i == self.cursor { - Color::Byte(246) - } else { - Color::Default - }, - Attr::Default, - ( - pos_inc(upper_left, (len, 0)), - pos_inc(upper_left, (cur_len + len, 0)), - ), - false, - ); - len += cur_len + 3; + let mut len = 0; + for (i, k) in self.layout.iter().enumerate() { + let cur_len = k.len(); + write_string_to_grid( + k.as_str(), + grid, + Color::Default, + if i == self.cursor { + Color::Byte(246) + } else { + Color::Default + }, + Attr::Default, + ( + pos_inc(upper_left, (len, 0)), + pos_inc(upper_left, (cur_len + len, 0)), + ), + false, + ); + len += cur_len + 3; + } + self.dirty = false; } } fn process_event(&mut self, event: &mut UIEvent, _context: &mut Context) -> bool { @@ -550,25 +555,26 @@ where .remove(&self.layout[self.cursor]) .unwrap_or_default(), ); - return true; } UIEvent::Input(Key::Left) => { self.cursor = self.cursor.saturating_sub(1); - return true; } UIEvent::Input(Key::Right) if self.cursor < self.layout.len().saturating_sub(1) => { self.cursor += 1; - return true; } - _ => {} + _ => { + return false; + } } - - false - } - fn is_dirty(&self) -> bool { + self.set_dirty(); true } - fn set_dirty(&mut self) {} + fn is_dirty(&self) -> bool { + self.dirty + } + fn set_dirty(&mut self) { + self.dirty = true; + } fn id(&self) -> ComponentId { self.id @@ -695,7 +701,7 @@ impl AutoComplete { pub fn set_suggestions(&mut self, entries: Vec) -> bool { if entries.len() == self.entries.len() && entries == self.entries { - return false;; + return false; } let mut content = CellBuffer::new( diff --git a/ui/src/state.rs b/ui/src/state.rs index 27bcdfe2..326a906a 100644 --- a/ui/src/state.rs +++ b/ui/src/state.rs @@ -403,6 +403,9 @@ impl State { self.draw_component(i); } let mut areas: Vec = self.context.dirty_areas.drain(0..).collect(); + if areas.is_empty() { + return; + } /* Sort by x_start, ie upper_left corner's x coordinate */ areas.sort_by(|a, b| (a.0).0.partial_cmp(&(b.0).0).unwrap()); /* draw each dirty area */ @@ -510,9 +513,11 @@ impl State { ); } } + pub fn register_component(&mut self, component: Box) { self.components.push(component); } + /// Convert user commands to actions/method calls. fn parse_command(&mut self, cmd: &str) { let result = parse_command(&cmd.as_bytes()).to_full_result(); diff --git a/ui/src/workers.rs b/ui/src/workers.rs index 307ff6bd..7aa1c996 100644 --- a/ui/src/workers.rs +++ b/ui/src/workers.rs @@ -243,7 +243,7 @@ impl WorkController { } else if static_threads.contains_key(&thread_id) { static_threads.entry(thread_id).and_modify(|e| e.name = new_name); } else { - unreachable!() + static_threads.insert(thread_id, new_name.into()); } pulse.send(ThreadEvent::Pulse).unwrap(); } @@ -258,7 +258,7 @@ impl WorkController { static_threads.entry(thread_id).and_modify(|e| e.status = new_status); debug!(&static_threads[&thread_id]); } else { - unreachable!() + static_threads.insert(thread_id, Worker { status: new_status, .. String::new().into() }); } pulse.send(ThreadEvent::Pulse).unwrap(); } @@ -272,7 +272,7 @@ impl WorkController { } else if static_threads.contains_key(&thread_id) { static_threads.remove(&thread_id); } else { - unreachable!() + /* Nothing to do */ } pulse.send(ThreadEvent::Pulse).unwrap(); }