[polari/wip/bastianilso/error-handling: 1/4] Indicate server and room status in the roomList instead



commit a4dbb3309ee28193d63f7b6e547b9e3832757d13
Author: Bastian Ilsø <bastianilso src gnome org>
Date:   Sun Aug 2 17:05:24 2015 +0200

    Indicate server and room status in the roomList instead
    
    Instead of displaying notifications when connecting to
    a server, use less attention grabbing status indicators in
    the roomlist for displaying status of the rooms and servers
    individually.

 src/appNotifications.js |   34 -----------------
 src/application.js      |    6 +++
 src/mainWindow.js       |   26 -------------
 src/roomList.js         |   94 ++++++++++++++++++++++++++++++++++++++++++++--
 4 files changed, 95 insertions(+), 65 deletions(-)
---
diff --git a/src/appNotifications.js b/src/appNotifications.js
index 694c422..24d6009 100644
--- a/src/appNotifications.js
+++ b/src/appNotifications.js
@@ -89,40 +89,6 @@ const GridOutput = new Lang.Class({
     }
 });
 
-const ConnectingNotification = new Lang.Class({
-    Name: 'ConnectingNotification',
-    Extends: AppNotification,
-
-    _init: function(account) {
-        this.parent();
-
-        this._grid = new Gtk.Grid({ orientation: Gtk.Orientation.HORIZONTAL,
-                                    column_spacing: 12 });
-
-        this._grid.add(new Gtk.Spinner({ active: true }));
-
-        let text = _("Connecting to %s").format(account.display_name);
-        let label = new Gtk.Label({ label: text });
-        this._grid.add(label);
-
-        this.widget.add(this._grid);
-        this.widget.show_all();
-
-        let id = account.connect('notify::connection-status',
-                                 Lang.bind(this, this._onConnectionStatusChanged));
-        this.widget.connect('destroy',
-            function() {
-                account.disconnect(id);
-            });
-    },
-
-    _onConnectionStatusChanged: function(account) {
-        if (account.connection_status == Tp.ConnectionStatus.CONNECTING)
-            return;
-        this.close();
-    }
-});
-
 const NotificationQueue = new Lang.Class({
     Name: 'NotificationQueue',
 
diff --git a/src/application.js b/src/application.js
index 7262bfd..673d664 100644
--- a/src/application.js
+++ b/src/application.js
@@ -282,6 +282,8 @@ const Application = new Lang.Class({
         req.ensure_channel_async(preferredHandler, requestData.cancellable,
                                  Lang.bind(this,
                                            this._onEnsureChannel, requestData));
+        requestData.status = 'connecting';
+        this.emitJS('room-status-changed', requestData);
     },
 
     _retryRequest: function(requestData) {
@@ -318,8 +320,12 @@ const Application = new Lang.Class({
         } catch (e if e.matches(Tp.Error, Tp.Error.CANCELLED)) {
             // interrupted by user request, don't log
         } catch (e) {
+            requestData.status = 'disconnected';
+            this.emitJS('room-status-changed', requestData);
             logError(e, 'Failed to ensure channel');
         }
+        requestData.status = 'connected';
+        this.emitJS('room-status-changed', requestData);
 
         if (requestData.retry > 0)
             this._updateAccountName(account, requestData.originalNick, null);
diff --git a/src/mainWindow.js b/src/mainWindow.js
index 6e6ad86..a92358f 100644
--- a/src/mainWindow.js
+++ b/src/mainWindow.js
@@ -54,12 +54,6 @@ const MainWindow = new Lang.Class({
             Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION
         );
 
-        this._accountsMonitor = AccountsMonitor.getDefault();
-        this._accountsMonitor.connect('account-status-changed',
-                                      Lang.bind(this, this._onAccountChanged));
-        this._accountsMonitor.connect('account-added',
-                                      Lang.bind(this, this._onAccountChanged));
-
         this._roomManager = ChatroomManager.getDefault();
         this._roomManager.connect('active-changed',
                                   Lang.bind(this, this._activeRoomChanged));
@@ -119,26 +113,6 @@ const MainWindow = new Lang.Class({
                                  GLib.Variant.new('ai', this._currentSize));
     },
 
-    _onAccountChanged: function(am, account) {
-        if (account.connection_status != Tp.ConnectionStatus.CONNECTING)
-            return;
-
-        if (account._connectingNotification)
-            return;
-
-        let app = Gio.Application.get_default();
-        let notification = new AppNotifications.ConnectingNotification(account);
-        app.notificationQueue.addNotification(notification);
-        app.mark_busy();
-
-        account._connectingNotification = notification;
-        notification.widget.connect('destroy',
-            function() {
-                app.unmark_busy();
-                delete account._connectingNotification;
-            });
-    },
-
     _updateDecorations: function() {
         let layoutLeft = null;
         let layoutRight = null;
diff --git a/src/roomList.js b/src/roomList.js
index f7ee09f..122bbe3 100644
--- a/src/roomList.js
+++ b/src/roomList.js
@@ -8,6 +8,7 @@ const Tp = imports.gi.TelepathyGLib;
 
 const ChatroomManager = imports.chatroomManager;
 const Lang = imports.lang;
+const Mainloop = imports.mainloop;
 
 const RoomRow = new Lang.Class({
     Name: 'RoomRow',
@@ -82,6 +83,28 @@ const RoomRow = new Lang.Class({
         return Gdk.EVENT_STOP;
     },
 
+    updateRoomStatus: function(requestData) {
+        this._status = requestData.status;
+        let child = 'messages';
+
+        if (requestData.status == 'connecting') {
+            // Only show spinner if it takes more than 3 seconds to join the room
+            // and if we are waiting for the room itself (not the connection).
+            Mainloop.timeout_add(3000, Lang.bind(this,
+                function() {
+                    if (requestData.account.connection_status != Tp.ConnectionStatus.CONNECTED)
+                        return GLib.SOURCE_CONTINUE;
+                    else if (this._status == 'connecting')
+                        this._stack.visible_child_name = 'connecting';
+                    return GLib.SOURCE_REMOVE;
+                }));
+        } else if (requestData.status == 'disconnected') {
+            child = 'error';
+        }
+
+        this._stack.visible_child_name = child;
+    },
+
     _createWidget: function(gicon) {
         this.widget = new Gtk.ListBoxRow({ margin_bottom: 4 });
 
@@ -110,11 +133,19 @@ const RoomRow = new Lang.Class({
                                           shadow_type: Gtk.ShadowType.NONE });
         box.add(frame);
 
+        this._stack = new Gtk.Stack({ vhomogeneous: true, valign: Gtk.Align.CENTER });
+        this._stack.transition_type = Gtk.StackTransitionType.CROSSFADE;
+        let error = new Gtk.Image({icon_name: 'dialog-error-symbolic', halign: Gtk.Align.START });
+        this._stack.add_named(error, 'error');
         this._counter = new Gtk.Label({ width_chars: 2 });
         this._counter.get_style_context().add_class('pending-messages-count');
-        frame.add(this._counter);
+        this._stack.add_named(this._counter, 'messages');
+        let connecting = new Gtk.Spinner({active: true, halign: Gtk.Align.START });
+        this._stack.add_named(connecting, 'connecting');
+        frame.add(this._stack);
 
         this.widget.show_all();
+        this._stack.visible_child_name = 'messages';
     }
 });
 
@@ -143,11 +174,20 @@ const RoomList = new Lang.Class({
         this._roomManager.connect('active-changed',
                                   Lang.bind(this, this._activeRoomChanged));
 
+        this._networkMonitor = Gio.NetworkMonitor.get_default();
+
         let app = Gio.Application.get_default();
         this._leaveAction = app.lookup_action('leave-room');
         this._leaveAction.connect('activate',
                                   Lang.bind(this, this._onLeaveActivated));
 
+        app.connectJS('room-status-changed', Lang.bind(this,
+            function(app, requestData) {
+                let roomRow = this._roomRows[requestData.roomId];
+                if (roomRow)
+                    this._roomRows[requestData.roomId].updateRoomStatus(requestData);
+            }));
+
         let action;
         action = app.lookup_action('next-room');
         action.connect('activate', Lang.bind(this,
@@ -281,14 +321,58 @@ const RoomList = new Lang.Class({
         if (row.get_header())
             return;
 
-        let label = new Gtk.Label({ margin_bottom: 4, xalign: 0,
+        let hbox = new Gtk.Box({ margin_bottom: 4, spacing: 2, hexpand: true,
+                                orientation: Gtk.Orientation.HORIZONTAL, visible: true });
+        hbox.get_style_context().add_class('room-list-header');
+
+        let label = new Gtk.Label({ xalign: 0, margin: 4,
                                     max_width_chars: 15,
                                     ellipsize: Pango.EllipsizeMode.END });
-        label.get_style_context().add_class('room-list-header');
-
         account.bind_property('display-name', label, 'label',
                               GObject.BindingFlags.SYNC_CREATE);
-        row.set_header(label);
+        hbox.add(label);
+
+        let icon = new Gtk.Stack({ vhomogeneous: true, valign: Gtk.Align.CENTER });
+        icon.transition_type = Gtk.StackTransitionType.CROSSFADE;
+
+        let error = new Gtk.Image({icon_name: 'dialog-error-symbolic',halign: Gtk.Align.START });
+        icon.add_named(error, 'error');
+
+        let connecting = new Gtk.Spinner({active: true, halign: Gtk.Align.START });
+        icon.add_named(connecting, 'connecting');
+
+        icon.add_named(new Gtk.Box({visible: false}), 'none');
+
+        let displayStatus = function(binding) {
+            let status = binding.source.connection_status;
+            let reason = binding.source.connection_status_reason;
+            binding.target.visible_child_name = this._evaluateStatus(status, reason);
+        }
+
+        account.bind_property_full('connection-status', icon, 'visible-child-name',
+                                    GObject.BindingFlags.DEFAULT, Lang.bind(this, displayStatus), 
function(){});
+        hbox.add(icon);
+        hbox.show_all();
+
+        let status = account.connection_status;
+        let reason = account.connection_status_reason;
+        icon.visible_child_name = this._evaluateStatus(status, reason)
+
+        row.set_header(hbox);
+    },
+
+    _evaluateStatus: function(status, reason) {
+        let child = 'none';
+
+        if (status == Tp.ConnectionStatus.CONNECTING) {
+            if (this._networkMonitor.network_available)
+                child = 'connecting';
+        } else if (status == Tp.ConnectionStatus.DISCONNECTED) {
+            if (reason != Tp.ConnectionStatusReason.REQUESTED)
+                child = 'error';
+        }
+
+        return child;
     },
 
     _sort: function(row1, row2) {



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