From 43f4682ec40414d9cc32c01119c93d8b025761cc Mon Sep 17 00:00:00 2001 From: "Jasper St. Pierre" Date: Sun, 13 Oct 2013 23:06:09 -0400 Subject: [PATCH] messageTray: Make addButton/addAction take a callback This is a much simpler API for consumers to manage. https://bugzilla.gnome.org/show_bug.cgi?id=710137 --- js/ui/components/telepathyClient.js | 128 +++++++++++----------------- js/ui/messageTray.js | 37 ++++---- js/ui/notificationDaemon.js | 17 ++-- js/ui/overview.js | 6 +- js/ui/status/bluetooth.js | 48 ++++++----- 5 files changed, 99 insertions(+), 137 deletions(-) diff --git a/js/ui/components/telepathyClient.js b/js/ui/components/telepathyClient.js index 16c5f6712..739bb9064 100644 --- a/js/ui/components/telepathyClient.js +++ b/js/ui/components/telepathyClient.js @@ -1095,22 +1095,16 @@ const RoomInviteNotification = new Lang.Class({ * for example. */ this.addBody(_("%s is inviting you to join %s").format(inviter.get_alias(), channel.get_identifier())); - this.addAction('decline', _("Decline")); - this.addAction('accept', _("Accept")); - - this.connect('action-invoked', Lang.bind(this, function(self, action) { - switch (action) { - case 'decline': - dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, - '', function(src, result) { - src.leave_channels_finish(result)}); - break; - case 'accept': - dispatchOp.handle_with_time_async('', global.get_current_time(), - function(src, result) { - src.handle_with_time_finish(result)}); - break; - } + this.addAction(_("Decline"), Lang.bind(this, function() { + dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) { + src.leave_channels_finish(result); + }); + this.destroy(); + })); + this.addAction(_("Accept"), Lang.bind(this, function() { + dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) { + src.handle_with_time_finish(result); + }); this.destroy(); })); } @@ -1136,23 +1130,17 @@ const AudioVideoNotification = new Lang.Class({ this.setUrgency(MessageTray.Urgency.CRITICAL); - this.addAction('reject', _("Decline")); + this.addAction(_("Decline"), Lang.bind(this, function() { + dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) { + src.leave_channels_finish(result); + }); + this.destroy(); + })); /* translators: this is a button label (verb), not a noun */ - this.addAction('answer', _("Answer")); - - this.connect('action-invoked', Lang.bind(this, function(self, action) { - switch (action) { - case 'reject': - dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, - '', function(src, result) { - src.leave_channels_finish(result)}); - break; - case 'answer': - dispatchOp.handle_with_time_async('', global.get_current_time(), - function(src, result) { - src.handle_with_time_finish(result)}); - break; - } + this.addAction(_("Answer"), Lang.bind(this, function() { + dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) { + src.handle_with_time_finish(result); + }); this.destroy(); })); } @@ -1176,22 +1164,16 @@ const FileTransferNotification = new Lang.Class({ { customContent: true }); this.setResident(true); - this.addAction('decline', _("Decline")); - this.addAction('accept', _("Accept")); - - this.connect('action-invoked', Lang.bind(this, function(self, action) { - switch (action) { - case 'decline': - dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, - '', function(src, result) { - src.leave_channels_finish(result)}); - break; - case 'accept': - dispatchOp.handle_with_time_async('', global.get_current_time(), - function(src, result) { - src.handle_with_time_finish(result)}); - break; - } + this.addAction(_("Decline"), Lang.bind(this, function() { + dispatchOp.leave_channels_async(Tp.ChannelGroupChangeReason.NONE, '', function(src, result) { + src.leave_channels_finish(result); + }); + this.destroy(); + })); + this.addAction(_("Accept"), Lang.bind(this, function() { + dispatchOp.handle_with_time_async('', global.get_current_time(), function(src, result) { + src.handle_with_time_finish(result); + }); this.destroy(); })); } @@ -1239,27 +1221,20 @@ const SubscriptionRequestNotification = new Lang.Class({ this.addActor(layout); - this.addAction('decline', _("Decline")); - this.addAction('accept', _("Accept")); + this.addAction(_("Decline"), Lang.bind(this, function() { + contact.remove_async(function(src, result) { + src.remove_finish(result); + }); + })); + this.addAction(_("Accept"), Lang.bind(this, function() { + // Authorize the contact and request to see his status as well + contact.authorize_publication_async(function(src, result) { + src.authorize_publication_finish(result); + }); - this.connect('action-invoked', Lang.bind(this, function(self, action) { - switch (action) { - case 'decline': - contact.remove_async(function(src, result) { - src.remove_finish(result)}); - break; - case 'accept': - // Authorize the contact and request to see his status as well - contact.authorize_publication_async(function(src, result) { - src.authorize_publication_finish(result)}); - - contact.request_subscription_async('', function(src, result) { - src.request_subscription_finish(result)}); - break; - } - - // rely on _subscriptionStatesChangedCb to destroy the - // notification + contact.request_subscription_async('', function(src, result) { + src.request_subscription_finish(result); + }); })); this._changedId = contact.connect('subscription-states-changed', @@ -1358,18 +1333,11 @@ const AccountNotification = new Lang.Class({ this._account = account; - this.addAction('view', _("View account")); - - this.connect('action-invoked', Lang.bind(this, function(self, action) { - switch (action) { - case 'view': - let cmd = 'empathy-accounts --select-account=' + - account.get_path_suffix(); - let app_info = Gio.app_info_create_from_commandline(cmd, null, 0); - app_info.launch([], global.create_app_launch_context()); - break; - } - this.destroy(); + this.addAction(_("View account"), Lang.bind(this, function() { + let cmd = 'empathy-accounts --select-account=' + + account.get_path_suffix(); + let app_info = Gio.app_info_create_from_commandline(cmd, null, 0); + app_info.launch([], global.create_app_launch_context()); })); this._enabledId = account.connect('notify::enabled', diff --git a/js/ui/messageTray.js b/js/ui/messageTray.js index 2e1780ae7..e7e722e72 100644 --- a/js/ui/messageTray.js +++ b/js/ui/messageTray.js @@ -835,7 +835,7 @@ const Notification = new Lang.Class({ } }, - addButton: function(id, button) { + addButton: function(button, callback) { if (!this._buttonBox) { let box = new St.BoxLayout({ style_class: 'notification-actions' }); this.setActionArea(box, { x_expand: false, @@ -848,27 +848,36 @@ const Notification = new Lang.Class({ } this._buttonBox.add(button); - button.connect('clicked', Lang.bind(this, this._onActionInvoked, id)); + button.connect('clicked', Lang.bind(this, function() { + callback(); + + if (!this.resident) { + // We don't hide a resident notification when the user invokes one of its actions, + // because it is common for such notifications to update themselves with new + // information based on the action. We'd like to display the updated information + // in place, rather than pop-up a new notification. + this.emit('done-displaying'); + this.destroy(); + } + })); this.updated(); return button; }, // addAction: - // @id: the action ID // @label: the label for the action's button + // @callback: the callback for the action // // Adds a button with the given @label to the notification. All // action buttons will appear in a single row at the bottom of // the notification. - // - // If the button is clicked, the notification will emit the - // %action-invoked signal with @id as a parameter - addAction: function(id, label) { + addAction: function(label, callback) { let button = new St.Button({ style_class: 'notification-button', label: label, can_focus: true }); - return this.addButton(id, button); + + return this.addButton(button, callback); }, setUrgency: function(urgency) { @@ -1111,18 +1120,6 @@ const Notification = new Lang.Class({ this.actor.add_style_class_name('notification-unexpanded'); }, - _onActionInvoked: function(actor, mouseButtonClicked, id) { - this.emit('action-invoked', id); - if (!this.resident) { - // We don't hide a resident notification when the user invokes one of its actions, - // because it is common for such notifications to update themselves with new - // information based on the action. We'd like to display the updated information - // in place, rather than pop-up a new notification. - this.emit('done-displaying'); - this.destroy(); - } - }, - _onClicked: function() { this.emit('clicked'); // We hide all types of notifications once the user clicks on them because the common diff --git a/js/ui/notificationDaemon.js b/js/ui/notificationDaemon.js index 8410aedf4..c714ff138 100644 --- a/js/ui/notificationDaemon.js +++ b/js/ui/notificationDaemon.js @@ -389,10 +389,6 @@ const NotificationDaemon = new Lang.Class({ } this._emitNotificationClosed(ndata.id, notificationClosedReason); })); - notification.connect('action-invoked', Lang.bind(this, - function(n, actionId) { - this._emitActionInvoked(ndata.id, actionId); - })); } // Mark music notifications so they can be shown in the screen shield @@ -432,12 +428,13 @@ const NotificationDaemon = new Lang.Class({ for (let i = 0; i < actions.length - 1; i += 2) { let [actionId, label] = [actions[i], actions[i+1]]; if (actionId == 'default') { - notification.connect('clicked', Lang.bind(this, - function() { - this._emitActionInvoked(ndata.id, "default"); - })); + notification.connect('clicked', Lang.bind(this, function() { + this._emitActionInvoked(ndata.id, "default"); + })); } else { - notification.addButton(actionId, this._makeButton(id, label, useActionIcons)); + notification.addButton(this._makeButton(id, label, useActionIcons), Lang.bind(this, function() { + this._emitActionInvoked(ndata.id, actionId); + })); } } } @@ -659,7 +656,7 @@ const Source = new Lang.Class({ this.parent(title); }, - open: function(notification) { + open: function() { this.openApp(); this.destroyNonResidentNotifications(); }, diff --git a/js/ui/overview.js b/js/ui/overview.js index 93c2ec2bb..088532adc 100644 --- a/js/ui/overview.js +++ b/js/ui/overview.js @@ -78,10 +78,8 @@ const ShellInfo = new Lang.Class({ } this._undoCallback = undoCallback; - if (undoCallback) { - notification.addAction('system-undo', _("Undo")); - notification.connect('action-invoked', Lang.bind(this, this._onUndoClicked)); - } + if (undoCallback) + notification.addAction(_("Undo"), Lang.bind(this, this._onUndoClicked)); this._source.notify(notification); } diff --git a/js/ui/status/bluetooth.js b/js/ui/status/bluetooth.js index a302ac8fc..ce0aa0245 100644 --- a/js/ui/status/bluetooth.js +++ b/js/ui/status/bluetooth.js @@ -207,44 +207,46 @@ const PinNotification = new Lang.Class({ let key = event.get_key_symbol(); if (key == Clutter.KEY_Return) { if (this._canActivateOkButton()) - this.emit('action-invoked', 'ok'); + this._ok(); return true; } else if (key == Clutter.KEY_Escape) { - this.emit('action-invoked', 'cancel'); + this._cancel(); return true; } return false; })); this.addActor(this._entry); - let okButton = this.addAction('ok', _("OK")); - this.addAction('cancel', _("Cancel")); + let okButton = this.addAction(_("OK"), Lang.bind(this, this._ok)); + this.addAction(_("Cancel"), Lang.bind(this, this._cancel)); okButton.reactive = this._canActivateOkButton(); this._entry.clutter_text.connect('text-changed', Lang.bind(this, function() { okButton.reactive = this._canActivateOkButton(); })); + }, - this.connect('action-invoked', Lang.bind(this, function(self, action) { - if (action == 'ok') { - if (this._numeric) { - let num = parseInt(this._entry.text); - if (isNaN(num)) { - // user reply was empty, or was invalid - // cancel the operation - num = -1; - } - this._applet.agent_reply_passkey(this._devicePath, num); - } else - this._applet.agent_reply_pincode(this._devicePath, this._entry.text); - } else { - if (this._numeric) - this._applet.agent_reply_passkey(this._devicePath, -1); - else - this._applet.agent_reply_pincode(this._devicePath, null); + _ok: function() { + if (this._numeric) { + let num = parseInt(this._entry.text); + if (isNaN(num)) { + // user reply was empty, or was invalid + // cancel the operation + num = -1; } - this.destroy(); - })); + this._applet.agent_reply_passkey(this._devicePath, num); + } else { + this._applet.agent_reply_pincode(this._devicePath, this._entry.text); + } + this.destroy(); + }, + + _cancel: function() { + if (this._numeric) + this._applet.agent_reply_passkey(this._devicePath, -1); + else + this._applet.agent_reply_pincode(this._devicePath, null); + this.destroy(); }, _canActivateOkButton: function() {