diff --git a/crates/channel/src/channel_chat.rs b/crates/channel/src/channel_chat.rs index c08b657187..1877f7c0d2 100644 --- a/crates/channel/src/channel_chat.rs +++ b/crates/channel/src/channel_chat.rs @@ -257,11 +257,16 @@ impl ChannelChat { let mut cursor = chat.messages.cursor::<(ChannelMessageId, Count)>(); let message_id = ChannelMessageId::Saved(message_id); cursor.seek(&message_id, Bias::Left, &()); - return ControlFlow::Break(if cursor.start().0 == message_id { - Some(cursor.start().1 .0) - } else { - None - }); + return ControlFlow::Break( + if cursor + .item() + .map_or(false, |message| message.id == message_id) + { + Some(cursor.start().1 .0) + } else { + None + }, + ); } } ControlFlow::Continue(chat.load_more_messages(cx)) diff --git a/crates/collab_ui/src/chat_panel.rs b/crates/collab_ui/src/chat_panel.rs index 912ac936d6..add0723e85 100644 --- a/crates/collab_ui/src/chat_panel.rs +++ b/crates/collab_ui/src/chat_panel.rs @@ -257,6 +257,7 @@ impl ChatPanel { fn set_active_chat(&mut self, chat: ModelHandle, cx: &mut ViewContext) { if self.active_chat.as_ref().map(|e| &e.0) != Some(&chat) { + self.markdown_data.clear(); let id = { let chat = chat.read(cx); let channel = chat.channel().clone(); @@ -635,31 +636,38 @@ impl ChatPanel { scroll_to_message_id: Option, cx: &mut ViewContext, ) -> Task> { - if let Some((chat, _)) = &self.active_chat { - if chat.read(cx).channel().id == selected_channel_id { - return Task::ready(Ok(())); - } - } + let open_chat = self + .active_chat + .as_ref() + .and_then(|(chat, _)| { + (chat.read(cx).channel().id == selected_channel_id) + .then(|| Task::ready(anyhow::Ok(chat.clone()))) + }) + .unwrap_or_else(|| { + self.channel_store.update(cx, |store, cx| { + store.open_channel_chat(selected_channel_id, cx) + }) + }); - let open_chat = self.channel_store.update(cx, |store, cx| { - store.open_channel_chat(selected_channel_id, cx) - }); cx.spawn(|this, mut cx| async move { let chat = open_chat.await?; this.update(&mut cx, |this, cx| { - this.markdown_data = Default::default(); this.set_active_chat(chat.clone(), cx); })?; if let Some(message_id) = scroll_to_message_id { if let Some(item_ix) = - ChannelChat::load_history_since_message(chat, message_id, cx.clone()).await + ChannelChat::load_history_since_message(chat.clone(), message_id, cx.clone()) + .await { - this.update(&mut cx, |this, _| { - this.message_list.scroll_to(ListOffset { - item_ix, - offset_in_item: 0., - }); + this.update(&mut cx, |this, cx| { + if this.active_chat.as_ref().map_or(false, |(c, _)| *c == chat) { + this.message_list.scroll_to(ListOffset { + item_ix, + offset_in_item: 0., + }); + cx.notify(); + } })?; } } diff --git a/crates/collab_ui/src/notification_panel.rs b/crates/collab_ui/src/notification_panel.rs index 9e8016a439..35d216cf58 100644 --- a/crates/collab_ui/src/notification_panel.rs +++ b/crates/collab_ui/src/notification_panel.rs @@ -119,6 +119,7 @@ impl NotificationPanel { let mut old_dock_position = this.position(cx); this.subscriptions.extend([ + cx.observe(&this.notification_store, |_, _, cx| cx.notify()), cx.subscribe(&this.notification_store, Self::on_notification_event), cx.observe_global::(move |this: &mut Self, cx| { let new_dock_position = this.position(cx); @@ -469,12 +470,12 @@ impl NotificationPanel { return; }; - let id = entry.id; + let notification_id = entry.id; self.current_notification_toast = Some(( - id, + notification_id, cx.spawn(|this, mut cx| async move { cx.background().timer(TOAST_DURATION).await; - this.update(&mut cx, |this, cx| this.remove_toast(id, cx)) + this.update(&mut cx, |this, cx| this.remove_toast(notification_id, cx)) .ok(); }), )); @@ -484,6 +485,7 @@ impl NotificationPanel { workspace.show_notification(0, cx, |cx| { let workspace = cx.weak_handle(); cx.add_view(|_| NotificationToast { + notification_id, actor, text, workspace, @@ -645,6 +647,7 @@ fn render_icon_button(style: &IconButton, svg_path: &'static str) -> im } pub struct NotificationToast { + notification_id: u64, actor: Option>, text: String, workspace: WeakViewHandle, @@ -657,10 +660,18 @@ pub enum ToastEvent { impl NotificationToast { fn focus_notification_panel(&self, cx: &mut AppContext) { let workspace = self.workspace.clone(); + let notification_id = self.notification_id; cx.defer(move |cx| { workspace .update(cx, |workspace, cx| { - workspace.focus_panel::(cx); + if let Some(panel) = workspace.focus_panel::(cx) { + panel.update(cx, |panel, cx| { + let store = panel.notification_store.read(cx); + if let Some(entry) = store.notification_for_id(notification_id) { + panel.did_click_notification(&entry.clone().notification, cx); + } + }); + } }) .ok(); }) diff --git a/crates/notifications/src/notification_store.rs b/crates/notifications/src/notification_store.rs index 6aeb792e87..388f2e16d3 100644 --- a/crates/notifications/src/notification_store.rs +++ b/crates/notifications/src/notification_store.rs @@ -131,6 +131,17 @@ impl NotificationStore { cursor.item() } + pub fn notification_for_id(&self, id: u64) -> Option<&NotificationEntry> { + let mut cursor = self.notifications.cursor::(); + cursor.seek(&NotificationId(id), Bias::Left, &()); + if let Some(item) = cursor.item() { + if item.id == id { + return Some(item); + } + } + None + } + pub fn load_more_notifications(&self, cx: &mut ModelContext) -> Task> { let request = self .client @@ -145,6 +156,7 @@ impl NotificationStore { fn handle_connect(&mut self, cx: &mut ModelContext) -> Task> { self.notifications = Default::default(); self.channel_messages = Default::default(); + cx.notify(); self.load_more_notifications(cx) }