[polari/wip/fmuellner/nickserv: 14/29] chatroomManager: Split out room management



commit 2318d245e9b33a29d5720d26c6fe97d20df1f7db
Author: Florian Müllner <fmuellner gnome org>
Date:   Sat Jul 30 18:05:39 2016 +0200

    chatroomManager: Split out room management
    
    Originally rooms were tightly coupled with channels - a room was created
    and added when we observed a channel, and removed when the channel was
    invalidated - so doing room management in the telepathy observer/handler
    made a lot of sense. But nowadays where we show disconnected rooms, the
    only point where room management overlaps with channel handling is where
    we match a channel to a (usually existing) room. It is time to split out
    room management into its own class, including maintaining the list of
    saved channels (where updating the list got split from restoring rooms
    when the code moved into the application).
    
    https://bugzilla.gnome.org/show_bug.cgi?id=769655

 src/application.js                     |   76 +-----------
 src/chatroomManager.js                 |  160 ++++---------------------
 src/ircParser.js                       |    6 +-
 src/mainWindow.js                      |   25 +++-
 src/org.gnome.Polari.src.gresource.xml |    1 +
 src/roomList.js                        |   15 +--
 src/roomManager.js                     |  206 ++++++++++++++++++++++++++++++++
 src/roomStack.js                       |    5 +-
 8 files changed, 262 insertions(+), 232 deletions(-)
---
diff --git a/src/application.js b/src/application.js
index a5026dd..24bf63e 100644
--- a/src/application.js
+++ b/src/application.js
@@ -11,6 +11,7 @@ const Connections = imports.connections;
 const Lang = imports.lang;
 const MainWindow = imports.mainWindow;
 const PasteManager = imports.pasteManager;
+const RoomManager = imports.roomManager;
 const Utils = imports.utils;
 const NetworksManager = imports.networksManager;
 
