From 475609fe9264c37d3a8bc835ea654d2c2e047f9b Mon Sep 17 00:00:00 2001 From: Manos Pitsidianakis Date: Thu, 21 Mar 2024 13:35:41 +0200 Subject: [PATCH] listing: make {prev,next}_entry shortcut behavior consistent prev_entry, next_entry shortcuts (default bindings: Ctrl+p and Ctrl+n) were not behaving consistently in all different listing index styles. In particular in some conditions the switch entry shortcuts worked at most once because the cursor position was not updated properly. This commit fixes that. Signed-off-by: Manos Pitsidianakis --- meli/src/mail/listing/compact.rs | 175 +++++++++++------------ meli/src/mail/listing/conversations.rs | 168 +++++++++++----------- meli/src/mail/listing/plain.rs | 168 +++++++++++----------- meli/src/mail/listing/thread.rs | 187 +++++++++++++------------ 4 files changed, 360 insertions(+), 338 deletions(-) diff --git a/meli/src/mail/listing/compact.rs b/meli/src/mail/listing/compact.rs index 1efe7007..411b1b15 100644 --- a/meli/src/mail/listing/compact.rs +++ b/meli/src/mail/listing/compact.rs @@ -264,25 +264,21 @@ impl MailListingTrait for CompactListing { Box::new(roots.into_iter()) as Box>, ); - if let Some((thread_hash, env_hash)) = self + if self .get_thread_under_cursor(self.cursor_pos.2) - .and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0]))) + .and_then(|thread| { + self.rows + .thread_to_env + .get(&thread) + .and_then(|e| Some((thread, e.first()?))) + }) + .is_some() { if !force && old_cursor_pos == self.new_cursor_pos { self.kick_parent(self.parent, ListingMessage::UpdateView, context); } else if self.unfocused() { self.force_draw = true; self.dirty = true; - self.kick_parent( - self.parent, - ListingMessage::OpenEntryUnderCursor { - thread_hash, - env_hash, - show_thread: true, - go_to_first_unread: true, - }, - context, - ); self.set_focus(Focus::Entry, context); } } @@ -568,38 +564,32 @@ impl ListingTrait for CompactListing { fn next_entry(&mut self, context: &mut Context) { if self - .get_thread_under_cursor(self.cursor_pos.2 + 1) + .get_thread_under_cursor(self.new_cursor_pos.2 + 1) .is_some() { // [ref:TODO]: makes this less ugly. self.movement = Some(PageMovement::Down(1)); + self.perform_movement(None); self.force_draw = true; self.dirty = true; - self.cursor_pos.2 += 1; - self.new_cursor_pos.2 += 1; self.set_focus(Focus::Entry, context); - self.cursor_pos.2 -= 1; - self.new_cursor_pos.2 -= 1; } } fn prev_entry(&mut self, context: &mut Context) { - if self.cursor_pos.2 == 0 { + if self.new_cursor_pos.2 == 0 { return; } if self - .get_thread_under_cursor(self.cursor_pos.2 - 1) + .get_thread_under_cursor(self.new_cursor_pos.2 - 1) .is_some() { // [ref:TODO]: makes this less ugly. self.movement = Some(PageMovement::Up(1)); + self.perform_movement(None); self.force_draw = true; self.dirty = true; - self.cursor_pos.2 -= 1; - self.new_cursor_pos.2 -= 1; self.set_focus(Focus::Entry, context); - self.cursor_pos.2 += 1; - self.new_cursor_pos.2 += 1; } } @@ -665,52 +655,7 @@ impl ListingTrait for CompactListing { return; } - if let Some(mvm) = self.movement.take() { - match mvm { - PageMovement::Up(amount) => { - self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount); - } - PageMovement::PageUp(multiplier) => { - self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier); - } - PageMovement::Down(amount) => { - if self.new_cursor_pos.2 + amount + 1 < self.length { - self.new_cursor_pos.2 += amount; - } else { - self.new_cursor_pos.2 = self.length - 1; - } - } - PageMovement::PageDown(multiplier) => { - if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length { - self.new_cursor_pos.2 += rows * multiplier; - } else if self.new_cursor_pos.2 + rows * multiplier > self.length { - self.new_cursor_pos.2 = self.length - 1; - } else { - self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows; - } - } - PageMovement::Right(amount) => { - self.data_columns.x_offset += amount; - self.data_columns.x_offset = self.data_columns.x_offset.min( - self.data_columns - .widths - .iter() - .map(|w| w + 2) - .sum::() - .saturating_sub(2), - ); - } - PageMovement::Left(amount) => { - self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount); - } - PageMovement::Home => { - self.new_cursor_pos.2 = 0; - } - PageMovement::End => { - self.new_cursor_pos.2 = self.length - 1; - } - } - } + self.perform_movement(Some(rows)); if self.force_draw { grid.clear_area(area, self.color_cache.theme_default); @@ -876,7 +821,7 @@ impl ListingTrait for CompactListing { } Focus::Entry => { if let Some((thread_hash, env_hash)) = self - .get_thread_under_cursor(self.cursor_pos.2) + .get_thread_under_cursor(self.new_cursor_pos.2) .and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0]))) { self.force_draw = true; @@ -891,6 +836,7 @@ impl ListingTrait for CompactListing { }, context, ); + self.cursor_pos.2 = self.new_cursor_pos.2; } else { return; } @@ -1662,6 +1608,56 @@ impl CompactListing { } } } + + fn perform_movement(&mut self, height: Option) { + let rows = height.unwrap_or(1); + if let Some(mvm) = self.movement.take() { + match mvm { + PageMovement::Up(amount) => { + self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount); + } + PageMovement::PageUp(multiplier) => { + self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier); + } + PageMovement::Down(amount) => { + if self.new_cursor_pos.2 + amount + 1 < self.length { + self.new_cursor_pos.2 += amount; + } else { + self.new_cursor_pos.2 = self.length - 1; + } + } + PageMovement::PageDown(multiplier) => { + if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length { + self.new_cursor_pos.2 += rows * multiplier; + } else if self.new_cursor_pos.2 + rows * multiplier > self.length { + self.new_cursor_pos.2 = self.length - 1; + } else { + self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows; + } + } + PageMovement::Right(amount) => { + self.data_columns.x_offset += amount; + self.data_columns.x_offset = self.data_columns.x_offset.min( + self.data_columns + .widths + .iter() + .map(|w| w + 2) + .sum::() + .saturating_sub(2), + ); + } + PageMovement::Left(amount) => { + self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount); + } + PageMovement::Home => { + self.new_cursor_pos.2 = 0; + } + PageMovement::End => { + self.new_cursor_pos.2 = self.length - 1; + } + } + } + } } impl Component for CompactListing { @@ -1703,7 +1699,9 @@ impl Component for CompactListing { if let Some(mvm) = self.movement.as_ref() { match mvm { PageMovement::Up(amount) => { - for c in self.cursor_pos.2.saturating_sub(*amount)..=self.cursor_pos.2 { + for c in self.new_cursor_pos.2.saturating_sub(*amount) + ..=self.new_cursor_pos.2 + { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( thread, @@ -1719,8 +1717,8 @@ impl Component for CompactListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2.saturating_sub(*amount)) - .chain((self.cursor_pos.2 + 2)..self.length) + for c in (0..self.new_cursor_pos.2.saturating_sub(*amount)) + .chain((self.new_cursor_pos.2 + 2)..self.length) { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows @@ -1730,8 +1728,8 @@ impl Component for CompactListing { } } PageMovement::PageUp(multiplier) => { - for c in self.cursor_pos.2.saturating_sub(rows * multiplier) - ..=self.cursor_pos.2 + for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier) + ..=self.new_cursor_pos.2 { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( @@ -1749,8 +1747,8 @@ impl Component for CompactListing { } } PageMovement::Down(amount) => { - for c in - self.cursor_pos.2..self.length.min(self.cursor_pos.2 + amount + 1) + for c in self.new_cursor_pos.2 + ..self.length.min(self.new_cursor_pos.2 + amount + 1) { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( @@ -1767,8 +1765,9 @@ impl Component for CompactListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2).chain( - self.length.min(self.cursor_pos.2 + amount) + 1..self.length, + for c in (0..self.new_cursor_pos.2).chain( + self.length.min(self.new_cursor_pos.2 + amount) + 1 + ..self.length, ) { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows @@ -1778,8 +1777,10 @@ impl Component for CompactListing { } } PageMovement::PageDown(multiplier) => { - for c in self.cursor_pos.2 - ..self.length.min(self.cursor_pos.2 + rows * multiplier + 1) + for c in self.new_cursor_pos.2 + ..self + .length + .min(self.new_cursor_pos.2 + rows * multiplier + 1) { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( @@ -1796,8 +1797,8 @@ impl Component for CompactListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2).chain( - self.length.min(self.cursor_pos.2 + rows * multiplier) + 1 + for c in (0..self.new_cursor_pos.2).chain( + self.length.min(self.new_cursor_pos.2 + rows * multiplier) + 1 ..self.length, ) { if let Some(thread) = self.get_thread_under_cursor(c) { @@ -1809,7 +1810,7 @@ impl Component for CompactListing { } PageMovement::Right(_) | PageMovement::Left(_) => {} PageMovement::Home => { - for c in 0..=self.cursor_pos.2 { + for c in 0..=self.new_cursor_pos.2 { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( thread, @@ -1825,7 +1826,7 @@ impl Component for CompactListing { } } if modifier == Modifier::Intersection { - for c in (self.cursor_pos.2)..self.length { + for c in (self.new_cursor_pos.2)..self.length { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows .update_selection_with_thread(thread, |e| *e = false); @@ -1834,7 +1835,7 @@ impl Component for CompactListing { } } PageMovement::End => { - for c in self.cursor_pos.2..self.length { + for c in self.new_cursor_pos.2..self.length { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( thread, @@ -1850,7 +1851,7 @@ impl Component for CompactListing { } } if modifier == Modifier::Intersection { - for c in 0..self.cursor_pos.2 { + for c in 0..self.new_cursor_pos.2 { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows .update_selection_with_thread(thread, |e| *e = false); diff --git a/meli/src/mail/listing/conversations.rs b/meli/src/mail/listing/conversations.rs index d7b1ca96..ec124012 100644 --- a/meli/src/mail/listing/conversations.rs +++ b/meli/src/mail/listing/conversations.rs @@ -227,23 +227,20 @@ impl MailListingTrait for ConversationsListing { if !force && old_cursor_pos == self.new_cursor_pos && old_mailbox_hash == self.cursor_pos.1 { self.kick_parent(self.parent, ListingMessage::UpdateView, context); - } else if self.unfocused() { - if let Some((thread_hash, env_hash)) = self + } else if self.unfocused() + && self .get_thread_under_cursor(self.cursor_pos.2) - .and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0]))) - { - self.kick_parent( - self.parent, - ListingMessage::OpenEntryUnderCursor { - thread_hash, - env_hash, - show_thread: true, - go_to_first_unread: true, - }, - context, - ); - self.set_focus(Focus::Entry, context); - } + .and_then(|thread| { + self.rows + .thread_to_env + .get(&thread) + .and_then(|e| Some((thread, e.first()?))) + }) + .is_some() + { + self.force_draw = true; + self.dirty = true; + self.set_focus(Focus::Entry, context); } } @@ -412,38 +409,32 @@ impl ListingTrait for ConversationsListing { fn next_entry(&mut self, context: &mut Context) { if self - .get_thread_under_cursor(self.cursor_pos.2 + 1) + .get_thread_under_cursor(self.new_cursor_pos.2 + 1) .is_some() { // [ref:TODO]: makes this less ugly. self.movement = Some(PageMovement::Down(1)); + self.perform_movement(None); self.force_draw = true; self.dirty = true; - self.cursor_pos.2 += 1; - self.new_cursor_pos.2 += 1; self.set_focus(Focus::Entry, context); - self.cursor_pos.2 -= 1; - self.new_cursor_pos.2 -= 1; } } fn prev_entry(&mut self, context: &mut Context) { - if self.cursor_pos.2 == 0 { + if self.new_cursor_pos.2 == 0 { return; } if self - .get_thread_under_cursor(self.cursor_pos.2 - 1) + .get_thread_under_cursor(self.new_cursor_pos.2 - 1) .is_some() { // [ref:TODO]: makes this less ugly. self.movement = Some(PageMovement::Up(1)); + self.perform_movement(None); self.force_draw = true; self.dirty = true; - self.cursor_pos.2 -= 1; - self.new_cursor_pos.2 -= 1; self.set_focus(Focus::Entry, context); - self.cursor_pos.2 += 1; - self.new_cursor_pos.2 += 1; } } @@ -474,42 +465,12 @@ impl ListingTrait for ConversationsListing { return; } let rows = area.height() / 3; + if rows == 0 { return; } - if let Some(mvm) = self.movement.take() { - match mvm { - PageMovement::Up(amount) => { - self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount); - } - PageMovement::PageUp(multiplier) => { - self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier); - } - PageMovement::Down(amount) => { - if self.new_cursor_pos.2 + amount + 1 < self.length { - self.new_cursor_pos.2 += amount; - } else { - self.new_cursor_pos.2 = self.length.saturating_sub(1); - } - } - PageMovement::PageDown(multiplier) => { - if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length { - self.new_cursor_pos.2 += rows * multiplier; - } else if self.new_cursor_pos.2 + rows * multiplier > self.length { - self.new_cursor_pos.2 = self.length.saturating_sub(1); - } else { - self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows; - } - } - PageMovement::Right(_) | PageMovement::Left(_) => {} - PageMovement::Home => { - self.new_cursor_pos.2 = 0; - } - PageMovement::End => { - self.new_cursor_pos.2 = self.length.saturating_sub(1); - } - } - } + + self.perform_movement(Some(rows)); let prev_page_no = (self.cursor_pos.2).wrapping_div(rows); let page_no = (self.new_cursor_pos.2).wrapping_div(rows); @@ -643,8 +604,13 @@ impl ListingTrait for ConversationsListing { } Focus::Entry => { if let Some((thread_hash, env_hash)) = self - .get_thread_under_cursor(self.cursor_pos.2) - .and_then(|thread| self.rows.thread_to_env.get(&thread).map(|e| (thread, e[0]))) + .get_thread_under_cursor(self.new_cursor_pos.2) + .and_then(|thread| { + self.rows + .thread_to_env + .get(&thread) + .and_then(|e| Some((thread, *e.first()?))) + }) { self.force_draw = true; self.dirty = true; @@ -658,6 +624,7 @@ impl ListingTrait for ConversationsListing { }, context, ); + self.cursor_pos.2 = self.new_cursor_pos.2; } else { return; } @@ -1003,6 +970,43 @@ impl ConversationsListing { } } } + + fn perform_movement(&mut self, height: Option) { + let rows = height.unwrap_or(1); + if let Some(mvm) = self.movement.take() { + match mvm { + PageMovement::Up(amount) => { + self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount); + } + PageMovement::PageUp(multiplier) => { + self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier); + } + PageMovement::Down(amount) => { + if self.new_cursor_pos.2 + amount + 1 < self.length { + self.new_cursor_pos.2 += amount; + } else { + self.new_cursor_pos.2 = self.length.saturating_sub(1); + } + } + PageMovement::PageDown(multiplier) => { + if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length { + self.new_cursor_pos.2 += rows * multiplier; + } else if self.new_cursor_pos.2 + rows * multiplier > self.length { + self.new_cursor_pos.2 = self.length.saturating_sub(1); + } else { + self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows; + } + } + PageMovement::Right(_) | PageMovement::Left(_) => {} + PageMovement::Home => { + self.new_cursor_pos.2 = 0; + } + PageMovement::End => { + self.new_cursor_pos.2 = self.length.saturating_sub(1); + } + } + } + } } impl Component for ConversationsListing { @@ -1046,7 +1050,9 @@ impl Component for ConversationsListing { if let Some(mvm) = self.movement.as_ref() { match mvm { PageMovement::Up(amount) => { - for c in self.cursor_pos.2.saturating_sub(*amount)..=self.cursor_pos.2 { + for c in self.new_cursor_pos.2.saturating_sub(*amount) + ..=self.new_cursor_pos.2 + { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( thread, @@ -1062,8 +1068,8 @@ impl Component for ConversationsListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2.saturating_sub(*amount)) - .chain((self.cursor_pos.2 + 2)..self.length) + for c in (0..self.new_cursor_pos.2.saturating_sub(*amount)) + .chain((self.new_cursor_pos.2 + 2)..self.length) { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows @@ -1073,8 +1079,8 @@ impl Component for ConversationsListing { } } PageMovement::PageUp(multiplier) => { - for c in self.cursor_pos.2.saturating_sub(rows * multiplier) - ..=self.cursor_pos.2 + for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier) + ..=self.new_cursor_pos.2 { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( @@ -1092,8 +1098,8 @@ impl Component for ConversationsListing { } } PageMovement::Down(amount) => { - for c in self.cursor_pos.2 - ..std::cmp::min(self.length, self.cursor_pos.2 + amount + 1) + for c in self.new_cursor_pos.2 + ..std::cmp::min(self.length, self.new_cursor_pos.2 + amount + 1) { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( @@ -1110,9 +1116,9 @@ impl Component for ConversationsListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2).chain( - (std::cmp::min(self.length, self.cursor_pos.2 + amount + 1) + 1) - ..self.length, + for c in (0..self.new_cursor_pos.2).chain( + (std::cmp::min(self.length, self.new_cursor_pos.2 + amount + 1) + + 1)..self.length, ) { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows @@ -1122,9 +1128,9 @@ impl Component for ConversationsListing { } } PageMovement::PageDown(multiplier) => { - for c in self.cursor_pos.2 + for c in self.new_cursor_pos.2 ..std::cmp::min( - self.cursor_pos.2 + rows * multiplier + 1, + self.new_cursor_pos.2 + rows * multiplier + 1, self.length, ) { @@ -1143,9 +1149,9 @@ impl Component for ConversationsListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2).chain( + for c in (0..self.new_cursor_pos.2).chain( (std::cmp::min( - self.cursor_pos.2 + rows * multiplier + 1, + self.new_cursor_pos.2 + rows * multiplier + 1, self.length, ) + 1)..self.length, ) { @@ -1158,7 +1164,7 @@ impl Component for ConversationsListing { } PageMovement::Right(_) | PageMovement::Left(_) => {} PageMovement::Home => { - for c in 0..=self.cursor_pos.2 { + for c in 0..=self.new_cursor_pos.2 { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( thread, @@ -1174,7 +1180,7 @@ impl Component for ConversationsListing { } } if modifier == Modifier::Intersection { - for c in (self.cursor_pos.2 + 1)..self.length { + for c in (self.new_cursor_pos.2 + 1)..self.length { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows .update_selection_with_thread(thread, |e| *e = false); @@ -1183,7 +1189,7 @@ impl Component for ConversationsListing { } } PageMovement::End => { - for c in self.cursor_pos.2..self.length { + for c in self.new_cursor_pos.2..self.length { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows.update_selection_with_thread( thread, @@ -1199,7 +1205,7 @@ impl Component for ConversationsListing { } } if modifier == Modifier::Intersection { - for c in 0..self.cursor_pos.2 { + for c in 0..self.new_cursor_pos.2 { if let Some(thread) = self.get_thread_under_cursor(c) { self.rows .update_selection_with_thread(thread, |e| *e = false); @@ -1218,7 +1224,7 @@ impl Component for ConversationsListing { self.update_line(context, row); let row: usize = self.rows.env_order[&row]; - let page_no = (self.cursor_pos.2).wrapping_div(rows); + let page_no = (self.new_cursor_pos.2).wrapping_div(rows); let top_idx = page_no * rows; // Update row only if it's currently visible diff --git a/meli/src/mail/listing/plain.rs b/meli/src/mail/listing/plain.rs index 2e028d66..be7141de 100644 --- a/meli/src/mail/listing/plain.rs +++ b/meli/src/mail/listing/plain.rs @@ -271,23 +271,12 @@ impl MailListingTrait for PlainListing { self.redraw_list(context, items); drop(env_lck); - if let Some(env_hash) = self.get_env_under_cursor(self.cursor_pos.2) { + if self.get_env_under_cursor(self.new_cursor_pos.2).is_some() { if !force && old_cursor_pos == self.new_cursor_pos { self.kick_parent(self.parent, ListingMessage::UpdateView, context); } else if self.unfocused() { - let thread_hash = self.rows.env_to_thread[&env_hash]; self.force_draw = true; self.dirty = true; - self.kick_parent( - self.parent, - ListingMessage::OpenEntryUnderCursor { - thread_hash, - env_hash, - show_thread: false, - go_to_first_unread: false, - }, - context, - ); self.set_focus(Focus::Entry, context); } } @@ -331,28 +320,32 @@ impl ListingTrait for PlainListing { } fn next_entry(&mut self, context: &mut Context) { - if self.get_env_under_cursor(self.cursor_pos.2 + 1).is_some() { + if self + .get_env_under_cursor(self.new_cursor_pos.2 + 1) + .is_some() + { // [ref:TODO]: makes this less ugly. self.movement = Some(PageMovement::Down(1)); + self.perform_movement(None); self.force_draw = true; self.dirty = true; - self.cursor_pos.2 += 1; - self.new_cursor_pos.2 += 1; self.set_focus(Focus::Entry, context); } } fn prev_entry(&mut self, context: &mut Context) { - if self.cursor_pos.2 == 0 { + if self.new_cursor_pos.2 == 0 { return; } - if self.get_env_under_cursor(self.cursor_pos.2 - 1).is_some() { + if self + .get_env_under_cursor(self.new_cursor_pos.2 - 1) + .is_some() + { // [ref:TODO]: makes this less ugly. self.movement = Some(PageMovement::Up(1)); + self.perform_movement(None); self.force_draw = true; self.dirty = true; - self.cursor_pos.2 -= 1; - self.new_cursor_pos.2 -= 1; self.set_focus(Focus::Entry, context); } } @@ -418,52 +411,7 @@ impl ListingTrait for PlainListing { return; } - if let Some(mvm) = self.movement.take() { - match mvm { - PageMovement::Up(amount) => { - self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount); - } - PageMovement::PageUp(multiplier) => { - self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier); - } - PageMovement::Down(amount) => { - if self.new_cursor_pos.2 + amount + 1 < self.length { - self.new_cursor_pos.2 += amount; - } else { - self.new_cursor_pos.2 = self.length - 1; - } - } - PageMovement::PageDown(multiplier) => { - if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length { - self.new_cursor_pos.2 += rows * multiplier; - } else if self.new_cursor_pos.2 + rows * multiplier > self.length { - self.new_cursor_pos.2 = self.length - 1; - } else { - self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows; - } - } - PageMovement::Right(amount) => { - self.data_columns.x_offset += amount; - self.data_columns.x_offset = self.data_columns.x_offset.min( - self.data_columns - .widths - .iter() - .map(|w| w + 2) - .sum::() - .saturating_sub(2), - ); - } - PageMovement::Left(amount) => { - self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount); - } - PageMovement::Home => { - self.new_cursor_pos.2 = 0; - } - PageMovement::End => { - self.new_cursor_pos.2 = self.length.saturating_sub(1); - } - } - } + self.perform_movement(Some(rows)); if self.force_draw { grid.clear_area(area, self.color_cache.theme_default); @@ -623,7 +571,7 @@ impl ListingTrait for PlainListing { } Focus::Entry => { if let Some((thread_hash, env_hash)) = self - .get_env_under_cursor(self.cursor_pos.2) + .get_env_under_cursor(self.new_cursor_pos.2) .map(|env_hash| (self.rows.env_to_thread[&env_hash], env_hash)) { self.force_draw = true; @@ -638,6 +586,7 @@ impl ListingTrait for PlainListing { }, context, ); + self.cursor_pos.2 = self.new_cursor_pos.2; } else { return; } @@ -1317,6 +1266,56 @@ impl PlainListing { } } } + + fn perform_movement(&mut self, height: Option) { + let rows = height.unwrap_or(1); + if let Some(mvm) = self.movement.take() { + match mvm { + PageMovement::Up(amount) => { + self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount); + } + PageMovement::PageUp(multiplier) => { + self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier); + } + PageMovement::Down(amount) => { + if self.new_cursor_pos.2 + amount + 1 < self.length { + self.new_cursor_pos.2 += amount; + } else { + self.new_cursor_pos.2 = self.length - 1; + } + } + PageMovement::PageDown(multiplier) => { + if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length { + self.new_cursor_pos.2 += rows * multiplier; + } else if self.new_cursor_pos.2 + rows * multiplier > self.length { + self.new_cursor_pos.2 = self.length - 1; + } else { + self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows; + } + } + PageMovement::Right(amount) => { + self.data_columns.x_offset += amount; + self.data_columns.x_offset = self.data_columns.x_offset.min( + self.data_columns + .widths + .iter() + .map(|w| w + 2) + .sum::() + .saturating_sub(2), + ); + } + PageMovement::Left(amount) => { + self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount); + } + PageMovement::Home => { + self.new_cursor_pos.2 = 0; + } + PageMovement::End => { + self.new_cursor_pos.2 = self.length.saturating_sub(1); + } + } + } + } } impl Component for PlainListing { @@ -1358,7 +1357,9 @@ impl Component for PlainListing { if let Some(mvm) = self.movement.as_ref() { match mvm { PageMovement::Up(amount) => { - for c in self.cursor_pos.2.saturating_sub(*amount)..=self.cursor_pos.2 { + for c in self.new_cursor_pos.2.saturating_sub(*amount) + ..=self.new_cursor_pos.2 + { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( env_hash, @@ -1374,8 +1375,8 @@ impl Component for PlainListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2.saturating_sub(*amount)) - .chain((self.cursor_pos.2 + 2)..self.length) + for c in (0..self.new_cursor_pos.2.saturating_sub(*amount)) + .chain((self.new_cursor_pos.2 + 2)..self.length) { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows @@ -1385,8 +1386,8 @@ impl Component for PlainListing { } } PageMovement::PageUp(multiplier) => { - for c in self.cursor_pos.2.saturating_sub(rows * multiplier) - ..=self.cursor_pos.2 + for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier) + ..=self.new_cursor_pos.2 { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( @@ -1404,8 +1405,8 @@ impl Component for PlainListing { } } PageMovement::Down(amount) => { - for c in - self.cursor_pos.2..self.length.min(self.cursor_pos.2 + amount + 1) + for c in self.new_cursor_pos.2 + ..self.length.min(self.new_cursor_pos.2 + amount + 1) { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( @@ -1422,8 +1423,9 @@ impl Component for PlainListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2).chain( - self.length.min(self.cursor_pos.2 + amount) + 1..self.length, + for c in (0..self.new_cursor_pos.2).chain( + self.length.min(self.new_cursor_pos.2 + amount) + 1 + ..self.length, ) { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows @@ -1433,8 +1435,8 @@ impl Component for PlainListing { } } PageMovement::PageDown(multiplier) => { - for c in self.cursor_pos.2 - ..self.length.min(self.cursor_pos.2 + rows * multiplier) + for c in self.new_cursor_pos.2 + ..self.length.min(self.new_cursor_pos.2 + rows * multiplier) { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( @@ -1451,8 +1453,8 @@ impl Component for PlainListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2).chain( - self.length.min(self.cursor_pos.2 + rows * multiplier) + 1 + for c in (0..self.new_cursor_pos.2).chain( + self.length.min(self.new_cursor_pos.2 + rows * multiplier) + 1 ..self.length, ) { if let Some(env_hash) = self.get_env_under_cursor(c) { @@ -1464,7 +1466,7 @@ impl Component for PlainListing { } PageMovement::Right(_) | PageMovement::Left(_) => {} PageMovement::Home => { - for c in 0..=self.cursor_pos.2 { + for c in 0..=self.new_cursor_pos.2 { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( env_hash, @@ -1480,7 +1482,7 @@ impl Component for PlainListing { } } if modifier == Modifier::Intersection { - for c in (self.cursor_pos.2)..self.length { + for c in (self.new_cursor_pos.2)..self.length { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows .update_selection_with_env(env_hash, |e| *e = false); @@ -1489,7 +1491,7 @@ impl Component for PlainListing { } } PageMovement::End => { - for c in self.cursor_pos.2..self.length { + for c in self.new_cursor_pos.2..self.length { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( env_hash, @@ -1505,7 +1507,7 @@ impl Component for PlainListing { } } if modifier == Modifier::Intersection { - for c in 0..self.cursor_pos.2 { + for c in 0..self.new_cursor_pos.2 { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows .update_selection_with_env(env_hash, |e| *e = false); diff --git a/meli/src/mail/listing/thread.rs b/meli/src/mail/listing/thread.rs index 96c5ce03..1b1cee03 100644 --- a/meli/src/mail/listing/thread.rs +++ b/meli/src/mail/listing/thread.rs @@ -180,7 +180,7 @@ impl MailListingTrait for ThreadListing { .any(std::convert::identity); if is_selection_empty { return self - .get_env_under_cursor(self.cursor_pos.2) + .get_env_under_cursor(self.new_cursor_pos.2) .into_iter() .collect::<_>(); } @@ -251,12 +251,12 @@ impl MailListingTrait for ThreadListing { context: &Context, items: Box>, ) { - let account = &context.accounts[&self.cursor_pos.0]; - let threads = account.collection.get_threads(self.cursor_pos.1); + let account = &context.accounts[&self.new_cursor_pos.0]; + let threads = account.collection.get_threads(self.new_cursor_pos.1); self.length = 0; self.rows.clear(); if threads.len() == 0 { - let message: String = account[&self.cursor_pos.1].status(); + let message: String = account[&self.new_cursor_pos.1].status(); _ = self.data_columns.columns[0].resize_with_context(message.len(), 1, context); let area = self.data_columns.columns[0].area(); self.data_columns.columns[0].grid_mut().write_string( @@ -296,7 +296,7 @@ impl MailListingTrait for ThreadListing { let mut prev_group = ThreadHash::null(); let mut hide_from: bool = false; let threaded_repeat_identical_from_values: bool = *mailbox_settings!( - context[self.cursor_pos.0][&self.cursor_pos.1] + context[self.new_cursor_pos.0][&self.new_cursor_pos.1] .listing .threaded_repeat_identical_from_values ); @@ -307,7 +307,7 @@ impl MailListingTrait for ThreadListing { let envelope: EnvelopeRef = account.collection.get_env(env_hash); use melib::search::QueryTrait; if let Some(filter_query) = mailbox_settings!( - context[self.cursor_pos.0][&self.cursor_pos.1] + context[self.new_cursor_pos.0][&self.new_cursor_pos.1] .listing .filter ) @@ -447,28 +447,32 @@ impl ListingTrait for ThreadListing { } fn next_entry(&mut self, context: &mut Context) { - if self.get_env_under_cursor(self.cursor_pos.2 + 1).is_some() { + if self + .get_env_under_cursor(self.new_cursor_pos.2 + 1) + .is_some() + { // [ref:TODO]: makes this less ugly. self.movement = Some(PageMovement::Down(1)); + self.perform_movement(None); self.force_draw = true; self.dirty = true; - self.cursor_pos.2 += 1; - self.new_cursor_pos.2 += 1; self.set_focus(Focus::Entry, context); } } fn prev_entry(&mut self, context: &mut Context) { - if self.cursor_pos.2 == 0 { + if self.new_cursor_pos.2 == 0 { return; } - if self.get_env_under_cursor(self.cursor_pos.2 - 1).is_some() { + if self + .get_env_under_cursor(self.new_cursor_pos.2 - 1) + .is_some() + { // [ref:TODO]: makes this less ugly. self.movement = Some(PageMovement::Up(1)); + self.perform_movement(None); self.force_draw = true; self.dirty = true; - self.cursor_pos.2 -= 1; - self.new_cursor_pos.2 -= 1; self.set_focus(Focus::Entry, context); } } @@ -502,52 +506,7 @@ impl ListingTrait for ThreadListing { return; } - if let Some(mvm) = self.movement.take() { - match mvm { - PageMovement::Up(amount) => { - self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount); - } - PageMovement::PageUp(multiplier) => { - self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier); - } - PageMovement::Down(amount) => { - if self.new_cursor_pos.2 + amount + 1 < self.length { - self.new_cursor_pos.2 += amount; - } else { - self.new_cursor_pos.2 = self.length - 1; - } - } - PageMovement::PageDown(multiplier) => { - if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length { - self.new_cursor_pos.2 += rows * multiplier; - } else if self.new_cursor_pos.2 + rows * multiplier > self.length { - self.new_cursor_pos.2 = self.length - 1; - } else { - self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows; - } - } - PageMovement::Right(amount) => { - self.data_columns.x_offset += amount; - self.data_columns.x_offset = self.data_columns.x_offset.min( - self.data_columns - .widths - .iter() - .map(|w| w + 2) - .sum::() - .saturating_sub(2), - ); - } - PageMovement::Left(amount) => { - self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount); - } - PageMovement::Home => { - self.new_cursor_pos.2 = 0; - } - PageMovement::End => { - self.new_cursor_pos.2 = self.length.saturating_sub(1); - } - } - } + self.perform_movement(Some(rows)); if self.force_draw { grid.clear_area(area, self.color_cache.theme_default); @@ -729,8 +688,8 @@ impl ListingTrait for ThreadListing { } Focus::Entry => { if let Some((thread_hash, env_hash)) = self - .get_env_under_cursor(self.cursor_pos.2) - .map(|env_hash| (self.rows.env_to_thread[&env_hash], env_hash)) + .get_env_under_cursor(self.new_cursor_pos.2) + .and_then(|env_hash| Some((*self.rows.env_to_thread.get(&env_hash)?, env_hash))) { self.force_draw = true; self.dirty = true; @@ -744,6 +703,7 @@ impl ListingTrait for ThreadListing { }, context, ); + self.cursor_pos.2 = self.new_cursor_pos.2; } else { return; } @@ -1226,6 +1186,56 @@ impl ThreadListing { ); } } + + fn perform_movement(&mut self, height: Option) { + let rows = height.unwrap_or(1); + if let Some(mvm) = self.movement.take() { + match mvm { + PageMovement::Up(amount) => { + self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(amount); + } + PageMovement::PageUp(multiplier) => { + self.new_cursor_pos.2 = self.new_cursor_pos.2.saturating_sub(rows * multiplier); + } + PageMovement::Down(amount) => { + if self.new_cursor_pos.2 + amount + 1 < self.length { + self.new_cursor_pos.2 += amount; + } else { + self.new_cursor_pos.2 = self.length - 1; + } + } + PageMovement::PageDown(multiplier) => { + if self.new_cursor_pos.2 + rows * multiplier + 1 < self.length { + self.new_cursor_pos.2 += rows * multiplier; + } else if self.new_cursor_pos.2 + rows * multiplier > self.length { + self.new_cursor_pos.2 = self.length - 1; + } else { + self.new_cursor_pos.2 = (self.length.saturating_sub(1) / rows) * rows; + } + } + PageMovement::Right(amount) => { + self.data_columns.x_offset += amount; + self.data_columns.x_offset = self.data_columns.x_offset.min( + self.data_columns + .widths + .iter() + .map(|w| w + 2) + .sum::() + .saturating_sub(2), + ); + } + PageMovement::Left(amount) => { + self.data_columns.x_offset = self.data_columns.x_offset.saturating_sub(amount); + } + PageMovement::Home => { + self.new_cursor_pos.2 = 0; + } + PageMovement::End => { + self.new_cursor_pos.2 = self.length.saturating_sub(1); + } + } + } + } } impl Component for ThreadListing { @@ -1267,7 +1277,9 @@ impl Component for ThreadListing { if let Some(mvm) = self.movement.as_ref() { match mvm { PageMovement::Up(amount) => { - for c in self.cursor_pos.2.saturating_sub(*amount)..=self.cursor_pos.2 { + for c in self.new_cursor_pos.2.saturating_sub(*amount) + ..=self.new_cursor_pos.2 + { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( env_hash, @@ -1283,8 +1295,8 @@ impl Component for ThreadListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2.saturating_sub(*amount)) - .chain((self.cursor_pos.2 + 2)..self.length) + for c in (0..self.new_cursor_pos.2.saturating_sub(*amount)) + .chain((self.new_cursor_pos.2 + 2)..self.length) { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows @@ -1294,8 +1306,8 @@ impl Component for ThreadListing { } } PageMovement::PageUp(multiplier) => { - for c in self.cursor_pos.2.saturating_sub(rows * multiplier) - ..=self.cursor_pos.2 + for c in self.new_cursor_pos.2.saturating_sub(rows * multiplier) + ..=self.new_cursor_pos.2 { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( @@ -1313,8 +1325,8 @@ impl Component for ThreadListing { } } PageMovement::Down(amount) => { - for c in - self.cursor_pos.2..self.length.min(self.cursor_pos.2 + amount + 1) + for c in self.new_cursor_pos.2 + ..self.length.min(self.new_cursor_pos.2 + amount + 1) { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( @@ -1331,8 +1343,9 @@ impl Component for ThreadListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2).chain( - self.length.min(self.cursor_pos.2 + amount) + 1..self.length, + for c in (0..self.new_cursor_pos.2).chain( + self.length.min(self.new_cursor_pos.2 + amount) + 1 + ..self.length, ) { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows @@ -1342,8 +1355,8 @@ impl Component for ThreadListing { } } PageMovement::PageDown(multiplier) => { - for c in self.cursor_pos.2 - ..self.length.min(self.cursor_pos.2 + rows * multiplier) + for c in self.new_cursor_pos.2 + ..self.length.min(self.new_cursor_pos.2 + rows * multiplier) { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( @@ -1360,8 +1373,8 @@ impl Component for ThreadListing { } } if modifier == Modifier::Intersection { - for c in (0..self.cursor_pos.2).chain( - self.length.min(self.cursor_pos.2 + rows * multiplier) + 1 + for c in (0..self.new_cursor_pos.2).chain( + self.length.min(self.new_cursor_pos.2 + rows * multiplier) + 1 ..self.length, ) { if let Some(env_hash) = self.get_env_under_cursor(c) { @@ -1373,7 +1386,7 @@ impl Component for ThreadListing { } PageMovement::Right(_) | PageMovement::Left(_) => {} PageMovement::Home => { - for c in 0..=self.cursor_pos.2 { + for c in 0..=self.new_cursor_pos.2 { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( env_hash, @@ -1389,7 +1402,7 @@ impl Component for ThreadListing { } } if modifier == Modifier::Intersection { - for c in (self.cursor_pos.2)..self.length { + for c in (self.new_cursor_pos.2)..self.length { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows .update_selection_with_env(env_hash, |e| *e = false); @@ -1398,7 +1411,7 @@ impl Component for ThreadListing { } } PageMovement::End => { - for c in self.cursor_pos.2..self.length { + for c in self.new_cursor_pos.2..self.length { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows.update_selection_with_env( env_hash, @@ -1414,7 +1427,7 @@ impl Component for ThreadListing { } } if modifier == Modifier::Intersection { - for c in 0..self.cursor_pos.2 { + for c in 0..self.new_cursor_pos.2 { if let Some(env_hash) = self.get_env_under_cursor(c) { self.rows .update_selection_with_env(env_hash, |e| *e = false); @@ -1434,7 +1447,7 @@ impl Component for ThreadListing { while let Some(env_hash) = self.rows.row_updates.pop() { self.update_line(context, env_hash); let row: usize = self.rows.env_order[&env_hash]; - let envelope: EnvelopeRef = context.accounts[&self.cursor_pos.0] + let envelope: EnvelopeRef = context.accounts[&self.new_cursor_pos.0] .collection .get_env(env_hash); let row_attr = row_attr!( @@ -1536,17 +1549,17 @@ impl Component for ThreadListing { return true; } UIEvent::MailboxUpdate((ref idxa, ref idxf)) - if (*idxa, *idxf) == (self.new_cursor_pos.0, self.cursor_pos.1) => + if (*idxa, *idxf) == (self.new_cursor_pos.0, self.new_cursor_pos.1) => { self.refresh_mailbox(context, false); self.set_dirty(true); } - UIEvent::StartupCheck(ref f) if *f == self.cursor_pos.1 => { + UIEvent::StartupCheck(ref f) if *f == self.new_cursor_pos.1 => { self.refresh_mailbox(context, false); self.set_dirty(true); } UIEvent::EnvelopeRename(ref old_hash, ref new_hash) => { - let account = &context.accounts[&self.cursor_pos.0]; + let account = &context.accounts[&self.new_cursor_pos.0]; if !account.collection.contains_key(new_hash) { return false; } @@ -1568,7 +1581,7 @@ impl Component for ThreadListing { } } UIEvent::EnvelopeUpdate(ref env_hash) => { - let account = &context.accounts[&self.cursor_pos.0]; + let account = &context.accounts[&self.new_cursor_pos.0]; if !account.collection.contains_key(env_hash) { return false; } @@ -1592,7 +1605,7 @@ impl Component for ThreadListing { { if self.modifier_active && self.modifier_command.is_none() { self.modifier_command = Some(Modifier::default()); - } else if let Some(env_hash) = self.get_env_under_cursor(self.cursor_pos.2) { + } else if let Some(env_hash) = self.get_env_under_cursor(self.new_cursor_pos.2) { self.rows.update_selection_with_env(env_hash, |e| *e = !*e); self.set_dirty(true); } @@ -1612,13 +1625,13 @@ impl Component for ThreadListing { return true; } Action::Listing(Search(ref filter_term)) if !self.unfocused() => { - match context.accounts[&self.cursor_pos.0].search( + match context.accounts[&self.new_cursor_pos.0].search( filter_term, self.sort, - self.cursor_pos.1, + self.new_cursor_pos.1, ) { Ok(job) => { - let handle = context.accounts[&self.cursor_pos.0] + let handle = context.accounts[&self.new_cursor_pos.0] .main_loop_handler .job_executor .spawn_specialized("search".into(), job);