Authentication state

Handle SESSION_REVOKED on password page
This commit is contained in:
morethanwords 2020-10-31 04:10:44 +02:00
parent d62618d3f5
commit 6112219b58
12 changed files with 135 additions and 33 deletions

View File

@ -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<ContentAdditionType extends string, ButtonsAdditionType
promise.finally(() => {
this.wholeDiv.remove();
$rootScope.overlayIsActive = false;
animationIntersector.checkAnimations(false);
});
return promise;
@ -846,6 +848,7 @@ class AppMediaViewerBase<ContentAdditionType extends string, ButtonsAdditionType
void this.wholeDiv.offsetLeft; // reflow
this.wholeDiv.classList.add('active');
$rootScope.overlayIsActive = true;
animationIntersector.checkAnimations(true);
}
////////this.log('wasActive:', wasActive);

View File

@ -140,7 +140,7 @@ export function wrapVideo({doc, container, message, boxWidth, boxHeight, withTai
let img: HTMLImageElement;
if(message) {
if(!canAutoplay && doc.thumbs?.length) {
if(!canAutoplay) {
return wrapPhoto(doc, message, container, boxWidth, boxHeight, withTail, isOut, lazyLoadQueue, middleware);
}
@ -485,6 +485,10 @@ export function wrapPhoto(photo: MyPhoto | MyDocument, message: any, container:
}
}
if(!((photo as MyPhoto).sizes || (photo as MyDocument).thumbs)) {
return Promise.resolve();
}
//console.log('wrapPhoto downloaded:', photo, photo.downloaded, container);
const cacheContext = appPhotosManager.getCacheContext(photo);

View File

@ -16,7 +16,7 @@ export default class EventListenerBase<Listeners extends {[name: string]: Functi
(this.listeners[name] ?? (this.listeners[name] = [])).push({callback, once});
if(this.listenerResults.hasOwnProperty(name)) {
callback(this.listenerResults[name]);
callback(...this.listenerResults[name]);
if(once) {
this.removeListener(name, callback);

3
src/layer.d.ts vendored
View File

@ -1239,7 +1239,8 @@ export namespace AuthSentCode {
type: AuthSentCodeType,
phone_code_hash: string,
next_type?: AuthCodeType,
timeout?: number
timeout?: number,
phone_number?: string
};
}

View File

@ -1,6 +1,5 @@
import type { Dialog, DialogsStorage, FiltersStorage } from './appMessagesManager';
import type { AppStickersManager } from './appStickersManager';
import type { AppPeersManager } from './appPeersManager';
import { App, MOUNT_CLASS_TO, UserAuth } from '../mtproto/mtproto_config';
import EventListenerBase from '../../helpers/eventListenerBase';
import $rootScope from '../rootScope';
@ -8,6 +7,7 @@ import AppStorage from '../storage';
import { logger } from '../logger';
import type { AppUsersManager } from './appUsersManager';
import type { AppChatsManager } from './appChatsManager';
import type { AuthState } from '../../types';
const REFRESH_EVERY = 24 * 60 * 60 * 1000; // 1 day
const STATE_VERSION = App.version;
@ -28,7 +28,8 @@ type State = Partial<{
topPeers: number[],
recentSearch: number[],
stickerSets: AppStickersManager['stickerSets'],
version: typeof STATE_VERSION
version: typeof STATE_VERSION,
authState: AuthState
}>;
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');

View File

@ -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<any> => {
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<unknown>;
@ -59,7 +51,7 @@ let onFirstMount = (): Promise<any> => {
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<any> => {
if(!editable) changePhone();
});
} else {
} else { */
editButton.addEventListener('click', function() {
return pageSignIn.mount();
});
}
//}
let cleanup = () => {
setTimeout(() => {
@ -186,6 +178,7 @@ let onFirstMount = (): Promise<any> => {
// 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<any> => {
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<any> => {
/* 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<any> => {
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<any> => {
}
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<br>for a code (type: ${authCode.type._})`;
break;
}
appStateManager.pushToState('authState', {_: 'authStateAuthCode', sentCode: _authCode});
appStateManager.saveState();
}, () => {
codeInput.focus();
});

View File

@ -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() => {

View File

@ -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<any> => {
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<any> => {
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;

View File

@ -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;

View File

@ -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;

View File

@ -222,4 +222,9 @@
{"name": "sortStatus", "type": "number"},
{"name": "num", "type": "number"}
]
}, {
"predicate": "auth.sentCode",
"params": [
{"name": "phone_number", "type": "string"}
]
}]

31
src/types.d.ts vendored
View File

@ -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<T, R> = Omit<T, keyof R> & R;
//export type Parameters<T> = T extends (... args: infer T) => any ? T : never;
export type ArgumentTypes<F extends Function> = F extends (...args: infer A) => any ? A : never;
export type ArgumentTypes<F extends Function> = 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'
};
}