@@ -35,8 +36,6 @@ const Application = new Lang.Class({
     vfunc_startup: function() {
         this.parent();
 
-        this._settings = new Gio.Settings({ schema_id: 'org.gnome.Polari' });
-
         let actionEntries = [
           { name: 'show-join-dialog',
             activate: Lang.bind(this, this._onShowJoinDialog),
@@ -48,7 +47,6 @@ const Application = new Lang.Class({
             activate: Lang.bind(this, this._onMessageUser),
             parameter_type: GLib.VariantType.new('(sssu)') },
           { name: 'leave-room',
-            activate: Lang.bind(this, this._onLeaveRoom),
             parameter_type: GLib.VariantType.new('(ss)') },
           { name: 'leave-current-room',
             activate: Lang.bind(this, this._onLeaveCurrentRoom),
@@ -120,14 +118,11 @@ const Application = new Lang.Class({
         for (let i = 1; i < 10; i++)
             this.set_accels_for_action('app.nth-room(%d)'.format(i), ['<Alt>' + i]);
 
+        this._roomManager = RoomManager.getDefault();
         this._chatroomManager = ChatroomManager.getDefault();
         this._accountsMonitor = AccountsMonitor.getDefault();
         this._networksManager = NetworksManager.getDefault();
 
-        this._accountsMonitor.connect('account-removed', Lang.bind(this,
-            function(am, account) {
-                this._removeSavedChannelsForAccount(account.object_path);
-            }));
         this._accountsMonitor.connect('account-status-changed',
                                       Lang.bind(this, this._onAccountStatusChanged));
 
@@ -279,78 +274,21 @@ const Application = new Lang.Class({
         this._window.showJoinRoomDialog();
     },
 
-    _savedChannelIndex: function(savedChannels, account, channel) {
-        let accountPath = account.get_object_path();
-        let matchChannel = channel.toLowerCase();
-        for (let i = 0; i < savedChannels.length; i++)
-            if (savedChannels[i].account.deep_unpack() == accountPath &&
-                savedChannels[i].channel.deep_unpack().toLowerCase() == matchChannel)
-                return i;
-        return -1;
-    },
-
-    _addSavedChannel: function(account, channel) {
-        let savedChannels = this._settings.get_value('saved-channel-list').deep_unpack();
-        if (this._savedChannelIndex(savedChannels, account, channel) != -1)
-            return;
-        savedChannels.push({
-            account: GLib.Variant.new('s', account.get_object_path()),
-            channel: GLib.Variant.new('s', channel)
-        });
-        this._settings.set_value('saved-channel-list',
-                                 GLib.Variant.new('aa{sv}', savedChannels));
-    },
-
-    _removeSavedChannel: function(account, channel) {
-        let savedChannels = this._settings.get_value('saved-channel-list').deep_unpack();
-        let pos = this._savedChannelIndex(savedChannels, account, channel);
-        if (pos < 0)
-            return;
-        savedChannels.splice(pos, 1);
-        this._settings.set_value('saved-channel-list',
-                                 GLib.Variant.new('aa{sv}', savedChannels));
-    },
-
-    _removeSavedChannelsForAccount: function(accountPath) {
-        let savedChannels = this._settings.get_value('saved-channel-list').deep_unpack();
-
-        let savedChannels = savedChannels.filter(function(a) {
-            return !a.account.equal(accountPath);
-        });
-        this._settings.set_value('saved-channel-list',
-                                 GLib.Variant.new('aa{sv}', savedChannels));
-    },
-
-    _handleJoinQueryAction: function(accountPath, time) {
+    _maybePresent: function(time) {
         let [present, ] = Tp.user_action_time_should_present(time);
 
         if (!this._window || present)
             this.activate();
-
-        let account = this._accountsMonitor.lookupAccount(accountPath);
-
-        // the account was removed since the channel was saved
-        if (!account)
-            this._removeSavedChannelsForAccount(accountPath);
     },
 
     _onJoinRoom: function(action, parameter) {
         let [accountPath, channelName, time] = parameter.deep_unpack();
-        this._accountsMonitor.prepare(() => {
-            let account = this._accountsMonitor.lookupAccount(accountPath);
-            if (!account)
-                return;
-
-            this._handleJoinQueryAction(accountPath, time);
-            this._addSavedChannel(account, channelName);
-        });
+        this._maybePresent(time);
     },
 
     _onMessageUser: function(action, parameter) {
         let [accountPath, contactName, message, time] = parameter.deep_unpack();
-        this._accountsMonitor.prepare(() => {
-            this._handleJoinQueryAction(accountPath, time);
-        });
+        this._maybePresent(time);
     },
 
     _ensureRetryData: function(account) {
@@ -453,10 +391,6 @@ const Application = new Lang.Class({
         this._restoreAccountName(account);
     },
 
-    _onLeaveRoom: function(action, parameter) {
-        this._removeSavedChannel(room.account, room.channel_name);
-    },
-
     _onLeaveCurrentRoom: function() {
         let room = this._window.active_room;
         if (!room)
diff --git a/src/chatroomManager.js b/src/chatroomManager.js
index 58912bf..9e8a5bc 100644
--- a/src/chatroomManager.js
+++ b/src/chatroomManager.js
@@ -5,6 +5,7 @@ const Tp = imports.gi.TelepathyGLib;
 
 const AccountsMonitor = imports.accountsMonitor;
 const Lang = imports.lang;
+const RoomManager = imports.roomManager;
 const Signals = imports.signals;
 const Utils = imports.utils;
 
@@ -145,8 +146,6 @@ const _ChatroomManager = new Lang.Class({
     Name: '_ChatroomManager',
 
     _init: function() {
-        this._rooms = {};
-
         this._app = Gio.Application.get_default();
         this._app.connect('prepare-shutdown', () => {
             [...this._pendingRequests.values()].forEach(r => { r.cancel(); });
@@ -155,17 +154,17 @@ const _ChatroomManager = new Lang.Class({
         this._pendingRequests = new Map();
 
         this._networkMonitor = Gio.NetworkMonitor.get_default();
+        this._roomManager = RoomManager.getDefault();
+        this._roomManager.connect('room-added', (mgr, room) => {
+            this._connectRoom(room);
+        });
         this._accountsMonitor = AccountsMonitor.getDefault();
         this._amIsPrepared = false;
         this._accountsMonitor.prepare(Lang.bind(this, this._onPrepared));
-
-        this._settings = new Gio.Settings({ schema_id: 'org.gnome.Polari' });
     },
 
     _onPrepared: function() {
         let actions = [
-            { name: 'join-room',
-              handler: Lang.bind(this, this._onJoinActivated) },
             { name: 'message-user',
               handler: Lang.bind(this, this._onQueryActivated) },
             { name: 'leave-room',
@@ -219,63 +218,33 @@ const _ChatroomManager = new Lang.Class({
 
         this._accountsMonitor.connect('account-enabled',
                                       Lang.bind(this, this._onAccountEnabled));
-        this._accountsMonitor.connect('account-disabled',
-                                      Lang.bind(this, this._onAccountDisabled));
-        this._accountsMonitor.connect('account-removed',
-                                      Lang.bind(this, this._onAccountDisabled));
         this._accountsMonitor.connect('account-status-changed', Lang.bind(this, function(monitor, account) {
             if (account.connection_status == Tp.ConnectionStatus.CONNECTED)
-                this._restoreSavedChannels(account);
+                this._connectRooms(account);
         }));
 
-        let selectedChannel = this._settings.get_value('last-selected-channel').deep_unpack();
-
-        for (let prop in selectedChannel)
-            selectedChannel[prop] = selectedChannel[prop].deep_unpack();
-
-        if (selectedChannel.account && selectedChannel.channel)
-             this._restoreChannel(selectedChannel);
-
-        this._restoreSavedChannels(null);
+        this._connectRooms(null);
 
         this._networkMonitor.connect('notify::network-available', Lang.bind(this,
             function() {
                 if (this._networkMonitor.network_available)
-                    this._restoreSavedChannels(null);
+                    this._connectRooms(null);
             }));
     },
 
     _onAccountEnabled: function(mon, account) {
-        this._restoreSavedChannels(account);
+        this._connectRooms(account);
     },
 
-    _onAccountDisabled: function(mon, account) {
-        for (let id in this._rooms) {
-            let room = this._rooms[id];
-            if (room.account == account)
-                this._removeRoom(room);
-        }
-    },
-
-    _restoreSavedChannels: function(account) {
-        let savedChannels = this._settings.get_value('saved-channel-list').deep_unpack();
-        for (let i = 0; i < savedChannels.length; i++) {
-            let serializedChannel = savedChannels[i];
-            for (let prop in serializedChannel)
-                serializedChannel[prop] = serializedChannel[prop].deep_unpack();
-
-            if (account == null || serializedChannel.account == account.object_path)
-                this._restoreChannel(serializedChannel);
-        }
+    _connectRooms: function(account) {
+        this._roomManager.rooms.forEach(room => {
+            if (account == null || room.account == account)
+                this._connectRoom(room);
+        });
     },
 
-    _restoreChannel: function(serializedChannel) {
-        let action = this._app.lookup_action('join-room');
-        let parameter = GLib.Variant.new('(ssu)',
-                                        [serializedChannel.account,
-                                         serializedChannel.channel,
-                                         0]);
-        action.activate(parameter);
+    _connectRoom: function(room) {
+        this._requestChannel(room.account, room.type, room.channel_name, null);
     },
 
     _requestChannel: function(account, targetType, targetId, callback) {
@@ -358,21 +327,6 @@ const _ChatroomManager = new Lang.Class({
             }));
     },
 
-    _onJoinActivated: function(action, parameter) {
-        let [accountPath, channelName, time] = parameter.deep_unpack();
-        let account = this._accountsMonitor.lookupAccount(accountPath);
-
-        if (!account || !account.enabled)
-            return;
-
-        let room = this._ensureRoom(account, channelName, Tp.HandleType.ROOM);
-        let [present, ] = Tp.user_action_time_should_present(time);
-        if (present)
-            this._setActiveRoom(room);
-
-        this._requestChannel(account, Tp.HandleType.ROOM, channelName, null);
-    },
-
     _onQueryActivated: function(action, parameter) {
         let [accountPath, channelName, message, time] = parameter.deep_unpack();
         let account = this._accountsMonitor.lookupAccount(accountPath);
@@ -380,24 +334,18 @@ const _ChatroomManager = new Lang.Class({
         if (!account || !account.enabled)
             return;
 
-        let room = this._ensureRoom(account, channelName, Tp.HandleType.CONTACT);
-        let [present, ] = Tp.user_action_time_should_present(time);
-        if (present)
-            this._setActiveRoom(room);
-
         this._requestChannel(account, Tp.HandleType.CONTACT, channelName,
                              Lang.bind(this, this._sendMessage, message));
     },
 
     _onLeaveActivated: function(action, parameter) {
         let [id, message] = parameter.deep_unpack();
-        let room = this._rooms[id];
-        this._removeRoom(room);
 
         let request = this._pendingRequests.get(id);
         if (request)
             request.cancel();
 
+        let room = this._roomManager.lookupRoom(id);
         if (!room.channel)
             return;
 
@@ -412,29 +360,6 @@ const _ChatroomManager = new Lang.Class({
         });
     },
 
-    _ensureRoom: function(account, channelName, type) {
-        let room = this._rooms[Polari.create_room_id(account, channelName, type)];
-        if (room)
-            return room;
-
-        let room = new Polari.Room({ account: account,
-                                     channel_name: channelName,
-                                     type: type });
-        this._addRoom(room);
-
-        return room;
-    },
-
-    _ensureRoomForChannel: function(channel) {
-        let account = channel.connection.get_account();
-        let targetContact = channel.target_contact;
-        let channelName = targetContact ? targetContact.alias
-                                        : channel.identifier;
-        let room = this._ensureRoom(account, channelName, channel.handle_type);
-        room.channel = channel;
-        return room;
-    },
-
     _isAuthChannel: function(channel) {
         return channel.channel_type == Tp.IFACE_CHANNEL_TYPE_SERVER_AUTHENTICATION;
     },
@@ -479,7 +404,7 @@ const _ChatroomManager = new Lang.Class({
                       return;
                 }
 
-                let room = this._ensureRoomForChannel(channel);
+                this._roomManager.ensureRoomForChannel(channel, 0);
             }));
     },
 
@@ -496,52 +421,11 @@ const _ChatroomManager = new Lang.Class({
                     return;
                 }
 
-                let room = this._ensureRoomForChannel(channel);
-                //channel.join_async('', null);
-
-                if (present) {
+                if (present)
                     this._app.activate();
-                    this._setActiveRoom(room);
-                }
-            }));
-    },
-
-    _addRoom: function(room) {
-        if (this._rooms[room.id])
-            return;
-
-        this._rooms[room.id] = room;
-        this.emit('room-added', room);
-    },
-
-    _removeRoom: function(room) {
-        if (!this._rooms[room.id])
-            return;
-
-        if (room == this._lastActiveRoom)
-            this._lastActiveRoom = null;
-
-        delete this._rooms[room.id];
-        this.emit('room-removed', room);
-    },
-
-    _setActiveRoom: function(room) {
-        this._app.active_window.active_room = room;
-    },
 
-    getRoomByName: function(name) {
-        for (let id in this._rooms)
-            if (this._rooms[id].channel_name == name)
-                return this._rooms[id];
-        return null;
-    },
-
-    getRoomById: function(id) {
-        return this._rooms[id];
-    },
-
-    get roomCount() {
-        return Object.keys(this._rooms).length;
+                this._roomManager.ensureRoomForChannel(channel, userTime);
+                //channel.join_async('', null);
+            }));
     }
 });
-Signals.addSignalMethods(_ChatroomManager.prototype);
diff --git a/src/ircParser.js b/src/ircParser.js
index 2be4e04..9528935 100644
--- a/src/ircParser.js
+++ b/src/ircParser.js
@@ -3,8 +3,8 @@ const GLib = imports.gi.GLib;
 const Tp = imports.gi.TelepathyGLib;
 
 const AppNotifications = imports.appNotifications;
-const ChatroomManager = imports.chatroomManager;
 const Lang = imports.lang;
+const RoomManager = imports.roomManager;
 const Signals = imports.signals;
 const Utils = imports.utils;
 
@@ -44,7 +44,7 @@ const IrcParser = new Lang.Class({
 
     _init: function(room) {
         this._app = Gio.Application.get_default();
-        this._roomManager = ChatroomManager.getDefault();
+        this._roomManager = RoomManager.getDefault();
         this._room = room;
     },
 
@@ -220,7 +220,7 @@ const IrcParser = new Lang.Class({
                 let room = null;;
                 let name = argv[0];
                 if (name)
-                    room = this._roomManager.getRoomByName(name);
+                    room = this._roomManager.lookupRoomByName(name);
                 if (room)
                     argv.shift(); // first arg was a room name
                 else
diff --git a/src/mainWindow.js b/src/mainWindow.js
index 85b51d0..51e4239 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -8,11 +8,11 @@ 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;
 const RoomList = imports.roomList;
+const RoomManager = imports.roomManager;
 const RoomStack = imports.roomStack;
 const UserList = imports.userList;
 const Utils = imports.utils;
@@ -167,11 +167,12 @@ const MainWindow = new Lang.Class({
                                       Lang.bind(this, this._onAccountsChanged));
         this._onAccountsChanged(this._accountsMonitor);
 
-        this._roomManager = ChatroomManager.getDefault();
-        this._roomManager.connect('room-added',
-                                  Lang.bind(this, this._onRoomAdded));
+        this._roomManager = RoomManager.getDefault();
+        this._roomManager.connect('rooms-loaded',
+                                  Lang.bind(this, this._onRoomsLoaded));
         this._roomManager.connect('room-removed',
                                   Lang.bind(this, this._onRoomRemoved));
+        this._onRoomsLoaded();
 
         this._updateUserListLabel();
 
@@ -328,10 +329,22 @@ const MainWindow = new Lang.Class({
         );
     },
 
-    _onRoomAdded: function(mgr, room) {
+    _onRoomsLoaded: function(mgr) {
         if (this.active_room)
             return;
-        this.active_room = room;
+
+        let selectedRoom = this._settings.get_value('last-selected-channel').deep_unpack();
+        for (let prop in selectedRoom)
+            selectedRoom[prop] = selectedRoom[prop].deep_unpack();
+
+        let roomId = null;
+        let account = this._accountsMonitor.lookupAccount(selectedRoom.account);
+        let channelName = selectedRoom.channel;
+        if (account && account.enabled && channelName)
+            roomId = Polari.create_room_id(account, channelName, Tp.HandleType.ROOM);
+
+        this.active_room = this._roomManager.lookupRoom(roomId) ||
+                           this._roomManager.rooms.shift();
     },
 
     _onRoomRemoved: function(mgr, room) {
diff --git a/src/org.gnome.Polari.src.gresource.xml b/src/org.gnome.Polari.src.gresource.xml
index 6acfd23..ec4d5a9 100644
--- a/src/org.gnome.Polari.src.gresource.xml
+++ b/src/org.gnome.Polari.src.gresource.xml
@@ -15,6 +15,7 @@
     <file>networksManager.js</file>
     <file>pasteManager.js</file>
     <file>roomList.js</file>
+    <file>roomManager.js</file>
     <file>roomStack.js</file>
     <file>tabCompletion.js</file>
     <file>userList.js</file>
diff --git a/src/roomList.js b/src/roomList.js
index 0600eba..e3bc769 100644
--- a/src/roomList.js
+++ b/src/roomList.js
@@ -7,8 +7,8 @@ const Pango = imports.gi.Pango;
 const Tp = imports.gi.TelepathyGLib;
 
 const AccountsMonitor = imports.accountsMonitor;
-const ChatroomManager = imports.chatroomManager;
 const Lang = imports.lang;
+const RoomManager = imports.roomManager;
 
 function _onPopoverVisibleChanged(popover) {
     let context = popover.relative_to.get_style_context();
@@ -370,16 +370,15 @@ const RoomList = new Lang.Class({
             });
         });
 
-        this._roomManager = ChatroomManager.getDefault();
+        this._roomManager = RoomManager.getDefault();
         this._roomManager.connect('room-added',
                                   Lang.bind(this, this._roomAdded));
         this._roomManager.connect('room-removed',
                                   Lang.bind(this, this._roomRemoved));
+        this._roomManager.rooms.forEach(r => { this._roomAdded(this._roomManager, r); });
 
         let app = Gio.Application.get_default();
         let actions = [
-            { name: 'leave-room',
-              handler: Lang.bind(this, this._onLeaveActivated) },
             { name: 'next-room',
               handler: () => { this._moveSelection(Gtk.DirectionType.DOWN); } },
             { name: 'previous-room',
@@ -416,14 +415,6 @@ const RoomList = new Lang.Class({
         this._activeRoomChanged();
     },
 
-    _onLeaveActivated: function(action, param) {
-        let [id, ] = param.deep_unpack();
-        let row = this._roomRows.get(id);
-
-        this._moveSelectionFromRow(row);
-        row.hide();
-    },
-
     _rowToRoomIndex: function(index) {
         let placeholders = [...this._placeholders.values()];
         let nBefore = placeholders.filter(p => p.get_index() < index).length;
diff --git a/src/roomManager.js b/src/roomManager.js
new file mode 100644
index 0000000..41419b9
--- /dev/null
+++ b/src/roomManager.js
@@ -0,0 +1,206 @@
+const Gio = imports.gi.Gio;
+const GLib = imports.gi.GLib;
+const Polari = imports.gi.Polari;
+const Tp = imports.gi.TelepathyGLib;
+
+const AccountsMonitor = imports.accountsMonitor;
+const Lang = imports.lang;
+const Signals = imports.signals;
+
+let _singleton = null;
+
+function getDefault() {
+    if (_singleton == null)
+        _singleton = new _RoomManager();
+    return _singleton;
+}
+
+const _RoomManager = new Lang.Class({
+    Name: '_RoomManager',
+
+    _init: function() {
+        this._rooms = new Map();
+        this._settings = new Gio.Settings({ schema_id: 'org.gnome.Polari' })
+
+        this._accountsMonitor = AccountsMonitor.getDefault();
+
+        this._app = Gio.Application.get_default();
+        let actions = [
+            { name: 'join-room',
+              handler: Lang.bind(this, this._onJoinActivated) },
+            { name: 'message-user',
+              handler: Lang.bind(this, this._onQueryActivated) },
+            { name: 'leave-room',
+              after: true,
+              handler: Lang.bind(this, this._onLeaveActivated) }
+        ];
+        actions.forEach(a => {
+            if (a.after)
+                this._app.lookup_action(a.name).connect_after('activate', a.handler);
+            else
+                this._app.lookup_action(a.name).connect('activate', a.handler);
+        });
+
+        this._accountsMonitor.connect('account-enabled', (mon, account) => {
+            this._restoreRooms(account.object_path);
+        });
+        this._accountsMonitor.connect('account-disabled', (mon, account) => {
+            this._removeRooms(account.object_path);
+        });
+        this._accountsMonitor.connect('account-removed', (mon, account) => {
+            this._removeRooms(account.object_path);
+            this._removeSavedChannelsForAccount(account.object_path);
+        });
+        this._accountsMonitor.prepare(() => { this._restoreRooms(); });
+    },
+
+    lookupRoom: function(id) {
+        return this._rooms.get(id);
+    },
+
+    lookupRoomByName: function(name) {
+        for (let room of this._rooms.values())
+            if (room.channel_name == name)
+                return room;
+        return null;
+    },
+
+    lookupRoomByChannel: function(channel) {
+        let account = channel.connection.get_account();
+        let channelName = channel.identifier;
+        let id = Polari.create_room_id(account, channelName, channel.handle_type);
+        return this._rooms.get(id);
+    },
+
+    get roomCount() {
+        return this._rooms.size;
+    },
+
+    get rooms() {
+        return [...this._rooms.values()];
+    },
+
+    _onJoinActivated: function(action, parameter) {
+        let [accountPath, channelName, time] = parameter.deep_unpack();
+        this._addSavedChannel(accountPath, channelName);
+
+        this._accountsMonitor.prepare(() => {
+            this._ensureRoom(accountPath, channelName, Tp.HandleType.ROOM, time);
+        });
+    },
+
+    _onQueryActivated: function(action, parameter) {
+        let [accountPath, channelName, time, ] = parameter.deep_unpack();
+
+        this._accountsMonitor.prepare(() => {
+            this._ensureRoom(accountPath, channelName, Tp.HandleType.CONTACT, time);
+        });
+    },
+
+    _onLeaveActivated: function(action, parameter) {
+        let [id, ] = parameter.deep_unpack();
+        let room = this._rooms.get(id);
+
+        this._removeSavedChannel(room.account.object_path, room.channel_name);
+        this._removeRoom(room);
+    },
+
+    _restoreRooms: function(accountPath) {
+        this._settings.get_value('saved-channel-list').deep_unpack().forEach(c => {
+            for (let prop in c)
+                c[prop] = c[prop].deep_unpack();
+            if (accountPath == null || c.account == accountPath)
+                this._ensureRoom(c.account, c.channel, Tp.HandleType.ROOM, 0)
+        });
+        this.emit('rooms-loaded');
+    },
+
+    _removeRooms: function(accountPath) {
+        for (let room of this._rooms.values())
+            if (accountPath == null || room.account.object_path == accountPath)
+                this._removeRoom(room);
+    },
+
+    _findChannelIndex: function(channels, accountPath, channelName) {
+        let matchName = channelName.toLowerCase();
+        for (let i = 0; i < channels.length; i++)
+            if (channels[i].account.deep_unpack() == accountPath &&
+                channels[i].channel.deep_unpack().toLowerCase() == matchName)
+            return i;
+        return -1;
+    },
+
+    _addSavedChannel: function(accountPath, channelName) {
+        let channels = this._settings.get_value('saved-channel-list').deep_unpack();
+        if (this._findChannelIndex(channels, accountPath, channelName) != -1)
+            return;
+        channels.push({
+            account: new GLib.Variant('s', accountPath),
+            channel: new GLib.Variant('s', channelName)
+        });
+        this._settings.set_value('saved-channel-list',
+                                 new GLib.Variant('aa{sv}', channels));
+    },
+
+    _removeSavedChannel: function(accountPath, channelName) {
+        let channels = this._settings.get_value('saved-channel-list').deep_unpack();
+        let pos = this._findChannelIndex(channels, accountPath, channelName);
+        if (pos < 0)
+            return;
+        channels.splice(pos, 1);
+        this._settings.set_value('saved-channel-list',
+                                 new GLib.Variant('aa{sv}', channels));
+    },
+
+    _removeSavedChannelsForAccount: function(accountPath) {
+        let channels = this._settings.get_value('saved-channel-list').deep_unpack();
+        let account = new GLib.Variant('s', accountPath);
+
+        channels = channels.filter(c => !c.account.equal(account));
+        this._settings.set_value('saved-channel-list',
+                                 new GLib.Variant('aa{sv}', channels));
+    },
+
+    _ensureRoom: function(accountPath, channelName, type, time) {
+        let account = this._accountsMonitor.lookupAccount(accountPath);
+
+        if (!account) {
+            this._removeSavedChannelsForAccount(accountPath);
+            return null;
+        }
+
+        if (!account.enabled)
+            return null;
+
+        let id = Polari.create_room_id(account, channelName, type);
+        let room = this._rooms.get(id);
+        if (!room) {
+            room = new Polari.Room({ account: account,
+                                     channel_name: channelName,
+                                     type: type });
+            this._rooms.set(room.id, room);
+            this.emit('room-added', room);
+        }
+
+        let [present, ] = Tp.user_action_time_should_present(time);
+        if (present && this._app.active_window)
+            this._app.active_window.active_room = room;
+
+        return room;
+    },
+
+    ensureRoomForChannel: function(channel, time) {
+        let accountPath = channel.connection.get_account().object_path;
+        let targetContact = channel.target_contact;
+        let channelName = targetContact ? targetContact.alias
+                                        : channel.identifier;
+        let room = this._ensureRoom(accountPath, channelName, channel.handle_type, time);
+        room.channel = channel;
+    },
+
+    _removeRoom: function(room) {
+        if (this._rooms.delete(room.id))
+            this.emit('room-removed', room);
+    }
+});
+Signals.addSignalMethods(_RoomManager.prototype);
diff --git a/src/roomStack.js b/src/roomStack.js
index 6ede912..d8e444c 100644
--- a/src/roomStack.js
+++ b/src/roomStack.js
@@ -4,10 +4,10 @@ const GObject = imports.gi.GObject;
 const Gtk = imports.gi.Gtk;
 
 const AccountsMonitor = imports.accountsMonitor;
-const ChatroomManager = imports.chatroomManager;
 const ChatView = imports.chatView;
 const EntryArea = imports.entryArea;
 const Lang = imports.lang;
+const RoomManager = imports.roomManager;
 
 const RoomStack = new Lang.Class({
     Name: 'RoomStack',
@@ -26,12 +26,13 @@ const RoomStack = new Lang.Class({
         this._sizeGroup = new Gtk.SizeGroup({ mode: Gtk.SizeGroupMode.VERTICAL });
         this._rooms = new Map();
 
-        this._roomManager = ChatroomManager.getDefault();
+        this._roomManager = RoomManager.getDefault();
 
         this._roomManager.connect('room-added',
                                   Lang.bind(this, this._roomAdded));
         this._roomManager.connect('room-removed',
                                   Lang.bind(this, this._roomRemoved));
+        this._roomManager.rooms.forEach(r => { this._roomAdded(this._roomManager, r); });
 
         this.add_named(new ChatPlaceholder(this._sizeGroup), 'placeholder');
 


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