瀏覽代碼

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

Incorrect password hint
master
Дамян Минков 8 年之前
父節點
當前提交
1f75683581

+ 2
- 1
css/_variables.scss 查看文件

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

+ 11
- 0
css/input-control/_input-control.scss 查看文件

@@ -20,6 +20,8 @@
20 20
     }
21 21
 
22 22
     &__input {
23
+        margin-bottom: 8px;
24
+        @include transition(all .2s ease-in);
23 25
 
24 26
         &:last-child {
25 27
             margin-bottom: inherit;
@@ -28,6 +30,11 @@
28 30
         &::selection {
29 31
             background-color: $defaultDarkSelectionColor;
30 32
         }
33
+
34
+        &.error {
35
+            color: $errorColor;
36
+            border-color: $errorColor;
37
+        }
31 38
     }
32 39
 
33 40
     &__em {
@@ -41,6 +48,10 @@
41 48
         span {
42 49
             vertical-align: middle;
43 50
         }
51
+
52
+        &_error {
53
+            color: $errorColor;
54
+        }
44 55
     }
45 56
 
46 57
     &__container {

+ 1
- 0
css/themes/_light.scss 查看文件

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

+ 1
- 0
lang/main.json 查看文件

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

+ 0
- 31
modules/UI/invite/AskForPassword.js 查看文件

@@ -1,31 +0,0 @@
1
-/* global APP, $ */
2
-
3
-import UIUtil from '../util/UIUtil';
4
-
5
-/**
6
- * Show dialog which asks for required conference password.
7
- * @returns {Promise<string>} password or nothing if user canceled
8
- */
9
-export default function askForPassword () {
10
-    let titleKey = "dialog.passwordRequired";
11
-    let msgString = `
12
-        <input name="lockKey" type="text"
13
-               data-i18n="[placeholder]dialog.password"
14
-               autofocus>`;
15
-    return new Promise(function (resolve, reject) {
16
-        APP.UI.messageHandler.openTwoButtonDialog({
17
-            titleKey,
18
-            msgString,
19
-            leftButtonKey: "dialog.Ok",
20
-            submitFunction: $.noop,
21
-            closeFunction: function (e, v, m, f) {
22
-                if (v && f.lockKey) {
23
-                    resolve(UIUtil.escapeHtml(f.lockKey));
24
-                } else {
25
-                    reject(APP.UI.messageHandler.CANCEL);
26
-                }
27
-            },
28
-            focus: ':input:first'
29
-        });
30
-    });
31
-}

+ 18
- 11
modules/UI/invite/Invite.js 查看文件

@@ -32,7 +32,7 @@ class Invite {
32 32
                 error);
33 33
 
34 34
             if (!locked) {
35
-                this.roomLocker.resetPassword();
35
+                this.getRoomLocker().resetPassword();
36 36
             }
37 37
 
38 38
             this.setLockedFromElsewhere(locked);
@@ -46,14 +46,20 @@ class Invite {
46 46
             }
47 47
         });
48 48
 
49
+        this.conference.on(ConferenceEvents.CONFERENCE_JOINED, () => {
50
+            let roomLocker = this.getRoomLocker();
51
+            roomLocker.hideRequirePasswordDialog();
52
+        });
53
+
49 54
         APP.UI.addListener( UIEvents.INVITE_CLICKED,
50 55
                             () => { this.openLinkDialog(); });
51 56
 
