[polari/wip/raresv/userTrackerAndPopoversRebase: 18/24] Revert "userTracker (used to save us from later conflicts): patch based on the userTracker patch tha



commit 36420c593e49d0c2a8164bac8a26386a7c13061b
Author: raresv <rares visalom gmail com>
Date:   Tue Aug 2 22:00:42 2016 +0300

    Revert "userTracker (used to save us from later conflicts):
    patch based on the userTracker patch that introduced the
    global tracking of nicks. this is more or less the *final*
    second patch for the userTracker."
    
    This reverts commit e5113550ba848a85b1c396ba0829764c348100f4.

 src/userTracker.js |  368 +++++++++++++++++++++++++++++++---------------------
 1 files changed, 221 insertions(+), 147 deletions(-)
---
diff --git a/src/userTracker.js b/src/userTracker.js
index a9d0db2..7e78bbd 100644
--- a/src/userTracker.js
+++ b/src/userTracker.js
@@ -3,9 +3,6 @@ const Lang = imports.lang;
 const Tp = imports.gi.TelepathyGLib;
 const Signals = imports.signals;
 const GObject = imports.gi.GObject;
-const Utils = imports.utils;
-const Gio = imports.gi.Gio;
-const GLib = imports.gi.GLib;
 
 const AccountsMonitor = imports.accountsMonitor;
 const ChatroomManager = imports.chatroomManager;
