[polari/wip/fmuellner/nickserv: 42/62] mainWindow: Manage active room via an :active-room property



commit 59daae7275efe10f5b9db02295e9bf0b986ca551
Author: Florian Müllner <fmuellner gnome org>
Date:   Thu Jul 14 04:55:39 2016 +0200

    mainWindow: Manage active room via an :active-room property
    
    The ChatroomManager class hasn't aged very well, and has become
    increasingly muddy with regard to what it actually does and how
    it relates to other components (in particular the application):
    
     - ChatroomManager manages joined rooms, except updating
       which rooms should be joined is done by the application
    
     - ChatroomManager handles incoming channel requests from
       mission-control, but our own channel requests are made
       by the application
    
     - managing the list of rooms means we want it available as
       early as possible to other components; being a Telepathy
       handler and observer means we only want to start it when
       we should establish network connections
    
    We will untangle that mess over the next couple of commits, starting
    with something simple: managing the active room. Code-wise it would
    be convenient to keep using an always available singleton for this,
    with application being the obvious choice. However conceptually, the
    window is better suited to manage the active room, as the whole concept
    is tied to some visual representation - being "active" really means
    being the currently selected room in the window. If we are ever going
    to support more than a single main window, we surely don't want all
    windows to show the same room. Similarly, if we allow running in the
    background without any windows, the idea that any of the joined rooms
    was active seems silly. So move tracking of the active room from the
    ChatroomManager into the window.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=769655

 src/application.js     |   37 +++++++++++++++++++----------------
 src/chatroomManager.js |   36 ++++++++++++----------------------
 src/joinDialog.js      |    5 +--
 src/mainWindow.js      |   50 ++++++++++++++++++++++++++++++++++-------------
 src/roomList.js        |   22 ++++++++++++++------
 src/roomStack.js       |   22 +++++++++++++++-----
 src/userList.js        |   15 ++++++++-----
 7 files changed, 111 insertions(+), 76 deletions(-)
