diff --git a/src/buffer.rs b/src/buffer.rs index 4b18d0d4..fbd605e0 100644 --- a/src/buffer.rs +++ b/src/buffer.rs @@ -397,6 +397,17 @@ impl Buffer { .map(|message| Message::Highlights(highlights::Message::ScrollView(message))), } } + + pub fn is_scrolled_to_bottom(&self) -> Option { + match self { + Buffer::Empty | Buffer::FileTransfers(_) => None, + Buffer::Channel(channel) => Some(channel.scroll_view.is_scrolled_to_bottom()), + Buffer::Server(server) => Some(server.scroll_view.is_scrolled_to_bottom()), + Buffer::Query(query) => Some(query.scroll_view.is_scrolled_to_bottom()), + Buffer::Logs(log) => Some(log.scroll_view.is_scrolled_to_bottom()), + Buffer::Highlights(highlights) => Some(highlights.scroll_view.is_scrolled_to_bottom()), + } + } } impl From for Buffer { diff --git a/src/buffer/scroll_view.rs b/src/buffer/scroll_view.rs index 217e4d3f..3ae2b869 100644 --- a/src/buffer/scroll_view.rs +++ b/src/buffer/scroll_view.rs @@ -350,6 +350,10 @@ impl State { ) } + pub fn is_scrolled_to_bottom(&self) -> bool { + matches!(self.status, Status::Idle(Anchor::Bottom)) + } + pub fn scroll_to_message( &mut self, message: message::Hash, diff --git a/src/screen/dashboard.rs b/src/screen/dashboard.rs index e1595b4b..9bbcb74b 100644 --- a/src/screen/dashboard.rs +++ b/src/screen/dashboard.rs @@ -411,6 +411,35 @@ impl Dashboard { pane::Message::MaximizePane => self.maximize_pane(), pane::Message::Popout => return (self.popout_pane(main_window), None), pane::Message::Merge => return (self.merge_pane(config, main_window), None), + pane::Message::ScrollToBacklog => { + if let Some((window, pane)) = self.focus { + if let Some(state) = self.panes.get_mut(main_window.id, window, pane) { + return ( + state.buffer.scroll_to_backlog(&self.history, config).map( + move |message| { + Message::Pane( + window, + pane::Message::Buffer(pane, message), + ) + }, + ), + None, + ); + } + } + } + pane::Message::ScrollToBottom => { + if let Some((window, pane)) = self.focus { + if let Some(state) = self.panes.get_mut(main_window.id, window, pane) { + return ( + state.buffer.scroll_to_end().map(move |message| { + Message::Pane(window, pane::Message::Buffer(pane, message)) + }), + None, + ); + } + } + } } } Message::Sidebar(message) => { diff --git a/src/screen/dashboard/pane.rs b/src/screen/dashboard/pane.rs index 4c36fd83..a0775ee0 100644 --- a/src/screen/dashboard/pane.rs +++ b/src/screen/dashboard/pane.rs @@ -21,6 +21,8 @@ pub enum Message { ToggleShowTopic, Popout, Merge, + ScrollToBacklog, + ScrollToBottom, } #[derive(Clone)] @@ -162,6 +164,29 @@ impl TitleBar { let mut controls = row![].spacing(2); if let Buffer::Channel(state) = &buffer { + // Show scroll-to-bottom / scroll-to-backlog depending if scrollable is anchored to the end or not + let (icon, tooltip_text, message) = + if buffer.is_scrolled_to_bottom().unwrap_or_default() { + (icon::dot(), "Scroll to Backlog", Message::ScrollToBacklog) + } else { + (icon::cancel(), "Scroll to Bottom", Message::ScrollToBottom) + }; + + let scrollable_button = button(center(icon)) + .padding(5) + .width(22) + .height(22) + .on_press(message) + .style(|theme, status| theme::button::secondary(theme, status, false)); + + let scrollable_button_with_tooltip = tooltip( + scrollable_button, + show_tooltips.then_some(tooltip_text), + tooltip::Position::Bottom, + ); + + controls = controls.push(scrollable_button_with_tooltip); + // Show topic button only if there is a topic to show if let Some(topic) = clients.get_channel_topic(&state.server, &state.channel) { if topic.content.is_some() {