[polari/wip/fmuellner/combined-gsoc: 51/137] Added UserTracker class with local tracking only.



commit 6bf0e596bc8faa33edba7f2c4f66e142a04781b0
Author: raresv <rares visalom gmail com>
Date:   Mon Jun 27 14:12:46 2016 +0300

    Added UserTracker class with local tracking only.

 src/application.js                     |    7 ++
 src/chatView.js                        |  100 +++++----------------
 src/org.gnome.Polari.src.gresource.xml |    1 +
 src/userTracker.js                     |  148 ++++++++++++++++++++++++++++++++
 4 files changed, 180 insertions(+), 76 deletions(-)
---
diff --git a/src/application.js b/src/application.js
index 026772e..f4ffd2f 100644
--- a/src/application.js
+++ b/src/application.js
@@ -13,6 +13,7 @@ const MainWindow = imports.mainWindow;
 const PasteManager = imports.pasteManager;
 const Utils = imports.utils;
 const NetworksManager = imports.networksManager;
+const UserTracker = imports.userTracker;
 
 const MAX_RETRIES = 3;
 
@@ -48,6 +49,12 @@ const Application = new Lang.Class({
         this._accountsMonitor = AccountsMonitor.getDefault();
         this._networkMonitor = Gio.NetworkMonitor.get_default();
         this._networksManager = NetworksManager.getDefault();
+        /*created here as i couldn't make it work if it was created in the chatroomManager
+        (it didn't receive the room-added signal for the channels restored from the previous session)*/
+        this._globalUserTracker = new UserTracker.UserTracker(null);
+        this._globalUserTracker.connect('status-changed', Lang.bind(this, function(tracker, nick, status){
+            log("[Application] nick " + nick + " global status changed to " + status );
+        }));
 
         this._accountsMonitor.connect('account-removed', Lang.bind(this,
             function(am, account) {
diff --git a/src/chatView.js b/src/chatView.js
index b973702..e9b4555 100644
--- a/src/chatView.js
+++ b/src/chatView.js
@@ -14,6 +14,7 @@ const Mainloop = imports.mainloop;
 const PasteManager = imports.pasteManager;
 const Signals = imports.signals;
 const Utils = imports.utils;
+const UserTracker = imports.userTracker;
 
 const MAX_NICK_CHARS = 8;
 const IGNORE_STATUS_TIME = 5;
@@ -303,6 +304,9 @@ const ChatView = new Lang.Class({
         this._statusCount = { left: 0, joined: 0, total: 0 };
         this._logWalker = null;
 
+        this._userTracker = new UserTracker.UserTracker(this._room);
+        this._userTracker.connect('status-changed', Lang.bind(this, this._onNickStatusChanged));
+
         this._room.account.connect('notify::nickname', Lang.bind(this,
             function() {
                 this._updateMaxNickChars(this._room.account.nickname.length);
@@ -378,19 +382,6 @@ const ChatView = new Lang.Class({
         });
     },
 
-    _foreachNickTag: function(func) {
-        let tagTable = this._view.get_buffer().get_tag_table();
-        tagTable.foreach(function(tag) {
-            if (tag._contacts)
-                func(tag);
-        });
-    },
-
-    _resetNickTag: function(nickTag) {
-        nickTag._contacts = [];
-        this._updateTagStatus(nickTag);
-    },
-
     _onStyleUpdated: function() {
         let context = this.get_style_context();
         context.save();
@@ -442,8 +433,6 @@ const ChatView = new Lang.Class({
                 tag[prop] = tagProps[prop];
             }
         });
-
-        this._foreachNickTag(t => { this._updateTagStatus(t); });
     },
 
     vfunc_destroy: function() {
@@ -547,15 +536,6 @@ const ChatView = new Lang.Class({
 
         if (!this._channel)
             return;
-
-        if (this._room.type == Tp.HandleType.ROOM) {
-            let members = this._channel.group_dup_members_contacts();
-            for (let j = 0; j < members.length; j++)
-                this._trackContact(members[j]);
-        } else {
-                this._trackContact(this._channel.connection.self_contact);
-                this._trackContact(this._channel.target_contact);
-        }
     },
 
     get max_nick_chars() {
@@ -856,38 +836,13 @@ const ChatView = new Lang.Class({
         return NICKTAG_PREFIX + Polari.util_get_basenick(nick);
     },
 
-    _trackContact: function(contact) {
-        let nickTag = this._lookupTag(this._getNickTagName(contact.alias));
-        if (!nickTag)
-           return;
-
-        let alreadyTracked = nickTag._contacts.some(c => c.alias == contact.alias);
-
-        if (!alreadyTracked)
-            nickTag._contacts.push(contact);
-
-        this._updateTagStatus(nickTag);
-    },
+    _onNickStatusChanged: function(tracker, nickName, status) {
+        let nickTag = this._lookupTag(this._getNickTagName(nickName));
 
-    _untrackContact: function(contact) {
-        let nickTag = this._lookupTag(this._getNickTagName(contact.alias));
         if (!nickTag)
             return;
 
-        let indexToDelete = nickTag._contacts.map(c => c.alias).indexOf(contact.alias);
-
-        if (indexToDelete > -1) {
-            nickTag._contacts.splice(indexToDelete, 1);
-
-            this._updateTagStatus(nickTag);
-        }
-    },
-
-    _updateTagStatus: function(tag) {
-        if (tag._contacts.length == 0)
-            tag.foreground_rgba = this._inactiveNickColor;
-        else
-            tag.foreground_rgba = this._activeNickColor;
+        this._updateNickTag(nickTag, status);
     },
 
     _onChannelChanged: function() {
@@ -906,19 +861,6 @@ const ChatView = new Lang.Class({
                                  : this._room.account.nickname;
         this._updateMaxNickChars(nick.length);
 
-        if (this._channel) {
-            if (this._room.type == Tp.HandleType.ROOM) {
-                let members = this._channel.group_dup_members_contacts();
-                for (let j = 0; j < members.length; j++)
-                    this._trackContact(members[j]);
-            } else {
-                this._trackContact(this._channel.connection.self_contact);
-                this._trackContact(this._channel.target_contact);
-            }
-        } else {
-            this._foreachNickTag(t => { this._resetNickTag(t); });
-        }
-
         if (!this._channel)
             return;
 
@@ -943,8 +885,6 @@ const ChatView = new Lang.Class({
     _onMemberRenamed: function(room, oldMember, newMember) {
         let text = _("%s is now known as %s").format(oldMember.alias, newMember.alias);
         this._insertStatus(text, oldMember.alias, 'renamed');
-        this._untrackContact(oldMember);
-        this._trackContact(newMember);
     },
 
     _onMemberDisconnected: function(room, member, message) {
@@ -952,7 +892,6 @@ const ChatView = new Lang.Class({
         if (message)
             text += ' (%s)'.format(message);
         this._insertStatus(text, member.alias, 'left');
-        this._untrackContact(member);
     },
 
     _onMemberKicked: function(room, member, actor) {
@@ -961,7 +900,6 @@ const ChatView = new Lang.Class({
                                                          actor.alias)
                   : _("%s has been kicked").format(member.alias);
         this._insertStatus(message, member.alias, 'left');
-        this._untrackContact(member);
     },
 
     _onMemberBanned: function(room, member, actor) {
@@ -970,13 +908,11 @@ const ChatView = new Lang.Class({
                                                          actor.alias)
                   : _("%s has been banned").format(member.alias)
         this._insertStatus(message, member.alias, 'left');
-        this._untrackContact(member);
     },
 
     _onMemberJoined: function(room, member) {
         let text = _("%s joined").format(member.alias);
         this._insertStatus(text, member.alias, 'joined');
-        this._trackContact(member);
     },
 
     _onMemberLeft: function(room, member, message) {
@@ -986,7 +922,6 @@ const ChatView = new Lang.Class({
             text += ' (%s)'.format(message);
 
         this._insertStatus(text, member.alias, 'left');
-        this._untrackContact(member);
     },
 
     _onMessageReceived: function(channel, tpMessage) {
@@ -1211,7 +1146,6 @@ const ChatView = new Lang.Class({
 
         let iter = this._view.buffer.get_end_iter();
         this._insertMessage(iter, message, this._state);
-        this._trackContact(tpMessage.sender);
 
         if (shouldHighlight &&
             !(this._toplevelFocus && this._active)) {
@@ -1270,10 +1204,8 @@ const ChatView = new Lang.Class({
                 let nickTag = this._lookupTag(nickTagName);
 
                 if (!nickTag) {
-                    nickTag = new Gtk.TextTag({ name: nickTagName });
+                    nickTag = this._createNickTag(message.nick);
                     this._view.get_buffer().get_tag_table().add(nickTag);
-
-                    this._resetNickTag(nickTag);
                 }
                 tags.push(nickTag);
                 if (needsGap)
@@ -1314,6 +1246,22 @@ const ChatView = new Lang.Class({
                               this._view.buffer.create_mark(null, iter, true));
     },
 
+    _createNickTag: function(nickName) {
+        let nickTagName = this._getNickTagName(nickName);
+
+        let tag = new Gtk.TextTag({ name: nickTagName });
+        this._updateNickTag(tag, this._userTracker.getNickStatus(nickName));
+
+        return tag;
+    },
+
+    _updateNickTag: function(tag, status) {
+        if (status == Tp.ConnectionPresenceType.AVAILABLE)
+            tag.foreground_rgba = this._activeNickColor;
+        else
+            tag.foreground_rgba = this._inactiveNickColor;
+    },
+
     _createUrlTag: function(url) {
         if (url.indexOf(':') == -1)
             url = 'http://' + url;
diff --git a/src/org.gnome.Polari.src.gresource.xml b/src/org.gnome.Polari.src.gresource.xml
index 441772b..6e18e30 100644
--- a/src/org.gnome.Polari.src.gresource.xml
+++ b/src/org.gnome.Polari.src.gresource.xml
@@ -23,5 +23,6 @@
     <file>tabCompletion.js</file>
     <file>userList.js</file>
     <file>utils.js</file>
+    <file>userTracker.js</file>
   </gresource>
 </gresources>
diff --git a/src/userTracker.js b/src/userTracker.js
new file mode 100644
index 0000000..392e46b
--- /dev/null
+++ b/src/userTracker.js
@@ -0,0 +1,148 @@
+const Polari = imports.gi.Polari;
+const Lang = imports.lang;
+const Tp = imports.gi.TelepathyGLib;
+const Signals = imports.signals;
+const ChatroomManager = imports.chatroomManager;
+
+
+const UserTracker = new Lang.Class({
+    Name: 'UserTracker',
+
+    _init: function(room) {
+        this._referenceRoomSignals = [
+            { name: 'notify::channel',
+              handler: Lang.bind(this, this._onChannelChanged) },
+            { name: 'member-renamed',
+              handler: Lang.bind(this, this._onMemberRenamed) },
+            { name: 'member-disconnected',
+              handler: Lang.bind(this, this._onMemberDisconnected) },
+            { name: 'member-kicked',
+              handler: Lang.bind(this, this._onMemberKicked) },
+            { name: 'member-banned',
+              handler: Lang.bind(this, this._onMemberBanned) },
+            { name: 'member-joined',
+              handler: Lang.bind(this, this._onMemberJoined) },
+            { name: 'member-left',
+              handler: Lang.bind(this, this._onMemberLeft) }
+        ];
+
+        this._contactMapping = new Map();
+
+        if (!room) {
+            log("global user tracker created");
+            this._chatroomManager = ChatroomManager.getDefault();
+
+            this._chatroomManager.connect('room-added', Lang.bind(this, this._onRoomAdded));
+            this._chatroomManager.connect('room-removed', Lang.bind(this, this._onRoomRemoved));
+        } else {
+            this._room = room;
+
+            this._onRoomAdded(null, this._room);
+            this._onChannelChanged(this._room);
+        }
+    },
+
+    _onRoomAdded: function(roomManager , room) {
+        this._roomSignals = [];
+        this._referenceRoomSignals.forEach(Lang.bind(this, function(signal) {
+            this._roomSignals.push(room.connect(signal.name, signal.handler));
+        }));
+    },
+
+    _onRoomRemoved: function(roomManager, room) {
+        for (let i = 0; i < this._roomSignals.length; i++)
+            room.disconnect(this._roomSignals[i]);
+        this._roomSignals = [];
+    },
+
+    _onChannelChanged: function(emittingRoom) {
+        if (emittingRoom.channel) {
+            let members;
+            if (emittingRoom.type == Tp.HandleType.ROOM)
+                members = emittingRoom.channel.group_dup_members_contacts();
+            else
+                members = [emittingRoom.channel.connection.self_contact, 
emittingRoom.channel.target_contact];
+
+            members.forEach(m => {
+                m._room = emittingRoom;
+                this._trackMember(m);
+            });
+        } else {
+            for ([baseNick, basenickContacts] of this._contactMapping) {
+                basenickContacts.forEach(Lang.bind(this, function(member) {
+                    if (member._room == emittingRoom)
+                        this._untrackMember(member);
+                }));
+
+                this._contactMapping.delete(baseNick);
+            }
+        }
+    },
+
+    _onMemberRenamed: function(room, oldMember, newMember) {
+        oldMember._room = room;
+        newMember._room = room;
+        this._untrackMember(oldMember);
+        this._trackMember(newMember);
+    },
+
+    _onMemberDisconnected: function(room, member, message) {
+        member._room = room;
+        this._untrackMember(member);
+    },
+
+    _onMemberKicked: function(room, member, actor) {
+        member._room = room;
+        this._untrackMember(member);
+    },
+
+    _onMemberBanned: function(room, member, actor) {
+        member._room = room;
+        this._untrackMember(member);
+    },
+
+    _onMemberJoined: function(room, member) {
+        member._room = room;
+        this._trackMember(member);
+    },
+
+    _onMemberLeft: function(room, member, message) {
+        member._room = room;
+        this._untrackMember(member);
+    },
+
+    _trackMember: function(member) {
+        let baseNick = Polari.util_get_basenick(member.alias);
+
+        if (this._contactMapping.has(baseNick))
+            this._contactMapping.get(baseNick).push(member);
+        else
+            this._contactMapping.set(baseNick, [member]);
+
+        if (this._contactMapping.get(baseNick).length == 1)
+            this.emit('status-changed', member.alias, Tp.ConnectionPresenceType.AVAILABLE);
+    },
+
+    _untrackMember: function(member) {
+        let baseNick = Polari.util_get_basenick(member.alias);
+
+        let contacts = this._contactMapping.get(baseNick) || [];
+        let indexToDelete = contacts.map(c => c.alias).indexOf(member.alias);
+
+        if (indexToDelete > -1) {
+            contacts.splice(indexToDelete, 1);
+
+            if (contacts.length == 0)
+                this.emit('status-changed', member.alias, Tp.ConnectionPresenceType.OFFLINE);
+        }
+    },
+
+    getNickStatus: function(nickName) {
+        let baseNick = Polari.util_get_basenick(nickName);
+
+        let contacts = this._contactMapping.get(baseNick) || [];
+        return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
+                                    : Tp.ConnectionPresenceType.AVAILABLE;
+    },
+});
+Signals.addSignalMethods(UserTracker.prototype);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]