aboutsummaryrefslogtreecommitdiff
path: root/main/src/ui/launcher_badge.vala
blob: aa07fbaada16b7367f86dee7ce0bb66c42a15c8b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
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;
    }
}

}