[polari/wip/raresv/userTrackerAndPopoversRebase: 20/24] userTracker: move notification logic from chatroomManager into userTracker.
- From: Rares Visalom <raresvisalom src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [polari/wip/raresv/userTrackerAndPopoversRebase: 20/24] userTracker: move notification logic from chatroomManager into userTracker.
- Date: Fri, 5 Aug 2016 23:41:52 +0000 (UTC)
commit 131f3371e3bfe526bfd56df7fb54e9e42dce57b3
Author: raresv <rares visalom gmail com>
Date: Fri Aug 5 17:01:24 2016 +0300
userTracker: move notification logic from chatroomManager into userTracker.
userTracker: minor cleanup.
userTracker: split out the function that ensures the
fact that there is a contact mapping for the specified
room and used this fufuncton in
UserTracker.getBestMatchContactInRoom(). The reason for
this is that any popover opened until polari is connected
will result in an error (because the mapping was not
ensured before).
userTracker: add new contacts-changed::basenick detailed signal and emit it whenever the contacts change
for a basenick. This is used to update the user in the UserDetails class. Rename getBestMatchingContactInRoom
to lookupContact.
userTracker: Add notifications-emitted signal (already removed in this patch).
userTracker: add getNotifyActionName() method.
userTracker: remove the notification-emitted signal, update the state of the notify action, update its
enabled property and fix unwatchUser() method params.
userTracker: replace old notification logic with GActions. Also fix a bug with the
contacts-changed::basenick signal.
userTracker: remove unnneded comment.
userTracker: use format strings for notifications in
order to be able to translate the text.
userTracker: Base watchNick() on baseNick
It doesn't really make sense to call watchNick() for a particular
nickname rather than a basenick - the callback would only be called
if the first contact that appears online matches the parameter.
Rather than expecting callers to remember to call the method for
a basenick, handle that ourselves.
userTracker: Split out some code
userTracker: Split out another helper
userTracker: Clean up _trackMember()
It currently takes a map parameter which is set to either the global
or per-room mapping. But then it's always called in pairs for either
map, and behaves differently based on which map it was called with.
Just remove the map parameter and handle both maps internally.
userTracker: Minor cleanup
A contact is unique within a room, so if we remove a contact from
a room mapping, we can just search by alias and don't need the
room name.
The same doesn't apply when we remove a contact from the global
contacts list, where the same contact can be added for multiple
rooms. But then we only really care about the number of contacts
for a particular baseNick, so it doesn't matter if we just remove
the first match ...
userTracker: Give _clearUsersFromRoom() the _trackMember() treatment
userTracker: Clean up _untrackMember as well
userTracker: more cleanups
userTracker: Cut-down on signals handlers
We don't care about whether a user left or was kicked/banned - just
use the same handler for all those signals.
userTracker: Don't reset handlerCounter when ensuring handlerMapping
userTracker: Simplify some more
userTracker: Don't run handlers twice on disconnect
_untrackMember() already calls the handlers for us, no need for a repeat
run ...
userTracker: Remove unnecessary method split
userTracker: Be a bit more concise
Variables don't exist in a vacuum, we have context - if a method is
called getNotifyActionName(), it's clear enough that 'name' and 'action'
don't refer to a frobnicate action ...
userTracker: Add some comments
userTracker: minor fixes.
userTracker: rename _userTrackerMapping to _userTrackers.
userTracker: send nickname along with the contacts-changed signal.
userTracker: store room signals in a local variable, not in a class property.
userTracker: rename the _globalContactsMapping Map to _baseNickContacts.
userTracker: rename emittingRoom to room.
userTracker: send nickname along with the contacts-changed signal.
userTracker: store room signals in a local variable, not in a class property.
userTracker: rename the _globalContactsMapping Map to _baseNickContacts.
userTracker: rename emittingRoom to room.
userTracker: clean _onChannelChanged() by saving one level of indentation.
userTracker: move getNickRoomStatus() method near the getNickStatus() method.
userTracker: rename (un)watchUser() to (un)watchRoomStatus().
userTracker: rewrite the way the _handlerCounter is user. This makes it more readable
userTracker: rename emitWatchedUserNotification() to _emitNotification().
userTracker: getNotifyActionName() now returns the full name of the action and the track/untrack methods
are cleaner.
userTracker: fix consistency issues regarding the use of
basenick instead of member.alias (aka nickname).
userTracker: use the enabled property of the GAction that's used for notifications. This fixes the
notifyButton visibility bug. The notifyButton would remain visible even when the user was online.
userTracker: squashed commit of multiple userTracker
commits.
userTracker: Fix exceptions when leaving room
When we only guard signal disconnections with the test for the right
account, we end up trying to clear out room data from accounts that
are not tracking that room ...
userTracker: Don't clear out all room data on disconnect
Disconnecting means tracked users for that room are no longer valid
and need to be cleared out, but both watch handlers and room signal
IDs are still valid and we need to keep them.
userTracker: Fix untracking members on disconnect
Array.forEach() doesn't handle array changes while running the loop,
so replace it with a while loop that can deal with the changing
array size.
userTracker: Don't split out disconnectSignals() method
It can be replaced by a one-liner in the only place it is used ...
userTracker: Same for deleteRoomData ...
userTracker: Minor cleanup
When a room is removed, rather than duplicating the condition for
whether the room is tracked, we can just check whether we have
room data for it - everything the function does will be useless
anyway if we don't have any data to operate on ...
userTracker: replace while loop with forEach
userTracker: Remove connectRoomSignals()
Splitting out the code doesn't add any clarity over just setting
up signals in onRoomAdded() ...
userTracker: Remove some roomData helpers
getRoomContacts(), getRoomHandlers() and getRoomSignals() hide the
nested maps in roomData, which helps making the code more readable.
However wrapping the Map() API for roomData itself only hides that
roomData is a map, which doesn't seem useful.
userTracker: Remove unneeded call to ensureRoomMapping()
_onChannelChanged() is only run when we connected to the 'notify::channel'
signal - we store the handler ID in the roomData, so the data must exist
when the handler is connected.
userTracker: Don't prefix roomData properties
this._roomData.get(room)._contactMapping looks "wrong", namely like
accessing something else's private property. Prefixing roomData
itself already makes it clear that other module's don't have any
business in poking around the property, so we don't need to prefix
the individual properties anyway ...
userTracker: renamed _emitNotification() to _notifyNickAvailable() and swapped its parmas
userTracker: renamed _getNotifyActionName() to _getNotifyActionNameInternal()
userTracker: rename _roomMapping Map to _roomData and provide some helper methods to access the property.
userTracker: use the notify action name as an id for the notification.
src/userTracker.js | 426 +++++++++++++++++++++++++--------------------------
1 files changed, 209 insertions(+), 217 deletions(-)
---
diff --git a/src/userTracker.js b/src/userTracker.js
index 7e78bbd..5f53f2e 100644
--- a/src/userTracker.js
+++ b/src/userTracker.js
@@ -3,6 +3,9 @@ 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;
@@ -19,7 +22,7 @@ const UserStatusMonitor = new Lang.Class({
Name: 'UserStatusMonitor',
_init: function() {
- this._userTrackersMaping = new Map();
+ this._userTrackers = new Map();
this._accountsMonitor = AccountsMonitor.getDefault();
this._accountsMonitor.connect('account-added', Lang.bind(this, this._onAccountAdded));
@@ -27,30 +30,22 @@ const UserStatusMonitor = new Lang.Class({
},
_onAccountAdded: function(accountsMonitor, account) {
- this._addUserTrackerForAccount(account);
- },
-
- _onAccountRemoved: function(accountsMonitor, account) {
- this._removeUserTrackerForAccount(account);
- },
-
- _addUserTrackerForAccount: function(account) {
- if (this._userTrackersMaping.has(account))
+ if (this._userTrackers.has(account))
return;
- this._userTrackersMaping.set(account, new UserTracker(account));
+ this._userTrackers.set(account, new UserTracker(account));
},
- _removeUserTrackerForAccount: function(account) {
- if (!this._userTrackersMaping.has(account))
+ _onAccountRemoved: function(accountsMonitor, account) {
+ if (!this._userTrackers.has(account))
return;
- this._userTrackersMaping.delete(account);
+ this._userTrackers.delete(account);
},
getUserTrackerForAccount: function(account) {
- if (this._userTrackersMaping.has(account))
- return this._userTrackersMaping.get(account);
+ if (this._userTrackers.has(account))
+ return this._userTrackers.get(account);
return null;
}
});
@@ -65,250 +60,209 @@ 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._globalContactMapping = new Map();
- this._roomMapping = new Map();
+ this._baseNickContacts = new Map();
+ this._roomData = new Map();
this._handlerCounter = 0;
-
- this._userStatusMonitor = getUserStatusMonitor();
+ this._app = Gio.Application.get_default();
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) {
- if (room.account == this._account)
- this._connectRoomSignalsForRoom(room);
+ _getRoomContacts: function(room) {
+ return this._roomData.get(room).contactMapping;
},
- _onRoomRemoved: function(roomManager, room) {
- if (room.account == this._account)
- this._disconnectRoomSignalsForRoom(room);
+ _getRoomHandlers: function(room) {
+ return this._roomData.get(room).handlerMapping;
+ },
- this._clearUsersFromRoom(this._globalContactMapping, room);
- this._clearUsersFromRoom(this._roomMapping.get(room)._contactMapping, room);
+ _getRoomSignals: function(room) {
+ return this._roomData.get(room).roomSignals;
},
- _connectRoomSignalsForRoom: function(room) {
+ _onRoomAdded: function(roomManager, room) {
+ if (room.account != this._account)
+ return;
+
this._ensureRoomMappingForRoom(room);
- let roomData = this._roomMapping.get(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) }
+ ];
- roomData._roomSignals = [];
- this._referenceRoomSignals.forEach(Lang.bind(this, function(signal) {
- roomData._roomSignals.push(room.connect(signal.name, signal.handler));
- }));
+ let signalIds = this._getRoomSignals(room);
+ roomSignals.forEach(signal => {
+ signalIds.push(room.connect(signal.name, signal.handler));
+ });
},
- _disconnectRoomSignalsForRoom: function(room) {
- let roomData = this._roomMapping.get(room);
+ _onRoomRemoved: function(roomManager, room) {
+ if (!this._roomData.has(room))
+ return;
- for (let i = 0; i < roomData._roomSignals.length; i++) {
- room.disconnect(roomData._roomSignals[i]);
- }
- roomData._roomSignals = [];
+ this._getRoomSignals(room).forEach(id => { room.disconnect(id); });
+ this._clearUsersFromRoom(room);
+ this._roomData.delete(room);
},
- _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);
- }
+ _onChannelChanged: function(room) {
+ if (!room.channel) {
+ this._clearUsersFromRoom(room);
+ return;
}
- },
- _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);
- }));
+ 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];
- mapping.delete(baseNick);
- }
+ /*keep track of initial members in the room, both locally and
+ globally*/
+ members.forEach(m => { this._trackMember(m, room); });
},
- _ensureRoomMappingForRoom: function(room) {
- if (!this._roomMapping.has(room))
- this._roomMapping.set(room, {});
+ _clearUsersFromRoom: function(room) {
+ let map = this._getRoomContacts(room);
+ for ([baseNick, contacts] of map)
+ contacts.slice().forEach((m) => { this._untrackMember(m, room); });
},
- _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;
- }
+ _ensureRoomMappingForRoom: function(room) {
+ if (this._roomData.has(room))
+ return;
+ this._roomData.set(room, { contactMapping: new Map(),
+ handlerMapping: new Map(),
+ roomSignals: [] });
},
_onMemberRenamed: function(room, oldMember, newMember) {
- oldMember._room = room;
- newMember._room = 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);
+ this._untrackMember(oldMember, room);
+ this._trackMember(newMember, room);
},
- _onMemberDisconnected: function(room, member, message) {
- member._room = room;
-
- this._untrackMember(this._roomMapping.get(room)._contactMapping, member, room);
- this._untrackMember(this._globalContactMapping, member, room);
+ _onMemberJoined: function(room, member) {
+ this._trackMember(member, room);
},
- _onMemberKicked: function(room, member, actor) {
- member._room = room;
-
- this._untrackMember(this._roomMapping.get(room)._contactMapping, member, room);
- this._untrackMember(this._globalContactMapping, member, room);
+ _onMemberLeft: function(room, member) {
+ this._untrackMember(member, room);
},
- _onMemberBanned: function(room, member, actor) {
- member._room = room;
-
- this._untrackMember(this._roomMapping.get(room)._contactMapping, member, room);
- this._untrackMember(this._globalContactMapping, member, 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);
},
- _onMemberJoined: function(room, member) {
- member._room = room;
-
- this._trackMember(this._roomMapping.get(room)._contactMapping, member, room);
- this._trackMember(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);
},
- _onMemberLeft: function(room, member, message) {
- member._room = room;
+ _trackMember: function(member, room) {
+ let baseNick = Polari.util_get_basenick(member.alias);
+ let status = Tp.ConnectionPresenceType.AVAILABLE;
- this._untrackMember(this._roomMapping.get(room)._contactMapping, member, room);
- this._untrackMember(this._globalContactMapping, member, room);
- },
+ let map = this._baseNickContacts;
+ if (this._pushMember(map, baseNick, member) == 1) {
+ this.emit("status-changed::" + baseNick, baseNick, status);
- _trackMember: function(map, member, room) {
- let baseNick = Polari.util_get_basenick(member.alias);
+ if (this._shouldNotifyNick(member.alias))
+ this._notifyNickAvailable(member, room);
- if (map.has(baseNick))
- map.get(baseNick).push(member);
- else
- map.set(baseNick, [member]);
+ this._setNotifyActionEnabled(member.alias, false);
+ }
- //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)
+ let roomMap = this._getRoomContacts(room);
+ if (this._pushMember(roomMap, baseNick, member) == 1)
+ this._runHandlers(room, member, status);
- 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);
+ this.emit("contacts-changed::" + baseNick, member.alias);
},
- _untrackMember: function(map, member, room) {
- let baseNick = Polari.util_get_basenick(member.alias);
-
+ _popMember: function(map, baseNick, member) {
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);
+ 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, 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._setNotifyActionEnabled(member.alias, true);
+ }
+ 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);
},
getNickStatus: function(nickName) {
let baseNick = Polari.util_get_basenick(nickName);
- let contacts = this._globalContactMapping.get(baseNick) || [];
+ let contacts = this._baseNickContacts.get(baseNick) || [];
+ return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
+ : Tp.ConnectionPresenceType.AVAILABLE;
+ },
+
+ getNickRoomStatus: function(nickName, room) {
+ let baseNick = Polari.util_get_basenick(nickName);
+
+ 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;
@@ -319,41 +273,79 @@ const UserTracker = new Lang.Class({
return contacts[0];
},
- 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) {
+ watchRoomStatus: function(room, baseNick, callback) {
this._ensureRoomMappingForRoom(room);
- this._ensureHandlerMappingForRoom(room);
- this._roomMapping.get(room)._handlerMapping.set(this._handlerCounter, {
- nickName: nick,
+ this._getRoomHandlers(room).set(++this._handlerCounter, {
+ nickName: baseNick,
handler: callback
});
- this._handlerCounter++;
+ return this._handlerCounter;
+ },
- return this._handlerCounter - 1;
+ unwatchRoomStatus: function(room, handlerID) {
+ if (!this._roomData.has(room))
+ return;
+ this._getRoomHandlers(room).delete(handlerID);
},
- unwatchUser: function(room, nick, handlerID) {
- /*it wouldn't make sense to call _ensure() here, right?*/
+ _notifyNickAvailable: function (member, room) {
+ let notification = new Gio.Notification();
+ notification.set_title(_("User is online"));
+ notification.set_body(_("User %s is now online.").format(member.alias));
- /*rewrite into a single conditional?*/
- if (!this._roomMapping)
- return;
+ let param = GLib.Variant.new('(ssu)',
+ [ this._account.get_object_path(),
+ room.channel_name,
+ Utils.getTpEventTime() ]);
+ notification.set_default_action_and_target('app.join-room', param);
- if (!this._roomMapping.has(room))
- return;
+ this._app.send_notification(this._getNotifyActionNameInternal(member.alias), notification);
- if (!this._roomMapping.get(room)._handlerMapping)
- return;
+ let baseNick = Polari.util_get_basenick(member.alias);
+ },
+
+ _shouldNotifyNick: function(nickName) {
+ let actionName = this._getNotifyActionNameInternal(nickName);
+ let state = this._app.get_action_state(actionName);
+ return state ? state.get_boolean()
+ : false;
+ },
+
+ _setNotifyActionEnabled: function(nickName, enabled) {
+ let name = this._getNotifyActionNameInternal(nickName);
+ let action = this._app.lookup_action(name);
+ if (action)
+ action.enabled = enabled;
+ },
+
+ _getNotifyActionNameInternal: function(nickName) {
+ return 'notify-user-' +
+ this._account.get_path_suffix() + '-' +
+ Polari.util_get_basenick(nickName);
+ },
+
+ getNotifyActionName: function(nickName) {
+ let name = this._getNotifyActionNameInternal(nickName);
+
+ if (!this._app.lookup_action(name)) {
+ let status = this.getNickStatus(nickName);
+ let enabled = status == Tp.ConnectionPresenceType.OFFLINE;
+
+ let state = new GLib.Variant('b', false);
+ let action = new Gio.SimpleAction({ name: name,
+ enabled: enabled,
+ state: state });
+
+ action.connect('notify::enabled', () => {
+ if (!action.enabled)
+ action.change_state(GLib.Variant.new('b', false));
+ });
+
+ this._app.add_action(action);
+ }
- this._roomMapping.get(room)._handlerMapping.delete(handlerID);
+ return 'app.' + name;
}
});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]