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
This commit is contained in:
parent
c3cab28c9b
commit
59a7fdd2c9
@ -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;
|
||||
|
@ -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);
|
||||
}];
|
||||
|
||||
|
@ -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() {
|
||||
|
Loading…
Reference in New Issue
Block a user