diff --git a/CHANGELOG.md b/CHANGELOG.md index 444b6921..dd1d331f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ Thanks to @nate-sys and @jubalh for contributing to this release. - Default config updated with better comments, color config for join/part messages. (#412) - `/join` command errors now print usage help once instead of twice. +- Fix showing timestamp of the next message or activity after a `/clear`. # 2023/07/16: 0.11.0 diff --git a/crates/libtiny_tui/src/messaging.rs b/crates/libtiny_tui/src/messaging.rs index 21b34004..b2616e45 100644 --- a/crates/libtiny_tui/src/messaging.rs +++ b/crates/libtiny_tui/src/messaging.rs @@ -31,6 +31,7 @@ pub(crate) struct MessagingUI { // properly highlight mentions. nicks: Trie, + /// The last line in `msg_area` that shows join, leave, disconnect activities. last_activity_line: Option, /// Last timestamp added to the UI. @@ -236,8 +237,10 @@ fn get_input_field_max_height(window_height: i32) -> i32 { // Adding new messages impl MessagingUI { - /// Add a new line with the given timestamp (`ts`) if we don't already have a line for the - /// timestamp already. + /// Add a new line with the given timestamp (`ts`) if we're not already showing the timestamp. + /// + /// In compact layout this adds the indentation for the timestamp column if we're already + /// showing the timestamp. fn add_timestamp(&mut self, ts: Timestamp) { if let Some(ts_) = self.last_ts { if ts_ != ts { @@ -347,6 +350,8 @@ impl MessagingUI { pub(crate) fn clear(&mut self) { self.msg_area.clear(); + self.last_activity_line = None; + self.last_ts = None; } fn get_nick_color(&self, sender: &str) -> usize { @@ -368,6 +373,8 @@ impl MessagingUI { } pub(crate) fn join(&mut self, nick: &str, ts: Option, ignore: bool) { + self.nicks.insert(nick); + if !ignore { if let Some(ts) = ts { let line_idx = self.get_activity_line_idx(ts); @@ -377,8 +384,6 @@ impl MessagingUI { }); } } - - self.nicks.insert(nick); } pub(crate) fn part(&mut self, nick: &str, ts: Option, ignore: bool) { @@ -409,7 +414,7 @@ impl MessagingUI { fn get_activity_line_idx(&mut self, ts: Timestamp) -> usize { match &self.last_activity_line { - Some(l) if l.ts == ts && l.line_idx == self.msg_area.num_lines() - 1 => { + Some(l) if l.ts == ts && Some(l.line_idx) == self.msg_area.num_lines().checked_sub(1) => { let line_idx = l.line_idx; // FIXME: It's a bit hacky to add a space in this function which from the name // looks like a getter. diff --git a/crates/libtiny_tui/src/tests/layout.rs b/crates/libtiny_tui/src/tests/layout.rs index db09e844..903c2cc3 100644 --- a/crates/libtiny_tui/src/tests/layout.rs +++ b/crates/libtiny_tui/src/tests/layout.rs @@ -84,47 +84,46 @@ fn test_mnemonic_generation() { assert_eq!(tabs[8].switch, Some('b')); } -#[test] -fn test_compact_layout_activity_timestamp() { - // Test all combinations of - // - // 1.1 Message followed by activity - // 1.2 Message followed by message - // 1.3 Activity followed by message - // 1.4 Activity followed by activity - // - // and - // - // 2.1 Same timestamps - // 2.2 Different timestamps - // - // In total 8 scenarios. - - fn setup_tui() -> (TUI, MsgTarget<'static>) { - let mut tui = TUI::new_test(40, 5); - tui.set_layout(Layout::Aligned { max_nick_len: 12 }); - let serv = "irc.server_1.org"; - let chan = ChanNameRef::new("#chan"); - tui.new_server_tab(serv, None); - tui.set_nick(serv, "osa1"); - tui.new_chan_tab(serv, chan); - tui.next_tab(); // mentions -> server - tui.next_tab(); // server -> channel - tui.draw(); +fn setup_tui() -> (TUI, MsgTarget<'static>) { + let mut tui = TUI::new_test(40, 5); + tui.set_layout(Layout::Aligned { max_nick_len: 12 }); + let serv = "irc.server_1.org"; + let chan = ChanNameRef::new("#chan"); + tui.new_server_tab(serv, None); + tui.set_nick(serv, "osa1"); + tui.new_chan_tab(serv, chan); + tui.next_tab(); // mentions -> server + tui.next_tab(); // server -> channel + tui.draw(); - #[rustfmt::skip] - let screen = - "| | - | | - | | - |osa1: | - |mentions irc.server_1.org #chan |"; + #[rustfmt::skip] + let screen = + "| | + | | + | | + |osa1: | + |mentions irc.server_1.org #chan |"; - expect_screen(screen, &tui.get_front_buffer(), 40, 5, Location::caller()); + expect_screen(screen, &tui.get_front_buffer(), 40, 5, Location::caller()); - (tui, MsgTarget::Chan { serv, chan }) - } + (tui, MsgTarget::Chan { serv, chan }) +} +// Test all combinations of +// +// 1.1 Message followed by activity +// 1.2 Message followed by message +// 1.3 Activity followed by message +// 1.4 Activity followed by activity +// +// and +// +// 2.1 Same timestamps +// 2.2 Different timestamps +// +// In total 8 scenarios. +#[test] +fn test_compact_layout_activity_timestamp() { // 1.1 - 2.1 { let (mut tui, target) = setup_tui(); @@ -299,3 +298,25 @@ fn test_compact_layout_activity_timestamp() { expect_screen(screen, &tui.get_front_buffer(), 40, 5, Location::caller()); } } + +// Test that a timestamp is printed after a `clear`. +#[test] +fn test_clear_timestamp() { + let (mut tui, target) = setup_tui(); + + let ts = time::at_utc(time::Timespec::new(0, 0)); + tui.add_nick("test1", Some(ts), &target); + tui.clear(&target); + tui.add_nick("test2", Some(ts), &target); + tui.draw(); + + #[rustfmt::skip] + let screen = + "| | + | | + |00:00 +test2 | + |osa1: | + |mentions irc.server_1.org #chan |"; + + expect_screen(screen, &tui.get_front_buffer(), 40, 5, Location::caller()); +}