diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index a5560d7fcb6cd32c7f00578b835a4440185af531..95168b4e5ff97d419458c3043adf70e4631b7f1f 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -54,6 +54,7 @@ pub struct ChatPanel { pending_serialization: Task>, subscriptions: Vec, workspace: WeakViewHandle, + is_scrolled_to_bottom: bool, has_focus: bool, markdown_data: HashMap, } @@ -131,13 +132,14 @@ impl ChatPanel { }); let mut message_list = - ListState::::new(0, Orientation::Bottom, 1000., move |this, ix, cx| { + ListState::::new(0, Orientation::Bottom, 10., move |this, ix, cx| { this.render_message(ix, cx) }); - message_list.set_scroll_handler(|visible_range, _, this, cx| { + message_list.set_scroll_handler(|visible_range, count, this, cx| { if visible_range.start < MESSAGE_LOADING_THRESHOLD { this.load_more_messages(&LoadMoreMessages, cx); } + this.is_scrolled_to_bottom = visible_range.end == count; }); cx.add_view(|cx| { @@ -155,6 +157,7 @@ impl ChatPanel { has_focus: false, subscriptions: Vec::new(), workspace: workspace_handle, + is_scrolled_to_bottom: true, active: false, width: None, markdown_data: Default::default(), @@ -198,6 +201,10 @@ impl ChatPanel { }) } + pub fn is_scrolled_to_bottom(&self) -> bool { + self.is_scrolled_to_bottom + } + pub fn active_chat(&self) -> Option> { self.active_chat.as_ref().map(|(chat, _)| chat.clone()) } @@ -310,7 +317,7 @@ impl ChatPanel { } fn acknowledge_last_message(&mut self, cx: &mut ViewContext<'_, '_, ChatPanel>) { - if self.active { + if self.active && self.is_scrolled_to_bottom { if let Some((chat, _)) = &self.active_chat { chat.update(cx, |chat, cx| { chat.acknowledge_last_message(cx); diff --git a/crates/collab_ui/src/notification_panel.rs b/crates/collab_ui/src/notification_panel.rs index db0965dbc433637cca92d32e0a458535107ecf0f..744806f64ea0b07d710a69b878b72b7cc02ef007 100644 --- a/crates/collab_ui/src/notification_panel.rs +++ b/crates/collab_ui/src/notification_panel.rs @@ -460,6 +460,28 @@ impl NotificationPanel { } } + fn is_showing_notification(&self, notification: &Notification, cx: &AppContext) -> bool { + if let Notification::ChannelMessageMention { channel_id, .. } = ¬ification { + if let Some(workspace) = self.workspace.upgrade(cx) { + return workspace + .read_with(cx, |workspace, cx| { + if let Some(panel) = workspace.panel::(cx) { + return panel.read_with(cx, |panel, cx| { + panel.is_scrolled_to_bottom() + && panel.active_chat().map_or(false, |chat| { + chat.read(cx).channel().id == *channel_id + }) + }); + } + false + }) + .unwrap_or_default(); + } + } + + false + } + fn render_sign_in_prompt( &self, theme: &Arc, @@ -523,6 +545,10 @@ impl NotificationPanel { } fn add_toast(&mut self, entry: &NotificationEntry, cx: &mut ViewContext) { + if self.is_showing_notification(&entry.notification, cx) { + return; + } + let Some(NotificationPresenter { actor, text, .. }) = self.present_notification(entry, cx) else { return; @@ -540,6 +566,7 @@ impl NotificationPanel { self.workspace .update(cx, |workspace, cx| { + workspace.dismiss_notification::(0, cx); workspace.show_notification(0, cx, |cx| { let workspace = cx.weak_handle(); cx.add_view(|_| NotificationToast { diff --git a/styles/src/style_tree/chat_panel.ts b/styles/src/style_tree/chat_panel.ts index c4016c621491f6884ae7f7211ae3e3911c7364a8..bbcebbf4c839503963a9ef4a6b5202a23236c555 100644 --- a/styles/src/style_tree/chat_panel.ts +++ b/styles/src/style_tree/chat_panel.ts @@ -2,7 +2,6 @@ import { background, border, foreground, text } from "./components" import { icon_button } from "../component/icon_button" import { useTheme, with_opacity } from "../theme" import { interactive } from "../element" -import { Color } from "ayu/dist/color" export default function chat_panel(): any { const theme = useTheme()