[polari/wip/bastianilso/error-handling: 3/3] WIP: Show room error



commit 75658954ab1c7158c552fb59d4cbce2d0ae3a4f6
Author: Bastian Ilsø <bastianilso gnome org>
Date:   Thu Aug 13 18:00:36 2015 +0200

    WIP: Show room error

 src/application.js |   18 +++++++++++++++
 src/roomList.js    |   38 +++++++++++++++++++++++++++++++-
 src/roomStack.js   |   61 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 114 insertions(+), 3 deletions(-)
---
diff --git a/src/application.js b/src/application.js
index 318e949..f99c985 100644
--- a/src/application.js
+++ b/src/application.js
@@ -288,6 +288,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) {
@@ -326,9 +328,25 @@ 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');
+        } finally {
+            log('requestDatas target id is: ' + requestData.targetId);
+            if (requestData.targetId == '#nautilus') {
+                log('setting error to Tp.Error.Channel.Is.Full');
+                requestData.status = 'disconnected';
+                requestData.error = Tp.error_get_dbus_name(Tp.Error.CHANNEL_FULL);
+                this.emitJS('room-status-changed', requestData);
+            }
         }
 
+        if (requestData.targetId == '#nautilus')
+            return;
+
+        requestData.status = 'connected';
+        this.emitJS('room-status-changed', requestData);
+
         if (requestData.retry > 0)
             this._updateAccountName(account, requestData.originalNick, null);
         delete this._pendingRequests[requestData.roomId];
diff --git a/src/roomList.js b/src/roomList.js
index 2d578fb..ae5e34f 100644
--- a/src/roomList.js
+++ b/src/roomList.js
@@ -84,6 +84,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 });
 
@@ -112,11 +134,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';
     }
 });
 
@@ -307,6 +337,12 @@ const RoomList = new Lang.Class({
         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');
diff --git a/src/roomStack.js b/src/roomStack.js
index dae4c6d..8e8ce09 100644
--- a/src/roomStack.js
+++ b/src/roomStack.js
@@ -1,5 +1,7 @@
 const Gio = imports.gi.Gio;
 const Gtk = imports.gi.Gtk;
+const Tp = imports.gi.TelepathyGLib;
+const GLib = imports.gi.GLib;
 
 const AccountsMonitor = imports.accountsMonitor;
 const ChatroomManager = imports.chatroomManager;
@@ -7,6 +9,8 @@ const ChatView = imports.chatView;
 const EntryArea = imports.entryArea;
 const Lang = imports.lang;
 
+const TP_CURRENT_TIME = GLib.MAXUINT32;
+
 const RoomStack = new Lang.Class({
     Name: 'RoomStack',
 
@@ -26,6 +30,17 @@ const RoomStack = new Lang.Class({
                                   Lang.bind(this, this._activeRoomChanged));
         this._roomManager.connect('active-state-changed',
                                   Lang.bind(this, this._updateSensitivity));
+        let app = Gio.Application.get_default();
+        app.connectJS('room-status-changed', Lang.bind(this,
+            function(app, requestData) {
+                let id = requestData.roomId;
+                if (!this._rooms[id])
+                    return;
+                if (requestData.status == 'disconnected')
+                    this._rooms[id].showError(requestData.error);
+                else
+                    this._rooms[id].hideError();
+            }));
 
         this._rooms = {};
 
@@ -155,6 +170,26 @@ const RoomView = new Lang.Class({
         this._entryArea = new EntryArea.EntryArea(room);
 
         this.widget = new Gtk.Box({ orientation: Gtk.Orientation.VERTICAL });
+
+        this._revealer = new Gtk.Revealer({ transition_type: Gtk.RevealerTransitionType.SLIDE_DOWN });
+        this._infobar = new Gtk.InfoBar({ message_type: Gtk.MessageType.ERROR });
+        this._errorLabel = new Gtk.Label({ halign: Gtk.Align.START });
+        this._button = new Gtk.Button({ label: _("Retry") });
+        this._button.connect('clicked', Lang.bind(this,
+            function() {
+                let app = Gio.Application.get_default();
+                let action = app.lookup_action('join-room');
+                action.activate(GLib.Variant.new('(ssu)',
+                                                [ this._room.account.get_object_path(),
+                                                  '#' + this._room.display_name,
+                                                  TP_CURRENT_TIME ]));
+            }));
+        this._infobar.get_content_area().add(new Gtk.Image({ icon_name: 'dialog-error-symbolic' }));
+        this._infobar.get_content_area().add(this._errorLabel);
+        this._infobar.get_action_area().add(this._button);
+        this._revealer.add(this._infobar);
+        this.widget.add(this._revealer);
+
         this.widget.add(this._view.widget);
 
         this.inputWidget = new Gtk.Frame();
@@ -162,11 +197,33 @@ const RoomView = new Lang.Class({
         this.widget.add(this.inputWidget);
 
         this.inputWidget.add(this._entryArea.widget);
-
+        this._room = room;
         this.widget.show_all();
     },
 
     set inputSensitive(sensitive) {
         this._entryArea.widget.sensitive = sensitive;
-    }
+    },
+
+    showError: function(error) {
+        this._errorLabel.label = this._getMessageFromError(error);
+        this._revealer.reveal_child = true;
+
+    },
+
+    _getMessageFromError: function (error) {
+        log(error);
+        if (error == Tp.error_get_dbus_name(Tp.Error.CHANNEL_BANNED))
+            return _("You are banned from this room.");
+        else if (error == Tp.error_get_dbus_name(Tp.Error.CHANNEL_FULL))
+            return _("The room is full.");
+        else if (error == Tp.error_get_dbus_name(Tp.Error.CHANNEL_INVITE_ONLY))
+            return _("The room is invite-only.");
+        else
+            return _("Failed to connect for an unknown reason.");
+    },
+
+    hideError: function() {
+        this._revealer.reveal_child = false;
+    },
 });


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