diff --git a/assets/icons/bell_badged.svg b/assets/icons/bell_badged.svg
new file mode 100644
index 0000000000..0c841dfcfd
--- /dev/null
+++ b/assets/icons/bell_badged.svg
@@ -0,0 +1,5 @@
+
diff --git a/crates/collab_ui/src/notification_panel.rs b/crates/collab_ui/src/notification_panel.rs
index 6f4ee1baae..24bbcbc027 100644
--- a/crates/collab_ui/src/notification_panel.rs
+++ b/crates/collab_ui/src/notification_panel.rs
@@ -47,6 +47,7 @@ pub struct NotificationPanel {
local_timezone: UtcOffset,
focus_handle: FocusHandle,
mark_as_read_tasks: HashMap>>,
+ unseen_notifications: Vec,
}
#[derive(Serialize, Deserialize)]
@@ -141,6 +142,7 @@ impl NotificationPanel {
active: false,
mark_as_read_tasks: HashMap::default(),
width: None,
+ unseen_notifications: Vec::new(),
};
let mut old_dock_position = this.position(cx);
@@ -441,6 +443,10 @@ impl NotificationPanel {
}
fn is_showing_notification(&self, notification: &Notification, cx: &ViewContext) -> bool {
+ if !self.active {
+ return false;
+ }
+
if let Notification::ChannelMessageMention { channel_id, .. } = ¬ification {
if let Some(workspace) = self.workspace.upgrade() {
return if let Some(panel) = workspace.read(cx).panel::(cx) {
@@ -465,9 +471,17 @@ impl NotificationPanel {
cx: &mut ViewContext,
) {
match event {
- NotificationEvent::NewNotification { entry } => self.add_toast(entry, cx),
+ NotificationEvent::NewNotification { entry } => {
+ if !self.is_showing_notification(&entry.notification, cx) {
+ self.unseen_notifications.push(entry.clone());
+ }
+ self.add_toast(entry, cx);
+ }
NotificationEvent::NotificationRemoved { entry }
- | NotificationEvent::NotificationRead { entry } => self.remove_toast(entry.id, cx),
+ | NotificationEvent::NotificationRead { entry } => {
+ self.unseen_notifications.retain(|n| n.id != entry.id);
+ self.remove_toast(entry.id, cx);
+ }
NotificationEvent::NotificationsUpdated {
old_range,
new_count,
@@ -650,15 +664,28 @@ impl Panel for NotificationPanel {
fn set_active(&mut self, active: bool, cx: &mut ViewContext) {
self.active = active;
+
+ if self.active {
+ self.unseen_notifications = Vec::new();
+ cx.notify();
+ }
+
if self.notification_store.read(cx).notification_count() == 0 {
cx.emit(Event::Dismissed);
}
}
fn icon(&self, cx: &gpui::WindowContext) -> Option {
- (NotificationPanelSettings::get_global(cx).button
- && self.notification_store.read(cx).notification_count() > 0)
- .then(|| IconName::Bell)
+ let show_button = NotificationPanelSettings::get_global(cx).button;
+ if !show_button {
+ return None;
+ }
+
+ if self.unseen_notifications.is_empty() {
+ return Some(IconName::Bell);
+ }
+
+ Some(IconName::BellBadged)
}
fn icon_tooltip(&self, _cx: &WindowContext) -> Option<&'static str> {
diff --git a/crates/ui/src/components/icon.rs b/crates/ui/src/components/icon.rs
index bdc691dc9a..3b8f3bc8ae 100644
--- a/crates/ui/src/components/icon.rs
+++ b/crates/ui/src/components/icon.rs
@@ -39,6 +39,7 @@ pub enum IconName {
Bell,
BellOff,
BellRing,
+ BellBadged,
Bolt,
CaseSensitive,
Check,
@@ -130,6 +131,7 @@ impl IconName {
IconName::Bell => "icons/bell.svg",
IconName::BellOff => "icons/bell_off.svg",
IconName::BellRing => "icons/bell_ring.svg",
+ IconName::BellBadged => "icons/bell_badged.svg",
IconName::Bolt => "icons/bolt.svg",
IconName::CaseSensitive => "icons/case_insensitive.svg",
IconName::Check => "icons/check.svg",