diff --git a/libdino/src/service/avatar_manager.vala b/libdino/src/service/avatar_manager.vala index b308aa2b..6b44b6ea 100644 --- a/libdino/src/service/avatar_manager.vala +++ b/libdino/src/service/avatar_manager.vala @@ -256,6 +256,24 @@ public class AvatarManager : StreamInteractionModule, Object { return null; } } + + public string? get_avatar_filepath(Account account, Jid jid_) { + Jid jid = jid_; + if (!stream_interactor.get_module(MucManager.IDENTITY).is_groupchat_occupant(jid_, account)) { + jid = jid_.bare_jid; + } + + string? hash = null; + if (user_avatars.has_key(jid)) { + hash = user_avatars[jid]; + } else if (vcard_avatars.has_key(jid)) { + hash = vcard_avatars[jid]; + } + + if (hash == null) return null; + + return Path.build_filename(folder, hash); + } } } diff --git a/plugins/windows-notification/CMakeLists.txt b/plugins/windows-notification/CMakeLists.txt index 70b434f1..d28fcaf7 100644 --- a/plugins/windows-notification/CMakeLists.txt +++ b/plugins/windows-notification/CMakeLists.txt @@ -10,11 +10,11 @@ vala_precompile(WINDOWS_NOTIFICATION_VALA_C SOURCES src/plugin.vala src/register_plugin.vala + src/helper.vala CUSTOM_VAPIS ${CMAKE_BINARY_DIR}/exports/xmpp-vala.vapi ${CMAKE_BINARY_DIR}/exports/dino.vapi ${CMAKE_BINARY_DIR}/exports/qlite.vapi - #${CMAKE_CURRENT_SOURCE_DIR}/vapi/openal.vapi PACKAGES ${WINDOWS_NOTIFICATION_PACKAGES} ) diff --git a/plugins/windows-notification/src/helper.vala b/plugins/windows-notification/src/helper.vala new file mode 100644 index 00000000..40b4bf2b --- /dev/null +++ b/plugins/windows-notification/src/helper.vala @@ -0,0 +1,113 @@ +using Gee; +using Gtk; + +using Dino.Entities; +using Xmpp; + +namespace Dino.Ui.Util { + +private static Jid get_relevant_jid(StreamInteractor stream_interactor, Account account, Jid jid, Conversation? conversation = null) { + Conversation conversation_ = conversation ?? stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(jid.bare_jid, account); + if (conversation_ != null && conversation_.type_ == Conversation.Type.GROUPCHAT) { + Jid? real_jid = stream_interactor.get_module(MucManager.IDENTITY).get_real_jid(jid, account); + if (real_jid != null) { + return real_jid.bare_jid; + } + } else { + return jid.bare_jid; + } + return jid; +} + +public static string get_conversation_display_name(StreamInteractor stream_interactor, Conversation conversation) { + if (conversation.type_ == Conversation.Type.CHAT) { + string? display_name = get_real_display_name(stream_interactor, conversation.account, conversation.counterpart); + if (display_name != null) return display_name; + return conversation.counterpart.to_string(); + } + if (conversation.type_ == Conversation.Type.GROUPCHAT) { + return get_groupchat_display_name(stream_interactor, conversation.account, conversation.counterpart); + } + if (conversation.type_ == Conversation.Type.GROUPCHAT_PM) { + return "%s from %s".printf(get_occupant_display_name(stream_interactor, conversation, conversation.counterpart), get_groupchat_display_name(stream_interactor, conversation.account, conversation.counterpart.bare_jid)); + } + return conversation.counterpart.to_string(); +} + +public static string get_participant_display_name(StreamInteractor stream_interactor, Conversation conversation, Jid participant, bool me_is_me = false) { + if (me_is_me) { + if (conversation.account.bare_jid.equals_bare(participant) || + (conversation.type_ == Conversation.Type.GROUPCHAT || conversation.type_ == Conversation.Type.GROUPCHAT_PM) && + conversation.nickname != null && participant.equals_bare(conversation.counterpart) && conversation.nickname == participant.resourcepart) { + return "Me"; + } + } + if (conversation.type_ == Conversation.Type.CHAT) { + return get_real_display_name(stream_interactor, conversation.account, participant, me_is_me) ?? participant.bare_jid.to_string(); + } + if ((conversation.type_ == Conversation.Type.GROUPCHAT || conversation.type_ == Conversation.Type.GROUPCHAT_PM) && conversation.counterpart.equals_bare(participant)) { + return get_occupant_display_name(stream_interactor, conversation, participant); + } + return participant.bare_jid.to_string(); +} + +private static string? get_real_display_name(StreamInteractor stream_interactor, Account account, Jid jid, bool me_is_me = false) { + if (jid.equals_bare(account.bare_jid)) { + if (me_is_me || account.alias == null || account.alias.length == 0) { + return "Me"; + } + return account.alias; + } + Roster.Item roster_item = stream_interactor.get_module(RosterManager.IDENTITY).get_roster_item(account, jid); + if (roster_item != null && roster_item.name != null && roster_item.name != "") { + return roster_item.name; + } + return null; +} + +private static string get_groupchat_display_name(StreamInteractor stream_interactor, Account account, Jid jid) { + MucManager muc_manager = stream_interactor.get_module(MucManager.IDENTITY); + string room_name = muc_manager.get_room_name(account, jid); + if (room_name != null && room_name != jid.localpart) { + return room_name; + } + if (muc_manager.is_private_room(account, jid)) { + Gee.List? other_occupants = muc_manager.get_other_offline_members(jid, account); + if (other_occupants != null && other_occupants.size > 0) { + var builder = new StringBuilder (); + foreach(Jid occupant in other_occupants) { + if (builder.len != 0) { + builder.append(", "); + } + builder.append((get_real_display_name(stream_interactor, account, occupant) ?? occupant.localpart ?? occupant.domainpart).split(" ")[0]); + } + return builder.str; + } + } + return jid.to_string(); +} + +private static string get_occupant_display_name(StreamInteractor stream_interactor, Conversation conversation, Jid jid, bool me_is_me = false, bool muc_real_name = false) { + if (muc_real_name) { + MucManager muc_manager = stream_interactor.get_module(MucManager.IDENTITY); + if (muc_manager.is_private_room(conversation.account, jid.bare_jid)) { + Jid? real_jid = muc_manager.get_real_jid(jid, conversation.account); + if (real_jid != null) { + string? display_name = get_real_display_name(stream_interactor, conversation.account, real_jid, me_is_me); + if (display_name != null) return display_name; + } + } + } + + // If it's us (jid=our real full JID), display our nick + if (conversation.type_ == Conversation.Type.GROUPCHAT_PM && conversation.account.bare_jid.equals_bare(jid)) { + var muc_conv = stream_interactor.get_module(ConversationManager.IDENTITY).get_conversation(conversation.counterpart.bare_jid, conversation.account, Conversation.Type.GROUPCHAT); + if (muc_conv != null && muc_conv.nickname != null) { + return muc_conv.nickname; + } + } + + return jid.resourcepart ?? jid.to_string(); +} + +} diff --git a/plugins/windows-notification/src/plugin.vala b/plugins/windows-notification/src/plugin.vala index 9c3571d1..90bb9ac2 100644 --- a/plugins/windows-notification/src/plugin.vala +++ b/plugins/windows-notification/src/plugin.vala @@ -4,7 +4,8 @@ using Dino.Entities; namespace Dino.Plugins.WindowsNotification { public class Plugin : RootInterface, Object { - public Dino.Application app; + private Dino.Application app; + private ulong signal_handler = 0; [CCode (has_target = false)] private delegate void notification_callback(void* conv); @@ -37,22 +38,53 @@ public class Plugin : RootInterface, Object { return; } - app.stream_interactor.get_module(NotificationEvents.IDENTITY).notify_content_item.connect((item, conversation) => { - if (item.type_ == "message") { - var message_item = (MessageItem)item; - var message = message_item.message.body; - var sender = conversation.nickname != null ? conversation.nickname : conversation.counterpart.to_string(); - var avatar = null; - if (show_message(sender, message, avatar, null, this) != 0) { - stderr.printf("Error sending notification."); - }; - } - }); + signal_handler = app.stream_interactor.get_module(NotificationEvents.IDENTITY).notify_content_item.connect(on_notify); } public void shutdown() { + if (signal_handler > 0) { + app.stream_interactor.get_module(NotificationEvents.IDENTITY).notify_content_item.disconnect(on_notify); + } uninit_library(); } + + private void on_notify(ContentItem content_item, Conversation conversation) { + string display_name = Dino.Ui.Util.get_conversation_display_name(app.stream_interactor, conversation); + string text = ""; + switch (content_item.type_) { + case MessageItem.TYPE: + var message_item = (content_item as MessageItem); + if (message_item != null) { + Message message = message_item.message; + if (message != null) { + text = message.body; + } + } + break; + case FileItem.TYPE: + FileItem file_item = content_item as FileItem; + if (file_item != null) { + FileTransfer transfer = file_item.file_transfer; + + bool file_is_image = transfer.mime_type != null && transfer.mime_type.has_prefix("image"); + if (transfer.direction == Message.DIRECTION_SENT) { + text = file_is_image ? "Image sent" : "File sent"; + } else { + text = file_is_image ? "Image received" : "File received"; + } + } + break; + } + if (app.stream_interactor.get_module(MucManager.IDENTITY).is_groupchat(conversation.counterpart, conversation.account)) { + string muc_occupant = Dino.Ui.Util.get_participant_display_name(app.stream_interactor, conversation, content_item.jid); + text = @"$muc_occupant: $text"; + } + var avatar_manager = app.stream_interactor.get_module(AvatarManager.IDENTITY); + var avatar = avatar_manager.get_avatar_filepath(conversation.account, conversation.counterpart); + if (show_message(display_name, text, avatar, null, this) != 0) { + stderr.printf("Error sending notification."); + }; + } } }