Merge pull request #1055 from BeatC/incorrect-password-hint

Incorrect password hint
This commit is contained in:
Дамян Минков 2016-11-08 14:29:06 -06:00 committed by GitHub
commit 1f75683581
9 changed files with 215 additions and 62 deletions

View File

@ -126,4 +126,5 @@ $selectActiveItemBg: $defaultDarkColor;
$inputControlEmColor: #f29424;
//buttons
$linkFontColor: #489afe;
$linkHoverFontColor: #287ade;
$linkHoverFontColor: #287ade;

View File

@ -20,6 +20,8 @@
}
&__input {
margin-bottom: 8px;
@include transition(all .2s ease-in);
&:last-child {
margin-bottom: inherit;
@ -28,6 +30,11 @@
&::selection {
background-color: $defaultDarkSelectionColor;
}
&.error {
color: $errorColor;
border-color: $errorColor;
}
}
&__em {
@ -41,6 +48,10 @@
span {
vertical-align: middle;
}
&_error {
color: $errorColor;
}
}
&__container {

View File

@ -55,6 +55,7 @@ $hintFontSize: em(13, 14);
$linkFontColor: #3572b0;
$linkHoverFontColor: darken(#3572b0, 10%);
$dropdownColor: #333;
$errorColor: #c61600;
// Popover colors
$popoverBg: #000;

View File

@ -199,6 +199,7 @@
"passwordError2": "This conversation isn't currently protected by a password. Only the owner of the conference can set a password.",
"connectError": "Oops! Something went wrong and we couldn't connect to the conference.",
"connectErrorWithMsg": "Oops! Something went wrong and we couldn't connect to the conference: __msg__",
"incorrectPassword": "Password is incorrect",
"connecting": "Connecting",
"copy": "Copy",
"error": "Error",

View File

@ -1,31 +0,0 @@
/* global APP, $ */
import UIUtil from '../util/UIUtil';
/**
* Show dialog which asks for required conference password.
* @returns {Promise<string>} password or nothing if user canceled
*/
export default function askForPassword () {
let titleKey = "dialog.passwordRequired";
let msgString = `
<input name="lockKey" type="text"
data-i18n="[placeholder]dialog.password"
autofocus>`;
return new Promise(function (resolve, reject) {
APP.UI.messageHandler.openTwoButtonDialog({
titleKey,
msgString,
leftButtonKey: "dialog.Ok",
submitFunction: $.noop,
closeFunction: function (e, v, m, f) {
if (v && f.lockKey) {
resolve(UIUtil.escapeHtml(f.lockKey));
} else {
reject(APP.UI.messageHandler.CANCEL);
}
},
focus: ':input:first'
});
});
}

View File

@ -32,7 +32,7 @@ class Invite {
error);
if (!locked) {
this.roomLocker.resetPassword();
this.getRoomLocker().resetPassword();
}
this.setLockedFromElsewhere(locked);
@ -46,14 +46,20 @@ class Invite {
}
});
this.conference.on(ConferenceEvents.CONFERENCE_JOINED, () => {
let roomLocker = this.getRoomLocker();
roomLocker.hideRequirePasswordDialog();
});
APP.UI.addListener( UIEvents.INVITE_CLICKED,
() => { this.openLinkDialog(); });
APP.UI.addListener( UIEvents.PASSWORD_REQUIRED,
() => {
let roomLocker = this.getRoomLocker();
this.setLockedFromElsewhere(true);
this.roomLocker.requirePassword().then(() => {
let pass = this.roomLocker.password;
roomLocker.requirePassword().then(() => {
let pass = roomLocker.password;
// we received that password is required, but user is trying
// anyway to login without a password, mark room as not
// locked in case he succeeds (maybe someone removed the
@ -62,7 +68,7 @@ class Invite {
// will be marked as locked.
if (!pass)
this.setLockedFromElsewhere(false);
this.conference.join(this.roomLocker.password);
this.conference.join(pass);
});
});
}
@ -124,7 +130,7 @@ class Invite {
* @returns {String} password
*/
getPassword() {
return this.roomLocker.password;
return this.getRoomLocker().password;
}
/**
@ -144,7 +150,7 @@ class Invite {
*/
setRoomUnlocked() {
if (this.isModerator) {
this.roomLocker.lock().then(() => {
this.getRoomLocker().lock().then(() => {
APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
this.updateView();
});
@ -159,8 +165,8 @@ class Invite {
*/
setRoomLocked(newPass) {
let isModerator = this.isModerator;
if (isModerator && (newPass || !this.roomLocker.isLocked)) {
this.roomLocker.lock(newPass).then(() => {
if (isModerator && (newPass || !this.getRoomLocker().isLocked)) {
this.getRoomLocker().lock(newPass).then(() => {
APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
this.updateView();
});
@ -182,7 +188,7 @@ class Invite {
* @returns {Boolean} isLocked
*/
isLocked() {
return this.roomLocker.isLocked;
return this.getRoomLocker().isLocked;
}
/**
@ -190,9 +196,10 @@ class Invite {
* @param isLocked
*/
setLockedFromElsewhere(isLocked) {
let oldLockState = this.roomLocker.isLocked;
let roomLocker = this.getRoomLocker();
let oldLockState = roomLocker.isLocked;
if (oldLockState !== isLocked) {
this.roomLocker.lockedElsewhere = isLocked;
roomLocker.lockedElsewhere = isLocked;
APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
this.updateView();
}

View File

@ -0,0 +1,161 @@
/* global APP */
import UIUtil from '../util/UIUtil';
/**
* Show dialog which asks for required conference password.
* @returns {Promise<string>} password or nothing if user canceled
*/
export default class RequirePasswordDialog {
constructor() {
this.titleKey = 'dialog.passwordRequired';
this.labelKey = 'dialog.passwordLabel';
this.errorKey = 'dialog.incorrectPassword';
this.errorId = 'passwordRequiredError';
this.inputId = 'passwordRequiredInput';
this.inputErrorClass = 'error';
this.isOpened = false;
}
/**
* Registering dialog listeners
* @private
*/
_registerListeners() {
let el = document.getElementById(this.inputId);
el.addEventListener('keypress', this._hideError.bind(this));
}
/**
* Helper method returning dialog body
* @returns {string}
* @private
*/
_getBodyMessage() {
return (
`<div class="input-control">
<label class="input-control__label"
data-i18n="${this.labelKey}"></label>
<input class="input-control__input" name="lockKey" type="text"
data-i18n="[placeholder]dialog.password"
autofocus id="${this.inputId}">
<p class="input-control__hint input-control__hint_error hide"
id="${this.errorId}"
data-i18n="${this.errorKey}"></p>
</div>`
);
}
/**
* Asking for a password
* @returns {Promise}
*/
askForPassword() {
if (!this.isOpened) {
return this.open();
}
return new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
this._showError();
});
}
/**
* Opens the dialog
* @returns {Promise}
*/
open() {
let { titleKey } = this;
let msgString = this._getBodyMessage();
return new Promise((resolve, reject) => {
this.resolve = resolve;
this.reject = reject;
let submitFunction = this._submitFunction.bind(this);
let closeFunction = this._closeFunction.bind(this);
this._dialog = APP.UI.messageHandler.openTwoButtonDialog({
titleKey,
msgString,
leftButtonKey: "dialog.Ok",
submitFunction,
closeFunction,
focus: ':input:first'
});
this._registerListeners();
this.isOpened = true;
});
}
/**
* Submit dialog callback
* @param e - event
* @param v - value
* @param m - message
* @param f - form
* @private
*/
_submitFunction(e, v, m, f) {
e.preventDefault();
this._processInput(v, f);
}
/**
* Processing input in dialog
* @param v - value
* @param f - form
* @private
*/
_processInput(v, f) {
if (v && f.lockKey) {
this.resolve(UIUtil.escapeHtml(f.lockKey));
} else {
this.reject(APP.UI.messageHandler.CANCEL);
}
}
/**
* Close dialog callback
* @private
*/
_closeFunction(e, v, m, f) {
this._processInput(v, f);
this._hideError();
this.close();
}
/**
* Method showing error hint
* @private
*/
_showError() {
let className = this.inputErrorClass;
let input = document.getElementById(this.inputId);
document.getElementById(this.errorId).classList.remove('hide');
input.classList.add(className);
input.select();
}
/**
* Method hiding error hint
* @private
*/
_hideError() {
let className = this.inputErrorClass;
document.getElementById(this.errorId).classList.add('hide');
document.getElementById(this.inputId).classList.remove(className);
}
/**
* Close the dialog
*/
close() {
if (this._dialog) {
this._dialog.close();
}
this.isOpened = false;
}
}

View File

@ -1,5 +1,5 @@
/* global APP, JitsiMeetJS */
import askForPassword from './AskForPassword';
import RequirePasswordDialog from './RequirePasswordDialog';
/**
* Show notification that user cannot set password for the conference
@ -31,7 +31,7 @@ const ConferenceErrors = JitsiMeetJS.errors.conference;
*/
export default function createRoomLocker (room) {
let password;
let requirePasswordDialog = new RequirePasswordDialog();
/**
* If the room was locked from someone other than us, we indicate it with
* this property in order to have correct roomLocker state of isLocked.
@ -104,7 +104,7 @@ export default function createRoomLocker (room) {
* Asks user for required conference password.
*/
requirePassword () {
return askForPassword().then(
return requirePasswordDialog.askForPassword().then(
newPass => { password = newPass; }
).catch(
reason => {
@ -116,6 +116,15 @@ export default function createRoomLocker (room) {
console.error(reason);
}
);
},
/**
* Hides require password dialog
*/
hideRequirePasswordDialog() {
if (requirePasswordDialog.isOpened) {
requirePasswordDialog.close();
}
}
};
}

View File

@ -1,4 +1,4 @@
/* global $, APP, toastr, Impromptu */
/* global $, APP, toastr */
import UIUtil from './UIUtil';
import jitsiLocalStorage from '../../util/JitsiLocalStorage';
@ -138,7 +138,7 @@ var messageHandler = {
}
});
APP.translation.translateElement(dialog, i18nOptions);
return dialog;
return $.prompt.getApi();
},
/**
* Shows a message to the user with two buttons: first is given as a
@ -242,7 +242,7 @@ var messageHandler = {
}
});
APP.translation.translateElement(twoButtonDialog);
return twoButtonDialog;
return $.prompt.getApi();
},
/**
@ -300,10 +300,10 @@ var messageHandler = {
args.closeText = '';
}
let dialog = new Impromptu(
let dialog = $.prompt(
msgString + generateDontShowCheckbox(dontShowAgain), args);
APP.translation.translateElement(dialog.getPrompt());
return dialog;
APP.translation.translateElement(dialog);
return $.prompt.getApi();
},
/**
@ -338,13 +338,6 @@ var messageHandler = {
};
},
/**
* Closes currently opened dialog.
*/
closeDialog: function () {
$.prompt.close();
},
/**
* Shows a dialog with different states to the user.
*
@ -367,9 +360,9 @@ var messageHandler = {
= this._getFormattedTitleString(currentState.titleKey);
}
}
let dialog = new Impromptu(statesObject, options);
APP.translation.translateElement(dialog.getPrompt(), translateOptions);
return dialog;
let dialog = $.prompt(statesObject, options);
APP.translation.translateElement(dialog, translateOptions);
return $.prompt.getApi();
},
/**