From 1d9bd1f620af61c12e552266f12c567604f2afc0 Mon Sep 17 00:00:00 2001 From: morethanwords Date: Sat, 31 Oct 2020 04:10:44 +0200 Subject: [PATCH] Authentication state Handle SESSION_REVOKED on password page --- src/components/appMediaViewer.ts | 3 + src/components/wrappers.ts | 6 +- src/helpers/eventListenerBase.ts | 2 +- src/layer.d.ts | 3 +- src/lib/appManagers/appStateManager.ts | 9 ++- src/pages/pageAuthCode.ts | 77 ++++++++++++++------ src/pages/pageIm.ts | 5 ++ src/pages/pagePassword.ts | 11 +++ src/pages/pageSignIn.ts | 6 +- src/pages/pageSignUp.ts | 10 ++- src/scripts/in/schema_additional_params.json | 5 ++ src/types.d.ts | 31 +++++++- 12 files changed, 135 insertions(+), 33 deletions(-) diff --git a/src/components/appMediaViewer.ts b/src/components/appMediaViewer.ts index 56bf5cf3..e0e25af6 100644 --- a/src/components/appMediaViewer.ts +++ b/src/components/appMediaViewer.ts @@ -12,6 +12,7 @@ import VideoPlayer from "../lib/mediaPlayer"; import { RichTextProcessor } from "../lib/richtextprocessor"; import $rootScope from "../lib/rootScope"; import { cancelEvent, fillPropertyValue, findUpClassName, generatePathData } from "../lib/utils"; +import animationIntersector from "./animationIntersector"; import appMediaPlaybackController from "./appMediaPlaybackController"; import AvatarElement from "./avatar"; import ButtonIcon from "./buttonIcon"; @@ -244,6 +245,7 @@ class AppMediaViewerBase { this.wholeDiv.remove(); $rootScope.overlayIsActive = false; + animationIntersector.checkAnimations(false); }); return promise; @@ -846,6 +848,7 @@ class AppMediaViewerBase; const REFRESH_KEYS = ['dialogs', 'allDialogsLoaded', 'messages', 'contactsList', 'stateCreatedTime', @@ -80,7 +81,11 @@ export class AppStateManager extends EventListenerBase<{ //return resolve(); if(auth?.id) { + // ! Warning ! DON'T delete this + this.state.authState = {_: 'authStateSignedIn'}; $rootScope.$broadcast('user_auth', {id: auth.id}); + } else if(!this.state.authState) { + this.state.authState = {_: 'authStateSignIn'}; } //console.timeEnd('load state'); diff --git a/src/pages/pageAuthCode.ts b/src/pages/pageAuthCode.ts index 24b26800..7e124835 100644 --- a/src/pages/pageAuthCode.ts +++ b/src/pages/pageAuthCode.ts @@ -1,4 +1,6 @@ import mediaSizes from '../helpers/mediaSizes'; +import { AuthSentCode, AuthSentCodeType } from '../layer'; +import appStateManager from '../lib/appManagers/appStateManager'; import LottieLoader, { RLottiePlayer } from '../lib/lottieLoader'; //import CryptoWorker from '../lib/crypto/cryptoworker'; //import apiManager from '../lib/mtproto/apiManager'; @@ -10,19 +12,9 @@ import pagePassword from './pagePassword'; import pageSignIn from './pageSignIn'; import pageSignUp from './pageSignUp'; -let authCode: { - _: string, // 'auth.sentCode' - pFlags: any, // {} - flags: number, - type: { - _: string, // 'auth.sentCodeTypeSms', - length: number - }, - phone_code_hash: string, - phone_number: string -} = null; +let authCode: AuthSentCode.authSentCode = null; -const EDITONSAMEPAGE = false; +//const EDITONSAMEPAGE = false; let headerElement: HTMLHeadElement = null; let sentTypeElement: HTMLParagraphElement = null; @@ -34,13 +26,13 @@ let onFirstMount = (): Promise => { let animation: RLottiePlayer; let idleAnimation: RLottiePlayer; - const CODELENGTH = authCode.type.length; + const CODELENGTH = (authCode.type as AuthSentCodeType.authSentCodeTypeApp).length; codeInput = page.pageEl.querySelector('#code') as HTMLInputElement; const codeInputLabel = codeInput.nextElementSibling as HTMLLabelElement; const editButton = page.pageEl.querySelector('.phone-edit') as HTMLElement; - if(EDITONSAMEPAGE) { + /* if(EDITONSAMEPAGE) { let editable = false; let changePhonePromise: Promise; @@ -59,7 +51,7 @@ let onFirstMount = (): Promise => { settings: { _: 'codeSettings' // that's how we sending Type } - /* lang_code: navigator.language || 'en' */ + //lang_code: navigator.language || 'en' }).then((code: any) => { console.log('got code 2', code); @@ -109,11 +101,11 @@ let onFirstMount = (): Promise => { if(!editable) changePhone(); }); - } else { + } else { */ editButton.addEventListener('click', function() { return pageSignIn.mount(); }); - } + //} let cleanup = () => { setTimeout(() => { @@ -186,6 +178,7 @@ let onFirstMount = (): Promise => { // end symbol = frame 165 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) { @@ -201,20 +194,38 @@ let onFirstMount = (): Promise => { lastLength = length; + playAnimation(length); + }); + + const playAnimation = (length: number) => { if(!animation) return; let frame: number; if(length) { frame = Math.round(Math.min(max, length) * (165 / max) + 11.33); - idleAnimation.canvas.style.display = 'none'; + if(idleAnimation) { + idleAnimation.stop(true); + idleAnimation.canvas.style.display = 'none'; + } + animation.canvas.style.display = ''; } else { + /* const cb = (frameNo: number) => { + if(frameNo <= 1) { */ + /* idleAnimation.play(); + idleAnimation.canvas.style.display = ''; + animation.canvas.style.display = 'none'; */ + /* animation.removeListener('enterFrame', cb); + } + }; + animation.addListener('enterFrame', cb); */ + frame = 0; } //animation.playSegments([1, 2]); - let direction = needFrame > frame ? -1 : 1; + const direction = needFrame > frame ? -1 : 1; //console.log('keydown', length, frame, direction); animation.setDirection(direction); @@ -229,6 +240,14 @@ let onFirstMount = (): Promise => { /* animation.goToAndStop(15, true); */ //animation.goToAndStop(length / max * ); + }; + + codeInput.addEventListener('focus', () => { + playAnimation(Math.max(codeInput.value.length, 1)); + }); + + codeInput.addEventListener('blur', () => { + playAnimation(0); }); let imageDiv = page.pageEl.querySelector('.auth-image') as HTMLDivElement; @@ -242,6 +261,11 @@ let onFirstMount = (): Promise => { height: size }, 'assets/img/TwoFactorSetupMonkeyIdle.tgs').then(animation => { idleAnimation = animation; + + // ! animationIntersector will stop animation instantly + if(!codeInput.value.length) { + animation.play(); + } }), LottieLoader.loadAnimationFromURL({ @@ -268,12 +292,12 @@ let onFirstMount = (): Promise => { } if(currentFrame == 0 && needFrame == 0) { - animation.curFrame = 0; + //animation.curFrame = 0; if(idleAnimation) { - animation.canvas.style.display = 'none'; idleAnimation.canvas.style.display = ''; - idleAnimation.restart(); + idleAnimation.play(); + animation.canvas.style.display = 'none'; } } }); @@ -288,6 +312,12 @@ const page = new Page('page-authCode', true, onFirstMount, (_authCode: typeof au if(!headerElement) { headerElement = page.pageEl.getElementsByClassName('phone')[0] as HTMLHeadElement; sentTypeElement = page.pageEl.getElementsByClassName('sent-type')[0] as HTMLParagraphElement; + } else { + codeInput.value = ''; + + const evt = document.createEvent('HTMLEvents'); + evt.initEvent('input', false, true); + codeInput.dispatchEvent(evt); } //let LottieLoader = (await import('../lib/lottieLoader')).default; @@ -307,6 +337,9 @@ const page = new Page('page-authCode', true, onFirstMount, (_authCode: typeof au sentTypeElement.innerHTML = `Please check everything
for a code (type: ${authCode.type._})`; break; } + + appStateManager.pushToState('authState', {_: 'authStateAuthCode', sentCode: _authCode}); + appStateManager.saveState(); }, () => { codeInput.focus(); }); diff --git a/src/pages/pageIm.ts b/src/pages/pageIm.ts index 908cb76d..048af630 100644 --- a/src/pages/pageIm.ts +++ b/src/pages/pageIm.ts @@ -1,9 +1,14 @@ //import {stackBlurImage} from '../lib/StackBlur'; +//import appStateManager from "../lib/appManagers/appStateManager"; +import appStateManager from "../lib/appManagers/appStateManager"; import { DEBUG } from "../lib/mtproto/mtproto_config"; import Page from "./page"; let onFirstMount = () => { //return; + appStateManager.pushToState('authState', {_: 'authStateSignedIn'}); + // ! TOO SLOW + /* appStateManager.saveState(); */ const promise = import('../lib/appManagers/appDialogsManager'); promise.finally(async() => { diff --git a/src/pages/pagePassword.ts b/src/pages/pagePassword.ts index 94d5eff4..02fdb9ac 100644 --- a/src/pages/pagePassword.ts +++ b/src/pages/pagePassword.ts @@ -4,6 +4,7 @@ import { putPreloader } from '../components/misc'; import mediaSizes from '../helpers/mediaSizes'; import { isAppleMobile, isSafari } from '../helpers/userAgent'; import { AccountPassword } from '../layer'; +import appStateManager from '../lib/appManagers/appStateManager'; import LottieLoader, { RLottiePlayer } from '../lib/lottieLoader'; //import passwordManager from '../lib/mtproto/passwordManager'; import apiManager from '../lib/mtproto/mtprotoworker'; @@ -25,8 +26,14 @@ let onFirstMount = (): Promise => { passwordInput = document.getElementById('password') as HTMLInputElement; const passwordInputLabel = passwordInput.nextElementSibling as HTMLLabelElement; const toggleVisible = page.pageEl.querySelector('.toggle-visible') as HTMLSpanElement; + let getStateInterval: number; let getState = () => { + // * just to check session relevance + if(!getStateInterval) { + getStateInterval = window.setInterval(getState, 10e3); + } + return !TEST && passwordManager.getState().then(_state => { state = _state; @@ -92,6 +99,7 @@ let onFirstMount = (): Promise => { id: response.user.id }); + clearInterval(getStateInterval); pageIm.mount(); if(animation) animation.remove(); break; @@ -149,6 +157,9 @@ const page = new Page('page-password', true, onFirstMount, null, () => { //if(!isAppleMobile) { passwordInput.focus(); //} + + appStateManager.pushToState('authState', {_: 'authStatePassword'}); + appStateManager.saveState(); }); export default page; diff --git a/src/pages/pageSignIn.ts b/src/pages/pageSignIn.ts index 53b64419..b0a809fe 100644 --- a/src/pages/pageSignIn.ts +++ b/src/pages/pageSignIn.ts @@ -1,6 +1,7 @@ import { formatPhoneNumber, putPreloader } from "../components/misc"; import Scrollable from '../components/scrollable'; import Countries, { Country as _Country } from "../countries"; +import appStateManager from "../lib/appManagers/appStateManager"; import apiManager from "../lib/mtproto/mtprotoworker"; import { App, Modes } from "../lib/mtproto/mtproto_config"; import { RichTextProcessor } from '../lib/richtextprocessor'; @@ -222,7 +223,7 @@ let onFirstMount = () => { }); */ telEl.addEventListener('keypress', function(this: typeof telEl, e) { - console.log('keypress', this.value); + //console.log('keypress', this.value); if(!btnNext.style.visibility &&/* this.value.length >= 9 && */ e.key == 'Enter') { return btnNext.click(); } else if(/\D/.test(e.key)) { @@ -322,6 +323,9 @@ const page = new Page('page-sign', true, onFirstMount, () => { btnNext.textContent = 'NEXT'; btnNext.removeAttribute('disabled'); + + appStateManager.pushToState('authState', {_: 'authStateSignIn'}); + appStateManager.saveState(); }); export default page; diff --git a/src/pages/pageSignUp.ts b/src/pages/pageSignUp.ts index cdd6d6a8..5e8ce7cd 100644 --- a/src/pages/pageSignUp.ts +++ b/src/pages/pageSignUp.ts @@ -1,14 +1,13 @@ import { putPreloader } from '../components/misc'; import PopupAvatar from '../components/popupAvatar'; +import appStateManager from '../lib/appManagers/appStateManager'; //import apiManager from '../lib/mtproto/apiManager'; import apiManager from '../lib/mtproto/mtprotoworker'; +import { AuthState } from '../types'; import Page from './page'; import pageIm from './pageIm'; -let authCode: { - 'phone_number': string, - 'phone_code_hash': string -} = null; +let authCode: AuthState.signUp['authCode'] = null; let onFirstMount = () => import('../lib/appManagers/appProfileManager').then(imported => { const pageElement = page.pageEl; @@ -116,6 +115,9 @@ let onFirstMount = () => import('../lib/appManagers/appProfileManager').then(imp const page = new Page('page-signUp', true, onFirstMount, (_authCode: typeof authCode) => { authCode = _authCode; + + appStateManager.pushToState('authState', {_: 'authStateSignUp', authCode: _authCode}); + appStateManager.saveState(); }); export default page; diff --git a/src/scripts/in/schema_additional_params.json b/src/scripts/in/schema_additional_params.json index 68914c35..f4ba7da3 100644 --- a/src/scripts/in/schema_additional_params.json +++ b/src/scripts/in/schema_additional_params.json @@ -222,4 +222,9 @@ {"name": "sortStatus", "type": "number"}, {"name": "num", "type": "number"} ] +}, { + "predicate": "auth.sentCode", + "params": [ + {"name": "phone_number", "type": "string"} + ] }] \ No newline at end of file diff --git a/src/types.d.ts b/src/types.d.ts index baf8f9ec..e51023ab 100644 --- a/src/types.d.ts +++ b/src/types.d.ts @@ -1,3 +1,4 @@ +import { AuthSentCode } from "./layer"; import type { ApiError } from "./lib/mtproto/apiManager"; export type InvokeApiOptions = Partial<{ @@ -32,4 +33,32 @@ export type Modify = Omit & R; //export type Parameters = T extends (... args: infer T) => any ? T : never; -export type ArgumentTypes = F extends (...args: infer A) => any ? A : never; \ No newline at end of file +export type ArgumentTypes = F extends (...args: infer A) => any ? A : never; + +export type AuthState = AuthState.signIn | AuthState.authCode | AuthState.password | AuthState.signUp | AuthState.signedIn; +export namespace AuthState { + export type signIn = { + _: 'authStateSignIn' + }; + + export type authCode = { + _: 'authStateAuthCode', + sentCode: AuthSentCode.authSentCode + }; + + export type password = { + _: 'authStatePassword' + }; + + export type signUp = { + _: 'authStateSignUp', + authCode: { + phone_number: string, + phone_code_hash: string + } + }; + + export type signedIn = { + _: 'authStateSignedIn' + }; +} \ No newline at end of file