[polari] Guard against PolariRoom:channel getting set/unset



commit 17bd1eaac3042928dab6caa7e8769213ed229108
Author: Florian Müllner <fmuellner gnome org>
Date:   Tue Dec 10 00:12:19 2013 +0100

    Guard against PolariRoom:channel getting set/unset
    
    This cannot happen currently, as the lifecycle of Rooms is bound
    to the corresponding channel, but this is about to change. So
    adjust the code to not assume that any room has a valid channel
    at any time, but update state appropriately as channels go away or
    become available.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=710271

 src/application.js    |    2 +-
 src/chatView.js       |   50 +++++++++++++++++++++++++++++++-----------------
 src/entryArea.js      |   38 +++++++++++++++++++++++++++---------
 src/lib/polari-room.c |    3 ++
 src/roomList.js       |   34 ++++++++++++++++++++++----------
 src/userList.js       |   18 +++++++++++++---
 6 files changed, 101 insertions(+), 44 deletions(-)
---
diff --git a/src/application.js b/src/application.js
index 88f660b..d37b2a3 100644
--- a/src/application.js
+++ b/src/application.js
@@ -190,7 +190,7 @@ const Application = new Lang.Class({
 
     _updateUserListAction: function(action) {
         let room = this._chatroomManager.getActiveRoom();
-        action.enabled = room && room.type == Tp.HandleType.ROOM;
+        action.enabled = room && room.type == Tp.HandleType.ROOM && room.channel;
     },
 
     _userListCreateHook: function(action) {
diff --git a/src/chatView.js b/src/chatView.js
index c59ae85..fceb657 100644
--- a/src/chatView.js
+++ b/src/chatView.js
@@ -113,20 +113,11 @@ const ChatView = new Lang.Class({
 
         this._linkCursor = Gdk.Cursor.new(Gdk.CursorType.HAND1);
 
-        let channelSignals = [
-            { name: 'message-received',
-              handler: Lang.bind(this, this._insertTpMessage) },
-            { name: 'message-sent',
-              handler: Lang.bind(this, this._insertTpMessage) },
-            { name: 'pending-message-removed',
-              handler: Lang.bind(this, this._pendingMessageRemoved) }
-        ];
         this._channelSignals = [];
-        channelSignals.forEach(Lang.bind(this, function(signal) {
-            this._channelSignals.push(room.channel.connect(signal.name, signal.handler));
-        }));
 
         let roomSignals = [
+            { name: 'notify::channel',
+              handler: Lang.bind(this, this._onChannelChanged) },
             { name: 'member-renamed',
               handler: Lang.bind(this, this._onMemberRenamed) },
             { name: 'member-disconnected',
@@ -144,12 +135,6 @@ const ChatView = new Lang.Class({
         roomSignals.forEach(Lang.bind(this, function(signal) {
             this._roomSignals.push(room.connect(signal.name, signal.handler));
         }));
-
-        room.channel.dup_pending_messages().forEach(Lang.bind(this,
-            function(message) {
-                this._insertTpMessage(room, message);
-            }));
-        this._checkMessages();
     },
 
     _createTags: function() {
@@ -440,7 +425,7 @@ const ChatView = new Lang.Class({
     },
 
     _checkMessages: function() {
-        if (!this._active || !this._toplevelFocus)
+        if (!this._active || !this._toplevelFocus || !this._room.channel)
             return;
 
         this._needsIndicator = true;
@@ -465,6 +450,35 @@ const ChatView = new Lang.Class({
         }
     },
 
+    _onChannelChanged: function() {
+        if (!this._room.channel) {
+            this._channelSignals = [];
+            return;
+        }
+
+        for (let i = 0; i < this._channelSignals.length; i++)
+            this._room.channel.disconnect(this._channelSignals[i]);
+        this._channelSignals = [];
+
+        let channelSignals = [
+            { name: 'message-received',
+              handler: Lang.bind(this, this._insertTpMessage) },
+            { name: 'message-sent',
+              handler: Lang.bind(this, this._insertTpMessage) },
+            { name: 'pending-message-removed',
+              handler: Lang.bind(this, this._pendingMessageRemoved) }
+        ];
+        channelSignals.forEach(Lang.bind(this, function(signal) {
+            this._channelSignals.push(this._room.channel.connect(signal.name, signal.handler));
+        }));
+
+        this._room.channel.dup_pending_messages().forEach(Lang.bind(this,
+            function(message) {
+                this._insertTpMessage(this._room, message);
+            }));
+        this._checkMessages();
+    },
+
     _onMemberRenamed: function(room, oldMember, newMember) {
         this._insertStatus(_("%s is now known as %s").format(oldMember.alias,
                                                              newMember.alias));
diff --git a/src/entryArea.js b/src/entryArea.js
index afe3705..62c2bfd 100644
--- a/src/entryArea.js
+++ b/src/entryArea.js
@@ -25,7 +25,7 @@ const EntryArea = new Lang.Class({
         this._roomManager = new ChatroomManager.getDefault();
         this._activeRoomChangedId =
             this._roomManager.connect('active-changed',
-                                      Lang.bind(this, this._activeRoomChanged));
+                                      Lang.bind(this, this._updateSensitivity));
 
         if (!room)
             return;
@@ -34,11 +34,10 @@ const EntryArea = new Lang.Class({
         this._membersChangedId =
             this._room.connect('members-changed',
                                Lang.bind(this, this._updateCompletions));
-        this._nicknameChangedId =
-            this._room.channel.connection.connect('notify::self-contact',
-                                                  Lang.bind(this,
-                                                            this._updateNick));
-        this._updateCompletions();
+        this._channelChangedId =
+            this._room.connect('notify::channel',
+                               Lang.bind(this, this._onChannelChanged));
+        this._onChannelChanged(room);
         this._updateNick();
     },
 
@@ -107,6 +106,7 @@ const EntryArea = new Lang.Class({
         let nicks = [];
 
         if (this._room &&
+            this._room.channel &&
             this._room.channel.has_interface(Tp.IFACE_CHANNEL_INTERFACE_GROUP)) {
             let members = this._room.channel.group_dup_members_contacts();
             nicks = members.map(function(member) { return member.alias; });
@@ -114,8 +114,9 @@ const EntryArea = new Lang.Class({
         this._completion.setCompletions(nicks);
     },
 
-    _activeRoomChanged: function(manager, room) {
-        this.widget.sensitive = this._room && this._room == room;
+    _updateSensitivity: function() {
+        let room = this._roomManager.getActiveRoom();
+        this.widget.sensitive = this._room && this._room == room && room.channel;
 
         if (!this.widget.sensitive)
             return;
@@ -127,6 +128,19 @@ const EntryArea = new Lang.Class({
             }));
     },
 
+    _onChannelChanged: function(room) {
+        this._updateCompletions();
+        this._updateSensitivity();
+
+        if (room.channel)
+            this._nicknameChangedId =
+                room.channel.connection.connect('notify::self-contact',
+                                                Lang.bind(this, this._updateNick));
+        else
+            this._nicknameChangedId = 0;
+    },
+
+
     _setNick: function(nick) {
         this._nickEntry.width_chars = Math.max(nick.length, ChatView.MAX_NICK_CHARS)
         this._nickEntry.placeholder_text = nick;
@@ -160,8 +174,9 @@ const EntryArea = new Lang.Class({
     },
 
     _updateNick: function() {
-        let nick = this._room ? this._room.channel.connection.self_contact.alias
-                              : '';
+        let channel = this._room ? this._room.channel : null;
+        let nick = channel ? channel.connection.self_contact.alias
+                           : this._room ? this._room.account.nickname : '';
 
         this._nickEntry.width_chars = Math.max(nick.length, ChatView.MAX_NICK_CHARS)
         this._nickEntry.placeholder_text = nick;
@@ -177,5 +192,8 @@ const EntryArea = new Lang.Class({
         if (this._nicknameChangedId)
             this._room.channel.connection.disconnect(this._nicknameChangedId);
         this._nicknameChangedId = 0;
+        if (this._channelChangedId)
+            this._room.disconnect(this._channelChangedId);
+        this._channelChangedId = 0;
     }
 });
diff --git a/src/lib/polari-room.c b/src/lib/polari-room.c
index 0a0151e..c21f877 100644
--- a/src/lib/polari-room.c
+++ b/src/lib/polari-room.c
@@ -242,6 +242,9 @@ update_self_nick (PolariRoom *room)
 
   g_clear_pointer (&priv->self_nick, g_free);
 
+  if (!room->priv->channel)
+    return;
+
   conn = tp_channel_get_connection (room->priv->channel);
   self = tp_connection_get_self_contact (conn);
 
diff --git a/src/roomList.js b/src/roomList.js
index c5c841d..c7d3988 100644
--- a/src/roomList.js
+++ b/src/roomList.js
@@ -25,10 +25,15 @@ const RoomRow = new Lang.Class({
         this._selectionModeAction.connect('notify::state',
                           Lang.bind(this, this._onSelectionModeChanged));
 
-        room.channel.connect('message-received',
-                             Lang.bind(this, this._updatePending));
-        room.channel.connect('pending-message-removed',
-                             Lang.bind(this, this._updatePending));
+        room.connect('notify::channel', Lang.bind(this,
+            function() {
+                if (!room.channel)
+                    return;
+                room.channel.connect('message-received',
+                                     Lang.bind(this, this._updatePending));
+                room.channel.connect('pending-message-removed',
+                                     Lang.bind(this, this._updatePending));
+            }));
         room.bind_property('display-name', this._roomLabel, 'label',
                            GObject.BindingFlags.SYNC_CREATE);
 
@@ -47,14 +52,21 @@ const RoomRow = new Lang.Class({
     _updatePending: function() {
         let room = this.widget.room;
 
-        let pending = room.channel.dup_pending_messages();
+        let pending;
         let numPendingHighlights;
-        if (room.channel.has_interface(Tp.IFACE_CHANNEL_INTERFACE_GROUP))
-            numPendingHighlights = pending.filter(function(m) {
-                return room.should_highlight_message(m);
-            }).length;
-        else
-            numPendingHighlights = pending.length;
+
+        if (room.channel) {
+            pending = room.channel.dup_pending_messages();
+            if (room.channel.has_interface(Tp.IFACE_CHANNEL_INTERFACE_GROUP))
+                numPendingHighlights = pending.filter(function(m) {
+                    return room.should_highlight_message(m);
+                }).length;
+            else
+                numPendingHighlights = pending.length;
+        } else {
+            pending = [];
+            numPendingHighlights = 0;
+        }
 
         this._counter.label = numPendingHighlights.toString();
         this._counter.opacity = numPendingHighlights > 0 ? 1. : 0.;
diff --git a/src/userList.js b/src/userList.js
index a6a259a..62e29e9 100644
--- a/src/userList.js
+++ b/src/userList.js
@@ -342,10 +342,8 @@ const UserList = new Lang.Class({
                      Lang.bind(this, this._onMemberJoined));
         room.connect('members-changed',
                      Lang.bind(this, this._onMembersChanged));
-
-        let members = room.channel.group_dup_members_contacts();
-        for (let i = 0; i < members.length; i++)
-            this._addMember(members[i]);
+        room.connect('notify::channel',
+                     Lang.bind(this, this._onChannelChanged));
 
         this.widget.show_all();
     },
@@ -373,6 +371,18 @@ const UserList = new Lang.Class({
         this._counterLabel.label = numMembers.toString();
     },
 
+    _onChannelChanged: function(room) {
+        this._list.foreach(function(w) { w.destroy(); });
+        this._rows = {};
+
+        if (!room.channel)
+            return;
+
+        let members = room.channel.group_dup_members_contacts();
+        for (let i = 0; i < members.length; i++)
+            this._addMember(members[i]);
+    },
+
     _addMember: function(member) {
         let row = new UserListRow(member);
         this._rows[member] = row;


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