mirror of
https://github.com/youwen5/iamb.git
synced 2025-08-04 03:28:28 -07:00
Clear desktop notification when message is read (#427)
Co-authored-by: Ulyssa <git@ulyssa.dev>
This commit is contained in:
parent
0ff8828a1c
commit
e9cdb3371a
4 changed files with 62 additions and 10 deletions
|
@ -92,6 +92,7 @@ use modalkit::{
|
||||||
|
|
||||||
use crate::config::ImagePreviewProtocolValues;
|
use crate::config::ImagePreviewProtocolValues;
|
||||||
use crate::message::ImageStatus;
|
use crate::message::ImageStatus;
|
||||||
|
use crate::notifications::NotificationHandle;
|
||||||
use crate::preview::{source_from_event, spawn_insert_preview};
|
use crate::preview::{source_from_event, spawn_insert_preview};
|
||||||
use crate::{
|
use crate::{
|
||||||
message::{Message, MessageEvent, MessageKey, MessageTimeStamp, Messages},
|
message::{Message, MessageEvent, MessageKey, MessageTimeStamp, Messages},
|
||||||
|
@ -1558,6 +1559,9 @@ pub struct ChatStore {
|
||||||
|
|
||||||
/// Collator for locale-aware text sorting.
|
/// Collator for locale-aware text sorting.
|
||||||
pub collator: feruca::Collator,
|
pub collator: feruca::Collator,
|
||||||
|
|
||||||
|
/// Notifications that should be dismissed when the user opens the room.
|
||||||
|
pub open_notifications: HashMap<OwnedRoomId, Vec<NotificationHandle>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ChatStore {
|
impl ChatStore {
|
||||||
|
@ -1582,6 +1586,7 @@ impl ChatStore {
|
||||||
draw_curr: None,
|
draw_curr: None,
|
||||||
ring_bell: false,
|
ring_bell: false,
|
||||||
focused: true,
|
focused: true,
|
||||||
|
open_notifications: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -561,6 +561,9 @@ impl Application {
|
||||||
IambAction::ClearUnreads => {
|
IambAction::ClearUnreads => {
|
||||||
let user_id = &store.application.settings.profile.user_id;
|
let user_id = &store.application.settings.profile.user_id;
|
||||||
|
|
||||||
|
// Clear any notifications we displayed:
|
||||||
|
store.application.open_notifications.clear();
|
||||||
|
|
||||||
for room_id in store.application.sync_info.chats() {
|
for room_id in store.application.sync_info.chats() {
|
||||||
if let Some(room) = store.application.rooms.get_mut(room_id) {
|
if let Some(room) = store.application.rooms.get_mut(room_id) {
|
||||||
room.fully_read(user_id);
|
room.fully_read(user_id);
|
||||||
|
|
|
@ -8,6 +8,7 @@ use matrix_sdk::{
|
||||||
events::{room::message::MessageType, AnyMessageLikeEventContent, AnySyncTimelineEvent},
|
events::{room::message::MessageType, AnyMessageLikeEventContent, AnySyncTimelineEvent},
|
||||||
serde::Raw,
|
serde::Raw,
|
||||||
MilliSecondsSinceUnixEpoch,
|
MilliSecondsSinceUnixEpoch,
|
||||||
|
OwnedRoomId,
|
||||||
RoomId,
|
RoomId,
|
||||||
},
|
},
|
||||||
Client,
|
Client,
|
||||||
|
@ -24,6 +25,21 @@ const IAMB_XDG_NAME: &str = match option_env!("IAMB_XDG_NAME") {
|
||||||
Some(iamb) => iamb,
|
Some(iamb) => iamb,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Handle for an open notification that should be closed when the user views it.
|
||||||
|
pub struct NotificationHandle(
|
||||||
|
#[cfg(all(feature = "desktop", unix, not(target_os = "macos")))]
|
||||||
|
Option<notify_rust::NotificationHandle>,
|
||||||
|
);
|
||||||
|
|
||||||
|
impl Drop for NotificationHandle {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
#[cfg(all(feature = "desktop", unix, not(target_os = "macos")))]
|
||||||
|
if let Some(handle) = self.0.take() {
|
||||||
|
handle.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn register_notifications(
|
pub async fn register_notifications(
|
||||||
client: &Client,
|
client: &Client,
|
||||||
settings: &ApplicationSettings,
|
settings: &ApplicationSettings,
|
||||||
|
@ -54,6 +70,7 @@ pub async fn register_notifications(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let room_id = room.room_id().to_owned();
|
||||||
match notification.event {
|
match notification.event {
|
||||||
RawAnySyncOrStrippedTimelineEvent::Sync(e) => {
|
RawAnySyncOrStrippedTimelineEvent::Sync(e) => {
|
||||||
match parse_full_notification(e, room, show_message).await {
|
match parse_full_notification(e, room, show_message).await {
|
||||||
|
@ -66,8 +83,14 @@ pub async fn register_notifications(
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
send_notification(¬ify_via, &store, &summary, body.as_deref())
|
send_notification(
|
||||||
.await;
|
¬ify_via,
|
||||||
|
&summary,
|
||||||
|
body.as_deref(),
|
||||||
|
room_id,
|
||||||
|
&store,
|
||||||
|
)
|
||||||
|
.await;
|
||||||
},
|
},
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
tracing::error!("Failed to extract notification data: {err}")
|
tracing::error!("Failed to extract notification data: {err}")
|
||||||
|
@ -86,13 +109,14 @@ pub async fn register_notifications(
|
||||||
|
|
||||||
async fn send_notification(
|
async fn send_notification(
|
||||||
via: &NotifyVia,
|
via: &NotifyVia,
|
||||||
store: &AsyncProgramStore,
|
|
||||||
summary: &str,
|
summary: &str,
|
||||||
body: Option<&str>,
|
body: Option<&str>,
|
||||||
|
room_id: OwnedRoomId,
|
||||||
|
store: &AsyncProgramStore,
|
||||||
) {
|
) {
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
if via.desktop {
|
if via.desktop {
|
||||||
send_notification_desktop(summary, body);
|
send_notification_desktop(summary, body, room_id, store).await;
|
||||||
}
|
}
|
||||||
#[cfg(not(feature = "desktop"))]
|
#[cfg(not(feature = "desktop"))]
|
||||||
{
|
{
|
||||||
|
@ -110,7 +134,12 @@ async fn send_notification_bell(store: &AsyncProgramStore) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "desktop")]
|
#[cfg(feature = "desktop")]
|
||||||
fn send_notification_desktop(summary: &str, body: Option<&str>) {
|
async fn send_notification_desktop(
|
||||||
|
summary: &str,
|
||||||
|
body: Option<&str>,
|
||||||
|
room_id: OwnedRoomId,
|
||||||
|
_store: &AsyncProgramStore,
|
||||||
|
) {
|
||||||
let mut desktop_notification = notify_rust::Notification::new();
|
let mut desktop_notification = notify_rust::Notification::new();
|
||||||
desktop_notification
|
desktop_notification
|
||||||
.summary(summary)
|
.summary(summary)
|
||||||
|
@ -125,8 +154,19 @@ fn send_notification_desktop(summary: &str, body: Option<&str>) {
|
||||||
desktop_notification.body(body);
|
desktop_notification.body(body);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(err) = desktop_notification.show() {
|
match desktop_notification.show() {
|
||||||
tracing::error!("Failed to send notification: {err}")
|
Err(err) => tracing::error!("Failed to send notification: {err}"),
|
||||||
|
Ok(handle) => {
|
||||||
|
#[cfg(all(unix, not(target_os = "macos")))]
|
||||||
|
_store
|
||||||
|
.lock()
|
||||||
|
.await
|
||||||
|
.application
|
||||||
|
.open_notifications
|
||||||
|
.entry(room_id)
|
||||||
|
.or_default()
|
||||||
|
.push(NotificationHandle(Some(handle)));
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -502,19 +502,23 @@ async fn send_receipts_forever(client: &Client, store: &AsyncProgramStore) {
|
||||||
loop {
|
loop {
|
||||||
interval.tick().await;
|
interval.tick().await;
|
||||||
|
|
||||||
let locked = store.lock().await;
|
let mut locked = store.lock().await;
|
||||||
let user_id = &locked.application.settings.profile.user_id;
|
let ChatStore { settings, open_notifications, rooms, .. } = &mut locked.application;
|
||||||
|
let user_id = &settings.profile.user_id;
|
||||||
|
|
||||||
let mut updates = Vec::new();
|
let mut updates = Vec::new();
|
||||||
for room in client.joined_rooms() {
|
for room in client.joined_rooms() {
|
||||||
let room_id = room.room_id();
|
let room_id = room.room_id();
|
||||||
let Some(info) = locked.application.rooms.get(&room_id) else {
|
let Some(info) = rooms.get(room_id) else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let changed = info.receipts(user_id).filter_map(|(thread, new_receipt)| {
|
let changed = info.receipts(user_id).filter_map(|(thread, new_receipt)| {
|
||||||
let old_receipt = sent.get(room_id).and_then(|ts| ts.get(thread));
|
let old_receipt = sent.get(room_id).and_then(|ts| ts.get(thread));
|
||||||
let changed = Some(new_receipt) != old_receipt;
|
let changed = Some(new_receipt) != old_receipt;
|
||||||
|
if changed {
|
||||||
|
open_notifications.remove(room_id);
|
||||||
|
}
|
||||||
changed.then(|| (room_id.to_owned(), thread.to_owned(), new_receipt.to_owned()))
|
changed.then(|| (room_id.to_owned(), thread.to_owned(), new_receipt.to_owned()))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue