From b2c0c1587521b9fd47437a7a9ebba16a6136a65c Mon Sep 17 00:00:00 2001 From: frosty Date: Tue, 25 Aug 2026 23:07:50 -0400 Subject: feat: add in notification replies --- main/src/ui/notifier_freedesktop.vala | 57 ++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'main') diff --git a/main/src/ui/notifier_freedesktop.vala b/main/src/ui/notifier_freedesktop.vala index 99428315..3c8bee1c 100644 --- a/main/src/ui/notifier_freedesktop.vala +++ b/main/src/ui/notifier_freedesktop.vala @@ -11,10 +11,12 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object { private DBusNotifications dbus_notifications; private bool supports_body_markup = false; private bool supports_body_hyperlinks = false; + private bool supports_inline_reply = false; private HashMap content_notifications = new HashMap(Conversation.hash_func, Conversation.equals_func); private HashMap> conversation_notifications = new HashMap>(Conversation.hash_func, Conversation.equals_func); private HashMap> action_listeners = new HashMap>(); + private HashMap reply_targets = new HashMap(); private HashMap call_notifications = new HashMap(Call.hash_func, Call.equals_func); public FreeDesktopNotifier(StreamInteractor stream_interactor, DBusNotifications dbus_notifications) { @@ -35,6 +37,9 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object { case "body-hyperlinks": supports_body_hyperlinks = true; break; + case "inline-reply": + supports_inline_reply = true; + break; } } @@ -46,6 +51,22 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object { dbus_notifications.notification_closed.connect((id) => { action_listeners.unset(id); + reply_targets.unset(id); + }); + + dbus_notifications.notification_replied.connect((id, text) => { + if (!reply_targets.has_key(id)) return; + + NotificationReplyTarget target = reply_targets[id]; + if (text.strip() != "") { + Dino.send_message(target.conversation, text, target.content_item_id, null, new ArrayList()); + } + + reply_targets.unset(id); + if (content_notifications.has_key(target.conversation) && content_notifications[target.conversation] == id) { + content_notifications.unset(target.conversation); + } + dbus_notifications.close_notification.begin(id); }); } @@ -62,7 +83,9 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object { } else { body = message.body; } - yield notify_content_item(conversation, conversation_display_name, participant_display_name, body); + ContentItem? reply_to_item = stream_interactor.get_module(ContentItemStore.IDENTITY).get_content_item_for_message(conversation, message); + int reply_to_id = reply_to_item != null ? reply_to_item.id : 0; + yield notify_content_item(conversation, conversation_display_name, participant_display_name, body, reply_to_id); } public async void notify_file(FileTransfer file_transfer, Conversation conversation, bool is_image, string conversation_display_name, string? participant_display_name) { @@ -77,10 +100,10 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object { text = "" + text + ""; } - yield notify_content_item(conversation, conversation_display_name, participant_display_name, text); + yield notify_content_item(conversation, conversation_display_name, participant_display_name, text, 0); } - private async void notify_content_item(Conversation conversation, string conversation_display_name, string? participant_display_name, string body_) { + private async void notify_content_item(Conversation conversation, string conversation_display_name, string? participant_display_name, string body_, int reply_to_id) { string body = body_; if (participant_display_name != null) { if (supports_body_markup) { @@ -96,10 +119,22 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object { hash_table["desktop-entry"] = new Variant.string(Dino.Application.get_default().get_application_id()); hash_table["category"] = new Variant.string("im.received"); string[] actions = new string[] {"default", "Open conversation"}; + if (reply_to_id != 0 && supports_inline_reply) { + actions += "inline-reply"; + actions += _("Reply"); + hash_table["x-kde-reply-placeholder-text"] = new Variant.string(_("Reply")); + hash_table["x-kde-reply-submit-button-text"] = new Variant.string(_("Send")); + } try { uint32 notification_id = yield dbus_notifications.notify("Dino", replace_id, "", conversation_display_name, body, actions, hash_table, -1); content_notifications[conversation] = notification_id; + if (reply_to_id != 0 && supports_inline_reply) { + reply_targets[notification_id] = new NotificationReplyTarget(conversation, reply_to_id); + } else { + reply_targets.unset(notification_id); + } + add_action_listener(notification_id, "default", () => { GLib.Application.get_default().activate_action("open-conversation", new Variant.int32(conversation.id)); }); @@ -284,12 +319,15 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object { } catch (Error e) { } } content_notifications.clear(); + reply_targets.clear(); } public async void retract_conversation_notifications(Conversation conversation) { try { if (content_notifications.has_key(conversation)) { - dbus_notifications.close_notification.begin(content_notifications[conversation]); + uint32 notification_id = content_notifications[conversation]; + dbus_notifications.close_notification.begin(notification_id); + reply_targets.unset(notification_id); content_notifications.unset(conversation); } @@ -323,6 +361,17 @@ public class Dino.Ui.FreeDesktopNotifier : NotificationProvider, Object { } delegate void ListenerFunc(); + + class NotificationReplyTarget { + public Conversation conversation; + public int content_item_id; + + public NotificationReplyTarget(Conversation conversation, int content_item_id) { + this.conversation = conversation; + this.content_item_id = content_item_id; + } + } + class ListenerFuncWrapper { public ListenerFunc func; -- cgit v1.3