diff --git a/src/helpers/toggleStorages.ts b/src/helpers/toggleStorages.ts new file mode 100644 index 00000000..aff16bb8 --- /dev/null +++ b/src/helpers/toggleStorages.ts @@ -0,0 +1,18 @@ +/* + * https://github.com/morethanwords/tweb + * Copyright (C) 2019-2021 Eduard Kuzmenko + * https://github.com/morethanwords/tweb/blob/master/LICENSE + */ + +import CacheStorageController from "../lib/cacheStorage"; +import AppStorage from "../lib/storage"; +import sessionStorage from "../lib/sessionStorage"; +import noop from "./noop"; + +export default function toggleStorages(enabled: boolean) { + return Promise.all([ + AppStorage.toggleStorage(enabled), + CacheStorageController.toggleStorage(enabled), + sessionStorage.toggleStorage(enabled) + ]).then(noop, noop); +} diff --git a/src/lib/appManagers/appStateManager.ts b/src/lib/appManagers/appStateManager.ts index f7525440..310a846b 100644 --- a/src/lib/appManagers/appStateManager.ts +++ b/src/lib/appManagers/appStateManager.ts @@ -11,7 +11,7 @@ import setDeepProperty from '../../helpers/object/setDeepProperty'; import MTProtoMessagePort from '../mtproto/mtprotoMessagePort'; export class AppStateManager { - private state: State; + private state: State = {} as any; private storage = stateStorage; // ! for mtproto worker use only @@ -23,10 +23,6 @@ export class AppStateManager { return Promise.resolve(this.state); } - public setState(state: State) { - return this.state = state; - } - public setByKey(key: string, value: any) { setDeepProperty(this.state, key, value); @@ -38,20 +34,20 @@ export class AppStateManager { this.pushToState(first, this.state[first]); } - public pushToState(key: T, value: State[T], direct = true) { + public pushToState(key: T, value: State[T], direct = true, onlyLocal?: boolean) { if(direct) { this.state[key] = value; } - this.setKeyValueToStorage(key, value); + this.setKeyValueToStorage(key, value, onlyLocal); } - public setKeyValueToStorage(key: T, value: State[T] = this.state[key]) { + public setKeyValueToStorage(key: T, value: State[T] = this.state[key], onlyLocal?: boolean) { MTProtoMessagePort.getInstance().invoke('mirror', {name: 'state', key, value}); this.storage.set({ [key]: value - }); + }, onlyLocal); } /* public resetState() { diff --git a/src/lib/appManagers/uiNotificationsManager.ts b/src/lib/appManagers/uiNotificationsManager.ts index 4b26d45a..268a3046 100644 --- a/src/lib/appManagers/uiNotificationsManager.ts +++ b/src/lib/appManagers/uiNotificationsManager.ts @@ -22,7 +22,6 @@ import webPushApiManager, { PushSubscriptionNotify } from "../mtproto/webPushApi import fixEmoji from "../richTextProcessor/fixEmoji"; import wrapPlainText from "../richTextProcessor/wrapPlainText"; import rootScope from "../rootScope"; -import stateStorage from "../stateStorage"; import appRuntimeManager from "./appRuntimeManager"; import { AppManagers } from "./managers"; import getPeerId from "./utils/peers/getPeerId"; @@ -493,7 +492,10 @@ export class UiNotificationsManager { } public updateLocalSettings = () => { - Promise.all(['notify_nodesktop', 'notify_volume', 'notify_novibrate', 'notify_nopreview', 'notify_nopush'].map((k) => stateStorage.get(k as any))) + const keys = ['notify_nodesktop', 'notify_volume', 'notify_novibrate', 'notify_nopreview', 'notify_nopush']; + const promises = keys.map(() => undefined); + // const promises = keys.map((k) => stateStorage.get(k as any)); + Promise.all(promises) .then((updSettings) => { this.settings.nodesktop = updSettings[0]; this.settings.volume = updSettings[1] === undefined ? 0.5 : updSettings[1]; diff --git a/src/lib/cacheStorage.ts b/src/lib/cacheStorage.ts index 23861fc9..2ff8292a 100644 --- a/src/lib/cacheStorage.ts +++ b/src/lib/cacheStorage.ts @@ -141,7 +141,3 @@ export default class CacheStorageController { })); } } - -//const cacheStorage = new CacheStorageController(); -//MOUNT_CLASS_TO.cacheStorage = cacheStorage; -//export default cacheStorage; diff --git a/src/lib/idb.ts b/src/lib/idb.ts index e6ba5a1c..6d1bf2f0 100644 --- a/src/lib/idb.ts +++ b/src/lib/idb.ts @@ -261,7 +261,7 @@ export default class IDBStorage, StoreName extends strin }, DEBUG ? 'delete: ' + entryName.join(', ') : '', storeName); } - public clear(storeName?: StoreName) { + public clear(storeName?: StoreName): Promise { return this.getObjectStore('readwrite', (objectStore) => objectStore.clear(), DEBUG ? 'clear' : '', storeName); } @@ -422,7 +422,12 @@ export default class IDBStorage, StoreName extends strin }; transaction.onerror = onError; - // transaction.oncomplete = () => onComplete('transaction'); + + // * have to wait while clearing or setting something + const waitForTransactionComplete = mode === 'readwrite'; + if(waitForTransactionComplete) { + transaction.oncomplete = () => onComplete(/* 'transaction' */); + } const timeout = setTimeout(() => { this.log.error('transaction not finished', transaction, log); @@ -438,6 +443,10 @@ export default class IDBStorage, StoreName extends strin const isArray = Array.isArray(callbackResult); const requests: IDBRequest[] = isArray ? callbackResult : [].concat(callbackResult) as any; + if(waitForTransactionComplete) { + return; + } + const length = requests.length; let left = length; diff --git a/src/lib/mtproto/apiManager.ts b/src/lib/mtproto/apiManager.ts index 9f1e4433..5f32e4ab 100644 --- a/src/lib/mtproto/apiManager.ts +++ b/src/lib/mtproto/apiManager.ts @@ -42,6 +42,7 @@ import pause from '../../helpers/schedulers/pause'; import ApiManagerMethods from './api_methods'; import { getEnvironment } from '../../environment/utils'; import AppStorage from '../storage'; +import toggleStorages from '../../helpers/toggleStorages'; /* var networker = apiManager.cachedNetworkers.websocket.upload[2]; networker.wrapMtpMessage({ @@ -296,7 +297,7 @@ export class ApiManager extends ApiManagerMethods { const clear = async() => { this.baseDcId = undefined; //this.telegramMeNotify(false); - await AppStorage.toggleStorage(false); + await toggleStorages(false); IDB.closeDatabases(); this.rootScope.dispatchEvent('logging_out'); }; diff --git a/src/lib/mtproto/mtproto.worker.ts b/src/lib/mtproto/mtproto.worker.ts index 73c3323f..d2f30666 100644 --- a/src/lib/mtproto/mtproto.worker.ts +++ b/src/lib/mtproto/mtproto.worker.ts @@ -17,12 +17,18 @@ import MTProtoMessagePort from './mtprotoMessagePort'; import RESET_STORAGES_PROMISE from '../appManagers/utils/storages/resetStoragesPromise'; import appManagersManager from '../appManagers/appManagersManager'; import listenMessagePort from '../../helpers/listenMessagePort'; +import { logger } from '../logger'; +import { State } from '../../config/state'; +import AppStorage from '../storage'; +import toggleStorages from '../../helpers/toggleStorages'; let _isServiceWorkerOnline = true; export function isServiceWorkerOnline() { return _isServiceWorkerOnline; } +const log = logger('MTPROTO'); + const port = new MTProtoMessagePort(); port.addMultipleEventsListeners({ environment: (environment) => { @@ -36,24 +42,23 @@ port.addMultipleEventsListeners({ }, state: ({state, resetStorages, pushedKeys, newVersion, oldVersion, userId}) => { + log('got state', state, pushedKeys); + appStateManager.userId = userId; appStateManager.newVersion = newVersion; appStateManager.oldVersion = oldVersion; - appStateManager.setState(state); - for(const key of pushedKeys) { - appStateManager.setKeyValueToStorage(key); - } + + (Object.keys(state) as any as (keyof State)[]).forEach((key) => { + appStateManager.pushToState(key, state[key], true, !pushedKeys.includes(key)); + }); RESET_STORAGES_PROMISE.resolve(resetStorages); }, - toggleStorage: (enabled) => { - // AppStorage.toggleStorage(enabled); - CacheStorageController.toggleStorage(enabled); - }, + toggleStorages: (enabled) => toggleStorages(enabled), event: (payload, source) => { - console.log('will redirect event', payload, source); + log('will redirect event', payload, source); port.invokeExceptSource('event', payload, source); }, @@ -94,7 +99,7 @@ port.addMultipleEventsListeners({ // }, }); -console.log('MTProto start'); +log('MTProto start'); appManagersManager.start(); appManagersManager.getManagers(); diff --git a/src/lib/mtproto/mtprotoMessagePort.ts b/src/lib/mtproto/mtprotoMessagePort.ts index fa3a236e..29079eb4 100644 --- a/src/lib/mtproto/mtprotoMessagePort.ts +++ b/src/lib/mtproto/mtprotoMessagePort.ts @@ -11,6 +11,7 @@ import type { StoragesResults } from "../appManagers/utils/storages/loadStorages import type { LocalStorageProxyTask } from "../localStorage"; import type { Awaited } from "../../types"; import type { Mirrors, MirrorTaskPayload } from "./mtprotoworker"; +import type toggleStorages from "../../helpers/toggleStorages"; import SuperMessagePort from "./superMessagePort"; export type MTProtoManagerTaskPayload = {name: string, method: string, args: any[]}; @@ -24,7 +25,7 @@ export default class MTProtoMessagePort extends S crypto: (payload: {method: string, args: any[]}) => Promise, state: (payload: {userId: UserId} & Awaited> & {storagesResults?: StoragesResults}) => void, manager: (payload: MTProtoManagerTaskPayload) => any, - toggleStorage: (enable: boolean) => void, + toggleStorages: typeof toggleStorages, serviceWorkerOnline: (online: boolean) => void, cryptoPort: (payload: void, source: MessageEventSource, event: MessageEvent) => void, createObjectURL: (blob: Blob) => string diff --git a/src/lib/mtproto/mtprotoworker.ts b/src/lib/mtproto/mtprotoworker.ts index 225a08e9..9f57a688 100644 --- a/src/lib/mtproto/mtprotoworker.ts +++ b/src/lib/mtproto/mtprotoworker.ts @@ -15,7 +15,7 @@ import webPushApiManager from './webPushApiManager'; import AppStorage from '../storage'; import appRuntimeManager from '../appManagers/appRuntimeManager'; import telegramMeWebManager from './telegramMeWebManager'; -import { CacheStorageDbName } from '../cacheStorage'; +import CacheStorageController, { CacheStorageDbName } from '../cacheStorage'; import pause from '../../helpers/schedulers/pause'; import isObject from '../../helpers/object/isObject'; import ENVIRONMENT from '../../environment'; @@ -26,9 +26,10 @@ import cryptoMessagePort from '../crypto/cryptoMessagePort'; import SuperMessagePort from './superMessagePort'; import IS_SHARED_WORKER_SUPPORTED from '../../environment/sharedWorkerSupport'; import type { State } from '../../config/state'; +import toggleStorages from '../../helpers/toggleStorages'; export interface ToggleStorageTask extends WorkerTaskVoidTemplate { - type: 'toggleStorage', + type: 'toggleStorages', payload: boolean }; @@ -157,7 +158,7 @@ class ApiManagerProxy extends MTProtoMessagePort { rootScope.addEventListener('logging_out', () => { const toClear: CacheStorageDbName[] = ['cachedFiles', 'cachedStreamChunks']; Promise.all([ - AppStorage.toggleStorage(false), + toggleStorages(false), sessionStorage.clear(), Promise.race([ telegramMeWebManager.setAuthorized(false), @@ -356,9 +357,10 @@ class ApiManagerProxy extends MTProtoMessagePort { } /// #endif - public toggleStorage(enabled: boolean) { - const task: ToggleStorageTask = {type: 'toggleStorage', payload: enabled}; - this.invoke('toggleStorage', enabled); + public async toggleStorages(enabled: boolean) { + await toggleStorages(enabled); + this.invoke('toggleStorages', enabled); + const task: ToggleStorageTask = {type: 'toggleStorages', payload: enabled}; this.postSWMessage(task); } diff --git a/src/lib/serviceWorker/index.service.ts b/src/lib/serviceWorker/index.service.ts index f16bd4c9..37084123 100644 --- a/src/lib/serviceWorker/index.service.ts +++ b/src/lib/serviceWorker/index.service.ts @@ -93,7 +93,7 @@ const taskListeners: { delete promises[task.id]; } }, - toggleStorage: (task: ToggleStorageTask) => { + toggleStorages: (task: ToggleStorageTask) => { CacheStorageController.toggleStorage(task.payload); } }; diff --git a/src/lib/storage.ts b/src/lib/storage.ts index 460a7ef8..18e88a54 100644 --- a/src/lib/storage.ts +++ b/src/lib/storage.ts @@ -13,6 +13,7 @@ import { Database } from "../config/databases"; import { MOUNT_CLASS_TO } from "../config/debug"; //import DATABASE_SESSION from "../config/databases/session"; import deferredPromise, { CancellablePromise } from "../helpers/cancellablePromise"; +import { IS_WORKER } from "../helpers/context"; import throttle from "../helpers/schedulers/throttle"; //import { WorkerTaskTemplate } from "../types"; import IDBStorage from "./idb"; @@ -295,6 +296,10 @@ export default class AppStorage< return Promise.all(this.STORAGES.map((storage) => { storage.useStorage = enabled; + if(!IS_WORKER) { + return; + } + if(!enabled) { storage.keysToSet.clear(); storage.keysToDelete.clear(); diff --git a/src/pages/pageSignIn.ts b/src/pages/pageSignIn.ts index 77b4eeca..21d406b6 100644 --- a/src/pages/pageSignIn.ts +++ b/src/pages/pageSignIn.ts @@ -341,10 +341,7 @@ let onFirstMount = () => { const keepSigned = signedCheckboxField.checked; rootScope.managers.appStateManager.pushToState('keepSigned', keepSigned); - AppStorage.toggleStorage(keepSigned); - CacheStorageController.toggleStorage(keepSigned); - apiManagerProxy.toggleStorage(keepSigned); - sessionStorage.toggleStorage(keepSigned); + apiManagerProxy.toggleStorages(keepSigned); }); apiManagerProxy.getState().then((state) => {