aboutsummaryrefslogtreecommitdiff
path: root/main
diff options
context:
space:
mode:
Diffstat (limited to 'main')
-rw-r--r--main/data/preferences_window/general_preferences_page.ui7
-rw-r--r--main/meson.build1
-rw-r--r--main/src/ui/application.vala11
-rw-r--r--main/src/ui/launcher_badge.vala118
-rw-r--r--main/src/view_model/preferences_dialog.vala1
-rw-r--r--main/src/windows/preferences_window/general_preferences_page.vala3
6 files changed, 141 insertions, 0 deletions
diff --git a/main/data/preferences_window/general_preferences_page.ui b/main/data/preferences_window/general_preferences_page.ui
index 50efd425..c8d78654 100644
--- a/main/data/preferences_window/general_preferences_page.ui
+++ b/main/data/preferences_window/general_preferences_page.ui
@@ -29,6 +29,13 @@
<object class="AdwPreferencesGroup">
<property name="title" translatable="yes">Notifications</property>
<child>
+ <object class="AdwSwitchRow" id="notification_badge_row">
+ <property name="title" translatable="yes">Notification _Badge</property>
+ <property name="subtitle" translatable="yes">Show the unread count on the application icon</property>
+ <property name="use-underline">True</property>
+ </object>
+ </child>
+ <child>
<object class="AdwSwitchRow" id="notification_messages_row">
<property name="title" translatable="yes">_Messages</property>
<property name="subtitle" translatable="yes">Notify when a new message arrives</property>
diff --git a/main/meson.build b/main/meson.build
index e387914f..56f31237 100644
--- a/main/meson.build
+++ b/main/meson.build
@@ -68,6 +68,7 @@ sources = files(
'src/ui/conversation_view.vala',
'src/ui/conversation_view_controller.vala',
'src/ui/global_search.vala',
+ 'src/ui/launcher_badge.vala',
'src/ui/main_window.vala',
'src/ui/main_window_controller.vala',
'src/ui/notifier_freedesktop.vala',
diff --git a/main/src/ui/application.vala b/main/src/ui/application.vala
index 9ac512d9..b72a8d0e 100644
--- a/main/src/ui/application.vala
+++ b/main/src/ui/application.vala
@@ -14,6 +14,7 @@ public class Dino.Ui.Application : Adw.Application, Dino.Application {
public MainWindow window;
public MainWindowController controller;
+ private LauncherBadge? launcher_badge;
private StatusNotifierItem? status_notifier_item;
public Database db { get; set; }
@@ -50,6 +51,12 @@ public class Dino.Ui.Application : Adw.Application, Dino.Application {
warning("Could not create Dino's tray icon: %s", e.message);
}
+ try {
+ launcher_badge = new LauncherBadge(stream_interactor);
+ } catch (IOError e) {
+ warning("Could not create Dino's launcher badge: %s", e.message);
+ }
+
NotificationEvents notification_events = stream_interactor.get_module(NotificationEvents.IDENTITY);
get_notifications_dbus.begin((_, res) => {
// It might take a bit to get the interface. NotificationEvents will queue any notifications in the meantime.
@@ -76,6 +83,10 @@ public class Dino.Ui.Application : Adw.Application, Dino.Application {
});
shutdown.connect(() => {
+ if (launcher_badge != null) {
+ launcher_badge.shutdown();
+ launcher_badge = null;
+ }
if (status_notifier_item != null) {
status_notifier_item.shutdown();
status_notifier_item = null;
diff --git a/main/src/ui/launcher_badge.vala b/main/src/ui/launcher_badge.vala
new file mode 100644
index 00000000..aa07fbaa
--- /dev/null
+++ b/main/src/ui/launcher_badge.vala
@@ -0,0 +1,118 @@
+using Gee;
+using GLib;
+
+using Dino.Entities;
+
+namespace Dino.Ui {
+
+[DBus (name = "com.canonical.Unity.LauncherEntry")]
+public class LauncherBadge : Object {
+ private const string APP_URI = "application://im.dino.Dino.desktop";
+ private const string BUS_NAME = "com.canonical.Unity";
+ private const string OBJECT_PATH = "/im/dino/Dino/LauncherEntry";
+
+ private StreamInteractor stream_interactor;
+ private DBusConnection connection;
+ private HashMap<Conversation, ulong> read_handler_ids = new HashMap<Conversation, ulong>(Conversation.hash_func, Conversation.equals_func);
+ private int64 unread_count = -1;
+ private uint object_registration_id;
+ private uint watcher_id;
+ private ulong conversation_activated_handler_id;
+ private ulong conversation_deactivated_handler_id;
+ private ulong new_item_handler_id;
+ private ulong setting_handler_id;
+
+ public signal void update(string app_uri, HashTable<string, Variant> properties);
+
+ public LauncherBadge(StreamInteractor stream_interactor) throws IOError {
+ this.stream_interactor = stream_interactor;
+ connection = Bus.get_sync(BusType.SESSION);
+ object_registration_id = connection.register_object(OBJECT_PATH, this);
+
+ ConversationManager conversation_manager = stream_interactor.get_module(ConversationManager.IDENTITY);
+ conversation_activated_handler_id = conversation_manager.conversation_activated.connect(add_conversation);
+ conversation_deactivated_handler_id = conversation_manager.conversation_deactivated.connect(remove_conversation);
+ new_item_handler_id = stream_interactor.get_module(ContentItemStore.IDENTITY).new_item.connect(() => update_count());
+ setting_handler_id = Dino.Application.get_default().settings.notify["notifications-badge"].connect(() => update_count(true));
+
+ foreach (Conversation conversation in conversation_manager.get_active_conversations()) {
+ connect_conversation(conversation);
+ }
+
+ watcher_id = Bus.watch_name_on_connection(
+ connection,
+ BUS_NAME,
+ BusNameWatcherFlags.NONE,
+ () => update_count(true));
+ update_count(true);
+ }
+
+ public void query(out string app_uri, out HashTable<string, Variant> properties) throws Error {
+ app_uri = APP_URI;
+ properties = get_properties();
+ }
+
+ internal void shutdown() {
+ unread_count = 0;
+ update(APP_URI, get_properties());
+
+ ConversationManager conversation_manager = stream_interactor.get_module(ConversationManager.IDENTITY);
+ conversation_manager.disconnect(conversation_activated_handler_id);
+ conversation_manager.disconnect(conversation_deactivated_handler_id);
+ stream_interactor.get_module(ContentItemStore.IDENTITY).disconnect(new_item_handler_id);
+ Dino.Application.get_default().settings.disconnect(setting_handler_id);
+
+ foreach (Conversation conversation in read_handler_ids.keys) {
+ conversation.disconnect(read_handler_ids[conversation]);
+ }
+ read_handler_ids.clear();
+
+ if (watcher_id != 0) {
+ Bus.unwatch_name(watcher_id);
+ watcher_id = 0;
+ }
+ if (object_registration_id != 0) {
+ connection.unregister_object(object_registration_id);
+ object_registration_id = 0;
+ }
+ }
+
+ private void add_conversation(Conversation conversation) {
+ connect_conversation(conversation);
+ update_count();
+ }
+
+ private void remove_conversation(Conversation conversation) {
+ if (read_handler_ids.has_key(conversation)) {
+ conversation.disconnect(read_handler_ids[conversation]);
+ read_handler_ids.unset(conversation);
+ }
+ update_count();
+ }
+
+ private void connect_conversation(Conversation conversation) {
+ if (read_handler_ids.has_key(conversation)) return;
+ read_handler_ids[conversation] = conversation.notify["read-up-to-item"].connect(() => update_count());
+ }
+
+ private void update_count(bool force = false) {
+ int64 count = 0;
+ ChatInteraction chat_interaction = stream_interactor.get_module(ChatInteraction.IDENTITY);
+ foreach (Conversation conversation in stream_interactor.get_module(ConversationManager.IDENTITY).get_active_conversations()) {
+ count += chat_interaction.get_num_unread(conversation);
+ }
+
+ if (!force && count == unread_count) return;
+ unread_count = count;
+ update(APP_URI, get_properties());
+ }
+
+ private HashTable<string, Variant> get_properties() {
+ HashTable<string, Variant> properties = new HashTable<string, Variant>(str_hash, str_equal);
+ properties["count"] = new Variant.int64(unread_count);
+ properties["count-visible"] = new Variant.boolean(Dino.Application.get_default().settings.notifications_badge && unread_count > 0);
+ return properties;
+ }
+}
+
+}
diff --git a/main/src/view_model/preferences_dialog.vala b/main/src/view_model/preferences_dialog.vala
index d7bad93a..09e22187 100644
--- a/main/src/view_model/preferences_dialog.vala
+++ b/main/src/view_model/preferences_dialog.vala
@@ -119,6 +119,7 @@ public class Dino.Ui.ViewModel.PreferencesDialog : Object {
settings.bind_property("notifications-group-chat-invitations", general_page, "notifications-group-chat-invitations", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
settings.bind_property("notifications-permission-requests", general_page, "notifications-permission-requests", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
settings.bind_property("notifications-connection-errors", general_page, "notifications-connection-errors", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
+ settings.bind_property("notifications-badge", general_page, "notifications-badge", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
settings.bind_property("convert-utf8-smileys", general_page, "convert-emojis", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL);
}
diff --git a/main/src/windows/preferences_window/general_preferences_page.vala b/main/src/windows/preferences_window/general_preferences_page.vala
index 81906643..733de889 100644
--- a/main/src/windows/preferences_window/general_preferences_page.vala
+++ b/main/src/windows/preferences_window/general_preferences_page.vala
@@ -11,6 +11,7 @@ public class Dino.Ui.ViewModel.GeneralPreferencesPage : Object {
public bool notifications_group_chat_invitations { get; set; }
public bool notifications_permission_requests { get; set; }
public bool notifications_connection_errors { get; set; }
+ public bool notifications_badge { get; set; }
public bool convert_emojis { get; set; }
}
@@ -26,6 +27,7 @@ public class Dino.Ui.GeneralPreferencesPage : Adw.PreferencesPage {
[GtkChild] private unowned Adw.SwitchRow notification_group_chat_invitations_row;
[GtkChild] private unowned Adw.SwitchRow notification_permission_requests_row;
[GtkChild] private unowned Adw.SwitchRow notification_connection_errors_row;
+ [GtkChild] private unowned Adw.SwitchRow notification_badge_row;
[GtkChild] private unowned Adw.SwitchRow emoji_row;
public ViewModel.GeneralPreferencesPage model { get; set; default = new ViewModel.GeneralPreferencesPage(); }
@@ -51,6 +53,7 @@ public class Dino.Ui.GeneralPreferencesPage : Adw.PreferencesPage {
model.bind_property("notifications-group-chat-invitations", notification_group_chat_invitations_row, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL),
model.bind_property("notifications-permission-requests", notification_permission_requests_row, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL),
model.bind_property("notifications-connection-errors", notification_connection_errors_row, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL),
+ model.bind_property("notifications-badge", notification_badge_row, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL),
model.bind_property("convert-emojis", emoji_row, "active", BindingFlags.SYNC_CREATE | BindingFlags.BIDIRECTIONAL)
};
} else {