[polari/wip/raresv/nick-popover: 36/47] chatView: Split out status tracking
- From: Florian Müllner <fmuellner src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [polari/wip/raresv/nick-popover: 36/47] chatView: Split out status tracking
- Date: Sun, 2 Oct 2016 18:30:12 +0000 (UTC)
commit 6c4ab588ca67beb398d889a0bff97d3e0414ded1
Author: raresv <rares visalom gmail com>
Date: Sun Aug 21 17:14:04 2016 +0300
chatView: Split out status tracking
Tracking the online status of nicks is not just useful for updating
colors in the chat log, so move the code to a dedicated module.
https://bugzilla.gnome.org/show_bug.cgi?id=760853
src/chatView.js | 116 +++++++++-------------------
src/org.gnome.Polari.src.gresource.xml | 1 +
src/userTracker.js | 129 ++++++++++++++++++++++++++++++++
3 files changed, 168 insertions(+), 78 deletions(-)
---
diff --git a/src/chatView.js b/src/chatView.js
index d8bde62..77118a9 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;
@@ -294,6 +295,9 @@ const ChatView = new Lang.Class({
this._initialPending = [];
this._statusCount = { left: 0, joined: 0, total: 0 };
+ 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);
@@ -386,19 +390,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();
@@ -451,7 +442,17 @@ const ChatView = new Lang.Class({
}
});
- this._foreachNickTag(t => { this._updateTagStatus(t); });
+ tagTable.foreach(tag => {
+ if(!tag.name)
+ return;
+
+ let nickname = this._getNickFromTagName(tag.name);
+
+ if (!nickname)
+ return;
+
+ this._updateNickTag(tag, this._userTracker.getNickStatus(nickname));
+ });
},
_onDestroy: function() {
@@ -554,15 +555,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() {
@@ -836,38 +828,10 @@ 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);
- },
-
- _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;
+ _getNickFromTagName: function(tagName) {
+ if (tagName.startsWith(NICKTAG_PREFIX))
+ return tagName.replace(NICKTAG_PREFIX, '');
+ return null;
},
_onChannelChanged: function() {
@@ -891,19 +855,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;
@@ -928,8 +879,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) {
@@ -937,7 +886,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) {
@@ -946,7 +894,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) {
@@ -955,13 +902,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) {
@@ -971,7 +916,6 @@ const ChatView = new Lang.Class({
text += ' (%s)'.format(message);
this._insertStatus(text, member.alias, 'left');
- this._untrackContact(member);
},
_onMessageReceived: function(channel, tpMessage) {
@@ -1194,7 +1138,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 (message.pendingId == undefined /* outgoing */ ||
(this._app.isRoomFocused(this._room) && this._pending.size == 0))
@@ -1237,9 +1180,10 @@ const ChatView = new Lang.Class({
if (!nickTag) {
nickTag = new Gtk.TextTag({ name: nickTagName });
- this._view.get_buffer().get_tag_table().add(nickTag);
- this._resetNickTag(nickTag);
+ this._updateNickTag(nickTag, this._userTracker.getNickStatus(message.nick));
+
+ this._view.get_buffer().get_tag_table().add(nickTag);
}
tags.push(nickTag);
if (needsGap)
@@ -1280,6 +1224,22 @@ const ChatView = new Lang.Class({
this._view.buffer.create_mark(null, iter, true));
},
+ _onNickStatusChanged: function(tracker, nickName, status) {
+ let nickTag = this._lookupTag(this._getNickTagName(nickName));
+
+ if (!nickTag)
+ return;
+
+ this._updateNickTag(nickTag, status);
+ },
+
+ _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 4e3a0ec..17dc187 100644
--- a/src/org.gnome.Polari.src.gresource.xml
+++ b/src/org.gnome.Polari.src.gresource.xml
@@ -20,5 +20,6 @@
<file>telepathyClient.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..57e2937
--- /dev/null
+++ b/src/userTracker.js
@@ -0,0 +1,129 @@
+const Polari = imports.gi.Polari;
+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 UserTracker = new Lang.Class({
+ Name: 'UserTracker',
+ Extends: GObject.Object,
+
+ Signals: {
+ 'status-changed': {
+ flags: GObject.SignalFlags.DETAILED,
+ param_types: [GObject.TYPE_STRING, GObject.TYPE_INT]
+ }
+ },
+
+ _init: function(room) {
+ this.parent();
+
+ this._baseNickContacts = new Map();
+
+ this._room = room;
+
+ this._onRoomAdded(this._room);
+ this._onChannelChanged(this._room);
+ },
+
+ _onRoomAdded: function(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) }
+ ];
+
+ roomSignals.forEach(Lang.bind(this, function(signal) {
+ room.connect(signal.name, signal.handler);
+ }));
+ }
+
+ _onChannelChanged: function(room) {
+ if (!room.channel) {
+ this._clearUsers();
+ return;
+ }
+
+ 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];
+
+ members.forEach(m => { this._trackMember(m); });
+ },
+
+ _clearUsers: function() {
+ for (let [baseNick, contacts] of this._baseNickContacts)
+ contacts.slice().forEach((m) => { this._untrackMember(m); });
+ },
+
+ _onMemberRenamed: function(room, oldMember, newMember) {
+ this._untrackMember(oldMember);
+ this._trackMember(newMember);
+ },
+
+ _onMemberJoined: function(room, member) {
+ this._trackMember(member);
+ },
+
+ _onMemberLeft: function(room, member) {
+ this._untrackMember(member);
+ },
+
+ _pushMember: function(baseNick, member) {
+ if (!this._baseNickContacts.has(baseNick))
+ this._baseNickContacts.set(baseNick, []);
+ let contacts = this._baseNickContacts.get(baseNick);
+ return contacts.push(member);
+ },
+
+ _trackMember: function(member) {
+ let baseNick = Polari.util_get_basenick(member.alias);
+ let status = Tp.ConnectionPresenceType.AVAILABLE;
+
+ if (this._pushMember(baseNick, member) == 1)
+ this.emit("status-changed::" + baseNick, baseNick, status);
+ },
+
+ _popMember: function(baseNick, member) {
+ let contacts = this._baseNickContacts.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) {
+ let baseNick = Polari.util_get_basenick(member.alias);
+ let status = Tp.ConnectionPresenceType.OFFLINE;
+
+ let [found, nContacts] = this._popMember(baseNick, member);
+ if (found)
+ if (nContacts == 0)
+ this.emit("status-changed::" + baseNick, member.alias, status);
+ },
+
+ getNickStatus: function(nickName) {
+ let baseNick = Polari.util_get_basenick(nickName);
+
+ let contacts = this._baseNickContacts.get(baseNick) || [];
+ return contacts.length == 0 ? Tp.ConnectionPresenceType.OFFLINE
+ : Tp.ConnectionPresenceType.AVAILABLE;
+ }
+});
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]