52 57
         APP.UI.addListener( UIEvents.PASSWORD_REQUIRED,
53 58
             () => {
59
+                let roomLocker = this.getRoomLocker();
54 60
                 this.setLockedFromElsewhere(true);
55
-                this.roomLocker.requirePassword().then(() => {
56
-                    let pass = this.roomLocker.password;
61
+                roomLocker.requirePassword().then(() => {
62
+                    let pass = roomLocker.password;
57 63
                     // we received that password is required, but user is trying
58 64
                     // anyway to login without a password, mark room as not
59 65
                     // locked in case he succeeds (maybe someone removed the
@@ -62,7 +68,7 @@ class Invite {
62 68
                     // will be marked as locked.
63 69
                     if (!pass)
64 70
                         this.setLockedFromElsewhere(false);
65
-                    this.conference.join(this.roomLocker.password);
71
+                    this.conference.join(pass);
66 72
                 });
67 73
             });
68 74
     }
@@ -124,7 +130,7 @@ class Invite {
124 130
      * @returns {String} password
125 131
      */
126 132
     getPassword() {
127
-        return this.roomLocker.password;
133
+        return this.getRoomLocker().password;
128 134
     }
129 135
 
130 136
     /**
@@ -144,7 +150,7 @@ class Invite {
144 150
      */
145 151
     setRoomUnlocked() {
146 152
         if (this.isModerator) {
147
-            this.roomLocker.lock().then(() => {
153
+            this.getRoomLocker().lock().then(() => {
148 154
                 APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
149 155
                 this.updateView();
150 156
             });
@@ -159,8 +165,8 @@ class Invite {
159 165
      */
160 166
     setRoomLocked(newPass) {
161 167
         let isModerator = this.isModerator;
162
-        if (isModerator && (newPass || !this.roomLocker.isLocked)) {
163
-            this.roomLocker.lock(newPass).then(() => {
168
+        if (isModerator && (newPass || !this.getRoomLocker().isLocked)) {
169
+            this.getRoomLocker().lock(newPass).then(() => {
164 170
                 APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
165 171
                 this.updateView();
166 172
             });
@@ -182,7 +188,7 @@ class Invite {
182 188
      * @returns {Boolean} isLocked
183 189
      */
184 190
     isLocked() {
185
-        return this.roomLocker.isLocked;
191
+        return this.getRoomLocker().isLocked;
186 192
     }
187 193
 
188 194
     /**
@@ -190,9 +196,10 @@ class Invite {
190 196
      * @param isLocked
191 197
      */
192 198
     setLockedFromElsewhere(isLocked) {
193
-        let oldLockState = this.roomLocker.isLocked;
199
+        let roomLocker = this.getRoomLocker();
200
+        let oldLockState = roomLocker.isLocked;
194 201
         if (oldLockState !== isLocked) {
195
-            this.roomLocker.lockedElsewhere = isLocked;
202
+            roomLocker.lockedElsewhere = isLocked;
196 203
             APP.UI.emitEvent(UIEvents.TOGGLE_ROOM_LOCK);
197 204
             this.updateView();
198 205
         }

+ 161
- 0
modules/UI/invite/RequirePasswordDialog.js 查看文件

@@ -0,0 +1,161 @@
1
+/* global APP */
2
+
3
+import UIUtil from '../util/UIUtil';
4
+
5
+/**
6
+ * Show dialog which asks for required conference password.
7
+ * @returns {Promise<string>} password or nothing if user canceled
8
+ */
9
+export default class RequirePasswordDialog {
10
+    constructor() {
11
+        this.titleKey = 'dialog.passwordRequired';
12
+        this.labelKey = 'dialog.passwordLabel';
13
+        this.errorKey = 'dialog.incorrectPassword';
14
+        this.errorId = 'passwordRequiredError';
15
+        this.inputId = 'passwordRequiredInput';
16
+        this.inputErrorClass = 'error';
17
+        this.isOpened = false;
18
+    }
19
+
20
+    /**
21
+     * Registering dialog listeners
22
+     * @private
23
+     */
24
+    _registerListeners() {
25
+        let el = document.getElementById(this.inputId);
26
+        el.addEventListener('keypress', this._hideError.bind(this));
27
+    }
28
+
29
+    /**
30
+     * Helper method returning dialog body
31
+     * @returns {string}
32
+     * @private
33
+     */
34
+    _getBodyMessage() {
35
+        return (
36
+            `<div class="input-control">
37
+                <label class="input-control__label"
38
+                       data-i18n="${this.labelKey}"></label>
39
+                <input class="input-control__input" name="lockKey" type="text"
40
+                   data-i18n="[placeholder]dialog.password"
41
+                   autofocus id="${this.inputId}">
42
+                <p class="input-control__hint input-control__hint_error hide"
43
+                   id="${this.errorId}"
44
+                   data-i18n="${this.errorKey}"></p>
45
+            </div>`
46
+        );
47
+    }
48
+
49
+    /**
50
+     * Asking for a password
51
+     * @returns {Promise}
52
+     */
53
+    askForPassword() {
54
+        if (!this.isOpened) {
55
+            return this.open();
56
+        }
57
+
58
+        return new Promise((resolve, reject) => {
59
+            this.resolve = resolve;
60
+            this.reject = reject;
61
+            this._showError();
62
+        });
63
+    }
64
+
65
+    /**
66
+     * Opens the dialog
67
+     * @returns {Promise}
68
+     */
69
+    open() {
70
+        let { titleKey } = this;
71
+        let msgString = this._getBodyMessage();
72
+
73
+        return new Promise((resolve, reject) => {
74
+            this.resolve = resolve;
75
+            this.reject = reject;
76
+            let submitFunction = this._submitFunction.bind(this);
77
+            let closeFunction = this._closeFunction.bind(this);
78
+
79
+            this._dialog = APP.UI.messageHandler.openTwoButtonDialog({
80
+                titleKey,
81
+                msgString,
82
+                leftButtonKey: "dialog.Ok",
83
+                submitFunction,
84
+                closeFunction,
85
+                focus: ':input:first'
86
+            });
87
+
88
+            this._registerListeners();
89
+            this.isOpened = true;
90
+        });
91
+    }
92
+
93
+    /**
94
+     * Submit dialog callback
95
+     * @param e - event
96
+     * @param v - value
97
+     * @param m - message
98
+     * @param f - form
99
+     * @private
100
+     */
101
+    _submitFunction(e, v, m, f) {
102
+        e.preventDefault();
103
+        this._processInput(v, f);
104
+    }
105
+
106
+    /**
107
+     * Processing input in dialog
108
+     * @param v - value
109
+     * @param f - form
110
+     * @private
111
+     */
112
+    _processInput(v, f) {
113
+        if (v && f.lockKey) {
114
+            this.resolve(UIUtil.escapeHtml(f.lockKey));
115
+        } else {
116
+            this.reject(APP.UI.messageHandler.CANCEL);
117
+        }
118
+    }
119
+
120
+    /**
121
+     * Close dialog callback
122
+     * @private
123
+     */
124
+    _closeFunction(e, v, m, f) {
125
+        this._processInput(v, f);
126
+        this._hideError();
127
+        this.close();
128
+    }
129
+
130
+    /**
131
+     * Method showing error hint
132
+     * @private
133
+     */
134
+    _showError() {
135
+        let className = this.inputErrorClass;
136
+        let input = document.getElementById(this.inputId);
137
+        document.getElementById(this.errorId).classList.remove('hide');
138
+        input.classList.add(className);
139
+        input.select();
140
+    }
141
+
142
+    /**
143
+     * Method hiding error hint
144
+     * @private
145
+     */
146
+    _hideError() {
147
+        let className = this.inputErrorClass;
148
+        document.getElementById(this.errorId).classList.add('hide');
149
+        document.getElementById(this.inputId).classList.remove(className);
150
+    }
151
+
152
+    /**
153
+     * Close the dialog
154
+     */
155
+    close() {
156
+        if (this._dialog) {
157
+            this._dialog.close();
158
+        }
159
+        this.isOpened = false;
160
+    }
161
+}

+ 12
- 3
modules/UI/invite/RoomLocker.js 查看文件

@@ -1,5 +1,5 @@
1 1
 /* global APP, JitsiMeetJS */
2
-import askForPassword from './AskForPassword';
2
+import RequirePasswordDialog from './RequirePasswordDialog';
3 3
 
4 4
 /**
5 5
  * Show notification that user cannot set password for the conference
@@ -31,7 +31,7 @@ const ConferenceErrors = JitsiMeetJS.errors.conference;
31 31
  */
32 32
 export default function createRoomLocker (room) {
33 33
     let password;
34
-
34
+    let requirePasswordDialog = new RequirePasswordDialog();
35 35
     /**
36 36
      * If the room was locked from someone other than us, we indicate it with
37 37
      * this property in order to have correct roomLocker state of isLocked.
@@ -104,7 +104,7 @@ export default function createRoomLocker (room) {
104 104
          * Asks user for required conference password.
105 105
          */
106 106
         requirePassword () {
107
-            return askForPassword().then(
107
+            return requirePasswordDialog.askForPassword().then(
108 108
                 newPass => { password = newPass; }
109 109
             ).catch(
110 110
                 reason => {
@@ -116,6 +116,15 @@ export default function createRoomLocker (room) {
116 116
                         console.error(reason);
117 117
                 }
118 118
             );
119
+        },
120
+
121
+        /**
122
+         * Hides require password dialog
123
+         */
124
+        hideRequirePasswordDialog() {
125
+            if (requirePasswordDialog.isOpened) {
126
+                requirePasswordDialog.close();
127
+            }
119 128
         }
120 129
     };
121 130
 }

+ 9
- 16
modules/UI/util/MessageHandler.js 查看文件

@@ -1,4 +1,4 @@
1
-/* global $, APP, toastr, Impromptu */
1
+/* global $, APP, toastr */
2 2
 
3 3
 import UIUtil from './UIUtil';
4 4
 import jitsiLocalStorage from '../../util/JitsiLocalStorage';
@@ -138,7 +138,7 @@ var messageHandler = {
138 138
             }
139 139
         });
140 140
         APP.translation.translateElement(dialog, i18nOptions);
141
-        return dialog;
141
+        return $.prompt.getApi();
142 142
     },
143 143
     /**
144 144
      * Shows a message to the user with two buttons: first is given as a
@@ -242,7 +242,7 @@ var messageHandler = {
242 242
             }
243 243
         });
244 244
         APP.translation.translateElement(twoButtonDialog);
245
-        return twoButtonDialog;
245
+        return $.prompt.getApi();
246 246
     },
247 247
 
248 248
     /**
@@ -300,10 +300,10 @@ var messageHandler = {
300 300
             args.closeText = '';
301 301
         }
302 302
 
303
-        let dialog = new Impromptu(
303
+        let dialog = $.prompt(
304 304
             msgString + generateDontShowCheckbox(dontShowAgain), args);
305
-        APP.translation.translateElement(dialog.getPrompt());
306
-        return dialog;
305
+        APP.translation.translateElement(dialog);
306
+        return $.prompt.getApi();
307 307
     },
308 308
 
309 309
     /**
@@ -338,13 +338,6 @@ var messageHandler = {
338 338
         };
339 339
     },
340 340
 
341
-    /**
342
-     * Closes currently opened dialog.
343
-     */
344
-    closeDialog: function () {
345
-        $.prompt.close();
346
-    },
347
-
348 341
     /**
349 342
      * Shows a dialog with different states to the user.
350 343
      *
@@ -367,9 +360,9 @@ var messageHandler = {
367 360
                     = this._getFormattedTitleString(currentState.titleKey);
368 361
             }
369 362
         }
370
-        let dialog = new Impromptu(statesObject, options);
371
-        APP.translation.translateElement(dialog.getPrompt(), translateOptions);
372
-        return dialog;
363
+        let dialog = $.prompt(statesObject, options);
364
+        APP.translation.translateElement(dialog, translateOptions);
365
+        return $.prompt.getApi();
373 366
     },
374 367
 
375 368
     /**

Loading…
取消
儲存