Two-factor:
Recovery email Fix enter shortcut on handhelds
This commit is contained in:
parent
c32a7cea12
commit
a6753d7325
38
src/components/codeInputField.ts
Normal file
38
src/components/codeInputField.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import InputField from "./inputField";
|
||||
|
||||
export default class CodeInputField extends InputField {
|
||||
constructor(options: {
|
||||
label?: string,
|
||||
name?: string,
|
||||
length: number,
|
||||
onFill: (code: number) => void
|
||||
}) {
|
||||
super({
|
||||
plainText: true,
|
||||
...options
|
||||
});
|
||||
|
||||
const input = this.input as HTMLInputElement;
|
||||
input.type = 'tel';
|
||||
input.setAttribute('required', '');
|
||||
input.autocomplete = 'off';
|
||||
|
||||
let lastLength = 0;
|
||||
this.input.addEventListener('input', (e) => {
|
||||
this.input.classList.remove('error');
|
||||
this.label.innerText = options.label;
|
||||
|
||||
const value = this.value.replace(/\D/g, '').slice(0, options.length);
|
||||
this.setValueSilently(value);
|
||||
|
||||
const length = this.value.length;
|
||||
if(length === options.length) { // submit code
|
||||
options.onFill(+this.value);
|
||||
} else if(length === lastLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastLength = length;
|
||||
});
|
||||
}
|
||||
}
|
@ -55,14 +55,14 @@ export function renderImageFromUrl(elem: HTMLElement | HTMLImageElement | SVGIma
|
||||
}
|
||||
}
|
||||
|
||||
export function putPreloader(elem: Element, returnDiv = false) {
|
||||
export function putPreloader(elem: Element, returnDiv = false): HTMLElement {
|
||||
const html = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" class="preloader-circular" viewBox="25 25 50 50">
|
||||
<circle class="preloader-path" cx="50" cy="50" r="20" fill="none" stroke-miterlimit="10"/>
|
||||
</svg>`;
|
||||
|
||||
if(returnDiv) {
|
||||
let div = document.createElement('div');
|
||||
const div = document.createElement('div');
|
||||
div.classList.add('preloader');
|
||||
div.innerHTML = html;
|
||||
|
||||
@ -74,6 +74,7 @@ export function putPreloader(elem: Element, returnDiv = false) {
|
||||
}
|
||||
|
||||
elem.innerHTML += html;
|
||||
return elem.lastElementChild as HTMLElement;
|
||||
}
|
||||
|
||||
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.putPreloader = putPreloader);
|
||||
|
@ -5,7 +5,7 @@ import Button from "../../../button";
|
||||
import SidebarSlider, { SliderSuperTab } from "../../../slider";
|
||||
import { wrapSticker } from "../../../wrappers";
|
||||
import InputField from "../../../inputField";
|
||||
import { attachClickEvent, cancelEvent } from "../../../../helpers/dom";
|
||||
import { attachClickEvent, cancelEvent, canFocus } from "../../../../helpers/dom";
|
||||
import PopupConfirmAction from "../../../popups/confirmAction";
|
||||
import { putPreloader } from "../../../misc";
|
||||
import passwordManager from "../../../../lib/mtproto/passwordManager";
|
||||
@ -19,6 +19,7 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
public plainPassword: string;
|
||||
public newPassword: string;
|
||||
public hint: string;
|
||||
public isFirst = false;
|
||||
|
||||
constructor(slider: SidebarSlider) {
|
||||
super(slider, true);
|
||||
@ -29,7 +30,7 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
this.title.innerHTML = 'Recovery Email';
|
||||
|
||||
const section = new SettingSection({
|
||||
caption: ' ',
|
||||
caption: '',
|
||||
noDelimiter: true
|
||||
});
|
||||
|
||||
@ -69,7 +70,7 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
inputField.input.addEventListener('keypress', (e) => {
|
||||
if(e.key === 'Enter') {
|
||||
cancelEvent(e);
|
||||
return btnContinue.click();
|
||||
return onContinueClick();
|
||||
}
|
||||
});
|
||||
|
||||
@ -78,13 +79,13 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
});
|
||||
|
||||
const btnContinue = Button('btn-primary btn-color-primary', {text: 'CONTINUE'});
|
||||
const btnSkip = Button('btn-primary btn-primary-transparent primary', {text: 'SKIP'});
|
||||
const btnSkip = Button('btn-primary btn-secondary btn-primary-transparent primary', {text: 'SKIP'});
|
||||
|
||||
const goNext = () => {
|
||||
new AppTwoStepVerificationSetTab(this.slider).open();
|
||||
};
|
||||
|
||||
attachClickEvent(btnContinue, (e) => {
|
||||
const onContinueClick = () => {
|
||||
const email = inputField.value.trim();
|
||||
const match = RichTextProcessor.matchEmail(email);
|
||||
if(!match || match[0].length !== email.length) {
|
||||
@ -93,7 +94,7 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
}
|
||||
|
||||
toggleButtons(true);
|
||||
putPreloader(btnContinue);
|
||||
const d = putPreloader(btnContinue);
|
||||
|
||||
passwordManager.updateSettings({
|
||||
hint: this.hint,
|
||||
@ -108,9 +109,6 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
|
||||
const tab = new AppTwoStepVerificationEmailConfirmationTab(this.slider);
|
||||
tab.state = this.state;
|
||||
tab.newPassword = this.newPassword;
|
||||
tab.plainPassword = this.plainPassword;
|
||||
tab.hint = this.hint;
|
||||
tab.email = email;
|
||||
tab.length = symbols;
|
||||
tab.open();
|
||||
@ -119,8 +117,10 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
}
|
||||
|
||||
toggleButtons(false);
|
||||
d.remove();
|
||||
});
|
||||
});
|
||||
};
|
||||
attachClickEvent(btnContinue, onContinueClick);
|
||||
|
||||
const toggleButtons = (freeze: boolean) => {
|
||||
if(freeze) {
|
||||
@ -145,7 +145,8 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
passwordManager.updateSettings({
|
||||
hint: this.hint,
|
||||
currentPassword: this.plainPassword,
|
||||
newPassword: this.newPassword
|
||||
newPassword: this.newPassword,
|
||||
email: ''
|
||||
}).then(() => {
|
||||
goNext();
|
||||
}, (err) => {
|
||||
@ -169,6 +170,7 @@ export default class AppTwoStepVerificationEmailTab extends SliderSuperTab {
|
||||
}
|
||||
|
||||
onOpenAfterTimeout() {
|
||||
if(!canFocus(this.isFirst)) return;
|
||||
this.inputField.input.focus();
|
||||
}
|
||||
}
|
||||
|
@ -4,21 +4,19 @@ import appStickersManager from "../../../../lib/appManagers/appStickersManager";
|
||||
import Button from "../../../button";
|
||||
import SidebarSlider, { SliderSuperTab } from "../../../slider";
|
||||
import { wrapSticker } from "../../../wrappers";
|
||||
import InputField from "../../../inputField";
|
||||
import { attachClickEvent } from "../../../../helpers/dom";
|
||||
import PopupConfirmAction from "../../../popups/confirmAction";
|
||||
import { putPreloader } from "../../../misc";
|
||||
import { attachClickEvent, canFocus, toggleDisability } from "../../../../helpers/dom";
|
||||
import passwordManager from "../../../../lib/mtproto/passwordManager";
|
||||
import AppTwoStepVerificationSetTab from "./passwordSet";
|
||||
import CodeInputField from "../../../codeInputField";
|
||||
import AppTwoStepVerificationEmailTab from "./email";
|
||||
import { putPreloader } from "../../../misc";
|
||||
|
||||
export default class AppTwoStepVerificationEmailConfirmationTab extends SliderSuperTab {
|
||||
public inputField: InputField;
|
||||
public codeInputField: CodeInputField;
|
||||
public state: AccountPassword;
|
||||
public plainPassword: string;
|
||||
public newPassword: string;
|
||||
public hint: string;
|
||||
public email: string;
|
||||
public length: number;
|
||||
public isFirst = false;
|
||||
|
||||
constructor(slider: SidebarSlider) {
|
||||
super(slider, true);
|
||||
@ -29,10 +27,12 @@ export default class AppTwoStepVerificationEmailConfirmationTab extends SliderSu
|
||||
this.title.innerHTML = 'Recovery Email';
|
||||
|
||||
const section = new SettingSection({
|
||||
caption: ' ',
|
||||
caption: 'Please enter code we\'ve just emailed at <b></b>',
|
||||
noDelimiter: true
|
||||
});
|
||||
|
||||
(section.caption.lastElementChild as HTMLElement).innerText = this.email;
|
||||
|
||||
const emoji = '📬';
|
||||
const doc = appStickersManager.getAnimatedEmojiSticker(emoji);
|
||||
const stickerContainer = document.createElement('div');
|
||||
@ -60,54 +60,69 @@ export default class AppTwoStepVerificationEmailConfirmationTab extends SliderSu
|
||||
const inputWrapper = document.createElement('div');
|
||||
inputWrapper.classList.add('input-wrapper');
|
||||
|
||||
const inputField = this.inputField = new InputField({
|
||||
const inputField = this.codeInputField = new CodeInputField({
|
||||
name: 'recovery-email-code',
|
||||
label: 'Code'
|
||||
label: 'Code',
|
||||
length: this.length,
|
||||
onFill: (code) => {
|
||||
freeze(true);
|
||||
|
||||
passwordManager.confirmPasswordEmail('' + code)
|
||||
.then(value => {
|
||||
if(!value) {
|
||||
|
||||
}
|
||||
|
||||
goNext();
|
||||
})
|
||||
.catch(err => {
|
||||
switch(err.type) {
|
||||
case 'CODE_INVALID':
|
||||
inputField.input.classList.add('error');
|
||||
inputField.label.innerText = 'Invalid Code';
|
||||
break;
|
||||
|
||||
default:
|
||||
console.error('confirm error', err);
|
||||
break;
|
||||
}
|
||||
|
||||
freeze(false);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
const btnContinue = Button('btn-primary btn-color-primary', {text: 'CONTINUE'});
|
||||
const btnSkip = Button('btn-primary btn-primary-transparent primary', {text: 'SKIP'});
|
||||
const btnChange = Button('btn-primary btn-primary-transparent primary', {text: 'CHANGE EMAIL'});
|
||||
const btnResend = Button('btn-primary btn-secondary btn-primary-transparent primary', {text: 'RE-SEND CODE'});
|
||||
|
||||
const goNext = () => {
|
||||
new AppTwoStepVerificationSetTab(this.slider).open();
|
||||
};
|
||||
|
||||
attachClickEvent(btnContinue, (e) => {
|
||||
|
||||
});
|
||||
const freeze = (disable: boolean) => {
|
||||
toggleDisability([inputField.input, btnChange, btnResend], disable);
|
||||
};
|
||||
|
||||
attachClickEvent(btnSkip, (e) => {
|
||||
const popup = new PopupConfirmAction('popup-skip-email', [{
|
||||
text: 'CANCEL',
|
||||
isCancel: true
|
||||
}, {
|
||||
text: 'SKIP',
|
||||
callback: () => {
|
||||
//inputContent.classList.add('sidebar-left-section-disabled');
|
||||
btnContinue.setAttribute('disabled', 'true');
|
||||
btnSkip.setAttribute('disabled', 'true');
|
||||
putPreloader(btnSkip);
|
||||
passwordManager.updateSettings({
|
||||
hint: this.hint,
|
||||
currentPassword: this.plainPassword,
|
||||
newPassword: this.newPassword
|
||||
}).then(() => {
|
||||
goNext();
|
||||
}, (err) => {
|
||||
btnContinue.removeAttribute('disabled');
|
||||
btnSkip.removeAttribute('disabled');
|
||||
});
|
||||
},
|
||||
isDanger: true,
|
||||
}], {
|
||||
title: 'Warning',
|
||||
text: 'No, seriously.<br/><br/>If you forget your password, you will lose access to your Telegram account. There will be no way to restore it.'
|
||||
attachClickEvent(btnChange, (e) => {
|
||||
freeze(true);
|
||||
passwordManager.cancelPasswordEmail().then(value => {
|
||||
this.slider.sliceTabsUntilTab(AppTwoStepVerificationEmailTab, this);
|
||||
this.close();
|
||||
}, () => {
|
||||
freeze(false);
|
||||
});
|
||||
|
||||
popup.show();
|
||||
});
|
||||
|
||||
inputWrapper.append(inputField.container, btnContinue, btnSkip);
|
||||
attachClickEvent(btnResend, (e) => {
|
||||
freeze(true);
|
||||
const d = putPreloader(btnResend);
|
||||
passwordManager.resendPasswordEmail().then(value => {
|
||||
d.remove();
|
||||
freeze(false);
|
||||
});
|
||||
});
|
||||
|
||||
inputWrapper.append(inputField.container, btnChange, btnResend);
|
||||
|
||||
inputContent.append(inputWrapper);
|
||||
|
||||
@ -115,6 +130,7 @@ export default class AppTwoStepVerificationEmailConfirmationTab extends SliderSu
|
||||
}
|
||||
|
||||
onOpenAfterTimeout() {
|
||||
this.inputField.input.focus();
|
||||
if(!canFocus(this.isFirst)) return;
|
||||
this.codeInputField.input.focus();
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import AppTwoStepVerificationTab from ".";
|
||||
import { SettingSection } from "../..";
|
||||
import { attachClickEvent, cancelEvent } from "../../../../helpers/dom";
|
||||
import { attachClickEvent, cancelEvent, canFocus } from "../../../../helpers/dom";
|
||||
import { isMobileSafari } from "../../../../helpers/userAgent";
|
||||
import { AccountPassword } from "../../../../layer";
|
||||
import passwordManager from "../../../../lib/mtproto/passwordManager";
|
||||
import RichTextProcessor from "../../../../lib/richtextprocessor";
|
||||
@ -16,6 +17,7 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
|
||||
public state: AccountPassword;
|
||||
public passwordInputField: PasswordInputField;
|
||||
public plainPassword: string;
|
||||
public isFirst = true;
|
||||
|
||||
constructor(slider: SidebarSlider) {
|
||||
super(slider, true);
|
||||
@ -56,7 +58,7 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
|
||||
}
|
||||
|
||||
if(e.key === 'Enter') {
|
||||
return btnContinue.click();
|
||||
return onContinueClick();
|
||||
}
|
||||
});
|
||||
|
||||
@ -69,6 +71,7 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
|
||||
return true;
|
||||
};
|
||||
|
||||
let onContinueClick: (e?: Event) => void;
|
||||
if(!isNew) {
|
||||
let getStateInterval: number;
|
||||
|
||||
@ -123,12 +126,15 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
|
||||
});
|
||||
};
|
||||
|
||||
attachClickEvent(btnContinue, submit);
|
||||
|
||||
onContinueClick = submit;
|
||||
|
||||
getState();
|
||||
} else {
|
||||
attachClickEvent(btnContinue, (e) => {
|
||||
cancelEvent(e);
|
||||
onContinueClick = (e) => {
|
||||
if(e) {
|
||||
cancelEvent(e);
|
||||
}
|
||||
|
||||
if(!verifyInput()) return;
|
||||
|
||||
const tab = new AppTwoStepVerificationReEnterPasswordTab(this.slider);
|
||||
@ -136,11 +142,14 @@ export default class AppTwoStepVerificationEnterPasswordTab extends SliderSuperT
|
||||
tab.newPassword = passwordInputField.value;
|
||||
tab.plainPassword = this.plainPassword;
|
||||
tab.open();
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
attachClickEvent(btnContinue, onContinueClick);
|
||||
}
|
||||
|
||||
onOpenAfterTimeout() {
|
||||
if(!canFocus(this.isFirst)) return;
|
||||
this.passwordInputField.input.focus();
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import { wrapSticker } from "../../../wrappers";
|
||||
import InputField from "../../../inputField";
|
||||
import AppTwoStepVerificationEmailTab from "./email";
|
||||
import { attachClickEvent, cancelEvent } from "../../../../helpers/dom";
|
||||
import { toast } from "../../../toast";
|
||||
|
||||
export default class AppTwoStepVerificationHintTab extends SliderSuperTab {
|
||||
public inputField: InputField;
|
||||
@ -23,7 +24,6 @@ export default class AppTwoStepVerificationHintTab extends SliderSuperTab {
|
||||
this.title.innerHTML = 'Password Hint';
|
||||
|
||||
const section = new SettingSection({
|
||||
caption: ' ',
|
||||
noDelimiter: true
|
||||
});
|
||||
|
||||
@ -60,28 +60,37 @@ export default class AppTwoStepVerificationHintTab extends SliderSuperTab {
|
||||
inputField.input.addEventListener('keypress', (e) => {
|
||||
if(e.key === 'Enter') {
|
||||
cancelEvent(e);
|
||||
return (inputField.value ? btnContinue : btnSkip).click();
|
||||
return inputField.value ? onContinueClick() : onSkipClick();
|
||||
}
|
||||
});
|
||||
|
||||
const goNext = (e: Event, saveHint: boolean) => {
|
||||
cancelEvent(e);
|
||||
const goNext = (e?: Event, saveHint?: boolean) => {
|
||||
if(e) {
|
||||
cancelEvent(e);
|
||||
}
|
||||
|
||||
const hint = saveHint ? inputField.value : undefined;
|
||||
if(hint && this.newPassword === hint) {
|
||||
toast('Hint must be different from your password');
|
||||
return;
|
||||
}
|
||||
|
||||
const tab = new AppTwoStepVerificationEmailTab(this.slider);
|
||||
tab.state = this.state;
|
||||
tab.plainPassword = this.plainPassword;
|
||||
tab.newPassword = this.newPassword;
|
||||
if(saveHint) {
|
||||
tab.hint = inputField.value;
|
||||
}
|
||||
tab.hint = hint;
|
||||
|
||||
tab.open();
|
||||
};
|
||||
|
||||
const btnContinue = Button('btn-primary btn-color-primary', {text: 'CONTINUE'});
|
||||
const btnSkip = Button('btn-primary btn-primary-transparent primary', {text: 'SKIP'});
|
||||
const btnSkip = Button('btn-primary btn-secondary btn-primary-transparent primary', {text: 'SKIP'});
|
||||
|
||||
attachClickEvent(btnContinue, (e) => goNext(e, true));
|
||||
attachClickEvent(btnSkip, (e) => goNext(e, false));
|
||||
const onContinueClick = (e?: Event) => goNext(e, true);
|
||||
const onSkipClick = (e?: Event) => goNext(e, false);
|
||||
attachClickEvent(btnContinue, onContinueClick);
|
||||
attachClickEvent(btnSkip, onSkipClick);
|
||||
|
||||
inputWrapper.append(inputField.container, btnContinue, btnSkip);
|
||||
|
||||
|
@ -8,6 +8,7 @@ import PopupConfirmAction from "../../../popups/confirmAction";
|
||||
import SidebarSlider, { SliderSuperTab } from "../../../slider";
|
||||
import { wrapSticker } from "../../../wrappers";
|
||||
import AppSettingsTab from "../settings";
|
||||
import AppTwoStepVerificationEmailTab from "./email";
|
||||
import AppTwoStepVerificationEnterPasswordTab from "./enterPassword";
|
||||
|
||||
export default class AppTwoStepVerificationTab extends SliderSuperTab {
|
||||
@ -19,7 +20,7 @@ export default class AppTwoStepVerificationTab extends SliderSuperTab {
|
||||
}
|
||||
|
||||
protected init() {
|
||||
this.container.classList.add('two-step-verification');
|
||||
this.container.classList.add('two-step-verification', 'two-step-verification-main');
|
||||
this.title.innerHTML = 'Two-Step Verification';
|
||||
|
||||
const section = new SettingSection({
|
||||
@ -55,7 +56,7 @@ export default class AppTwoStepVerificationTab extends SliderSuperTab {
|
||||
|
||||
const btnChangePassword = Button('btn-primary btn-transparent', {icon: 'edit', text: 'Change Password'});
|
||||
const btnDisablePassword = Button('btn-primary btn-transparent', {icon: 'passwordoff', text: 'Turn Password Off'});
|
||||
const btnSetRecoveryEmail = Button('btn-primary btn-transparent', {icon: 'email', text: 'Set Recovery Email'});
|
||||
const btnSetRecoveryEmail = Button('btn-primary btn-transparent', {icon: 'email', text: this.state.pFlags.has_recovery ? 'Change Recovery Email' : 'Set Recovery Email'});
|
||||
|
||||
attachClickEvent(btnChangePassword, () => {
|
||||
const tab = new AppTwoStepVerificationEnterPasswordTab(this.slider);
|
||||
@ -82,6 +83,16 @@ export default class AppTwoStepVerificationTab extends SliderSuperTab {
|
||||
popup.show();
|
||||
});
|
||||
|
||||
attachClickEvent(btnSetRecoveryEmail, () => {
|
||||
const tab = new AppTwoStepVerificationEmailTab(this.slider);
|
||||
tab.state = this.state;
|
||||
tab.hint = this.state.hint;
|
||||
tab.plainPassword = this.plainPassword;
|
||||
tab.newPassword = this.plainPassword;
|
||||
tab.isFirst = true;
|
||||
tab.open();
|
||||
});
|
||||
|
||||
c.append(btnChangePassword, btnDisablePassword, btnSetRecoveryEmail);
|
||||
} else {
|
||||
section.caption.innerHTML = 'You can set a password that will be required when you log in on a new device in addition to the code you get in the SMS.';
|
||||
|
@ -31,8 +31,7 @@ export default class AppTwoStepVerificationSetTab extends SliderSuperTab {
|
||||
loop: true,
|
||||
play: true,
|
||||
width: 160,
|
||||
height: 160,
|
||||
emoji
|
||||
height: 160
|
||||
}).then(() => {
|
||||
// this.animation = player;
|
||||
});
|
||||
|
@ -52,7 +52,7 @@ export default class AppTwoStepVerificationReEnterPasswordTab extends SliderSupe
|
||||
}
|
||||
|
||||
if(e.key === 'Enter') {
|
||||
return btnContinue.click();
|
||||
return onContinueClick();
|
||||
}
|
||||
});
|
||||
|
||||
@ -65,8 +65,11 @@ export default class AppTwoStepVerificationReEnterPasswordTab extends SliderSupe
|
||||
return true;
|
||||
};
|
||||
|
||||
attachClickEvent(btnContinue, (e) => {
|
||||
cancelEvent(e);
|
||||
const onContinueClick = (e?: Event) => {
|
||||
if(e) {
|
||||
cancelEvent(e);
|
||||
}
|
||||
|
||||
if(!verifyInput()) return;
|
||||
|
||||
const tab = new AppTwoStepVerificationHintTab(this.slider);
|
||||
@ -74,7 +77,8 @@ export default class AppTwoStepVerificationReEnterPasswordTab extends SliderSupe
|
||||
tab.plainPassword = this.plainPassword;
|
||||
tab.newPassword = this.newPassword;
|
||||
tab.open();
|
||||
});
|
||||
};
|
||||
attachClickEvent(btnContinue, onContinueClick);
|
||||
}
|
||||
|
||||
onOpenAfterTimeout() {
|
||||
|
@ -7,6 +7,7 @@ import AppPrivacyPhoneNumberTab from "./privacy/phoneNumber";
|
||||
import AppTwoStepVerificationTab from "./2fa";
|
||||
import passwordManager from "../../../lib/mtproto/passwordManager";
|
||||
import AppTwoStepVerificationEnterPasswordTab from "./2fa/enterPassword";
|
||||
import AppTwoStepVerificationEmailConfirmationTab from "./2fa/emailConfirmation";
|
||||
|
||||
export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
|
||||
constructor(slider: SidebarSlider) {
|
||||
@ -35,9 +36,15 @@ export default class AppPrivacyAndSecurityTab extends SliderSuperTab {
|
||||
title: 'Two-Step Verification',
|
||||
subtitle: 'Loading...',
|
||||
clickable: (e: Event) => {
|
||||
let tab: AppTwoStepVerificationTab | AppTwoStepVerificationEnterPasswordTab;
|
||||
let tab: AppTwoStepVerificationTab | AppTwoStepVerificationEnterPasswordTab | AppTwoStepVerificationEmailConfirmationTab;
|
||||
if(passwordState.pFlags.has_password) {
|
||||
tab = new AppTwoStepVerificationEnterPasswordTab(this.slider);
|
||||
} else if(passwordState.email_unconfirmed_pattern) {
|
||||
tab = new AppTwoStepVerificationEmailConfirmationTab(this.slider);
|
||||
tab.email = passwordState.email_unconfirmed_pattern;
|
||||
tab.length = 6;
|
||||
tab.isFirst = true;
|
||||
passwordManager.resendPasswordEmail();
|
||||
} else {
|
||||
tab = new AppTwoStepVerificationTab(this.slider);
|
||||
}
|
||||
|
@ -2,7 +2,7 @@ import { MessageEntity } from "../layer";
|
||||
import RichTextProcessor from "../lib/richtextprocessor";
|
||||
import ListenerSetter from "./listenerSetter";
|
||||
import { isTouchSupported } from "./touchSupport";
|
||||
import { isApple } from "./userAgent";
|
||||
import { isApple, isMobileSafari } from "./userAgent";
|
||||
import rootScope from "../lib/rootScope";
|
||||
import { MOUNT_CLASS_TO } from "../config/debug";
|
||||
import { doubleRaf } from "./schedulers";
|
||||
@ -784,3 +784,15 @@ export function disableTransition(elements: HTMLElement[]) {
|
||||
elements.forEach(el => el.classList.remove('no-transition'));
|
||||
});
|
||||
}
|
||||
|
||||
export function toggleDisability(elements: HTMLElement[], disable: boolean) {
|
||||
if(disable) {
|
||||
elements.forEach(el => el.setAttribute('disabled', 'true'));
|
||||
} else {
|
||||
elements.forEach(el => el.removeAttribute('disabled'));
|
||||
}
|
||||
}
|
||||
|
||||
export function canFocus(isFirstInput: boolean) {
|
||||
return !isMobileSafari || !isFirstInput;
|
||||
}
|
||||
|
@ -181,7 +181,7 @@ export class AppDialogsManager {
|
||||
public doms: {[peerId: number]: DialogDom} = {};
|
||||
|
||||
public chatsContainer = document.getElementById('chatlist-container') as HTMLDivElement;
|
||||
private chatsPreloader: HTMLDivElement;
|
||||
private chatsPreloader: HTMLElement;
|
||||
|
||||
public loadDialogsPromise: Promise<any>;
|
||||
|
||||
|
@ -80,6 +80,18 @@ export class PasswordManager {
|
||||
});
|
||||
}
|
||||
|
||||
public confirmPasswordEmail(code: string) {
|
||||
return apiManager.invokeApi('account.confirmPasswordEmail', {code});
|
||||
}
|
||||
|
||||
public resendPasswordEmail() {
|
||||
return apiManager.invokeApi('account.resendPasswordEmail');
|
||||
}
|
||||
|
||||
public cancelPasswordEmail() {
|
||||
return apiManager.invokeApi('account.cancelPasswordEmail');
|
||||
}
|
||||
|
||||
/* public requestRecovery(options: any = {}) {
|
||||
return apiManager.invokeApi('auth.requestPasswordRecovery', {}, options);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
import mediaSizes from '../helpers/mediaSizes';
|
||||
import { AuthSentCode, AuthSentCodeType } from '../layer';
|
||||
import { AuthSentCode, AuthSentCodeType, AuthSignIn } from '../layer';
|
||||
import appStateManager from '../lib/appManagers/appStateManager';
|
||||
import apiManager from '../lib/mtproto/mtprotoworker';
|
||||
import Page from './page';
|
||||
@ -7,8 +7,8 @@ import pageIm from './pageIm';
|
||||
import pagePassword from './pagePassword';
|
||||
import pageSignIn from './pageSignIn';
|
||||
import pageSignUp from './pageSignUp';
|
||||
import InputField from '../components/inputField';
|
||||
import TrackingMonkey from '../components/monkeys/tracking';
|
||||
import CodeInputField from '../components/codeInputField';
|
||||
|
||||
let authCode: AuthSentCode.authSentCode = null;
|
||||
|
||||
@ -17,24 +17,21 @@ let sentTypeElement: HTMLParagraphElement = null;
|
||||
let codeInput: HTMLInputElement;
|
||||
|
||||
let onFirstMount = (): Promise<any> => {
|
||||
let lastLength = 0;
|
||||
|
||||
const CODELENGTH = (authCode.type as AuthSentCodeType.authSentCodeTypeApp).length;
|
||||
|
||||
const codeInputField = new InputField({
|
||||
const codeInputField = new CodeInputField({
|
||||
label: 'Code',
|
||||
name: 'code',
|
||||
plainText: true
|
||||
length: CODELENGTH,
|
||||
onFill: (code) => {
|
||||
submitCode('' + code);
|
||||
}
|
||||
});
|
||||
|
||||
codeInput = codeInputField.input as HTMLInputElement;
|
||||
codeInput.type = 'tel';
|
||||
codeInput.setAttribute('required', '');
|
||||
codeInput.autocomplete = 'off';
|
||||
|
||||
page.pageEl.querySelector('.input-wrapper').append(codeInputField.container);
|
||||
|
||||
const codeInputLabel = codeInput.nextElementSibling as HTMLLabelElement;
|
||||
const editButton = page.pageEl.querySelector('.phone-edit') as HTMLElement;
|
||||
|
||||
editButton.addEventListener('click', function() {
|
||||
@ -50,7 +47,7 @@ let onFirstMount = (): Promise<any> => {
|
||||
const submitCode = (code: string) => {
|
||||
codeInput.setAttribute('disabled', 'true');
|
||||
|
||||
const params = {
|
||||
const params: AuthSignIn = {
|
||||
phone_number: authCode.phone_number,
|
||||
phone_code_hash: authCode.phone_code_hash,
|
||||
phone_code: code
|
||||
@ -92,15 +89,15 @@ let onFirstMount = (): Promise<any> => {
|
||||
break;
|
||||
case 'PHONE_CODE_EXPIRED':
|
||||
codeInput.classList.add('error');
|
||||
codeInputLabel.innerText = 'Code expired';
|
||||
codeInputField.label.innerText = 'Code expired';
|
||||
break;
|
||||
case 'PHONE_CODE_EMPTY':
|
||||
case 'PHONE_CODE_INVALID':
|
||||
codeInput.classList.add('error');
|
||||
codeInputLabel.innerText = 'Invalid Code';
|
||||
codeInputField.label.innerText = 'Invalid Code';
|
||||
break;
|
||||
default:
|
||||
codeInputLabel.innerText = err.type;
|
||||
codeInputField.label.innerText = err.type;
|
||||
break;
|
||||
}
|
||||
|
||||
@ -108,25 +105,6 @@ let onFirstMount = (): Promise<any> => {
|
||||
});
|
||||
};
|
||||
|
||||
codeInput.addEventListener('input', function(this: typeof codeInput, e) {
|
||||
this.classList.remove('error');
|
||||
codeInputLabel.innerText = 'Code';
|
||||
|
||||
this.value = this.value.replace(/\D/g, '');
|
||||
if(this.value.length > CODELENGTH) {
|
||||
this.value = this.value.slice(0, CODELENGTH);
|
||||
}
|
||||
|
||||
const length = this.value.length;
|
||||
if(length === CODELENGTH) { // submit code
|
||||
submitCode(this.value);
|
||||
} else if(length === lastLength) {
|
||||
return;
|
||||
}
|
||||
|
||||
lastLength = length;
|
||||
});
|
||||
|
||||
const imageDiv = page.pageEl.querySelector('.auth-image') as HTMLDivElement;
|
||||
const size = mediaSizes.isMobile ? 100 : 166;
|
||||
const monkey = new TrackingMonkey(codeInputField, size);
|
||||
|
@ -264,6 +264,10 @@
|
||||
|
||||
@include hover-background-effect();
|
||||
|
||||
&.danger {
|
||||
@include hover-background-effect(red);
|
||||
}
|
||||
|
||||
// * tgico
|
||||
&:before {
|
||||
color: #707579;
|
||||
|
@ -913,8 +913,14 @@
|
||||
margin-bottom: 1.125rem;
|
||||
}
|
||||
|
||||
.btn-primary + .btn-primary {
|
||||
margin-top: .125rem !important;
|
||||
&-main {
|
||||
.btn-primary + .btn-primary {
|
||||
margin-top: .125rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
margin-top: .5rem !important;
|
||||
}
|
||||
|
||||
.media-sticker-wrapper {
|
||||
@ -935,12 +941,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
&-hint, &-email {
|
||||
.btn-primary + .btn-primary {
|
||||
margin-top: .5rem !important;
|
||||
}
|
||||
}
|
||||
|
||||
&-hint {
|
||||
.media-sticker-wrapper {
|
||||
width: 160px;
|
||||
|
Loading…
x
Reference in New Issue
Block a user