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);