Fix scrolling to messages on clicking of notifications

This commit is contained in:
Max Brunsfeld 2023-10-19 14:04:34 -07:00
parent 851d7d0bc4
commit 44cb55fbe9
4 changed files with 60 additions and 24 deletions

View file

@ -257,11 +257,16 @@ impl ChannelChat {
let mut cursor = chat.messages.cursor::<(ChannelMessageId, Count)>(); let mut cursor = chat.messages.cursor::<(ChannelMessageId, Count)>();
let message_id = ChannelMessageId::Saved(message_id); let message_id = ChannelMessageId::Saved(message_id);
cursor.seek(&message_id, Bias::Left, &()); cursor.seek(&message_id, Bias::Left, &());
return ControlFlow::Break(if cursor.start().0 == message_id { return ControlFlow::Break(
Some(cursor.start().1 .0) if cursor
} else { .item()
None .map_or(false, |message| message.id == message_id)
}); {
Some(cursor.start().1 .0)
} else {
None
},
);
} }
} }
ControlFlow::Continue(chat.load_more_messages(cx)) ControlFlow::Continue(chat.load_more_messages(cx))

View file

@ -257,6 +257,7 @@ impl ChatPanel {
fn set_active_chat(&mut self, chat: ModelHandle<ChannelChat>, cx: &mut ViewContext<Self>) { fn set_active_chat(&mut self, chat: ModelHandle<ChannelChat>, cx: &mut ViewContext<Self>) {
if self.active_chat.as_ref().map(|e| &e.0) != Some(&chat) { if self.active_chat.as_ref().map(|e| &e.0) != Some(&chat) {
self.markdown_data.clear();
let id = { let id = {
let chat = chat.read(cx); let chat = chat.read(cx);
let channel = chat.channel().clone(); let channel = chat.channel().clone();
@ -635,31 +636,38 @@ impl ChatPanel {
scroll_to_message_id: Option<u64>, scroll_to_message_id: Option<u64>,
cx: &mut ViewContext<ChatPanel>, cx: &mut ViewContext<ChatPanel>,
) -> Task<Result<()>> { ) -> Task<Result<()>> {
if let Some((chat, _)) = &self.active_chat { let open_chat = self
if chat.read(cx).channel().id == selected_channel_id { .active_chat
return Task::ready(Ok(())); .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 { cx.spawn(|this, mut cx| async move {
let chat = open_chat.await?; let chat = open_chat.await?;
this.update(&mut cx, |this, cx| { this.update(&mut cx, |this, cx| {
this.markdown_data = Default::default();
this.set_active_chat(chat.clone(), cx); this.set_active_chat(chat.clone(), cx);
})?; })?;
if let Some(message_id) = scroll_to_message_id { if let Some(message_id) = scroll_to_message_id {
if let Some(item_ix) = 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.update(&mut cx, |this, cx| {
this.message_list.scroll_to(ListOffset { if this.active_chat.as_ref().map_or(false, |(c, _)| *c == chat) {
item_ix, this.message_list.scroll_to(ListOffset {
offset_in_item: 0., item_ix,
}); offset_in_item: 0.,
});
cx.notify();
}
})?; })?;
} }
} }

View file

@ -119,6 +119,7 @@ impl NotificationPanel {
let mut old_dock_position = this.position(cx); let mut old_dock_position = this.position(cx);
this.subscriptions.extend([ this.subscriptions.extend([
cx.observe(&this.notification_store, |_, _, cx| cx.notify()),
cx.subscribe(&this.notification_store, Self::on_notification_event), cx.subscribe(&this.notification_store, Self::on_notification_event),
cx.observe_global::<SettingsStore, _>(move |this: &mut Self, cx| { cx.observe_global::<SettingsStore, _>(move |this: &mut Self, cx| {
let new_dock_position = this.position(cx); let new_dock_position = this.position(cx);
@ -469,12 +470,12 @@ impl NotificationPanel {
return; return;
}; };
let id = entry.id; let notification_id = entry.id;
self.current_notification_toast = Some(( self.current_notification_toast = Some((
id, notification_id,
cx.spawn(|this, mut cx| async move { cx.spawn(|this, mut cx| async move {
cx.background().timer(TOAST_DURATION).await; 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(); .ok();
}), }),
)); ));
@ -484,6 +485,7 @@ impl NotificationPanel {
workspace.show_notification(0, cx, |cx| { workspace.show_notification(0, cx, |cx| {
let workspace = cx.weak_handle(); let workspace = cx.weak_handle();
cx.add_view(|_| NotificationToast { cx.add_view(|_| NotificationToast {
notification_id,
actor, actor,
text, text,
workspace, workspace,
@ -645,6 +647,7 @@ fn render_icon_button<V: View>(style: &IconButton, svg_path: &'static str) -> im
} }
pub struct NotificationToast { pub struct NotificationToast {
notification_id: u64,
actor: Option<Arc<User>>, actor: Option<Arc<User>>,
text: String, text: String,
workspace: WeakViewHandle<Workspace>, workspace: WeakViewHandle<Workspace>,
@ -657,10 +660,18 @@ pub enum ToastEvent {
impl NotificationToast { impl NotificationToast {
fn focus_notification_panel(&self, cx: &mut AppContext) { fn focus_notification_panel(&self, cx: &mut AppContext) {
let workspace = self.workspace.clone(); let workspace = self.workspace.clone();
let notification_id = self.notification_id;
cx.defer(move |cx| { cx.defer(move |cx| {
workspace workspace
.update(cx, |workspace, cx| { .update(cx, |workspace, cx| {
workspace.focus_panel::<NotificationPanel>(cx); if let Some(panel) = workspace.focus_panel::<NotificationPanel>(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(); .ok();
}) })

View file

@ -131,6 +131,17 @@ impl NotificationStore {
cursor.item() cursor.item()
} }
pub fn notification_for_id(&self, id: u64) -> Option<&NotificationEntry> {
let mut cursor = self.notifications.cursor::<NotificationId>();
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<Self>) -> Task<Result<()>> { pub fn load_more_notifications(&self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
let request = self let request = self
.client .client
@ -145,6 +156,7 @@ impl NotificationStore {
fn handle_connect(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> { fn handle_connect(&mut self, cx: &mut ModelContext<Self>) -> Task<Result<()>> {
self.notifications = Default::default(); self.notifications = Default::default();
self.channel_messages = Default::default(); self.channel_messages = Default::default();
cx.notify();
self.load_more_notifications(cx) self.load_more_notifications(cx)
} }