[polari/wip/fmuellner/nickserv: 4/21] chatroomManager: Handle channel requests



commit 411fdbc293d7b9b1fc3d8eabf7a7d7e637644526
Author: Florian Müllner <fmuellner gnome org>
Date:   Thu Aug 4 14:27:07 2016 +0200

    chatroomManager: Handle channel requests
    
    ChatroomManager already handles most connection-related actions - handling
    and observing channels and (re)connecting accounts. It makes sense to assume
    control over the remaining bit as well, and handle requesting new channels
    as well.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=769655

 po/POTFILES.in         |    1 +
 src/application.js     |  120 +++++++++---------------------------------------
 src/chatroomManager.js |   78 +++++++++++++++++++++++++++++++-
 3 files changed, 100 insertions(+), 99 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index c011eeb..5ea0453 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,6 +12,7 @@ data/resources/room-list-header.ui
 data/resources/user-list-details.ui
 src/application.js
 src/appNotifications.js
+src/chatroomManager.js
 src/chatView.js
 src/connections.js
 src/entryArea.js
diff --git a/src/application.js b/src/application.js
index 6bdc04b..3110617 100644
--- a/src/application.js
+++ b/src/application.js
@@ -29,7 +29,6 @@ const Application = new Lang.Class({
 
         GLib.set_application_name('Polari');
         this._window = null;
-        this._pendingRequests = new Map();
         this._retryData = new Map();
     },
 
@@ -38,7 +37,6 @@ const Application = new Lang.Class({
 
         this._chatroomManager = ChatroomManager.getDefault();
         this._accountsMonitor = AccountsMonitor.getDefault();
-        this._networkMonitor = Gio.NetworkMonitor.get_default();
         this._networksManager = NetworksManager.getDefault();
 
         this._accountsMonitor.connect('account-removed', Lang.bind(this,
@@ -141,12 +139,8 @@ const Application = new Lang.Class({
     vfunc_activate: function() {
         if (!this._window) {
             this._window = new MainWindow.MainWindow({ application: this });
-            this._window.connect('destroy', Lang.bind(this,
-                function() {
-                    for (let request of this._pendingRequests.values())
-                        request.cancel();
-                    this.emit('prepare-shutdown');
-            }));
+            this._window.connect('destroy',
+                                 () => { this.emit('prepare-shutdown'); });
             this._window.show_all();
 
             this._chatroomManager.lateInit();
@@ -327,7 +321,7 @@ const Application = new Lang.Class({
                                  GLib.Variant.new('aa{sv}', savedChannels));
     },
 
-    _requestChannel: function(accountPath, targetType, targetId, time, callback) {
+    _handleJoinQueryAction: function(accountPath, time) {
         let [present, ] = Tp.user_action_time_should_present(time);
 
         if (!this._window || present)
@@ -335,40 +329,28 @@ const Application = new Lang.Class({
 
         let account = this._accountsMonitor.lookupAccount(accountPath);
 
-        if (!account || !account.enabled) {
-            // the account was removed since the channel was saved
+        // 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)
-                this._removeSavedChannelsForAccount(accountPath);
-            return;
-        }
+                return;
 
-        if (!this._networkMonitor.network_available)
-            return;
+            this._handleJoinQueryAction(accountPath, time);
+            this._addSavedChannel(account, channelName);
+        });
+    },
 
-        let roomId = Polari.create_room_id(account,  targetId, targetType);
-        let cancellable = new Gio.Cancellable();
-        this._pendingRequests.set(roomId, cancellable);
-
-        // We already focused the room, so passing on the time to telepathy
-        // would have no effect at best, but could steal the focus when the
-        // user switched to a different room before the request completes
-        let req = Tp.AccountChannelRequest.new_text(account, 0);
-        req.set_target_id(targetType, targetId);
-        req.set_delegate_to_preferred_handler(true);
-        let preferredHandler = Tp.CLIENT_BUS_NAME_BASE + 'Polari';
-        req.ensure_and_observe_channel_async(preferredHandler, cancellable,
-            (o, res) => {
-                let channel = null;
-                try {
-                    channel = req.ensure_and_observe_channel_finish(res);
-                } catch(e) {
-                    Utils.debug('Failed to ensure channel: ' + e.message);
-                }
-
-                if (callback)
-                    callback(channel);
-                delete this._pendingRequests[roomId];
-            });
+    _onMessageUser: function(action, parameter) {
+        let [accountPath, contactName, message, time] = parameter.deep_unpack();
+        this._accountsMonitor.prepare(() => {
+            this._handleJoinQueryAction(accountPath, time);
+        });
     },
 
     _ensureRetryData: function(account) {
@@ -471,65 +453,7 @@ const Application = new Lang.Class({
         this._restoreAccountName(account);
     },
 
-    _onJoinRoom: function(action, parameter) {
-        let [accountPath, channelName, time] = parameter.deep_unpack();
-
-        this._accountsMonitor.prepare(() => {
-            let account = this._accountsMonitor.lookupAccount(accountPath);
-            if (!account)
-                return;
-
-            this._requestChannel(accountPath, Tp.HandleType.ROOM,
-                                 channelName, time);
-            this._addSavedChannel(account, channelName);
-        });
-    },
-
-    _onMessageUser: function(action, parameter) {
-        let [accountPath, contactName, message, time] = parameter.deep_unpack();
-        this._accountsMonitor.prepare(() => {
-            this._requestChannel(accountPath, Tp.HandleType.CONTACT,
-                                 contactName, time, Lang.bind(this, this._sendMessage, message));
-        });
-    },
-
-    _sendMessage: function(channel, message) {
-        if (!message || !channel)
-            return;
-
-        let TpMessage = Tp.ClientMessage.new_text(Tp.ChannelTextMessageType.NORMAL,
-                                                  message);
-        channel.send_message_async(TpMessage, 0, Lang.bind(this,
-            function(c, res) {
-            try {
-                c.send_message_finish(res);
-            } catch(e) {
-                // TODO: propagate to user
-                logError(e, 'Failed to send message')
-            }
-        }));
-    },
-
     _onLeaveRoom: function(action, parameter) {
-        let [roomId, message] = parameter.deep_unpack();
-        let reason = Tp.ChannelGroupChangeReason.NONE;
-        let room = this._chatroomManager.getRoomById(roomId);
-        if (!room)
-            return;
-        if (this._pendingRequests.has(roomId)) {
-            this._pendingRequests.get(roomId).cancel();
-        } else if (room.channel) {
-            if (!message.length)
-                message = _("Good Bye"); // TODO - our first setting?
-            room.channel.leave_async(reason, message, Lang.bind(this,
-                function(c, res) {
-                    try {
-                        c.leave_finish(res);
-                    } catch(e) {
-                        logError(e, 'Failed to leave channel');
-                    }
-                }));
-        }
         this._removeSavedChannel(room.account, room.channel_name);
     },
 
diff --git a/src/chatroomManager.js b/src/chatroomManager.js
index 6b7d10e..58912bf 100644
--- a/src/chatroomManager.js
+++ b/src/chatroomManager.js
@@ -148,6 +148,11 @@ const _ChatroomManager = new Lang.Class({
         this._rooms = {};
 
         this._app = Gio.Application.get_default();
+        this._app.connect('prepare-shutdown', () => {
+            [...this._pendingRequests.values()].forEach(r => { r.cancel(); });
+        });
+
+        this._pendingRequests = new Map();
 
         this._networkMonitor = Gio.NetworkMonitor.get_default();
         this._accountsMonitor = AccountsMonitor.getDefault();
@@ -273,6 +278,55 @@ const _ChatroomManager = new Lang.Class({
         action.activate(parameter);
     },
 
+    _requestChannel: function(account, targetType, targetId, callback) {
+        if (!account || !account.enabled)
+            return;
+
+        let roomId = Polari.create_room_id(account,  targetId, targetType);
+
+        let cancellable = new Gio.Cancellable();
+        this._pendingRequests.set(roomId, cancellable);
+
+        // Always use a timestamp of 0 for channels we request - rooms that
+        // the users requests are focused when handling the corresponding
+        // action, so presenting the room after the requests completes has
+        // no effect at best, but could steal the focus when the user switched
+        // to a different room in the meantime
+        let req = Tp.AccountChannelRequest.new_text(account, 0);
+        req.set_target_id(targetType, targetId);
+        req.set_delegate_to_preferred_handler(true);
+
+        let preferredHandler = Tp.CLIENT_BUS_NAME_BASE + 'Polari';
+        req.ensure_and_observe_channel_async(preferredHandler, cancellable,
+            (o, res) => {
+                let channel = null;
+                try {
+                    channel = req.ensure_and_observe_channel_finish(res);
+                } catch(e) {
+                    Utils.debug('Failed to ensure channel: ' + e.message);
+                }
+
+                if (callback)
+                    callback(channel);
+                this._pendingRequests.delete(roomId);
+            });
+    },
+
+    _sendMessage: function(channel, message) {
+        if (!message || !channel)
+            return;
+
+        let type = Tp.ChannelTextMessageType.NORMAL;
+        channel.send_message_async(Tp.ClientMessage.new_text(type, message), 0,
+            (c, res) => {
+                try {
+                    c.send_message_finish(res);
+                } catch(e) {
+                    log('Failed to send message: ' + e.message);
+                }
+            });
+    },
+
     _onConnectAccountActivated: function(action, parameter) {
         let accountPath = parameter.deep_unpack();
         let account = this._accountsMonitor.lookupAccount(accountPath);
@@ -315,6 +369,8 @@ const _ChatroomManager = new Lang.Class({
         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) {
@@ -328,12 +384,32 @@ const _ChatroomManager = new Lang.Class({
         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, ] = parameter.deep_unpack();
+        let [id, message] = parameter.deep_unpack();
         let room = this._rooms[id];
         this._removeRoom(room);
+
+        let request = this._pendingRequests.get(id);
+        if (request)
+            request.cancel();
+
+        if (!room.channel)
+            return;
+
+        let reason = Tp.ChannelGroupChangeReason.NONE;
+        message = message || _("Good Bye");
+        room.channel.leave_async(reason, message, (c, res) => {
+            try {
+                c.leave_finish(res);
+            } catch(e) {
+                log('Failed to leave channel: ' + e.message);
+            }
+        });
     },
 
     _ensureRoom: function(account, channelName, type) {


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