tweb/src/lib/appManagers/appStateManager.ts

142 lines
4.6 KiB
TypeScript
Raw Normal View History

import type { Dialog } from './appMessagesManager';
2020-09-26 00:47:43 +02:00
import type { AppStickersManager } from './appStickersManager';
import { App, MOUNT_CLASS_TO, UserAuth } from '../mtproto/mtproto_config';
import EventListenerBase from '../../helpers/eventListenerBase';
2020-11-15 04:33:47 +01:00
import rootScope from '../rootScope';
import AppStorage from '../storage';
import { logger } from '../logger';
import type { AppUsersManager } from './appUsersManager';
import type { AppChatsManager } from './appChatsManager';
import type { AuthState } from '../../types';
import type { AppMessagesIDsManager } from './appMessagesIDsManager';
import type FiltersStorage from '../storages/filters';
import type DialogsStorage from '../storages/dialogs';
2020-06-20 03:11:24 +02:00
2020-08-30 13:21:58 +02:00
const REFRESH_EVERY = 24 * 60 * 60 * 1000; // 1 day
const STATE_VERSION = App.version;
2020-08-30 13:21:58 +02:00
type State = Partial<{
dialogs: Dialog[],
allDialogsLoaded: DialogsStorage['allDialogsLoaded'],
//peers: {[peerID: string]: ReturnType<AppPeersManager['getPeer']>},
chats: {[peerID: string]: ReturnType<AppChatsManager['getChat']>},
users: {[peerID: string]: ReturnType<AppUsersManager['getUser']>},
2020-08-30 13:21:58 +02:00
messages: any[],
contactsList: number[],
updates: any,
filters: FiltersStorage['filters'],
maxSeenMsgID: number,
stateCreatedTime: number,
recentEmoji: string[],
topPeers: number[],
2020-09-26 00:47:43 +02:00
recentSearch: number[],
stickerSets: AppStickersManager['stickerSets'],
version: typeof STATE_VERSION,
authState: AuthState,
messagesIDsLocals: {
channelLocals: AppMessagesIDsManager['channelLocals'],
channelsByLocals: AppMessagesIDsManager['channelsByLocals'],
channelCurLocal: AppMessagesIDsManager['channelCurLocal'],
}
2020-08-31 18:48:46 +02:00
}>;
2020-08-30 13:21:58 +02:00
2020-09-26 00:47:43 +02:00
const REFRESH_KEYS = ['dialogs', 'allDialogsLoaded', 'messages', 'contactsList', 'stateCreatedTime',
'updates', 'maxSeenMsgID', 'filters', 'topPeers'] as any as Array<keyof State>;
export class AppStateManager extends EventListenerBase<{
save: (state: State) => void
}> {
public loaded: Promise<State>;
2020-06-20 03:11:24 +02:00
private log = logger('STATE'/* , LogLevels.error */);
2020-09-26 00:47:43 +02:00
private state: State;
2020-06-20 03:11:24 +02:00
constructor() {
super();
2020-06-20 03:11:24 +02:00
this.loadSavedState();
}
public loadSavedState() {
if(this.loaded) return this.loaded;
//console.time('load state');
2020-09-26 00:47:43 +02:00
return this.loaded = new Promise((resolve) => {
AppStorage.get<[State, UserAuth]>('state', 'user_auth').then(([state, auth]) => {
2020-08-30 13:21:58 +02:00
const time = Date.now();
if(state) {
if(state.version != STATE_VERSION) {
state = {};
} else if((state.stateCreatedTime || 0) + REFRESH_EVERY < time) {
this.log('will refresh state', state.stateCreatedTime, time);
REFRESH_KEYS.forEach(key => {
delete state[key];
});
//state = {};
}
2020-08-30 13:21:58 +02:00
}
2020-06-21 14:25:17 +02:00
this.state = state || {};
this.state.chats = state.chats || {};
this.state.users = state.users || {};
this.state.version = STATE_VERSION;
// ??= doesn't compiles
2020-08-30 13:21:58 +02:00
if(!this.state.hasOwnProperty('stateCreatedTime')) {
this.state.stateCreatedTime = Date.now();
}
this.log('state res', state);
2020-06-20 03:11:24 +02:00
//return resolve();
2020-06-20 03:11:24 +02:00
if(auth?.id) {
// ! Warning ! DON'T delete this
this.state.authState = {_: 'authStateSignedIn'};
2020-11-15 04:33:47 +01:00
rootScope.broadcast('user_auth', {id: auth.id});
} else if(!this.state.authState) {
this.state.authState = {_: 'authStateSignIn'};
}
//console.timeEnd('load state');
2020-06-20 03:11:24 +02:00
resolve(state);
}).catch(resolve).finally(() => {
setInterval(() => this.saveState(), 10000);
});
});
}
public getState() {
2020-09-26 00:47:43 +02:00
return this.state === undefined ? this.loadSavedState() : Promise.resolve(this.state);
2020-06-20 03:11:24 +02:00
}
public saveState() {
2020-09-26 00:47:43 +02:00
if(this.state === undefined) return;
2020-10-17 00:31:58 +02:00
//let perf = performance.now();
this.setListenerResult('save', this.state);
2020-10-17 00:31:58 +02:00
//this.log('saveState: event time:', performance.now() - perf);
2020-06-20 03:11:24 +02:00
//const pinnedOrders = appMessagesManager.dialogsStorage.pinnedOrders;
2020-10-17 00:31:58 +02:00
//perf = performance.now();
2020-06-20 03:11:24 +02:00
AppStorage.set({
state: this.state
2020-06-20 03:11:24 +02:00
});
2020-10-17 00:31:58 +02:00
//this.log('saveState: storage set time:', performance.now() - perf);
2020-06-20 03:11:24 +02:00
}
2020-08-30 13:21:58 +02:00
public pushToState<T extends keyof State>(key: T, value: State[T]) {
2020-06-20 03:11:24 +02:00
this.state[key] = value;
}
public setPeer(peerID: number, peer: any) {
const container = peerID > 0 ? this.state.users : this.state.chats;
if(container.hasOwnProperty(peerID)) return;
container[peerID] = peer;
2020-06-20 03:11:24 +02:00
}
}
//console.trace('appStateManager include');
2020-06-20 03:11:24 +02:00
const appStateManager = new AppStateManager();
MOUNT_CLASS_TO && (MOUNT_CLASS_TO.appStateManager = appStateManager);
2020-06-20 03:11:24 +02:00
export default appStateManager;