[gnome-shell] Login: add a spinner for better process indication
- From: StÃphane DÃmurget <stef src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] Login: add a spinner for better process indication
- Date: Tue, 20 Nov 2012 20:10:28 +0000 (UTC)
commit 59a7fdd2c9387ee4b9b6d2b92375e57496ff718f
Author: StÃphane DÃmurget <stephane demurget free fr>
Date: Sun Nov 18 22:49:54 2012 +0100
Login: add a spinner for better process indication
We need to do a better job of indicating login process. This can
sometimes take a few seconds (particularly if you get your password
wrong): we need to give better feedback of what's going on.
This adds a spinner next to the login button if the authorization takes
some time.
https://bugzilla.gnome.org/show_bug.cgi?id=687113
data/theme/gnome-shell.css | 4 ++
js/gdm/loginDialog.js | 104 ++++++++++++++++++++++++++++++++++----------
js/ui/unlockDialog.js | 66 ++++++++++++++++++++++++----
3 files changed, 142 insertions(+), 32 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index e99acb0..4890f2c 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -2213,6 +2213,10 @@ StScrollBar StButton#vhandle:active {
height: .75em;
}
+.login-dialog .modal-dialog-button-box {
+ spacing: 3px;
+}
+
.login-dialog .modal-dialog-button {
border-radius: 5px;
padding: 3px 18px;
diff --git a/js/gdm/loginDialog.js b/js/gdm/loginDialog.js
index c72ce47..1710322 100644
--- a/js/gdm/loginDialog.js
+++ b/js/gdm/loginDialog.js
@@ -39,6 +39,7 @@ const GdmUtil = imports.gdm.util;
const Lightbox = imports.ui.lightbox;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
+const Panel = imports.ui.panel;
const PanelMenu = imports.ui.panelMenu;
const Tweener = imports.ui.tweener;
const UserMenu = imports.ui.userMenu;
@@ -48,6 +49,10 @@ const _SCROLL_ANIMATION_TIME = 0.5;
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
const _LOGO_ICON_HEIGHT = 16;
+const WORK_SPINNER_ICON_SIZE = 24;
+const WORK_SPINNER_ANIMATION_DELAY = 1.0;
+const WORK_SPINNER_ANIMATION_TIME = 0.3;
+
let _loginDialog = null;
function _smoothlyResizeActor(actor, width, height) {
@@ -760,6 +765,7 @@ const LoginDialog = new Lang.Class({
this._promptBox.add(this._promptLoginHint);
this._signInButton = null;
+ this._workSpinner = null;
this._sessionList = new SessionList();
this._sessionList.connect('session-activated',
@@ -855,6 +861,7 @@ const LoginDialog = new Lang.Class({
this._promptEntry.text = '';
this._updateSensitivity(true);
+ this._setWorking(false);
},
_onDefaultSessionChanged: function(client, sessionId) {
@@ -927,34 +934,12 @@ const LoginDialog = new Lang.Class({
_showPrompt: function(forSecret) {
let hold = new Batch.Hold();
- let cancelButtonInfo = { action: Lang.bind(this, this.cancel),
- label: _("Cancel"),
- key: Clutter.Escape };
- let okButtonInfo = { action: Lang.bind(this, function() {
- hold.release();
- }),
- label: forSecret ? C_("button", "Sign In") : _("Next"),
- default: true };
- let buttons = [];
- if (!this._disableUserList || this._verifyingUser)
- buttons.push(cancelButtonInfo);
- buttons.push(okButtonInfo);
-
let tasks = [function() {
return this._fadeInPrompt();
},
function() {
- this.setButtons(buttons);
- this._signInButton = okButtonInfo.button;
-
- this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
-
- this._promptEntryTextChangedId =
- this._promptEntry.clutter_text.connect('text-changed',
- Lang.bind(this, function() {
- this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
- }));
+ this._prepareDialog(forSecret, hold);
},
hold];
@@ -964,6 +949,49 @@ const LoginDialog = new Lang.Class({
return batch.run();
},
+ _prepareDialog: function(forSecret, hold) {
+ this._workSpinner = new Panel.AnimatedIcon('process-working.svg', WORK_SPINNER_ICON_SIZE);
+ this._workSpinner.actor.opacity = 0;
+ this._workSpinner.actor.show();
+
+ this.buttonLayout.visible = true;
+ this.clearButtons();
+
+ if (!this._disableUserList || this._verifyingUser)
+ this.addButton({ action: Lang.bind(this, this.cancel),
+ label: _("Cancel"),
+ key: Clutter.Escape },
+ { expand: true,
+ x_fill: false,
+ y_fill: false,
+ x_align: St.Align.START,
+ y_align: St.Align.MIDDLE });
+ this.buttonLayout.add(this._workSpinner.actor,
+ { expand: false,
+ x_fill: false,
+ y_fill: false,
+ x_align: St.Align.END,
+ y_align: St.Align.MIDDLE });
+ this._signInButton = this.addButton({ action: Lang.bind(this, function() {
+ hold.release();
+ }),
+ label: forSecret ? C_("button", "Sign In") : _("Next"),
+ default: true },
+ { expand: false,
+ x_fill: false,
+ y_fill: false,
+ x_align: St.Align.END,
+ y_align: St.Align.MIDDLE });
+
+ this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
+
+ this._promptEntryTextChangedId =
+ this._promptEntry.clutter_text.connect('text-changed',
+ Lang.bind(this, function() {
+ this._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
+ }));
+ },
+
_updateSensitivity: function(sensitive) {
this._promptEntry.reactive = sensitive;
this._promptEntry.clutter_text.editable = sensitive;
@@ -987,6 +1015,8 @@ const LoginDialog = new Lang.Class({
}
let tasks = [function() {
+ this._setWorking(false);
+
return GdmUtil.fadeOutActor(this._promptBox);
},
@@ -996,6 +1026,8 @@ const LoginDialog = new Lang.Class({
this._updateSensitivity(true);
this._promptEntry.set_text('');
+ this.clearButtons();
+ this._workSpinner = null;
this._signInButton = null;
}];
@@ -1004,6 +1036,31 @@ const LoginDialog = new Lang.Class({
return batch.run();
},
+ _setWorking: function(working) {
+ if (!this._workSpinner)
+ return;
+
+ if (working) {
+ this._workSpinner.play();
+ Tweener.addTween(this._workSpinner.actor,
+ { opacity: 255,
+ delay: WORK_SPINNER_ANIMATION_DELAY,
+ time: WORK_SPINNER_ANIMATION_TIME,
+ transition: 'linear'
+ });
+ } else {
+ Tweener.addTween(this._workSpinner.actor,
+ { opacity: 0,
+ time: WORK_SPINNER_ANIMATION_TIME,
+ transition: 'linear',
+ onCompleteScope: this,
+ onComplete: function() {
+ this._workSpinner.stop();
+ }
+ });
+ }
+ },
+
_askQuestion: function(verifier, serviceName, question, passwordChar) {
this._promptLabel.set_text(question);
@@ -1017,6 +1074,7 @@ const LoginDialog = new Lang.Class({
function() {
let text = this._promptEntry.get_text();
this._updateSensitivity(false);
+ this._setWorking(true);
this._userVerifier.answerQuery(serviceName, text);
}];
diff --git a/js/ui/unlockDialog.js b/js/ui/unlockDialog.js
index 548bbe7..5cdce92 100644
--- a/js/ui/unlockDialog.js
+++ b/js/ui/unlockDialog.js
@@ -14,12 +14,14 @@ const St = imports.gi.St;
const Main = imports.ui.main;
const ModalDialog = imports.ui.modalDialog;
+const Panel = imports.ui.panel;
const ShellEntry = imports.ui.shellEntry;
const Tweener = imports.ui.tweener;
const UserMenu = imports.ui.userMenu;
const Batch = imports.gdm.batch;
const GdmUtil = imports.gdm.util;
+const LoginDialog = imports.gdm.loginDialog;
// The timeout before going back automatically to the lock screen (in seconds)
const IDLE_TIMEOUT = 2 * 60;
@@ -168,13 +170,33 @@ const UnlockDialog = new Lang.Class({
this._promptLoginHint.hide();
this.contentLayout.add_actor(this._promptLoginHint);
- let cancelButton = { label: _("Cancel"),
- action: Lang.bind(this, this._escape),
- key: Clutter.KEY_Escape };
- this._okButton = { label: _("Unlock"),
- action: Lang.bind(this, this._doUnlock),
- default: true };
- this.setButtons([cancelButton, this._okButton]);
+ this._workSpinner = new Panel.AnimatedIcon('process-working.svg', LoginDialog.WORK_SPINNER_ICON_SIZE);
+ this._workSpinner.actor.opacity = 0;
+ this._workSpinner.actor.show();
+
+ this.buttonLayout.visible = true;
+ this.addButton({ label: _("Cancel"),
+ action: Lang.bind(this, this._escape),
+ key: Clutter.KEY_Escape },
+ { expand: true,
+ x_fill: false,
+ y_fill: false,
+ x_align: St.Align.START,
+ y_align: St.Align.MIDDLE });
+ this.buttonLayout.add(this._workSpinner.actor,
+ { expand: false,
+ x_fill: false,
+ y_fill: false,
+ x_align: St.Align.END,
+ y_align: St.Align.MIDDLE });
+ this._okButton = this.addButton({ label: _("Unlock"),
+ action: Lang.bind(this, this._doUnlock),
+ default: true },
+ { expand: false,
+ x_fill: false,
+ y_fill: false,
+ x_align: St.Align.END,
+ y_align: St.Align.MIDDLE });
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
style_class: 'login-dialog-not-listed-label' });
@@ -214,8 +236,30 @@ const UnlockDialog = new Lang.Class({
},
_updateOkButtonSensitivity: function(sensitive) {
- this._okButton.button.reactive = sensitive;
- this._okButton.button.can_focus = sensitive;
+ this._okButton.reactive = sensitive;
+ this._okButton.can_focus = sensitive;
+ },
+
+ _setWorking: function(working) {
+ if (working) {
+ this._workSpinner.play();
+ Tweener.addTween(this._workSpinner.actor,
+ { opacity: 255,
+ delay: LoginDialog.WORK_SPINNER_ANIMATION_DELAY,
+ time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
+ transition: 'linear'
+ });
+ } else {
+ Tweener.addTween(this._workSpinner.actor,
+ { opacity: 0,
+ time: LoginDialog.WORK_SPINNER_ANIMATION_TIME,
+ transition: 'linear',
+ onCompleteScope: this,
+ onComplete: function() {
+ this._workSpinner.stop();
+ }
+ });
+ }
},
_showMessage: function(userVerifier, message, styleClass) {
@@ -248,6 +292,7 @@ const UnlockDialog = new Lang.Class({
this._currentQuery = serviceName;
this._updateSensitivity(true);
+ this._setWorking(false);
},
_showLoginHint: function(verifier, message) {
@@ -266,6 +311,7 @@ const UnlockDialog = new Lang.Class({
// the actual reply to GDM will be sent as soon as asked
this._firstQuestionAnswer = this._promptEntry.text;
this._updateSensitivity(false);
+ this._setWorking(true);
return;
}
@@ -276,6 +322,7 @@ const UnlockDialog = new Lang.Class({
this._currentQuery = null;
this._updateSensitivity(false);
+ this._setWorking(true);
this._userVerifier.answerQuery(query, this._promptEntry.text);
},
@@ -296,6 +343,7 @@ const UnlockDialog = new Lang.Class({
this._promptEntry.text = '';
this._updateSensitivity(false);
+ this._setWorking(false);
},
_escape: function() {
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]