[polari/wip/raresv/userTracker] combined trackers, userTracker part 9



commit 186ff27b9de534800460eae7d4dd980c6045139a
Author: raresv <rares visalom gmail com>
Date:   Fri Jul 1 23:14:45 2016 +0300

    combined trackers, userTracker part 9

 src/chatView.js    |    2 +-
 src/userTracker.js |  193 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 192 insertions(+), 3 deletions(-)
---
diff --git a/src/chatView.js b/src/chatView.js
index ef42d00..dbebdf5 100644
--- a/src/chatView.js
+++ b/src/chatView.js
@@ -1204,7 +1204,7 @@ const ChatView = new Lang.Class({
         let nickTagName = this._getNickTagName(nickName);
 
         let tag = new Gtk.TextTag({ name: nickTagName });
-        this._updateNickTag(tag, this._userTracker.getNickStatus(nickName));
+        this._updateNickTag(tag, this._userTracker.getNickGlobalStatus(nickName));
 
         return tag;
     },
diff --git a/src/userTracker.js b/src/userTracker.js
index 392e46b..cec3f87 100644
--- a/src/userTracker.js
+++ b/src/userTracker.js
@@ -4,8 +4,8 @@ const Tp = imports.gi.TelepathyGLib;
 const Signals = imports.signals;
 const ChatroomManager = imports.chatroomManager;
 
-
-const UserTracker = new Lang.Class({
+/*left the old tracker here in order to compare the versions*/
+/*const UserTracker = new Lang.Class({
     Name: 'UserTracker',
 
     _init: function(room) {
@@ -144,5 +144,194 @@ const UserTracker = new Lang.Class({
         return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
                                     : Tp.ConnectionPresenceType.AVAILABLE;
     },
+});*/
+
+const UserTracker = new Lang.Class({
+    Name: 'UserTracker',
+
+    _init: function() {
+        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._globalContactMapping = new Map();
+        this._roomMapping = new Map();
+
+        this._chatroomManager = ChatroomManager.getDefault();
+        this._chatroomManager.connect('room-added', Lang.bind(this, this._onRoomAdded));
+        this._chatroomManager.connect('room-removed', Lang.bind(this, this._onRoomRemoved));
+    },
+
+    _onRoomAdded: function(roomManager, room) {
+        this._connectRoomSignalsForRoom(room);
+    },
+
+    _onRoomRemoved: function(roomManager, room) {
+        this._disconnectRoomSignalsForRoom(room);
+    },
+
+    _connectRoomSignalsForRoom: function(room) {
+        if (!this._roomMapping.get(room))
+            this._roomMapping.set(room, {});
+
+        let roomData = this._roomMapping.get(room);
+
+        roomData._roomSignals = [];
+        this._referenceRoomSignals.forEach(Lang.bind(this, function(signal) {
+            roomData._roomSignals.push(room.connect(signal.name, signal.handler));
+        }));
+    },
+
+    _disconnectRoomSignalsForRoom: function(room) {
+        let roomData = this._roomMapping.get(room);
+
+        for (let i = 0; i < roomData._roomSignals.length; i++) {
+            room.disconnect(roomData._roomSignals[i]);
+        }
+        roomData._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];
+
+            /*if there is no map keeping track of the users in the emittingRoom
+            create it*/
+            if (!this._roomMapping.get(emittingRoom)._contactMapping)
+                this._roomMapping.get(emittingRoom)._contactMapping = new Map();
+
+            /*keep track of initial members in the emittingRoom, both locally and
+            globally*/
+            members.forEach(m => {
+                m._room = emittingRoom;
+                this._trackMember(this._roomMapping.get(emittingRoom)._contactMapping, m);
+                this._trackMember(this._globalContactMapping, m);
+            });
+        } else {
+            /*handle the absence of a channel for the global case*/
+            for ([baseNick, basenickContacts] of this._globalContactMapping) {
+                basenickContacts.forEach(Lang.bind(this, function(member) {
+                    if (member._room == emittingRoom)
+                        /*safe to delete while iterating?*/
+                        this._untrackMember(this._globalContactMapping, member);
+                }));
+
+                this._globalContactMapping.delete(baseNick);
+            }
+            /*handle the absence of a channel for the local case*/
+            for ([baseNick, basenickContacts] of this._roomMapping.get(emittingRoom)._contactMapping) {
+                basenickContacts.forEach(Lang.bind(this, function(member) {
+                    if (member._room == emittingRoom)
+                        /*safe to delete while iterating?*/
+                        this._untrackMember(this._roomMapping.get(emittingRoom)._contactMapping, member);
+                }));
+
+                this._roomMapping.get(emittingRoom)._contactMapping.delete(baseNick);
+            }
+        }
+    },
+
+    _onMemberRenamed: function(room, oldMember, newMember) {
+        oldMember._room = room;
+        newMember._room = room;
+
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, oldMember);
+        this._untrackMember(this._globalContactMapping, oldMember);
+        this._trackMember(this._roomMapping.get(room)._contactMapping, newMember);
+        this._trackMember(this._globalContactMapping, newMember);
+    },
+
+    _onMemberDisconnected: function(room, member, message) {
+        member._room = room;
+
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, member);
+        this._untrackMember(this._globalContactMapping, member);
+    },
+
+    _onMemberKicked: function(room, member, actor) {
+        member._room = room;
+
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, member);
+        this._untrackMember(this._globalContactMapping, member);
+    },
+
+    _onMemberBanned: function(room, member, actor) {
+        member._room = room;
+
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, member);
+        this._untrackMember(this._globalContactMapping, member);
+    },
+
+    _onMemberJoined: function(room, member) {
+        member._room = room;
+
+        this._trackMember(this._roomMapping.get(room)._contactMapping, member);
+        this._trackMember(this._globalContactMapping, member);
+    },
+
+    _onMemberLeft: function(room, member, message) {
+        member._room = room;
+
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, member);
+        this._untrackMember(this._globalContactMapping, member);
+    },
+
+    _trackMember: function(map, member) {
+        let baseNick = Polari.util_get_basenick(member.alias);
+
+        if (map.has(baseNick))
+            map.get(baseNick).push(member);
+        else
+            map.set(baseNick, [member]);
+
+        if (map.get(baseNick).length == 1)
+            if (map == this._globalContactMapping)
+                log("[Global UserTracker] User " + member.alias + " is now globally available");
+            else
+                log("[Local UserTracker] User " + member.alias + " is now available in room " + 
member._room.channelName);
+    },
+
+    _untrackMember: function(map, member) {
+        let baseNick = Polari.util_get_basenick(member.alias);
+
+        let contacts = map.get(baseNick) || [];
+        /*i really don;t like this search. maybe use a for loop?*/
+        let indexToDelete = contacts.map(c => c.alias + "|" + c._room.channelName).indexOf(member.alias + 
"|" + member._room.channelName);
+
+        if (indexToDelete > -1) {
+            contacts.splice(indexToDelete, 1);
+
+            if (contacts.length == 0)
+                if (map == this._globalContactMapping)
+                    log("[Global UserTracker] User " + member.alias + " is now globally offline");
+                else
+                    log("[Local UserTracker] User " + member.alias + " is now offline in room " + 
member._room.channelName);
+        }
+    },
+
+    getNickGlobalStatus: function(nickName) {
+        let baseNick = Polari.util_get_basenick(nickName);
+
+        let contacts = this._globalContactMapping.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]