---
diff --git a/src/application.js b/src/application.js
index 193cb2d..6bdc04b 100644
--- a/src/application.js
+++ b/src/application.js
@@ -69,7 +69,7 @@ const Application = new Lang.Class({
             parameter_type: GLib.VariantType.new('(ss)') },
           { name: 'leave-current-room',
             activate: Lang.bind(this, this._onLeaveCurrentRoom),
-            create_hook: Lang.bind(this, this._leaveRoomCreateHook),
+            create_hook: (a) => { a.enabled = false; },
             accels: ['<Primary>w'] },
           { name: 'authenticate-account',
             parameter_type: GLib.VariantType.new('(os)') },
@@ -154,6 +154,20 @@ const Application = new Lang.Class({
         this._window.present();
     },
 
+    vfunc_window_added: function(window) {
+        this.parent(window);
+
+        let action = this.lookup_action('leave-current-room');
+        window.connect('notify::active-room', () => {
+            action.enabled = window.active_room != null;
+        });
+        action.enabled = window.active_room != null;
+
+        window.connect('active-room-state-changed',
+                       Lang.bind(this, this._updateUserListAction));
+        this._updateUserListAction();
+    },
+
     vfunc_open: function(files) {
         this.activate();
 
@@ -253,29 +267,18 @@ const Application = new Lang.Class({
             }));
     },
 
-    _leaveRoomCreateHook: function(action) {
-        this._chatroomManager.connect('active-changed', Lang.bind(this,
-            function() {
-                action.enabled = this._chatroomManager.getActiveRoom() != null;
-            }));
-        action.enabled = this._chatroomManager.getActiveRoom() != null;
-    },
-
-    _updateUserListAction: function(action) {
-        let room = this._chatroomManager.getActiveRoom();
+    _updateUserListAction: function() {
+        let room = this.active_window.active_room;
+        let action = this.lookup_action('user-list');
         action.enabled = room && room.type == Tp.HandleType.ROOM && room.channel;
     },
 
     _userListCreateHook: function(action) {
-        this._chatroomManager.connect('active-state-changed', Lang.bind(this,
-            function() {
-                this._updateUserListAction(action);
-            }));
         action.connect('notify::enabled', function() {
             if (!action.enabled)
                 action.change_state(GLib.Variant.new('b', false));
         });
-        this._updateUserListAction(action);
+        action.enabled = false;
     },
 
     _onShowJoinDialog: function() {
@@ -531,7 +534,7 @@ const Application = new Lang.Class({
     },
 
     _onLeaveCurrentRoom: function() {
-        let room = this._chatroomManager.getActiveRoom();
+        let room = this._window.active_room;
         if (!room)
             return;
         let action = this.lookup_action('leave-room');
diff --git a/src/chatroomManager.js b/src/chatroomManager.js
index 653b3d2..c59c0cb 100644
--- a/src/chatroomManager.js
+++ b/src/chatroomManager.js
@@ -146,7 +146,6 @@ const _ChatroomManager = new Lang.Class({
 
     _init: function() {
         this._rooms = {};
-        this._activeRoom = null;
 
         this._app = Gio.Application.get_default();
 
@@ -157,6 +156,10 @@ const _ChatroomManager = new Lang.Class({
 
         this._app.connect('prepare-shutdown',
                           Lang.bind(this, this._onPrepareShutdown));
+        this._app.connect('window-added', (a, w) => {
+            w.connect('notify::active-room',
+                      Lang.bind(this, this._onActiveRoomChanged));
+        });
 
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.Polari' });
 
@@ -320,7 +323,7 @@ const _ChatroomManager = new Lang.Class({
         let room = this._ensureRoom(account, channelName, Tp.HandleType.ROOM);
         let [present, ] = Tp.user_action_time_should_present(time);
         if (present)
-            this.setActiveRoom(room);
+            this._setActiveRoom(room);
     },
 
     _onQueryActivated: function(action, parameter) {
@@ -333,7 +336,7 @@ const _ChatroomManager = new Lang.Class({
         let room = this._ensureRoom(account, channelName, Tp.HandleType.CONTACT);
         let [present, ] = Tp.user_action_time_should_present(time);
         if (present)
-            this.setActiveRoom(room);
+            this._setActiveRoom(room);
     },
 
     _onLeaveActivated: function(action, parameter) {
@@ -411,7 +414,7 @@ const _ChatroomManager = new Lang.Class({
 
                 let room = this._ensureRoomForChannel(channel);
                 if (this.roomCount == 1)
-                    this.setActiveRoom(room);
+                    this._setActiveRoom(room);
             }));
     },
 
@@ -432,7 +435,7 @@ const _ChatroomManager = new Lang.Class({
                 //channel.join_async('', null);
 
                 if (present || this.roomCount == 1)
-                    this.setActiveRoom(room);
+                    this._setActiveRoom(room);
 
                 if (present)
                     this._app.activate();
@@ -443,17 +446,11 @@ const _ChatroomManager = new Lang.Class({
         if (this._rooms[room.id])
             return;
 
-        room._channelChangedId = room.connect('notify::channel', Lang.bind(this,
-            function(room) {
-                if (room == this._activeRoom)
-                    this.emit('active-state-changed');
-            }));
-
         this._rooms[room.id] = room;
         this.emit('room-added', room);
 
         if (this.roomCount == 1)
-            this.setActiveRoom(room);
+            this._setActiveRoom(room);
     },
 
     _removeRoom: function(room) {
@@ -463,8 +460,6 @@ const _ChatroomManager = new Lang.Class({
         if (room == this._lastActiveRoom)
             this._lastActiveRoom = null;
 
-        room.disconnect(room._channelChangedId);
-        delete room._channelChangedId;
         delete this._rooms[room.id];
         this.emit('room-removed', room);
     },
@@ -480,20 +475,15 @@ const _ChatroomManager = new Lang.Class({
         }
     },
 
-    setActiveRoom: function(room) {
-        if (room == this._activeRoom)
-            return;
+    _onActiveRoomChanged: function(window) {
+        let room = window.active_room;
 
         if (room && room.type == Tp.HandleType.ROOM)
             this._lastActiveRoom = room;
-
-        this._activeRoom = room;
-        this.emit('active-changed', room);
-        this.emit('active-state-changed');
     },
 
-    getActiveRoom: function() {
-        return this._activeRoom;
+    _setActiveRoom: function(room) {
+        this._app.active_window.active_room = room;
     },
 
     getRoomByName: function(name) {
diff --git a/src/joinDialog.js b/src/joinDialog.js
index 9e6e2b4..8c7f2be 100644
--- a/src/joinDialog.js
+++ b/src/joinDialog.js
@@ -6,7 +6,6 @@ const Tp = imports.gi.TelepathyGLib;
 const Tpl = imports.gi.TelepathyLogger;
 
 const AccountsMonitor = imports.accountsMonitor;
-const ChatroomManager = imports.chatroomManager;
 const Connections = imports.connections;
 const Lang = imports.lang;
 const Utils = imports.utils;
@@ -58,7 +57,6 @@ const JoinDialog = new Lang.Class({
         this._setupConnectionPage();
 
         this._accountsMonitor = AccountsMonitor.getDefault();
-        this._roomManager = ChatroomManager.getDefault();
 
         this._accounts = {};
         this._accountsMonitor.enabledAccounts.forEach(a => {
@@ -229,7 +227,8 @@ const JoinDialog = new Lang.Class({
             this._connectionCombo.append(names[i], names[i]);
         this._connectionCombo.sensitive = names.length > 1;
 
-        let activeRoom = this._roomManager.getActiveRoom();
+        let activeRoom = this.transient_for ? this.transient_for.active_room
+                                            : null;
         let activeIndex = 0;
         if(activeRoom)
             activeIndex = Math.max(names.indexOf(activeRoom.account.display_name), 0);
diff --git a/src/mainWindow.js b/src/mainWindow.js
index 8114590..4c491ab 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -3,11 +3,11 @@ const Gio = imports.gi.Gio;
 const GLib = imports.gi.GLib;
 const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
+const Polari = imports.gi.Polari;
 const Tp = imports.gi.TelepathyGLib;
 
 const AccountsMonitor = imports.accountsMonitor;
 const AppNotifications = imports.appNotifications;
-const ChatroomManager = imports.chatroomManager;
 const JoinDialog = imports.joinDialog;
 const Lang = imports.lang;
 const Mainloop = imports.mainloop;
@@ -109,25 +109,33 @@ const MainWindow = new Lang.Class({
                                                       'subtitle-visible',
                                                       'subtitle-visible',
                                                       GObject.ParamFlags.READABLE,
-                                                      false)
+                                                      false),
+        'active-room': GObject.ParamSpec.object('active-room',
+                                                'active-room',
+                                                'active-room',
+                                                GObject.ParamFlags.READWRITE,
+                                                Polari.Room.$gtype)
     },
+    Signals: { 'active-room-state-changed': {} },
 
     _init: function(params) {
         this._subtitle = '';
         params.show_menubar = false;
 
+        this._room = null;
+
+        this._displayNameChangedId = 0;
+        this._topicChangedId = 0;
+        this._membersChangedId = 0;
+        this._channelChangedId = 0;
+
         this.parent(params);
 
         this._addApplicationStyle();
 
-        this._room = null;
         this._settings = new Gio.Settings({ schema_id: 'org.gnome.Polari' });
         this._gtkSettings = Gtk.Settings.get_default();
 
-        this._displayNameChangedId = 0;
-        this._topicChangedId = 0;
-        this._membersChangedId = 0;
-
         this._currentSize = [-1, -1];
         this._isMaximized = false;
         this._isFullscreen = false;
@@ -158,12 +166,6 @@ const MainWindow = new Lang.Class({
                                       Lang.bind(this, this._onAccountsChanged));
         this._onAccountsChanged(this._accountsMonitor);
 
-        this._roomManager = ChatroomManager.getDefault();
-        this._roomManager.connect('active-changed',
-                                  Lang.bind(this, this._activeRoomChanged));
-        this._roomManager.connect('active-state-changed',
-                                  Lang.bind(this, this._updateUserListLabel));
-
         this._updateUserListLabel();
 
         this._userListAction = app.lookup_action('user-list');
@@ -185,6 +187,9 @@ const MainWindow = new Lang.Class({
         this.connect('window-state-event', Lang.bind(this, this._onWindowStateEvent));
         this.connect('size-allocate', Lang.bind(this, this._onSizeAllocate));
         this.connect('destroy', Lang.bind(this, this._onDestroy));
+        this.connect('notify::active-room', () => {
+            this._updateUserListLabel();
+        });
 
         let size = this._settings.get_value('window-size').deep_unpack();
         if (size.length == 2)
@@ -241,20 +246,32 @@ const MainWindow = new Lang.Class({
         this._titlebarRight.set_decoration_layout(layoutRight);
     },
 
-    _activeRoomChanged: function(manager, room) {
+    get active_room() {
+        return this._room;
+    },
+
+    set active_room(room) {
+        if (room == this._room)
+            return;
+
         if (this._room) {
             this._room.disconnect(this._displayNameChangedId);
             this._room.disconnect(this._topicChangedId);
             this._room.disconnect(this._membersChangedId);
+            this._room.disconnect(this._channelChangedId);
         }
         this._displayNameChangedId = 0;
         this._topicChangedId = 0;
         this._membersChangedId = 0;
+        this._channelChangedId = 0;
 
         this._room = room;
 
         this._updateTitlebar();
 
+        this.notify('active-room');
+        this.emit('active-room-state-changed');
+
         if (!this._room)
             return; // finished
 
@@ -267,6 +284,11 @@ const MainWindow = new Lang.Class({
         this._membersChangedId =
             this._room.connect('members-changed',
                                Lang.bind(this, this._updateUserListLabel));
+        this._channelChangedId =
+            this._room.connect('notify::channel', () => {
+                this._updateUserListLabel();
+                this.emit('active-room-state-changed');
+            });
     },
 
     _addApplicationStyle: function() {
diff --git a/src/roomList.js b/src/roomList.js
index f67e575..0600eba 100644
--- a/src/roomList.js
+++ b/src/roomList.js
@@ -375,8 +375,6 @@ const RoomList = new Lang.Class({
                                   Lang.bind(this, this._roomAdded));
         this._roomManager.connect('room-removed',
                                   Lang.bind(this, this._roomRemoved));
-        this._roomManager.connect('active-changed',
-                                  Lang.bind(this, this._activeRoomChanged));
 
         let app = Gio.Application.get_default();
         let actions = [
@@ -409,6 +407,15 @@ const RoomList = new Lang.Class({
         });
     },
 
+    vfunc_realize: function() {
+        this.parent();
+
+        let toplevel = this.get_toplevel();
+        toplevel.connect('notify::active-room',
+                         Lang.bind(this, this._activeRoomChanged));
+        this._activeRoomChanged();
+    },
+
     _onLeaveActivated: function(action, param) {
         let [id, ] = param.deep_unpack();
         let row = this._roomRows.get(id);
@@ -468,8 +475,8 @@ const RoomList = new Lang.Class({
         if (this._roomManager.roomCount == 0)
             return;
 
-        let activeRoom = this._roomManager.getActiveRoom();
-        let current = this._roomRows.get(activeRoom.id);
+        let toplevel = this.get_toplevel();
+        let current = this._roomRows.get(toplevel.active_room.id);
 
         if (current != row)
             return;
@@ -485,7 +492,7 @@ const RoomList = new Lang.Class({
         let newSelected = this.get_selected_row();
         if (newSelected != row)
             newActive = newSelected.room;
-        this._roomManager.setActiveRoom(newActive);
+        toplevel.active_room = newActive;
 
         if (selected != row)
             this.select_row(selected);
@@ -555,7 +562,8 @@ const RoomList = new Lang.Class({
         this._placeholders.get(account).visible = !hasRooms;
     },
 
-    _activeRoomChanged: function(roomManager, room) {
+    _activeRoomChanged: function() {
+        let room = this.get_toplevel().active_room;
         if (!room)
             return;
         let row = this._roomRows.get(room.id);
@@ -568,7 +576,7 @@ const RoomList = new Lang.Class({
     },
 
     vfunc_row_selected: function(row) {
-        this._roomManager.setActiveRoom(row ? row.room : null);
+        this.get_toplevel().active_room = row ? row.room : null;
         if (row)
             row.selected();
     },
diff --git a/src/roomStack.js b/src/roomStack.js
index 521dd80..6ede912 100644
--- a/src/roomStack.js
+++ b/src/roomStack.js
@@ -32,10 +32,6 @@ const RoomStack = new Lang.Class({
                                   Lang.bind(this, this._roomAdded));
         this._roomManager.connect('room-removed',
                                   Lang.bind(this, this._roomRemoved));
-        this._roomManager.connect('active-changed',
-                                  Lang.bind(this, this._activeRoomChanged));
-        this._roomManager.connect('active-state-changed',
-                                  Lang.bind(this, this._updateSensitivity));
 
         this.add_named(new ChatPlaceholder(this._sizeGroup), 'placeholder');
 
@@ -47,6 +43,19 @@ const RoomStack = new Lang.Class({
             }));
     },
 
+    vfunc_realize: function() {
+        this.parent();
+
+        let toplevel = this.get_toplevel();
+
+        toplevel.connect('notify::active-room',
+                         Lang.bind(this, this._activeRoomChanged));
+        toplevel.connect('active-room-state-changed',
+                         Lang.bind(this, this._updateSensitivity));
+        this._activeRoomChanged();
+        this._updateSensitivity();
+    },
+
     get entry_area_height() {
         return this._entryAreaHeight;
     },
@@ -65,12 +74,13 @@ const RoomStack = new Lang.Class({
         this._rooms.delete(room.id);
     },
 
-    _activeRoomChanged: function(manager, room) {
+    _activeRoomChanged: function() {
+        let room = this.get_toplevel().active_room;
         this.set_visible_child_name(room ? room.id : 'placeholder');
     },
 
     _updateSensitivity: function() {
-        let room = this._roomManager.getActiveRoom();
+        let room = this.get_toplevel().active_room;
         if (!room)
             return;
         let sensitive = room && room.channel;
diff --git a/src/userList.js b/src/userList.js
index 6009c1d..4850fdb 100644
--- a/src/userList.js
+++ b/src/userList.js
@@ -6,7 +6,6 @@ const Gtk = imports.gi.Gtk;
 const Pango = imports.gi.Pango;
 const Tp = imports.gi.TelepathyGLib;
 
-const ChatroomManager = imports.chatroomManager;
 const Lang = imports.lang;
 const Mainloop = imports.mainloop;
 
@@ -34,10 +33,14 @@ const UserListPopover = new Lang.Class({
         this._revealer.connect('notify::child-revealed', Lang.bind(this, function() {
             this._revealer.transition_duration = 250;
         }));
+    },
+
+    vfunc_realize: function() {
+        this.parent();
 
-        this._roomManager = new ChatroomManager.getDefault();
-        this._roomManager.connect('active-changed',
-                                  Lang.bind(this, this._activeRoomChanged));
+        let toplevel = this.get_toplevel();
+        toplevel.connect('notify::active-room',
+                         Lang.bind(this, this._activeRoomChanged));
     },
 
     _createWidget: function() {
@@ -59,7 +62,7 @@ const UserListPopover = new Lang.Class({
         this._box.show_all();
     },
 
-    _activeRoomChanged: function(manager, room) {
+    _activeRoomChanged: function() {
         this._entry.text = '';
 
         if (this._userList)
@@ -71,7 +74,7 @@ const UserListPopover = new Lang.Class({
         if (this._userList)
             return;
 
-        let room = this._roomManager.getActiveRoom();
+        let room = this.get_toplevel().active_room;
         if (!room || room.type != Tp.HandleType.ROOM)
             return;
 


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