diff --git a/src/components/codeInputField.ts b/src/components/codeInputField.ts
new file mode 100644
index 00000000..889c9753
--- /dev/null
+++ b/src/components/codeInputField.ts
@@ -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;
+ });
+ }
+}
diff --git a/src/components/misc.ts b/src/components/misc.ts
index 5c3cf6a7..0309ae9e 100644
--- a/src/components/misc.ts
+++ b/src/components/misc.ts
@@ -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 = `
`;
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);
diff --git a/src/components/sidebarLeft/tabs/2fa/email.ts b/src/components/sidebarLeft/tabs/2fa/email.ts
index 4632b1e5..2d8f8e39 100644
--- a/src/components/sidebarLeft/tabs/2fa/email.ts
+++ b/src/components/sidebarLeft/tabs/2fa/email.ts
@@ -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();
}
}
diff --git a/src/components/sidebarLeft/tabs/2fa/emailConfirmation.ts b/src/components/sidebarLeft/tabs/2fa/emailConfirmation.ts
index e2163656..668ff5bd 100644
--- a/src/components/sidebarLeft/tabs/2fa/emailConfirmation.ts
+++ b/src/components/sidebarLeft/tabs/2fa/emailConfirmation.ts
@@ -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 ',
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.
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();
+ attachClickEvent(btnResend, (e) => {
+ freeze(true);
+ const d = putPreloader(btnResend);
+ passwordManager.resendPasswordEmail().then(value => {
+ d.remove();
+ freeze(false);
+ });
});
- inputWrapper.append(inputField.container, btnContinue, btnSkip);
+ 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();
}
}
diff --git a/src/components/sidebarLeft/tabs/2fa/enterPassword.ts b/src/components/sidebarLeft/tabs/2fa/enterPassword.ts
index e8dca6ea..0a23255e 100644
--- a/src/components/sidebarLeft/tabs/2fa/enterPassword.ts
+++ b/src/components/sidebarLeft/tabs/2fa/enterPassword.ts
@@ -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();
}
}
diff --git a/src/components/sidebarLeft/tabs/2fa/hint.ts b/src/components/sidebarLeft/tabs/2fa/hint.ts
index fd82bbe0..2f04a082 100644
--- a/src/components/sidebarLeft/tabs/2fa/hint.ts
+++ b/src/components/sidebarLeft/tabs/2fa/hint.ts
@@ -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);
diff --git a/src/components/sidebarLeft/tabs/2fa/index.ts b/src/components/sidebarLeft/tabs/2fa/index.ts
index e2671908..2ea1286c 100644
--- a/src/components/sidebarLeft/tabs/2fa/index.ts
+++ b/src/components/sidebarLeft/tabs/2fa/index.ts
@@ -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.';
diff --git a/src/components/sidebarLeft/tabs/2fa/passwordSet.ts b/src/components/sidebarLeft/tabs/2fa/passwordSet.ts
index a2ae3bfa..ce4b0fd7 100644
--- a/src/components/sidebarLeft/tabs/2fa/passwordSet.ts
+++ b/src/components/sidebarLeft/tabs/2fa/passwordSet.ts
@@ -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;
});
diff --git a/src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts b/src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts
index 100802d9..89df6200 100644
--- a/src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts
+++ b/src/components/sidebarLeft/tabs/2fa/reEnterPassword.ts
@@ -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() {
diff --git a/src/components/sidebarLeft/tabs/privacyAndSecurity.ts b/src/components/sidebarLeft/tabs/privacyAndSecurity.ts
index c88dc26a..2903707e 100644
--- a/src/components/sidebarLeft/tabs/privacyAndSecurity.ts
+++ b/src/components/sidebarLeft/tabs/privacyAndSecurity.ts
@@ -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);
}
diff --git a/src/helpers/dom.ts b/src/helpers/dom.ts
index 4a805c11..64154227 100644
--- a/src/helpers/dom.ts
+++ b/src/helpers/dom.ts
@@ -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;
+}
diff --git a/src/lib/appManagers/appDialogsManager.ts b/src/lib/appManagers/appDialogsManager.ts
index 6dfeb404..6c2606f9 100644
--- a/src/lib/appManagers/appDialogsManager.ts
+++ b/src/lib/appManagers/appDialogsManager.ts
@@ -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;
diff --git a/src/lib/mtproto/passwordManager.ts b/src/lib/mtproto/passwordManager.ts
index b466cfd4..d149ced3 100644
--- a/src/lib/mtproto/passwordManager.ts
+++ b/src/lib/mtproto/passwordManager.ts
@@ -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);
}
diff --git a/src/pages/pageAuthCode.ts b/src/pages/pageAuthCode.ts
index a712cea2..f7417fb8 100644
--- a/src/pages/pageAuthCode.ts
+++ b/src/pages/pageAuthCode.ts
@@ -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 => {
- 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 => {
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 => {
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 => {
});
};
- 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);
diff --git a/src/scss/partials/_button.scss b/src/scss/partials/_button.scss
index f40a351d..48248d1e 100644
--- a/src/scss/partials/_button.scss
+++ b/src/scss/partials/_button.scss
@@ -264,6 +264,10 @@
@include hover-background-effect();
+ &.danger {
+ @include hover-background-effect(red);
+ }
+
// * tgico
&:before {
color: #707579;
diff --git a/src/scss/partials/_leftSidebar.scss b/src/scss/partials/_leftSidebar.scss
index cdca1a3d..d3b14689 100644
--- a/src/scss/partials/_leftSidebar.scss
+++ b/src/scss/partials/_leftSidebar.scss
@@ -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;