Merge pull request #761 from mozilla/i741
added maxPasswordLength and passwordError messages
This commit is contained in:
commit
b39bbaf6fb
|
@ -106,6 +106,10 @@ a {
|
||||||
padding-right: 10px;
|
padding-right: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.input--error {
|
||||||
|
border-color: var(--errorColor);
|
||||||
|
}
|
||||||
|
|
||||||
.input--noBtn {
|
.input--noBtn {
|
||||||
border-radius: 6px;
|
border-radius: 6px;
|
||||||
}
|
}
|
||||||
|
@ -215,6 +219,10 @@ a {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.error {
|
||||||
|
color: var(--errorColor);
|
||||||
|
}
|
||||||
|
|
||||||
.title {
|
.title {
|
||||||
font-size: 33px;
|
font-size: 33px;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
|
|
|
@ -135,9 +135,11 @@ export default function(state, emitter) {
|
||||||
state.storage.writeFile(file);
|
state.storage.writeFile(file);
|
||||||
metrics.addedPassword({ size: file.size });
|
metrics.addedPassword({ size: file.size });
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
state.settingPassword = false;
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
state.passwordSetError = err;
|
||||||
|
} finally {
|
||||||
|
state.settingPassword = false;
|
||||||
}
|
}
|
||||||
render();
|
render();
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,11 +21,17 @@ export default class OwnedFile {
|
||||||
}
|
}
|
||||||
|
|
||||||
async setPassword(password) {
|
async setPassword(password) {
|
||||||
this.password = password;
|
try {
|
||||||
this._hasPassword = true;
|
this.password = password;
|
||||||
this.keychain.setPassword(password, this.url);
|
this._hasPassword = true;
|
||||||
const result = await setPassword(this.id, this.ownerToken, this.keychain);
|
this.keychain.setPassword(password, this.url);
|
||||||
return result;
|
const result = await setPassword(this.id, this.ownerToken, this.keychain);
|
||||||
|
return result;
|
||||||
|
} catch (e) {
|
||||||
|
this.password = null;
|
||||||
|
this._hasPassword = false;
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
del() {
|
del() {
|
||||||
|
|
|
@ -21,11 +21,9 @@ module.exports = function(state, emit) {
|
||||||
<div class="uploadArea"
|
<div class="uploadArea"
|
||||||
ondragover=${dragover}
|
ondragover=${dragover}
|
||||||
ondragleave=${dragleave}>
|
ondragleave=${dragleave}>
|
||||||
<div id="upload-img">
|
<img
|
||||||
<img
|
src="${assets.get('upload.svg')}"
|
||||||
src="${assets.get('upload.svg')}"
|
title="${state.translate('uploadSvgAlt')}"/>
|
||||||
title="${state.translate('uploadSvgAlt')}"/>
|
|
||||||
</div>
|
|
||||||
<div class="uploadArea__msg">
|
<div class="uploadArea__msg">
|
||||||
${state.translate('uploadPageDropMessage')}
|
${state.translate('uploadPageDropMessage')}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -11,14 +11,6 @@
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.error {
|
|
||||||
color: var(--errorColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input--error {
|
|
||||||
border-color: var(--errorColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
@media (max-device-width: 520px), (max-width: 520px) {
|
@media (max-device-width: 520px), (max-width: 520px) {
|
||||||
.passwordSection {
|
.passwordSection {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
const html = require('choo/html');
|
const html = require('choo/html');
|
||||||
|
const MAX_LENGTH = 32;
|
||||||
|
|
||||||
module.exports = function(file, state, emit) {
|
module.exports = function(file, state, emit) {
|
||||||
const loading = state.settingPassword;
|
const loading = state.settingPassword;
|
||||||
const pwd = file.hasPassword;
|
const pwd = file.hasPassword;
|
||||||
const formClass = pwd
|
const sectionClass =
|
||||||
? 'passwordInput'
|
pwd || state.passwordSetError
|
||||||
: 'passwordInput passwordInput--hidden';
|
? 'passwordInput'
|
||||||
|
: 'passwordInput passwordInput--hidden';
|
||||||
const inputClass = loading || pwd ? 'input' : 'input input--noBtn';
|
const inputClass = loading || pwd ? 'input' : 'input input--noBtn';
|
||||||
let btnClass = 'inputBtn inputBtn--password inputBtn--hidden';
|
let btnClass = 'inputBtn inputBtn--password inputBtn--hidden';
|
||||||
if (loading) {
|
if (loading) {
|
||||||
|
@ -13,26 +15,25 @@ module.exports = function(file, state, emit) {
|
||||||
} else if (pwd) {
|
} else if (pwd) {
|
||||||
btnClass = 'inputBtn inputBtn--password';
|
btnClass = 'inputBtn inputBtn--password';
|
||||||
}
|
}
|
||||||
|
|
||||||
const action = pwd
|
const action = pwd
|
||||||
? state.translate('changePasswordButton')
|
? state.translate('changePasswordButton')
|
||||||
: state.translate('addPasswordButton');
|
: state.translate('addPasswordButton');
|
||||||
return html`
|
return html`
|
||||||
<div>
|
<div class="${sectionClass}">
|
||||||
<form
|
<form
|
||||||
class="${formClass}"
|
class="passwordInput__form"
|
||||||
onsubmit=${setPassword}
|
onsubmit=${setPassword}
|
||||||
data-no-csrf>
|
data-no-csrf>
|
||||||
<input id="password-input"
|
<input id="password-input"
|
||||||
${loading ? 'disabled' : ''}
|
${loading ? 'disabled' : ''}
|
||||||
class="${inputClass}"
|
class="${inputClass}"
|
||||||
maxlength="32"
|
maxlength="${MAX_LENGTH}"
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
type="password"
|
type="password"
|
||||||
oninput=${inputChanged}
|
oninput=${inputChanged}
|
||||||
onfocus=${focused}
|
onfocus=${focused}
|
||||||
placeholder="${
|
placeholder="${
|
||||||
pwd
|
pwd && !state.passwordSetError
|
||||||
? passwordPlaceholder(file.password)
|
? passwordPlaceholder(file.password)
|
||||||
: state.translate('unlockInputPlaceholder')
|
: state.translate('unlockInputPlaceholder')
|
||||||
}">
|
}">
|
||||||
|
@ -42,22 +43,28 @@ module.exports = function(file, state, emit) {
|
||||||
class="${btnClass}"
|
class="${btnClass}"
|
||||||
value="${loading ? '' : action}">
|
value="${loading ? '' : action}">
|
||||||
</form>
|
</form>
|
||||||
<div class="passwordInput__msg">${message(
|
<label
|
||||||
loading,
|
class="passwordInput__msg ${
|
||||||
pwd,
|
state.passwordSetError ? 'passwordInput__msg--error' : ''
|
||||||
state.translate('passwordIsSet')
|
}"
|
||||||
)}</div>
|
for="password-input">${message(state, pwd)}</label>
|
||||||
</div>
|
</div>`;
|
||||||
`;
|
|
||||||
|
|
||||||
function inputChanged() {
|
function inputChanged() {
|
||||||
const pwdmsg = document.querySelector('.passwordInput__msg');
|
state.passwordSetError = null;
|
||||||
if (pwdmsg) {
|
|
||||||
pwdmsg.textContent = '';
|
|
||||||
}
|
|
||||||
const resetInput = document.getElementById('password-input');
|
const resetInput = document.getElementById('password-input');
|
||||||
const resetBtn = document.getElementById('password-btn');
|
const resetBtn = document.getElementById('password-btn');
|
||||||
if (resetInput.value.length > 0) {
|
const pwdmsg = document.querySelector('.passwordInput__msg');
|
||||||
|
const length = resetInput.value.length;
|
||||||
|
|
||||||
|
if (length === MAX_LENGTH) {
|
||||||
|
pwdmsg.textContent = state.translate('maxPasswordLength', {
|
||||||
|
length: MAX_LENGTH
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
pwdmsg.textContent = '';
|
||||||
|
}
|
||||||
|
if (length > 0) {
|
||||||
resetBtn.classList.remove('inputBtn--hidden');
|
resetBtn.classList.remove('inputBtn--hidden');
|
||||||
resetInput.classList.remove('input--noBtn');
|
resetInput.classList.remove('input--noBtn');
|
||||||
} else {
|
} else {
|
||||||
|
@ -91,9 +98,12 @@ function passwordPlaceholder(password) {
|
||||||
return password ? password.replace(/./g, '●') : '●●●●●●●●●●●●';
|
return password ? password.replace(/./g, '●') : '●●●●●●●●●●●●';
|
||||||
}
|
}
|
||||||
|
|
||||||
function message(loading, pwd, deflt) {
|
function message(state, pwd) {
|
||||||
if (loading || !pwd) {
|
if (state.passwordSetError) {
|
||||||
|
return state.translate('passwordSetError');
|
||||||
|
}
|
||||||
|
if (state.settingPassword || !pwd) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
return deflt;
|
return state.translate('passwordIsSet');
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,28 @@
|
||||||
.passwordInput {
|
.passwordInput {
|
||||||
display: flex;
|
width: 90%;
|
||||||
flex-wrap: nowrap;
|
|
||||||
width: 80%;
|
|
||||||
padding: 10px 5px 5px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.passwordInput__msg {
|
|
||||||
height: 100px;
|
height: 100px;
|
||||||
margin: 0 5px;
|
padding: 10px 5px 5px;
|
||||||
font-size: 15px;
|
|
||||||
color: var(--lightTextColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.passwordInput--hidden {
|
.passwordInput--hidden {
|
||||||
visibility: hidden;
|
visibility: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.passwordInput__form {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: nowrap;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.passwordInput__msg {
|
||||||
|
font-size: 15px;
|
||||||
|
color: var(--lightTextColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
.passwordInput__msg--error {
|
||||||
|
color: var(--errorColor);
|
||||||
|
}
|
||||||
|
|
||||||
.inputBtn--loading {
|
.inputBtn--loading {
|
||||||
background-image: url('../assets/spinner.svg');
|
background-image: url('../assets/spinner.svg');
|
||||||
background-position: center;
|
background-position: center;
|
||||||
|
|
|
@ -9,7 +9,7 @@ module.exports = function(state, emit) {
|
||||||
<div class="checkbox">
|
<div class="checkbox">
|
||||||
<input
|
<input
|
||||||
${file.hasPassword ? 'disabled' : ''}
|
${file.hasPassword ? 'disabled' : ''}
|
||||||
${file.hasPassword ? 'checked' : ''}
|
${file.hasPassword || state.passwordSetError ? 'checked' : ''}
|
||||||
class="checkbox__input"
|
class="checkbox__input"
|
||||||
id="add-password"
|
id="add-password"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
|
@ -26,7 +26,7 @@ module.exports = function(state, emit) {
|
||||||
const unlockInput = document.getElementById('password-input');
|
const unlockInput = document.getElementById('password-input');
|
||||||
const boxChecked = e.target.checked;
|
const boxChecked = e.target.checked;
|
||||||
document
|
document
|
||||||
.querySelector('form.passwordInput')
|
.querySelector('.passwordInput')
|
||||||
.classList.toggle('passwordInput--hidden', !boxChecked);
|
.classList.toggle('passwordInput--hidden', !boxChecked);
|
||||||
if (boxChecked) {
|
if (boxChecked) {
|
||||||
unlockInput.focus();
|
unlockInput.focus();
|
||||||
|
|
|
@ -103,8 +103,6 @@ requirePasswordCheckbox = Require a password to download this file
|
||||||
addPasswordButton = Add password
|
addPasswordButton = Add password
|
||||||
changePasswordButton = Change
|
changePasswordButton = Change
|
||||||
passwordTryAgain = Incorrect password. Try again.
|
passwordTryAgain = Incorrect password. Try again.
|
||||||
# This label is followed by the password needed to download a file
|
|
||||||
passwordResult = Password: { $password }
|
|
||||||
reportIPInfringement = Report IP Infringement
|
reportIPInfringement = Report IP Infringement
|
||||||
javascriptRequired = Firefox Send requires JavaScript
|
javascriptRequired = Firefox Send requires JavaScript
|
||||||
whyJavascript = Why does Firefox Send require JavaScript?
|
whyJavascript = Why does Firefox Send require JavaScript?
|
||||||
|
@ -115,3 +113,7 @@ expiresHoursMinutes = { $hours }h { $minutes }m
|
||||||
expiresMinutes = { $minutes }m
|
expiresMinutes = { $minutes }m
|
||||||
# A short status message shown when a password is successfully set
|
# A short status message shown when a password is successfully set
|
||||||
passwordIsSet = Password set
|
passwordIsSet = Password set
|
||||||
|
# A short status message shown when the user enters a long password
|
||||||
|
maxPasswordLength = Maximum password length: { $length }
|
||||||
|
# A short status message shown when there was an error setting the password
|
||||||
|
passwordSetError = This password could not be set
|
||||||
|
|
Loading…
Reference in New Issue