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;
|
height: .75em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.login-dialog .modal-dialog-button-box {
|
||||||
|
spacing: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
.login-dialog .modal-dialog-button {
|
.login-dialog .modal-dialog-button {
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
padding: 3px 18px;
|
padding: 3px 18px;
|
||||||
|
@ -39,6 +39,7 @@ const GdmUtil = imports.gdm.util;
|
|||||||
const Lightbox = imports.ui.lightbox;
|
const Lightbox = imports.ui.lightbox;
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
const ModalDialog = imports.ui.modalDialog;
|
||||||
|
const Panel = imports.ui.panel;
|
||||||
const PanelMenu = imports.ui.panelMenu;
|
const PanelMenu = imports.ui.panelMenu;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const UserMenu = imports.ui.userMenu;
|
const UserMenu = imports.ui.userMenu;
|
||||||
@ -48,6 +49,10 @@ const _SCROLL_ANIMATION_TIME = 0.5;
|
|||||||
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
|
const _TIMED_LOGIN_IDLE_THRESHOLD = 5.0;
|
||||||
const _LOGO_ICON_HEIGHT = 16;
|
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;
|
let _loginDialog = null;
|
||||||
|
|
||||||
function _smoothlyResizeActor(actor, width, height) {
|
function _smoothlyResizeActor(actor, width, height) {
|
||||||
@ -760,6 +765,7 @@ const LoginDialog = new Lang.Class({
|
|||||||
this._promptBox.add(this._promptLoginHint);
|
this._promptBox.add(this._promptLoginHint);
|
||||||
|
|
||||||
this._signInButton = null;
|
this._signInButton = null;
|
||||||
|
this._workSpinner = null;
|
||||||
|
|
||||||
this._sessionList = new SessionList();
|
this._sessionList = new SessionList();
|
||||||
this._sessionList.connect('session-activated',
|
this._sessionList.connect('session-activated',
|
||||||
@ -855,6 +861,7 @@ const LoginDialog = new Lang.Class({
|
|||||||
this._promptEntry.text = '';
|
this._promptEntry.text = '';
|
||||||
|
|
||||||
this._updateSensitivity(true);
|
this._updateSensitivity(true);
|
||||||
|
this._setWorking(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
_onDefaultSessionChanged: function(client, sessionId) {
|
_onDefaultSessionChanged: function(client, sessionId) {
|
||||||
@ -927,26 +934,54 @@ const LoginDialog = new Lang.Class({
|
|||||||
_showPrompt: function(forSecret) {
|
_showPrompt: function(forSecret) {
|
||||||
let hold = new Batch.Hold();
|
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() {
|
let tasks = [function() {
|
||||||
return this._fadeInPrompt();
|
return this._fadeInPrompt();
|
||||||
},
|
},
|
||||||
|
|
||||||
function() {
|
function() {
|
||||||
this.setButtons(buttons);
|
this._prepareDialog(forSecret, hold);
|
||||||
this._signInButton = okButtonInfo.button;
|
},
|
||||||
|
|
||||||
|
hold];
|
||||||
|
|
||||||
|
let batch = new Batch.ConcurrentBatch(this, tasks);
|
||||||
|
|
||||||
|
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._updateSignInButtonSensitivity(this._promptEntry.text.length > 0);
|
||||||
|
|
||||||
@ -957,13 +992,6 @@ const LoginDialog = new Lang.Class({
|
|||||||
}));
|
}));
|
||||||
},
|
},
|
||||||
|
|
||||||
hold];
|
|
||||||
|
|
||||||
let batch = new Batch.ConcurrentBatch(this, tasks);
|
|
||||||
|
|
||||||
return batch.run();
|
|
||||||
},
|
|
||||||
|
|
||||||
_updateSensitivity: function(sensitive) {
|
_updateSensitivity: function(sensitive) {
|
||||||
this._promptEntry.reactive = sensitive;
|
this._promptEntry.reactive = sensitive;
|
||||||
this._promptEntry.clutter_text.editable = sensitive;
|
this._promptEntry.clutter_text.editable = sensitive;
|
||||||
@ -987,6 +1015,8 @@ const LoginDialog = new Lang.Class({
|
|||||||
}
|
}
|
||||||
|
|
||||||
let tasks = [function() {
|
let tasks = [function() {
|
||||||
|
this._setWorking(false);
|
||||||
|
|
||||||
return GdmUtil.fadeOutActor(this._promptBox);
|
return GdmUtil.fadeOutActor(this._promptBox);
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -996,6 +1026,8 @@ const LoginDialog = new Lang.Class({
|
|||||||
this._updateSensitivity(true);
|
this._updateSensitivity(true);
|
||||||
this._promptEntry.set_text('');
|
this._promptEntry.set_text('');
|
||||||
|
|
||||||
|
this.clearButtons();
|
||||||
|
this._workSpinner = null;
|
||||||
this._signInButton = null;
|
this._signInButton = null;
|
||||||
}];
|
}];
|
||||||
|
|
||||||
@ -1004,6 +1036,31 @@ const LoginDialog = new Lang.Class({
|
|||||||
return batch.run();
|
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) {
|
_askQuestion: function(verifier, serviceName, question, passwordChar) {
|
||||||
this._promptLabel.set_text(question);
|
this._promptLabel.set_text(question);
|
||||||
|
|
||||||
@ -1017,6 +1074,7 @@ const LoginDialog = new Lang.Class({
|
|||||||
function() {
|
function() {
|
||||||
let text = this._promptEntry.get_text();
|
let text = this._promptEntry.get_text();
|
||||||
this._updateSensitivity(false);
|
this._updateSensitivity(false);
|
||||||
|
this._setWorking(true);
|
||||||
this._userVerifier.answerQuery(serviceName, text);
|
this._userVerifier.answerQuery(serviceName, text);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
|
@ -14,12 +14,14 @@ const St = imports.gi.St;
|
|||||||
|
|
||||||
const Main = imports.ui.main;
|
const Main = imports.ui.main;
|
||||||
const ModalDialog = imports.ui.modalDialog;
|
const ModalDialog = imports.ui.modalDialog;
|
||||||
|
const Panel = imports.ui.panel;
|
||||||
const ShellEntry = imports.ui.shellEntry;
|
const ShellEntry = imports.ui.shellEntry;
|
||||||
const Tweener = imports.ui.tweener;
|
const Tweener = imports.ui.tweener;
|
||||||
const UserMenu = imports.ui.userMenu;
|
const UserMenu = imports.ui.userMenu;
|
||||||
|
|
||||||
const Batch = imports.gdm.batch;
|
const Batch = imports.gdm.batch;
|
||||||
const GdmUtil = imports.gdm.util;
|
const GdmUtil = imports.gdm.util;
|
||||||
|
const LoginDialog = imports.gdm.loginDialog;
|
||||||
|
|
||||||
// The timeout before going back automatically to the lock screen (in seconds)
|
// The timeout before going back automatically to the lock screen (in seconds)
|
||||||
const IDLE_TIMEOUT = 2 * 60;
|
const IDLE_TIMEOUT = 2 * 60;
|
||||||
@ -168,13 +170,33 @@ const UnlockDialog = new Lang.Class({
|
|||||||
this._promptLoginHint.hide();
|
this._promptLoginHint.hide();
|
||||||
this.contentLayout.add_actor(this._promptLoginHint);
|
this.contentLayout.add_actor(this._promptLoginHint);
|
||||||
|
|
||||||
let cancelButton = { label: _("Cancel"),
|
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),
|
action: Lang.bind(this, this._escape),
|
||||||
key: Clutter.KEY_Escape };
|
key: Clutter.KEY_Escape },
|
||||||
this._okButton = { label: _("Unlock"),
|
{ 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),
|
action: Lang.bind(this, this._doUnlock),
|
||||||
default: true };
|
default: true },
|
||||||
this.setButtons([cancelButton, this._okButton]);
|
{ 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"),
|
let otherUserLabel = new St.Label({ text: _("Log in as another user"),
|
||||||
style_class: 'login-dialog-not-listed-label' });
|
style_class: 'login-dialog-not-listed-label' });
|
||||||
@ -214,8 +236,30 @@ const UnlockDialog = new Lang.Class({
|
|||||||
},
|
},
|
||||||
|
|
||||||
_updateOkButtonSensitivity: function(sensitive) {
|
_updateOkButtonSensitivity: function(sensitive) {
|
||||||
this._okButton.button.reactive = sensitive;
|
this._okButton.reactive = sensitive;
|
||||||
this._okButton.button.can_focus = 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) {
|
_showMessage: function(userVerifier, message, styleClass) {
|
||||||
@ -248,6 +292,7 @@ const UnlockDialog = new Lang.Class({
|
|||||||
|
|
||||||
this._currentQuery = serviceName;
|
this._currentQuery = serviceName;
|
||||||
this._updateSensitivity(true);
|
this._updateSensitivity(true);
|
||||||
|
this._setWorking(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
_showLoginHint: function(verifier, message) {
|
_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
|
// the actual reply to GDM will be sent as soon as asked
|
||||||
this._firstQuestionAnswer = this._promptEntry.text;
|
this._firstQuestionAnswer = this._promptEntry.text;
|
||||||
this._updateSensitivity(false);
|
this._updateSensitivity(false);
|
||||||
|
this._setWorking(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -276,6 +322,7 @@ const UnlockDialog = new Lang.Class({
|
|||||||
this._currentQuery = null;
|
this._currentQuery = null;
|
||||||
|
|
||||||
this._updateSensitivity(false);
|
this._updateSensitivity(false);
|
||||||
|
this._setWorking(true);
|
||||||
|
|
||||||
this._userVerifier.answerQuery(query, this._promptEntry.text);
|
this._userVerifier.answerQuery(query, this._promptEntry.text);
|
||||||
},
|
},
|
||||||
@ -296,6 +343,7 @@ const UnlockDialog = new Lang.Class({
|
|||||||
this._promptEntry.text = '';
|
this._promptEntry.text = '';
|
||||||
|
|
||||||
this._updateSensitivity(false);
|
this._updateSensitivity(false);
|
||||||
|
this._setWorking(false);
|
||||||
},
|
},
|
||||||
|
|
||||||
_escape: function() {
|
_escape: function() {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user