From d8bb9897a42209a7bb56951b8a7bc5807822e5c4 Mon Sep 17 00:00:00 2001 From: LAGonauta Date: Thu, 26 Nov 2020 18:50:03 -0300 Subject: [PATCH] Add support for custom actions on notification --- .../src/DinoWinToastLib.h | 37 ++++- .../src/DinoWinToastLib_AMD64.lib | Bin 5186 -> 6038 bytes .../src/DinoWinToastTemplate.h | 36 ++--- .../src/win_notification_provider.vala | 153 +++++++++++------- .../vapi/DinoWinToastLib.vapi | 42 ++++- .../vapi/DinoWinToastTemplate.vapi | 8 +- 6 files changed, 186 insertions(+), 90 deletions(-) diff --git a/plugins/windows-notification/src/DinoWinToastLib.h b/plugins/windows-notification/src/DinoWinToastLib.h index 69723666..c7c70933 100644 --- a/plugins/windows-notification/src/DinoWinToastLib.h +++ b/plugins/windows-notification/src/DinoWinToastLib.h @@ -6,9 +6,40 @@ #ifdef __cplusplus extern "C" { #endif - typedef void(*dinoWinToastLibNotificationCallback)(int conv_id, void* userdata); - DINOWINTOASTLIB_API int dinoWinToastLibInit(); - DINOWINTOASTLIB_API int dinoWinToastLibShowMessage(dino_wintoasttemplate templ, int conv_id, dinoWinToastLibNotificationCallback click_callback, void* callback_target); + typedef enum { + Reason_Activated = 0, + Reason_ApplicationHidden, + Reason_TimedOut + } dinoWinToastLib_Notification_Reason; + + typedef void(*dinoWinToastLib_Notification_Callback_Simple)(void* userdata); + typedef void(*dinoWinToastLib_Notification_Callback_ActivatedWithActionIndex)(int action_id, void* userdata); + typedef void(*dinoWinToastLib_Notification_Callback_Dismissed)(dinoWinToastLib_Notification_Reason reason, void* userdata); + + typedef struct { + dinoWinToastLib_Notification_Callback_Simple activated; + void* activated_context; + void(*activated_free)(void*); + + dinoWinToastLib_Notification_Callback_ActivatedWithActionIndex activatedWithIndex; + void* activatedWithIndex_context; + void(*activatedWithIndex_free)(void*); + + dinoWinToastLib_Notification_Callback_Dismissed dismissed; + void* dismissed_context; + void(*dismissed_free)(void*); + + dinoWinToastLib_Notification_Callback_Simple failed; + void* failed_context; + void(*failed_free)(void*); + + } dinoWinToastLib_Notification_Callbacks; + + DINOWINTOASTLIB_API dinoWinToastLib_Notification_Callbacks* dinoWinToastLib_NewCallbacks(); + DINOWINTOASTLIB_API void dinoWinToastLib_DestroyCallbacks(dinoWinToastLib_Notification_Callbacks* callbacks); + + DINOWINTOASTLIB_API int dinoWinToastLib_Init(); + DINOWINTOASTLIB_API int dinoWinToastLib_ShowMessage(dino_wintoasttemplate templ, dinoWinToastLib_Notification_Callbacks* callbacks); #ifdef __cplusplus } // extern "C" #endif \ No newline at end of file diff --git a/plugins/windows-notification/src/DinoWinToastLib_AMD64.lib b/plugins/windows-notification/src/DinoWinToastLib_AMD64.lib index c508e807a64cfa9d699c0eba5631c65dea718217..190f4ca5c53352a1f21259efda2abe4cca8f076c 100644 GIT binary patch delta 1284 zcmaJ=OGs2<6h3zz&iwPZk9mopaof}wRO4i$13eZA74$$eQ<1J?&eYK0STmt6%2|}O z3hO`+QPiSM+u0gI5iJ5yoQ09tQfg7^B1l3z|GiQ(-pLE!z4v_Q@&EsK&i^+2_~2xG zJlYyn^{3wj0J{NPO90+5fS3YMN(STw01j!^fZRnkLFq6M+yKxqN?$^NayfjR2K5q>T? z^8fI1Ckj>-rv*1^&bs2XP_m3izsF?{aGqDq^cr1iy$X7Q_ffqyT&K&6?t+pMr&KhsKgba2VD6Z>j>JGku^f1^&P?07HOc0a^)&tOK#tK4FfGzS(DlBa_s7#M$bRsP{;&vCbITJ}r(+obw(D*`rvT zntAxSLT3U))Rrx}B5Mby-0}(*%Wh@1>|U%aR9B|U*F25JMY~xOehIaV^KW3UrKJER z4Oou=t1%$VZ1PwmjGpYxRZjqG{LUIci>b3wW{tN+00Jb4P!Qu4RD_`+1Q`)T2kJpi zP*T1`Tk@f1TYecZ2aVi}DEsn+lj)t-w!PzayTIbzbna+pl>35v4%&0sDx{tK|Gs5v2)Dp>nq#FRVnIx`FfI`=!dBh66tj?PB$&nulLwAq~i1Fr%4(%ylkAlnR80v z#o0f3t`PDoG(usTPt8m3-1}XJhE1E=f { + app.activate_action("open-conversation", conversation.id); + }; + + callbacks.activatedWithIndex = (index) => { + if (index == 0) { + app.activate_action("accept-subscription", conversation.id); + } else if (index == 1) { + app.activate_action("deny-subscription", conversation.id); + } + }; + + if (!ShowMessage(template, callbacks) == 0) { warning("Failed showing subscription request notification"); } - - // HashTable hash_table = new HashTable(null, null); - // hash_table["image-data"] = yield get_conversation_icon(conversation); - // string[] actions = new string[] {"default", "Open conversation", "accept", _("Accept"), "deny", _("Deny")}; - // try { - // uint32 notification_id = dbus_notifications.notify("Dino", 0, "", summary, body, actions, hash_table, 0); - - // if (!conversation_notifications.has_key(conversation)) { - // conversation_notifications[conversation] = new ArrayList(); - // } - // conversation_notifications[conversation].add(notification_id); - - // add_action_listener(notification_id, "default", () => { - // GLib.Application.get_default().activate_action("open-conversation", new Variant.int32(conversation.id)); - // }); - // add_action_listener(notification_id, "accept", () => { - // GLib.Application.get_default().activate_action("accept-subscription", new Variant.int32(conversation.id)); - // }); - // add_action_listener(notification_id, "deny", () => { - // GLib.Application.get_default().activate_action("deny-subscription", new Variant.int32(conversation.id)); - // }); - // } catch (Error e) { - // warning("Failed showing subscription request notification: %s", e.message); - // } } public async void notify_connection_error(Account account, ConnectionManager.ConnectionError error) { @@ -97,7 +102,7 @@ namespace Dino.Plugins.WindowsNotification { break; } - if (!show_message(summary, body, null, 0, stub)) { + if (!show_message(summary, body, null, null)) { warning("Failed showing connection error notification"); } } @@ -109,15 +114,39 @@ namespace Dino.Plugins.WindowsNotification { string summary = _("Invitation to %s").printf(display_room); string body = _("%s invited you to %s").printf(inviter_display_name, display_room); + DinoWinToastTemplate template; + var image_path = get_avatar(conversation); + if (image_path != null) { + template = new DinoWinToastTemplate(TemplateType.ImageAndText02); + template.setImagePath(image_path); + } else { + template = new DinoWinToastTemplate(TemplateType.Text02); + } + + template.setTextField(summary, TextField.FirstLine); + template.setTextField(body, TextField.SecondLine); + + template.addAction(_("Accept")); + template.addAction(_("Deny")); + Conversation group_conversation = stream_interactor.get_module(ConversationManager.IDENTITY).create_conversation(room_jid, account, Conversation.Type.GROUPCHAT); - if (!show_message(summary, body, get_avatar(direct_conversation), group_conversation.id, stub)) { // action not enabled yet + var callbacks = new Callbacks(); + callbacks.activated = () => { + app.activate_action("open-muc-join", group_conversation.id); + }; + + callbacks.activatedWithIndex = (index) => { + if (index == 0) { + app.activate_action("deny-invite", group_conversation.id); + } else if (index == 1) { + app.activate_action("open-muc-join", group_conversation.id); + } + }; + + if (!ShowMessage(template, callbacks)) { warning("Failed showing muc invite notification"); } - // HashTable hash_table = new HashTable(null, null); - // hash_table["image-data"] = yield get_conversation_icon(direct_conversation); - // string[] actions = new string[] {"default", "", "reject", _("Reject"), "accept", _("Accept")}; - // try { // uint32 notification_id = dbus_notifications.notify("Dino", 0, "", summary, body, actions, hash_table, 0); @@ -137,32 +166,38 @@ namespace Dino.Plugins.WindowsNotification { } public async void notify_voice_request(Conversation conversation, Jid from_jid) { - string display_name = Dino.get_participant_display_name(stream_interactor, conversation, from_jid); string display_room = Dino.get_conversation_display_name(stream_interactor, conversation, _("%s from %s")); string summary = _("Permission request"); string body = _("%s requests the permission to write in %s").printf(display_name, display_room); - if (!show_message(summary, body, get_avatar(conversation), conversation.id, stub)) { // missing actions + DinoWinToastTemplate template; + var image_path = get_avatar(conversation); + if (image_path != null) { + template = new DinoWinToastTemplate(TemplateType.ImageAndText02); + template.setImagePath(image_path); + } else { + template = new DinoWinToastTemplate(TemplateType.Text02); + } + + template.setTextField(summary, TextField.FirstLine); + template.setTextField(body, TextField.SecondLine); + + template.addAction(_("Accept")); + template.addAction(_("Deny")); + + var callbacks = new Callbacks(); + callbacks.activatedWithIndex = (index) => { + if (index == 0) { + app.activate_action("deny-invite", conversation.id); + } else if (index == 1) { + app.activate_action("open-muc-join", conversation.id); + } + }; + + if (!ShowMessage(template, callbacks) == 0) { warning("Failed showing voice request notification"); } - - // HashTable hash_table = new HashTable(null, null); - // hash_table["image-data"] = yield get_conversation_icon(conversation); - // string[] actions = new string[] {"deny", _("Deny"), "accept", _("Accept")}; - - // try { - // uint32 notification_id = dbus_notifications.notify("Dino", 0, "", summary, body, actions, hash_table, 0); - - // add_action_listener(notification_id, "accept", () => { - // GLib.Application.get_default().activate_action("deny-invite", new Variant.int32(conversation.id)); - // }); - // add_action_listener(notification_id, "deny", () => { - // GLib.Application.get_default().activate_action("open-muc-join", new Variant.int32(conversation.id)); - // }); - // } catch (Error e) { - // warning("Failed showing voice request notification: %s", e.message); - // } } public async void retract_content_item_notifications() { @@ -185,7 +220,7 @@ namespace Dino.Plugins.WindowsNotification { // content_notifications.unset(conversation); } - private bool show_message(string sender, string message, string? image_path, int conv_id, NotificationCallback callback) { + private bool show_message(string sender, string message, string? image_path, Callbacks? callbacks = null) { DinoWinToastTemplate template; if (image_path != null) { template = new DinoWinToastTemplate(TemplateType.ImageAndText02); @@ -196,7 +231,10 @@ namespace Dino.Plugins.WindowsNotification { template.setTextField(sender, TextField.FirstLine); template.setTextField(message, TextField.SecondLine); - return ShowMessage(template, conv_id, callback) == 0; + if (callbacks != null) { + return ShowMessage(template, callbacks) == 0; + } + return ShowMessage(template, new Callbacks()) == 0; } private async void notify_content_item(Conversation conversation, string conversation_display_name, string? participant_display_name, string body_) { @@ -206,18 +244,13 @@ namespace Dino.Plugins.WindowsNotification { } var avatar = get_avatar(conversation); - if (!show_message(conversation_display_name, body, avatar, conversation.id, onclick_callback)) { + var callbacks = new Callbacks(); + callbacks.activated = () => app.activate_action("open-conversation", conversation.id); + if (!show_message(conversation_display_name, body, avatar, callbacks)) { warning("Failed showing content item notification"); } } - private void onclick_callback(int conv_id) { - this.app.activate_action("open-conversation", conv_id); - } - - private void stub(int conv_id) { - } - private string? get_avatar(Conversation conversation) { var avatar_manager = app.stream_interactor.get_module(AvatarManager.IDENTITY); return avatar_manager.get_avatar_filepath(conversation.account, conversation.counterpart); diff --git a/plugins/windows-notification/vapi/DinoWinToastLib.vapi b/plugins/windows-notification/vapi/DinoWinToastLib.vapi index a4c92057..25077d46 100644 --- a/plugins/windows-notification/vapi/DinoWinToastLib.vapi +++ b/plugins/windows-notification/vapi/DinoWinToastLib.vapi @@ -1,13 +1,45 @@ [CCode (cheader_filename = "DinoWinToastLib.h")] namespace DinoWinToast { - [CCode (cname = "dinoWinToastLibNotificationCallback", has_target = true)] - public delegate void NotificationCallback(int conv_id); + [CCode (cname = "dinoWinToastLib_Notification_Reason", cprefix = "Reason_")] + public enum Reason { + Activated, + ApplicationHidden, + TimedOut + } - [CCode (cname = "dinoWinToastLibInit")] + [CCode (cname = "dinoWinToastLib_Notification_Callback_Simple", has_target = true)] + public delegate void NotificationCallbackSimple(); + + [CCode (cname = "dinoWinToastLib_Notification_Callback_ActivatedWithActionIndex", has_target = true)] + public delegate void NotificationCallbackWithActionIndex(int actionId); + + [CCode (cname = "dinoWinToastLib_Notification_Callback_Dismissed", has_target = true)] + public delegate void NotificationCallbackDismissed(Reason reason); + + [CCode (cname = "dinoWinToastLib_Notification_Callbacks", free_function = "dinoWinToastLib_DestroyCallbacks")] + [Compact] + public class Callbacks { + [CCode (delegate_target_cname = "activated_context", destroy_notify_cname = "activated_free")] + public NotificationCallbackSimple activated; + + [CCode (delegate_target_cname = "activatedWithIndex_context", destroy_notify_cname = "activatedWithIndex_free")] + public NotificationCallbackWithActionIndex activatedWithIndex; + + [CCode (delegate_target_cname = "dismissed_context", destroy_notify_cname = "dismissed_free")] + public NotificationCallbackDismissed dismissed; + + [CCode (delegate_target_cname = "failed_context", destroy_notify_cname = "failed_free")] + public NotificationCallbackSimple failed; + + [CCode (cname = "dinoWinToastLib_NewCallbacks")] + public Callbacks(); + } + + [CCode (cname = "dinoWinToastLib_Init")] public int Init(); - [CCode (cname = "dinoWinToastLibShowMessage")] - public int ShowMessage(DinoWinToastTemplate templ, int conv_id, NotificationCallback callback); + [CCode (cname = "dinoWinToastLib_ShowMessage")] + public int ShowMessage(DinoWinToastTemplate templ, Callbacks callbacks); } diff --git a/plugins/windows-notification/vapi/DinoWinToastTemplate.vapi b/plugins/windows-notification/vapi/DinoWinToastTemplate.vapi index 59fc4740..ca5b2fc7 100644 --- a/plugins/windows-notification/vapi/DinoWinToastTemplate.vapi +++ b/plugins/windows-notification/vapi/DinoWinToastTemplate.vapi @@ -1,27 +1,27 @@ [CCode (cheader_filename = "DinoWinToastTemplate.h")] namespace DinoWinToast { - [CCode (cname = "dino_wintoasttemplate_duration", cprefix = "")] + [CCode (cname = "dino_wintoasttemplate_duration", cprefix = "Duration_")] public enum Duration { System, Short, Long } - [CCode (cname = "dino_wintoasttemplate_audiooption", cprefix = "")] + [CCode (cname = "dino_wintoasttemplate_audiooption", cprefix = "AudioOption_")] public enum AudioOption { Default, Silent, Loop } - [CCode (cname = "dino_wintoasttemplate_textfield", cprefix = "")] + [CCode (cname = "dino_wintoasttemplate_textfield", cprefix = "TextField_")] public enum TextField { FirstLine, SecondLine, ThirdLine } - [CCode (cname = "dino_wintoasttemplate_wintoasttemplatetype", cprefix = "")] + [CCode (cname = "dino_wintoasttemplate_wintoasttemplatetype", cprefix = "TemplateType_")] public enum TemplateType { ImageAndText01, ImageAndText02,