[polari/wip/raresv/userTrackerAndPopoversRebase: 17/24] userTracker: patch based on the userTracker patch that introduced the global tracking of nicks. this
- From: Rares Visalom <raresvisalom src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [polari/wip/raresv/userTrackerAndPopoversRebase: 17/24] userTracker: patch based on the userTracker patch that introduced the global tracking of nicks. this
- Date: Fri, 5 Aug 2016 23:41:37 +0000 (UTC)
commit 39bb464b75a544abaa74603670e62b7140c56f7b
Author: raresv <rares visalom gmail com>
Date: Thu Aug 4 14:44:59 2016 +0300
userTracker: 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.
userTracker: add the UserStatusMonitor class in order to handle all the trackers and fix conflicts in the
UserTracker class.
src/userTracker.js | 289 ++++++++++++++++++++++++++++++++++++----------------
1 files changed, 200 insertions(+), 89 deletions(-)
---
diff --git a/src/userTracker.js b/src/userTracker.js
index d9cac5b..a9d0db2 100644
--- a/src/userTracker.js
+++ b/src/userTracker.js
@@ -3,9 +3,55 @@ 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;
+let _singleton = null;
+
+function getUserStatusMonitor() {
+ if (_singleton == null)
+ _singleton = new UserStatusMonitor();
+ return _singleton;
+}
+
+const UserStatusMonitor = new Lang.Class({
+ Name: 'UserStatusMonitor',
+
+ _init: function() {
+ this._userTrackers = 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))
+ return;
+
+ this._userTrackers.set(account, new UserTracker(account));
+ },
+
+ _onAccountRemoved: function(accountsMonitor, account) {
+ if (!this._userTrackers.has(account))
+ return;
+
+ this._userTrackers.delete(account);
+ },
+
+ getUserTrackerForAccount: function(account) {
+ if (this._userTrackers.has(account))
+ return this._userTrackers.get(account);
+ return null;
+ }
+});
+
const UserTracker = new Lang.Class({
Name: 'UserTracker',
@@ -16,152 +62,200 @@ 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(room) {
+ _init: function(account) {
this.parent();
- this._referenceRoomSignals = [
+ this._account = account;
+
+ this._baseNickContacts = new Map();
+ this._roomData = new Map();
+ this._handlerCounter = 0;
+
+ 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;
+ },
+
+ _getRoomHandlers: function(room) {
+ return this._roomData.get(room).handlerMapping;
+ },
+
+ _getRoomSignals: function(room) {
+ return this._roomData.get(room).roomSignals;
+ },
+
+ _onRoomAdded: function(roomManager, room) {
+ if (room.account != this._account)
+ return;
+
+ 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._onMemberDisconnected) },
+ handler: Lang.bind(this, this._onMemberLeft) },
{ name: 'member-kicked',
- handler: Lang.bind(this, this._onMemberKicked) },
+ handler: Lang.bind(this, this._onMemberLeft) },
{ name: 'member-banned',
- handler: Lang.bind(this, this._onMemberBanned) },
+ handler: Lang.bind(this, this._onMemberLeft) },
{ name: 'member-joined',
handler: Lang.bind(this, this._onMemberJoined) },
{ name: 'member-left',
handler: Lang.bind(this, this._onMemberLeft) }
];
- this._contactMapping = new Map();
+ let signalIds = this._getRoomSignals(room);
+ roomSignals.forEach(signal => {
+ signalIds.push(room.connect(signal.name, signal.handler));
+ });
+ },
- if (!room) {
- log("global user tracker created");
- this._chatroomManager = ChatroomManager.getDefault();
+ _onRoomRemoved: function(roomManager, room) {
+ if (!this._roomData.has(room))
+ return;
- 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._getRoomSignals(room).forEach(id => { room.disconnect(id); });
+ this._clearUsersFromRoom(room);
+ this._roomData.delete(room);
+ },
- this._onRoomAdded(null, this._room);
- this._onChannelChanged(this._room);
+ _onChannelChanged: function(room) {
+ if (!room.channel) {
+ this._clearUsersFromRoom(room);
+ return;
}
- },
- _onRoomAdded: function(roomManager , room) {
- this._roomSignals = [];
- this._referenceRoomSignals.forEach(Lang.bind(this, function(signal) {
- this._roomSignals.push(room.connect(signal.name, signal.handler));
- }));
+ 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];
+
+ /*keep track of initial members in the room, both locally and
+ globally*/
+ members.forEach(m => { this._trackMember(m, room); });
},
- _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);
- }
- }
+ _clearUsersFromRoom: function(room) {
+ let map = this._getRoomContacts(room);
+ for ([baseNick, contacts] of map)
+ contacts.slice().forEach((m) => { this._untrackMember(m, room); });
},
- _onMemberRenamed: function(room, oldMember, newMember) {
- oldMember._room = room;
- newMember._room = room;
- this._untrackMember(oldMember);
- this._trackMember(newMember);
+ _ensureRoomMappingForRoom: function(room) {
+ if (this._roomData.has(room))
+ return;
+ this._roomData.set(room, { contactMapping: new Map(),
+ handlerMapping: new Map(),
+ roomSignals: [] });
},
- _onMemberDisconnected: function(room, member, message) {
- member._room = room;
- this._untrackMember(member);
+ _onMemberRenamed: function(room, oldMember, newMember) {
+ this._untrackMember(oldMember, room);
+ this._trackMember(newMember, room);
},
- _onMemberKicked: function(room, member, actor) {
- member._room = room;
- this._untrackMember(member);
+ _onMemberJoined: function(room, member) {
+ this._trackMember(member, room);
},
- _onMemberBanned: function(room, member, actor) {
- member._room = room;
- this._untrackMember(member);
+ _onMemberLeft: function(room, member) {
+ this._untrackMember(member, room);
},
- _onMemberJoined: function(room, member) {
- member._room = room;
- this._trackMember(member);
+ _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);
},
- _onMemberLeft: function(room, member, message) {
- member._room = room;
- this._untrackMember(member);
+ _pushMember: function(map, baseNick, member) {
+ if (!map.has(baseNick))
+ map.set(baseNick, []);
+ let contacts = map.get(baseNick);
+ return contacts.push(member);
},
- _trackMember: function(member) {
+ _trackMember: function(member, room) {
let baseNick = Polari.util_get_basenick(member.alias);
+ let status = Tp.ConnectionPresenceType.AVAILABLE;
- if (this._contactMapping.has(baseNick))
- this._contactMapping.get(baseNick).push(member);
- else
- this._contactMapping.set(baseNick, [member]);
+ let map = this._baseNickContacts;
+ if (this._pushMember(map, baseNick, member) == 1)
+ this.emit("status-changed::" + baseNick, baseNick, status);
- if (this._contactMapping.get(baseNick).length == 1)
- this.emit("status-changed::"+baseNick, member.alias, Tp.ConnectionPresenceType.AVAILABLE);
+ let roomMap = this._getRoomContacts(room);
+ if (this._pushMember(roomMap, baseNick, member) == 1)
+ this._runHandlers(room, member, status);
+
+ this.emit("contacts-changed::" + baseNick, member.alias);
+ },
+
+ _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];
},
- _untrackMember: function(member) {
+ _untrackMember: function(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 contacts = this._contactMapping.get(baseNick) || [];
- let indexToDelete = contacts.map(c => c.alias).indexOf(member.alias);
+ let roomMap = this._getRoomContacts(room);
+ [found, nContacts] = this._popMember(roomMap, baseNick, member);
+ if (found && nContacts == 0)
+ this._runHandlers(room, member, status);
+ },
- if (indexToDelete > -1) {
- contacts.splice(indexToDelete, 1);
+ getNickStatus: function(nickName) {
+ let baseNick = Polari.util_get_basenick(nickName);
- if (contacts.length == 0)
- this.emit("status-changed::"+baseNick, member.alias, Tp.ConnectionPresenceType.OFFLINE);
- }
+ let contacts = this._baseNickContacts.get(baseNick) || [];
+ return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
+ : Tp.ConnectionPresenceType.AVAILABLE;
},
- getNickStatus: function(nickName) {
+ getNickRoomStatus: function(nickName, room) {
let baseNick = Polari.util_get_basenick(nickName);
- let contacts = this._contactMapping.get(baseNick) || [];
+ this._ensureRoomMappingForRoom(room);
+
+ let contacts = this._getRoomContacts(room).get(baseNick) || [];
return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
: Tp.ConnectionPresenceType.AVAILABLE;
},
- getBestMatchingContact: function(nickName) {
+ lookupContact: function(nickName) {
let baseNick = Polari.util_get_basenick(nickName);
- let contacts = this._contactMapping.get(baseNick) || [];
- /*even possible?*/
+ let contacts = this._baseNickContacts.get(baseNick) || [];
+
if (contacts.length == 0)
return null;
@@ -170,5 +264,22 @@ const UserTracker = new Lang.Class({
return contacts[i];
return contacts[0];
+ },
+
+ watchRoomStatus: function(room, baseNick, callback) {
+ this._ensureRoomMappingForRoom(room);
+
+ this._getRoomHandlers(room).set(++this._handlerCounter, {
+ nickName: baseNick,
+ handler: callback
+ });
+
+ return this._handlerCounter;
+ },
+
+ unwatchRoomStatus: function(room, handlerID) {
+ if (!this._roomData.has(room))
+ return;
+ this._getRoomHandlers(room).delete(handlerID);
}
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]