@@ -22,32 +19,38 @@ const UserStatusMonitor = new Lang.Class({
     Name: 'UserStatusMonitor',
 
     _init: function() {
-        this._userTrackers = new Map();
+        this._userTrackersMaping = new Map();
         this._accountsMonitor = AccountsMonitor.getDefault();
 
         this._accountsMonitor.connect('account-added', Lang.bind(this, this._onAccountAdded));
         this._accountsMonitor.connect('account-removed', Lang.bind(this, this._onAccountRemoved));
-
-        this._accountsMonitor.dupAccounts().forEach(a => { this._onAccountAdded(this._accountsMonitor, a); 
});
     },
 
     _onAccountAdded: function(accountsMonitor, account) {
-        if (this._userTrackers.has(account))
+        this._addUserTrackerForAccount(account);
+    },
+
+    _onAccountRemoved: function(accountsMonitor, account) {
+        this._removeUserTrackerForAccount(account);
+    },
+
+    _addUserTrackerForAccount: function(account) {
+        if (this._userTrackersMaping.has(account))
             return;
 
-        this._userTrackers.set(account, new UserTracker(account));
+        this._userTrackersMaping.set(account, new UserTracker(account));
     },
 
-    _onAccountRemoved: function(accountsMonitor, account) {
-        if (!this._userTrackers.has(account))
+    _removeUserTrackerForAccount: function(account) {
+        if (!this._userTrackersMaping.has(account))
             return;
 
-        this._userTrackers.delete(account);
+        this._userTrackersMaping.delete(account);
     },
 
     getUserTrackerForAccount: function(account) {
-        if (this._userTrackers.has(account))
-            return this._userTrackers.get(account);
+        if (this._userTrackersMaping.has(account))
+            return this._userTrackersMaping.get(account);
         return null;
     }
 });
@@ -62,200 +65,250 @@ const UserTracker = new Lang.Class({
             flags: GObject.SignalFlags.DETAILED,
             param_types: [GObject.TYPE_STRING, GObject.TYPE_INT]
         },
-        'contacts-changed': {
-            flags: GObject.SignalFlags.DETAILED,
-            param_types: [GObject.TYPE_STRING]
-        }
     },
 
     _init: function(account) {
         this.parent();
+        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._account = account;
 
-        this._baseNickContacts = new Map();
-        this._roomData = new Map();
+        this._globalContactMapping = new Map();
+        this._roomMapping = new Map();
         this._handlerCounter = 0;
 
+        this._userStatusMonitor = getUserStatusMonitor();
+
         this._chatroomManager = ChatroomManager.getDefault();
         this._chatroomManager.connect('room-added', Lang.bind(this, this._onRoomAdded));
         this._chatroomManager.connect('room-removed', Lang.bind(this, this._onRoomRemoved));
     },
 
-    _getRoomContacts: function(room) {
-        return this._roomData.get(room).contactMapping;
+    _onRoomAdded: function(roomManager, room) {
+        if (room.account == this._account)
+            this._connectRoomSignalsForRoom(room);
     },
 
-    _getRoomHandlers: function(room) {
-        return this._roomData.get(room).handlerMapping;
-    },
+    _onRoomRemoved: function(roomManager, room) {
+        if (room.account == this._account)
+            this._disconnectRoomSignalsForRoom(room);
 
-    _getRoomSignals: function(room) {
-        return this._roomData.get(room).roomSignals;
+        this._clearUsersFromRoom(this._globalContactMapping, room);
+        this._clearUsersFromRoom(this._roomMapping.get(room)._contactMapping, room);
     },
 
-    _onRoomAdded: function(roomManager, room) {
-        if (room.account != this._account)
-            return;
-
+    _connectRoomSignalsForRoom: function(room) {
         this._ensureRoomMappingForRoom(room);
 
-        let roomSignals = [
-            { 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._onMemberLeft) },
-            { name: 'member-kicked',
-              handler: Lang.bind(this, this._onMemberLeft) },
-            { name: 'member-banned',
-              handler: Lang.bind(this, this._onMemberLeft) },
-            { name: 'member-joined',
-              handler: Lang.bind(this, this._onMemberJoined) },
-            { name: 'member-left',
-              handler: Lang.bind(this, this._onMemberLeft) }
-        ];
+        let roomData = this._roomMapping.get(room);
 
-        let signalIds = this._getRoomSignals(room);
-        roomSignals.forEach(signal => {
-            signalIds.push(room.connect(signal.name, signal.handler));
-        });
+        roomData._roomSignals = [];
+        this._referenceRoomSignals.forEach(Lang.bind(this, function(signal) {
+            roomData._roomSignals.push(room.connect(signal.name, signal.handler));
+        }));
     },
 
-    _onRoomRemoved: function(roomManager, room) {
-        if (!this._roomData.has(room))
-            return;
+    _disconnectRoomSignalsForRoom: function(room) {
+        let roomData = this._roomMapping.get(room);
 
-        this._getRoomSignals(room).forEach(id => { room.disconnect(id); });
-        this._clearUsersFromRoom(room);
-        this._roomData.delete(room);
+        for (let i = 0; i < roomData._roomSignals.length; i++) {
+            room.disconnect(roomData._roomSignals[i]);
+        }
+        roomData._roomSignals = [];
     },
 
-    _onChannelChanged: function(room) {
-        if (!room.channel) {
-            this._clearUsersFromRoom(room);
-            return;
+    _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];
+
+            /*is this needed here?*/
+            this._ensureRoomMappingForRoom(emittingRoom);
+
+            /*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();
+
+            /*if there is no map keeping track of the local status change handlers*/
+            this._ensureHandlerMappingForRoom(emittingRoom);
+
+            /*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, emittingRoom);
+                this._trackMember(this._globalContactMapping, m, emittingRoom);
+            });
+        } else {
+            /*handle the absence of a channel for the global case*/
+            this._clearUsersFromRoom(this._globalContactMapping, emittingRoom);
+            /*handle the absence of a channel for the local case*/
+            this._clearUsersFromRoom(this._roomMapping.get(emittingRoom)._contactMapping, emittingRoom);
+
+            /*since we have no channel, all users must be locally marked offline. so call the callbacks*/
+            for ([handlerID, handlerInfo] of this._roomMapping.get(emittingRoom)._handlerMapping) {
+                if (handlerInfo.nickName)
+                    handlerInfo.handler(handlerInfo.nickName, Tp.ConnectionPresenceType.OFFLINE);
+            }
         }
+    },
 
-        let members;
-        if (room.type == Tp.HandleType.ROOM)
-            members = room.channel.group_dup_members_contacts();
-        else
-            members = [room.channel.connection.self_contact, room.channel.target_contact];
+    _clearUsersFromRoom: function(mapping, room) {
+        for ([baseNick, basenickContacts] of mapping) {
+            basenickContacts.forEach(Lang.bind(this, function(member) {
+                if (member._room == room)
+                    /*safe to delete while iterating?*/
+                    this._untrackMember(mapping, member, room);
+            }));
 
-        /*keep track of initial members in the room, both locally and
-        globally*/
-        members.forEach(m => { this._trackMember(m, room); });
+            mapping.delete(baseNick);
+        }
     },
 
-    _clearUsersFromRoom: function(room) {
-        let map = this._getRoomContacts(room);
-        for ([baseNick, contacts] of map)
-            contacts.slice().forEach((m) => { this._untrackMember(m, room); });
+    _ensureRoomMappingForRoom: function(room) {
+        if (!this._roomMapping.has(room))
+            this._roomMapping.set(room, {});
     },
 
-    _ensureRoomMappingForRoom: function(room) {
-        if (this._roomData.has(room))
-            return;
-        this._roomData.set(room, { contactMapping: new Map(),
-                                   handlerMapping: new Map(),
-                                   roomSignals: [] });
+    _ensureHandlerMappingForRoom: function(room) {
+        /*if there is no map keeping track of the local status change handlers*/
+        if (!this._roomMapping.get(room)._handlerMapping) {
+            this._roomMapping.get(room)._handlerMapping = new Map();
+            this._handlerCounter = 0;
+        }
     },
 
     _onMemberRenamed: function(room, oldMember, newMember) {
-        this._untrackMember(oldMember, room);
-        this._trackMember(newMember, room);
-    },
+        oldMember._room = room;
+        newMember._room = room;
 
-    _onMemberJoined: function(room, member) {
-        this._trackMember(member, room);
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, oldMember, room);
+        this._untrackMember(this._globalContactMapping, oldMember, room);
+        this._trackMember(this._roomMapping.get(room)._contactMapping, newMember, room);
+        this._trackMember(this._globalContactMapping, newMember, room);
     },
 
-    _onMemberLeft: function(room, member) {
-        this._untrackMember(member, room);
-    },
+    _onMemberDisconnected: function(room, member, message) {
+        member._room = room;
 
-    _runHandlers: function(room, member, status) {
-        let baseNick = Polari.util_get_basenick(member.alias);
-        let roomHandlers = this._getRoomHandlers(room);
-        for ([id, info] of roomHandlers)
-            if (!info.nickName || info.nickName == baseNick)
-                info.handler(baseNick, status);
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, member, room);
+        this._untrackMember(this._globalContactMapping, member, room);
     },
 
-    _pushMember: function(map, baseNick, member) {
-        if (!map.has(baseNick))
-            map.set(baseNick, []);
-        let contacts = map.get(baseNick);
-        return contacts.push(member);
+    _onMemberKicked: function(room, member, actor) {
+        member._room = room;
+
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, member, room);
+        this._untrackMember(this._globalContactMapping, member, room);
     },
 
-    _trackMember: function(member, room) {
-        let baseNick = Polari.util_get_basenick(member.alias);
-        let status = Tp.ConnectionPresenceType.AVAILABLE;
+    _onMemberBanned: function(room, member, actor) {
+        member._room = room;
 
-        let map = this._baseNickContacts;
-        if (this._pushMember(map, baseNick, member) == 1)
-            this.emit("status-changed::" + baseNick, baseNick, status);
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, member, room);
+        this._untrackMember(this._globalContactMapping, member, room);
+    },
 
-        let roomMap = this._getRoomContacts(room);
-        if (this._pushMember(roomMap, baseNick, member) == 1)
-            this._runHandlers(room, member, status);
+    _onMemberJoined: function(room, member) {
+        member._room = room;
 
-        this.emit("contacts-changed::" + baseNick, member.alias);
+        this._trackMember(this._roomMapping.get(room)._contactMapping, member, room);
+        this._trackMember(this._globalContactMapping, member, room);
     },
 
-    _popMember: function(map, baseNick, member) {
-        let contacts = map.get(baseNick) || [];
-        let index = contacts.map(c => c.alias).indexOf(member.alias);
-        if (index < 0)
-            return [false, contacts.length];
-        contacts.splice(index, 1);
-        return [true, contacts.length];
+    _onMemberLeft: function(room, member, message) {
+        member._room = room;
+
+        this._untrackMember(this._roomMapping.get(room)._contactMapping, member, room);
+        this._untrackMember(this._globalContactMapping, member, room);
     },
 
-    _untrackMember: function(member, room) {
+    _trackMember: function(map, member, room) {
         let baseNick = Polari.util_get_basenick(member.alias);
-        let status = Tp.ConnectionPresenceType.OFFLINE;
-
-        let map = this._baseNickContacts;
-        let [found, nContacts] = this._popMember(map, baseNick, member);
-        if (found) {
-            if (nContacts == 0)
-                this.emit("status-changed::" + baseNick, member.alias, status);
-            this.emit("contacts-changed::" + baseNick, member.alias);
-        }
 
-        let roomMap = this._getRoomContacts(room);
-        [found, nContacts] = this._popMember(roomMap, baseNick, member);
-        if (found && nContacts == 0)
-            this._runHandlers(room, member, status);
+        if (map.has(baseNick))
+            map.get(baseNick).push(member);
+        else
+            map.set(baseNick, [member]);
+
+        //was on HEAD
+        /*if (this._contactMapping.get(baseNick).length == 1)
+            this.emit("status-changed::"+baseNick, member.alias, Tp.ConnectionPresenceType.AVAILABLE);*/
+        if (map == this._globalContactMapping)log("length: " + 
this._globalContactMapping.get(baseNick).length)
+
+        if (map.get(baseNick).length == 1)
+            if (map == this._globalContactMapping) {
+                this.emit("global-status-changed::" + member.alias, Tp.ConnectionPresenceType.AVAILABLE);
+                log("[global status] user " + member.alias + " is globally online");
+            }
+            else
+                //log("[Local UserTracker] User " + member.alias + " is now available in room " + 
member._room.channelName + " on " + this._account.get_display_name());
+                for ([handlerID, handlerInfo] of this._roomMapping.get(room)._handlerMapping)
+                    if (handlerInfo.nickName == member.alias)
+                        handlerInfo.handler(handlerInfo.nickName, Tp.ConnectionPresenceType.AVAILABLE);
+                    else if (!handlerInfo.nickName)
+                        handlerInfo.handler(member.alias, Tp.ConnectionPresenceType.AVAILABLE);
     },
 
-    getNickStatus: function(nickName) {
-        let baseNick = Polari.util_get_basenick(nickName);
+    _untrackMember: function(map, member, room) {
+        let baseNick = Polari.util_get_basenick(member.alias);
 
-        let contacts = this._baseNickContacts.get(baseNick) || [];
-        return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
-                                    : Tp.ConnectionPresenceType.AVAILABLE;
+        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) {
+            let removedMember = contacts.splice(indexToDelete, 1)[0];
+
+            if (contacts.length == 0)
+                //was on HEAD
+                /*this.emit("status-changed::"+baseNick, member.alias, Tp.ConnectionPresenceType.OFFLINE);*/
+                if (map == this._globalContactMapping) {
+                    this.emit("global-status-changed::" + member.alias, Tp.ConnectionPresenceType.OFFLINE);
+                    log("[global status] user " + member.alias + " is globally offline");
+                }
+                else
+                    //log("[Local UserTracker] User " + member.alias + " is now offline in room " + 
member._room.channelName + " on " + this._account.get_display_name());
+                    for ([handlerID, handlerInfo] of this._roomMapping.get(room)._handlerMapping)
+                        if (handlerInfo.nickName == member.alias)
+                            handlerInfo.handler(handlerInfo.nickName, Tp.ConnectionPresenceType.OFFLINE);
+                        else if (!handlerInfo.nickName)
+                            handlerInfo.handler(member.alias, Tp.ConnectionPresenceType.OFFLINE);
+        }
     },
 
-    getNickRoomStatus: function(nickName, room) {
+    getNickStatus: function(nickName) {
         let baseNick = Polari.util_get_basenick(nickName);
 
-        this._ensureRoomMappingForRoom(room);
-
-        let contacts = this._getRoomContacts(room).get(baseNick) || [];
+        let contacts = this._globalContactMapping.get(baseNick) || [];
         return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
                                     : Tp.ConnectionPresenceType.AVAILABLE;
     },
 
-    lookupContact: function(nickName) {
+    getBestMatchingContact: function(nickName) {
         let baseNick = Polari.util_get_basenick(nickName);
+        let contacts = this._contactMapping.get(baseNick) || [];
 
-        let contacts = this._baseNickContacts.get(baseNick) || [];
-
+        /*even possible?*/
         if (contacts.length == 0)
             return null;
 
@@ -266,20 +319,41 @@ const UserTracker = new Lang.Class({
         return contacts[0];
     },
 
-    watchRoomStatus: function(room, baseNick, callback) {
+    getNickRoomStatus: function(nickName, room) {
+        let baseNick = Polari.util_get_basenick(nickName);
+
+        let contacts = this._roomMapping.get(room)._contactMapping.get(baseNick) || [];
+        return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
+                                    : Tp.ConnectionPresenceType.AVAILABLE;
+    },
+
+    watchUser: function(room, nick, callback) {
         this._ensureRoomMappingForRoom(room);
+        this._ensureHandlerMappingForRoom(room);
 
-        this._getRoomHandlers(room).set(++this._handlerCounter, {
-            nickName: baseNick,
+        this._roomMapping.get(room)._handlerMapping.set(this._handlerCounter, {
+            nickName: nick,
             handler: callback
         });
 
-        return this._handlerCounter;
+        this._handlerCounter++;
+
+        return this._handlerCounter - 1;
     },
 
-    unwatchRoomStatus: function(room, handlerID) {
-        if (!this._roomData.has(room))
+    unwatchUser: function(room, nick, handlerID) {
+        /*it wouldn't make sense to call _ensure() here, right?*/
+
+        /*rewrite into a single conditional?*/
+        if (!this._roomMapping)
             return;
-        this._getRoomHandlers(room).delete(handlerID);
+
+        if (!this._roomMapping.has(room))
+            return;
+
+        if (!this._roomMapping.get(room)._handlerMapping)
+            return;
+
+        this._roomMapping.get(room)._handlerMapping.delete(handlerID);
     }
 });


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