tweb/public/0.acb684dc35d9188bd6be.chun...

1 line
84 KiB
Plaintext

{"version":3,"sources":["webpack:///./src/helpers/noop.ts","webpack:///./src/config/databases/state.ts","webpack:///./src/helpers/schedulers/throttle.ts","webpack:///./src/lib/rootScope.ts","webpack:///./src/config/debug.ts","webpack:///./src/helpers/object.ts","webpack:///./src/lib/logger.ts","webpack:///./src/helpers/cancellablePromise.ts","webpack:///./src/helpers/eventListenerBase.ts","webpack:///./src/helpers/context.ts","webpack:///./src/lib/localStorage.ts","webpack:///./src/lib/sessionStorage.ts","webpack:///./src/helpers/random.ts","webpack:///./src/config/modes.ts","webpack:///./src/lib/stateStorage.ts","webpack:///./src/helpers/blob.ts","webpack:///./src/lib/idb.ts","webpack:///./src/lib/storage.ts"],"names":["noop","name","version","stores","throttle","fn","ms","shouldRunFirst","isPending","args","interval","_args","setInterval","clearInterval","RootScope","super","overlaysActive","myId","idle","isIDLE","deactivated","focusPromise","Promise","resolve","focusResolve","connectionStatus","peerId","filterId","config","forwarded_count_max","edit_time_limit","pinned_dialogs_count_max","pinned_infolder_count_max","message_length_max","caption_length_max","this","addEventListener","e","id","status","undefined","_themeColorElem","document","head","querySelector","color","themeColor","isNight","themeColorElem","setAttribute","darkModeMediaQuery","window","matchMedia","checkDarkMode","systemTheme","matches","dispatchEvent","setTheme","addListener","err","colorScheme","documentElement","classList","toggle","setThemeColor","value","isOverlayActive","getTheme","settings","theme","themes","find","t","rootScope","DEBUG","debug","MOUNT_CLASS_TO","self","copy","obj","Date","getTime","Array","isArray","map","el","clonedObj","constructor","prop","hasOwnProperty","deepEqual","x","y","ok","Object","keys","tx","length","every","key","defineNotNumerableProperties","names","props","writable","configurable","out","forEach","defineProperties","getObjectKeysAndSort","object","sort","ids","Map","i","a","b","safeReplaceObject","wasObject","newObject","safeReplaceArrayInObject","v","isObject","getDeepProperty","splitted","split","o","setDeepProperty","slice","join","pop","validateInitObject","initObject","currentObject","onReplace","previousKey","safeAssign","fromObject","LogTypes","LOG_LEVELS","None","Error","Warn","Log","Debug","_logTimer","now","dT","toFixed","logger","prefix","type","ignoreDebugReset","console","log","warn","info","error","trace","setPrefix","_prefix","setLevel","level","reduce","acc","deferredPromise","deferredHelper","isFulfilled","isRejected","notify","notifyAll","lastNotify","listeners","callback","addNotifyListener","push","deferred","reject","catch","finally","cancel","assign","EventListenerBase","reuseResults","_constructor","listenerResults","options","once","findAndSplice","l","arr","listener","findIndex","removeEventListener","isWebWorker","WorkerGlobalScope","isServiceWorker","ServiceWorkerGlobalScope","isWorker","notifyServiceWorker","all","clients","matchAll","includeUncontrolled","then","postMessage","notifyWorker","notifySomeone","bind","cache","useStorage","test","useCache","localStorage","getItem","JSON","parse","onlyLocal","stringified","stringify","setItem","saveLocal","removeItem","delete","enabled","set","clear","taskId","tasks","STORAGES","storage","result","payload","prototype","call","apply","proxy","sessionStorage","appStorage","arrays","8","Uint8Array","16","Uint16Array","32","Uint32Array","nextRandomUint","bits","array","crypto","getRandomValues","randomLong","Modes","location","search","indexOf","http","ssl","multipleConnections","asServiceWorker","stateStorage","readBlobAs","blob","method","reader","FileReader","target","readBlobAsText","readBlobAsDataURL","readBlobAsUint8Array","readBlobAsArrayBuffer","buffer","blobConstruct","blobParts","mimeType","safeMimeType","blobSafeMimeType","Blob","bb","BlobBuilder","blobPart","append","getBlob","db","storeName","storageIsAvailable","openDatabase","preserve","onclose","close","createNew","openDbPromise","request","indexedDB","open","message","finished","setTimeout","onerror","onsuccess","event","calledNew","onabort","transaction","onversionchange","onupgradeneeded","oldVersion","newVersion","store","objectStoreNames","contains","os","createObjectStore","indexes","index","createIndex","indexName","keyPath","objectParameters","entryName","concat","getObjectStore","objectStore","idx","put","fileName","save","get","mode","perf","performance","clearTimeout","timeout","oncomplete","results","r","requests","getAll","getPromises","keysToSet","Set","saveDeferred","keysToDelete","deleteDeferred","saveThrottled","size","from","values","deleteThrottled","getThrottled","includes","getFromCache","p","setToCache","add"],"mappings":"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","file":"0.acb684dc35d9188bd6be.chunk.js","sourcesContent":["export default function noop() {}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport { Database } from '.';\r\n\r\nconst DATABASE_STATE: Database<'session' | 'stickerSets' | 'users' | 'chats' | 'messages' | 'dialogs'> = {\r\n name: 'tweb',\r\n version: 7,\r\n stores: [{\r\n name: 'session'\r\n }, {\r\n name: 'stickerSets'\r\n }, {\r\n name: 'users'\r\n }, {\r\n name: 'chats'\r\n }, {\r\n name: 'dialogs'\r\n }, {\r\n name: 'messages'\r\n }]\r\n};\r\n\r\nexport default DATABASE_STATE;\r\n","// * Jolly Cobra's schedulers\r\n\r\nimport { AnyToVoidFunction } from \"../../types\";\r\n\r\nexport default function throttle<F extends AnyToVoidFunction>(\r\n fn: F,\r\n ms: number,\r\n shouldRunFirst = true,\r\n) {\r\n let interval: number | null = null;\r\n let isPending: boolean;\r\n let args: Parameters<F>;\r\n\r\n return (..._args: Parameters<F>) => {\r\n isPending = true;\r\n args = _args;\r\n\r\n if(!interval) {\r\n if(shouldRunFirst) {\r\n isPending = false;\r\n // @ts-ignore\r\n fn(...args);\r\n }\r\n\r\n interval = setInterval(() => {\r\n if (!isPending) {\r\n clearInterval(interval!);\r\n interval = null;\r\n return;\r\n }\r\n\r\n isPending = false;\r\n // @ts-ignore\r\n fn(...args);\r\n }, ms) as any;\r\n }\r\n };\r\n}\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport type { Message, StickerSet, Update, NotifyPeer, PeerNotifySettings, ConstructorDeclMap, Config } from \"../layer\";\nimport type { MyDocument } from \"./appManagers/appDocsManager\";\nimport type { AppMessagesManager, Dialog, MessagesStorage } from \"./appManagers/appMessagesManager\";\nimport type { Poll, PollResults } from \"./appManagers/appPollsManager\";\nimport type { MyDialogFilter } from \"./storages/filters\";\nimport type { UserTyping } from \"./appManagers/appProfileManager\";\nimport type Chat from \"../components/chat/chat\";\nimport type { UserAuth } from \"./mtproto/mtproto_config\";\nimport type { State, Theme } from \"./appManagers/appStateManager\";\nimport type { MyDraftMessage } from \"./appManagers/appDraftsManager\";\nimport type { PushSubscriptionNotify } from \"./mtproto/webPushApiManager\";\nimport type { PushNotificationObject } from \"./serviceWorker/push\";\nimport type { ConnectionStatusChange } from \"./mtproto/connectionStatus\";\nimport EventListenerBase from \"../helpers/eventListenerBase\";\nimport { MOUNT_CLASS_TO } from \"../config/debug\";\n\nexport type BroadcastEvents = {\n 'user_update': number,\n 'user_auth': UserAuth,\n 'peer_changed': number,\n 'peer_changing': Chat,\n 'peer_pinned_messages': {peerId: number, mids?: number[], pinned?: boolean, unpinAll?: true},\n 'peer_pinned_hidden': {peerId: number, maxId: number},\n 'peer_typings': {peerId: number, typings: UserTyping[]},\n 'peer_block': {peerId: number, blocked: boolean},\n 'peer_title_edit': number,\n 'peer_bio_edit': number,\n\n 'filter_delete': MyDialogFilter,\n 'filter_update': MyDialogFilter,\n 'filter_order': number[],\n \n 'dialog_draft': {peerId: number, dialog: Dialog, drop: boolean, draft: MyDraftMessage | undefined, index: number},\n 'dialog_unread': {peerId: number},\n 'dialog_flush': {peerId: number},\n 'dialog_drop': {peerId: number, dialog?: Dialog},\n 'dialog_migrate': {migrateFrom: number, migrateTo: number},\n //'dialog_top': Dialog,\n 'dialog_notify_settings': Dialog,\n // 'dialog_order': {dialog: Dialog, pos: number},\n 'dialogs_multiupdate': {[peerId: string]: Dialog},\n 'dialogs_archived_unread': {count: number},\n \n 'history_append': {storage: MessagesStorage, peerId: number, mid: number},\n 'history_update': {storage: MessagesStorage, peerId: number, mid: number},\n 'history_reply_markup': {peerId: number},\n 'history_multiappend': AppMessagesManager['newMessagesToHandle'],\n 'history_delete': {peerId: number, msgs: Set<number>},\n 'history_forbidden': number,\n 'history_reload': number,\n 'history_focus': {peerId: number, threadId?: number, mid?: number},\n //'history_request': void,\n \n 'message_edit': {storage: MessagesStorage, peerId: number, mid: number},\n 'message_views': {peerId: number, mid: number, views: number},\n 'message_sent': {storage: MessagesStorage, tempId: number, tempMessage: any, mid: number, message: Message.message},\n 'messages_pending': void,\n 'messages_read': void,\n 'messages_downloaded': {peerId: number, mids: number[]},\n 'messages_media_read': {peerId: number, mids: number[]},\n\n 'replies_updated': Message.message,\n\n 'scheduled_new': {peerId: number, mid: number},\n 'scheduled_delete': {peerId: number, mids: number[]},\n\n 'album_edit': {peerId: number, groupId: string, deletedMids: number[]},\n\n 'stickers_installed': StickerSet.stickerSet,\n 'stickers_deleted': StickerSet.stickerSet,\n\n 'media_play': {doc: MyDocument, message: Message.message, media: HTMLMediaElement},\n 'media_pause': void,\n 'media_playback_params': {volume: number, muted: boolean, playbackRate: number},\n 'media_stop': void,\n \n 'state_cleared': void,\n 'state_synchronized': number | void,\n 'state_synchronizing': number | void,\n \n 'contacts_update': number,\n 'avatar_update': number,\n 'chat_full_update': number,\n 'poll_update': {poll: Poll, results: PollResults},\n 'chat_update': number,\n 'invalidate_participants': number,\n //'channel_settings': {channelId: number},\n 'webpage_updated': {id: string, msgs: {peerId: number, mid: number, isScheduled: boolean}[]},\n\n 'connection_status_change': ConnectionStatusChange,\n 'settings_updated': {key: string, value: any},\n 'draft_updated': {peerId: number, threadId: number, draft: MyDraftMessage | undefined, force?: boolean},\n \n 'event-heavy-animation-start': void,\n 'event-heavy-animation-end': void,\n \n 'im_mount': void,\n 'im_tab_change': number,\n \n 'idle': boolean,\n \n 'overlay_toggle': boolean,\n \n 'background_change': void,\n \n 'privacy_update': Update.updatePrivacy,\n \n 'notify_settings': Update.updateNotifySettings,\n 'notify_peer_type_settings': {key: Exclude<NotifyPeer['_'], 'notifyPeer'>, settings: PeerNotifySettings},\n \n 'language_change': string,\n \n 'theme_change': void,\n \n 'instance_activated': void,\n 'instance_deactivated': void,\n \n 'push_notification_click': PushNotificationObject,\n 'push_init': PushSubscriptionNotify,\n 'push_subscribe': PushSubscriptionNotify,\n 'push_unsubscribe': PushSubscriptionNotify,\n \n 'emoji_recent': string,\n \n 'download_start': string,\n 'download_progress': any,\n 'document_downloaded': MyDocument,\n\n 'context_menu_toggle': boolean\n};\n\nexport class RootScope extends EventListenerBase<{\n [name in Update['_']]: (update: ConstructorDeclMap[name]) => void\n} & {\n [name in keyof BroadcastEvents]: (e: BroadcastEvents[name]) => void\n}> {\n public overlaysActive = 0;\n public myId = 0;\n public idle = {\n isIDLE: true,\n deactivated: false,\n focusPromise: Promise.resolve(),\n focusResolve: () => {}\n };\n public connectionStatus: {[name: string]: ConnectionStatusChange} = {};\n public settings: State['settings'];\n public peerId = 0;\n public filterId = 0;\n public systemTheme: Theme['name'];\n public config: Partial<Config.config> = {\n forwarded_count_max: 100,\n edit_time_limit: 86400 * 2,\n pinned_dialogs_count_max: 5,\n pinned_infolder_count_max: 100,\n message_length_max: 4096,\n caption_length_max: 1024,\n };\n\n public themeColor: string;\n private _themeColorElem: Element;\n\n constructor() {\n super();\n\n this.addEventListener('peer_changed', (peerId) => {\n this.peerId = peerId;\n });\n\n this.addEventListener('user_auth', (e) => {\n this.myId = e.id;\n });\n\n this.addEventListener('connection_status_change', (e) => {\n const status = e;\n this.connectionStatus[e.name] = status;\n });\n\n this.addEventListener('idle', (isIDLE) => {\n if(isIDLE) {\n this.idle.focusPromise = new Promise((resolve) => {\n this.idle.focusResolve = resolve;\n });\n } else {\n this.idle.focusResolve();\n }\n });\n }\n\n get themeColorElem() {\n if(this._themeColorElem !== undefined) {\n return this._themeColorElem;\n }\n\n return this._themeColorElem = document.head.querySelector('[name=\"theme-color\"]') as Element || null;\n }\n\n public setThemeColor(color = this.themeColor) {\n if(!color) {\n color = this.isNight() ? '#212121' : '#ffffff';\n }\n\n const themeColorElem = this.themeColorElem;\n if(themeColorElem) {\n themeColorElem.setAttribute('content', color);\n }\n }\n\n public setThemeListener() {\n try {\n const darkModeMediaQuery = window.matchMedia('(prefers-color-scheme: dark)');\n const checkDarkMode = () => {\n //const theme = this.getTheme();\n this.systemTheme = darkModeMediaQuery.matches ? 'night' : 'day';\n //const newTheme = this.getTheme();\n\n if(this.myId) {\n this.dispatchEvent('theme_change');\n } else {\n this.setTheme();\n }\n };\n\n if('addEventListener' in darkModeMediaQuery) {\n darkModeMediaQuery.addEventListener('change', checkDarkMode);\n } else if('addListener' in darkModeMediaQuery) {\n (darkModeMediaQuery as any).addListener(checkDarkMode);\n }\n\n checkDarkMode();\n } catch(err) {\n\n }\n }\n\n public setTheme() {\n const isNight = this.isNight();\n const colorScheme = document.head.querySelector('[name=\"color-scheme\"]');\n if(colorScheme) {\n colorScheme.setAttribute('content', isNight ? 'dark' : 'light');\n }\n\n document.documentElement.classList.toggle('night', isNight);\n this.setThemeColor();\n }\n\n get isOverlayActive() {\n return this.overlaysActive > 0;\n }\n\n set isOverlayActive(value: boolean) {\n this.overlaysActive += value ? 1 : -1;\n this.dispatchEvent('overlay_toggle', this.isOverlayActive);\n }\n\n public isNight() {\n return this.getTheme().name === 'night';\n }\n\n public getTheme(name: Theme['name'] = this.settings.theme === 'system' ? this.systemTheme : this.settings.theme) {\n return this.settings.themes.find(t => t.name === name);\n }\n}\n\nconst rootScope = new RootScope();\nMOUNT_CLASS_TO.rootScope = rootScope;\nexport default rootScope;\n\n/* rootScope.addEventListener('album_edit', (e) => {\n \n});\n\nrootScope.addEventListener<'album_edit'>('album_edit', (e) => {\n \n}); */\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport Modes from \"./modes\";\r\n\r\nexport const DEBUG = process.env.NODE_ENV !== 'production' || Modes.debug;\r\nconst ctx: any = typeof(window) !== 'undefined' ? window : self;\r\nexport const MOUNT_CLASS_TO: any = DEBUG || true/* && false */ ? ctx : {};\r\nexport default DEBUG;\r\n\r\n//let m = DEBUG;\r\n/* if(!DEBUG) {\r\n ctx.sandpitTurtle = () => {\r\n //if(!m) {\r\n for(let i in MOUNT_CLASS_TO) {\r\n ctx[i] = MOUNT_CLASS_TO[i];\r\n }\r\n //m = true;\r\n //}\r\n \r\n //DEBUG = !DEBUG;\r\n };\r\n} */\r\n\r\n/* export const superDebug = (object: any, key: string) => {\r\n var d = object[key];\r\n var beforeStr = '', afterStr = '';\r\n for(var r of d) {\r\n beforeStr += r.before.hex + '\\n';\r\n afterStr += r.after.hex + '\\n';\r\n }\r\n\r\n beforeStr = beforeStr.trim();\r\n afterStr = afterStr.trim();\r\n //var beforeStr = d.map(r => r.before.hex).join('\\n');\r\n //var afterStr = d.map(r => r.after.hex).join('\\n');\r\n\r\n var dada = (name: string, str: string) => {\r\n var a = document.createElement('a');\r\n a.target = '_blank';\r\n a.download = name + '.txt';\r\n a.href = URL.createObjectURL(new Blob([str], {\r\n type: 'text/plain'\r\n }));\r\n document.body.append(a);\r\n a.click();\r\n };\r\n\r\n dada(key + '_' + 'before', beforeStr);\r\n dada(key + '_' + 'after', afterStr);\r\n}\r\n\r\nMOUNT_CLASS_TO.superDebug = superDebug; */\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nexport function copy<T>(obj: T): T {\r\n //in case of premitives\r\n if(obj === null || typeof(obj) !== \"object\") {\r\n return obj;\r\n }\r\n \r\n //date objects should be \r\n if(obj instanceof Date) {\r\n return new Date(obj.getTime()) as any;\r\n }\r\n \r\n //handle Array\r\n if(Array.isArray(obj)) {\r\n // @ts-ignore\r\n const clonedArr: T = obj.map(el => copy(el)) as any as T;\r\n return clonedArr;\r\n }\r\n \r\n //lastly, handle objects\r\n // @ts-ignore\r\n let clonedObj = new obj.constructor();\r\n for(var prop in obj){\r\n if(obj.hasOwnProperty(prop)) {\r\n clonedObj[prop] = copy(obj[prop]);\r\n }\r\n }\r\n return clonedObj;\r\n}\r\n\r\nexport function deepEqual(x: any, y: any): boolean {\r\n const ok = Object.keys, tx = typeof x, ty = typeof y;\r\n return x && y && tx === 'object' && tx === ty ? (\r\n ok(x).length === ok(y).length &&\r\n ok(x).every(key => deepEqual(x[key], y[key]))\r\n ) : (x === y);\r\n}\r\n\r\nexport function defineNotNumerableProperties(obj: {[key: string]: any}, names: string[]) {\r\n //const perf = performance.now();\r\n const props = {writable: true, configurable: true};\r\n const out: {[name: string]: typeof props} = {};\r\n names.forEach(name => {\r\n if(obj[name] === undefined) {\r\n out[name] = props;\r\n }\r\n });\r\n Object.defineProperties(obj, out);\r\n //console.log('defineNotNumerableProperties time:', performance.now() - perf);\r\n}\r\n\r\nexport function getObjectKeysAndSort(object: {[key: string]: any}, sort: 'asc' | 'desc' = 'asc') {\r\n if(!object) return [];\r\n const ids = object instanceof Map ? [...object.keys()] : Object.keys(object).map(i => +i);\r\n if(sort === 'asc') return ids.sort((a, b) => a - b);\r\n else return ids.sort((a, b) => b - a);\r\n}\r\n\r\nexport function safeReplaceObject(wasObject: any, newObject: any) {\r\n if(!wasObject) {\r\n return newObject;\r\n }\r\n\r\n for(var key in wasObject) {\r\n if(!newObject.hasOwnProperty(key)) {\r\n delete wasObject[key];\r\n }\r\n }\r\n\r\n for(var key in newObject) {\r\n //if (newObject.hasOwnProperty(key)) { // useless\r\n wasObject[key] = newObject[key];\r\n //}\r\n }\r\n \r\n return wasObject;\r\n}\r\n\r\n/**\r\n * Will be used for FILE_REFERENCE_EXPIRED\r\n * @param key \r\n * @param wasObject \r\n * @param newObject \r\n */\r\nexport function safeReplaceArrayInObject<K>(key: K, wasObject: any, newObject: any) {\r\n if('byteLength' in newObject[key]) { // Uint8Array\r\n newObject[key] = [...newObject[key]];\r\n }\r\n\r\n if(wasObject && wasObject[key] !== newObject[key]) {\r\n wasObject[key].length = newObject[key].length;\r\n (newObject[key] as any[]).forEach((v, i) => {\r\n wasObject[key][i] = v;\r\n });\r\n\r\n /* wasObject[key].set(newObject[key]); */\r\n newObject[key] = wasObject[key];\r\n }\r\n}\r\n\r\nexport function isObject(object: any) {\r\n return typeof(object) === 'object' && object !== null;\r\n}\r\n\r\nexport function getDeepProperty(object: any, key: string) {\r\n const splitted = key.split('.');\r\n let o: any = object;\r\n splitted.forEach(key => {\r\n if(!key) {\r\n return;\r\n }\r\n \r\n // @ts-ignore\r\n o = o[key];\r\n });\r\n \r\n return o;\r\n}\r\n\r\nexport function setDeepProperty(object: any, key: string, value: any) {\r\n const splitted = key.split('.');\r\n getDeepProperty(object, splitted.slice(0, -1).join('.'))[splitted.pop()] = value;\r\n}\r\n\r\nexport function validateInitObject(initObject: any, currentObject: any, onReplace?: (key: string) => void, previousKey?: string) {\r\n for(const key in initObject) {\r\n if(typeof(currentObject[key]) !== typeof(initObject[key])) {\r\n currentObject[key] = copy(initObject[key]);\r\n onReplace && onReplace(previousKey || key);\r\n } else if(isObject(initObject[key])) {\r\n validateInitObject(initObject[key], currentObject[key], onReplace, previousKey || key);\r\n }\r\n }\r\n}\r\n\r\nexport function safeAssign(object: any, fromObject: any) {\r\n if(!fromObject) return;\r\n \r\n for(let i in fromObject) {\r\n if(fromObject[i] !== undefined) {\r\n object[i] = fromObject[i];\r\n }\r\n }\r\n}\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nimport DEBUG from \"../config/debug\";\n\nexport enum LogTypes {\n None = 0,\n Error = 1,\n Warn = 2,\n Log = 4,\n Debug = 8\n};\n\nexport const LOG_LEVELS = [LogTypes.None, LogTypes.Error, LogTypes.Warn, LogTypes.Log, LogTypes.Debug];\n\nconst _logTimer = Date.now();\nfunction dT() {\n return '[' + ((Date.now() - _logTimer) / 1000).toFixed(3) + ']';\n}\n\nexport function logger(prefix: string, type: LogTypes = LogTypes.Log | LogTypes.Warn | LogTypes.Error, ignoreDebugReset = false) {\n if(!DEBUG && !ignoreDebugReset/* || true */) {\n type = LogTypes.Error;\n }\n\n //level = LogLevels.log | LogLevels.warn | LogLevels.error | LogLevels.debug\n\n function Log(...args: any[]) {\n return type & LogTypes.Log && console.log(dT(), prefix, ...args);\n }\n \n Log.warn = function(...args: any[]) {\n return type & LogTypes.Warn && console.warn(dT(), prefix, ...args);\n };\n \n Log.info = function(...args: any[]) {\n return type & LogTypes.Log && console.info(dT(), prefix, ...args);\n };\n \n Log.error = function(...args: any[]) {\n return type & LogTypes.Error && console.error(dT(), prefix, ...args);\n };\n \n Log.trace = function(...args: any[]) {\n return type & LogTypes.Log && console.trace(dT(), prefix, ...args);\n };\n\n /* Log.debug = function(...args: any[]) {\n return level & LogLevels.debug && console.log(dT(), prefix, ...args);\n }; */\n\n Log.debug = function(...args: any[]) {\n return type & LogTypes.Debug && console.debug(dT(), prefix, ...args);\n };\n\n Log.setPrefix = function(_prefix: string) {\n prefix = '[' + _prefix + ']:';\n };\n\n Log.setPrefix(prefix);\n\n Log.setLevel = function(level: 0 | 1 | 2 | 3 | 4) {\n type = LOG_LEVELS.slice(0, level + 1).reduce((acc, v) => acc | v, 0) as any;\n };\n \n return Log;\n};\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport noop from \"./noop\";\r\n\r\nexport interface CancellablePromise<T> extends Promise<T> {\r\n resolve?: (value: T) => void,\r\n reject?: (...args: any[]) => void,\r\n cancel?: () => void,\r\n\r\n notify?: (...args: any[]) => void,\r\n notifyAll?: (...args: any[]) => void,\r\n lastNotify?: any,\r\n listeners?: Array<(...args: any[]) => void>,\r\n addNotifyListener?: (callback: (...args: any[]) => void) => void,\r\n\r\n isFulfilled?: boolean,\r\n isRejected?: boolean\r\n}\r\n\r\nexport function deferredPromise<T>() {\r\n let deferredHelper: any = {\r\n isFulfilled: false, \r\n isRejected: false,\r\n\r\n notify: () => {}, \r\n notifyAll: (...args: any[]) => {\r\n deferredHelper.lastNotify = args;\r\n deferredHelper.listeners.forEach((callback: any) => callback(...args));\r\n }, \r\n\r\n listeners: [],\r\n addNotifyListener: (callback: (...args: any[]) => void) => {\r\n if(deferredHelper.lastNotify) {\r\n callback(...deferredHelper.lastNotify);\r\n }\r\n\r\n deferredHelper.listeners.push(callback);\r\n }\r\n };\r\n\r\n let deferred: CancellablePromise<T> = new Promise<T>((resolve, reject) => {\r\n deferredHelper.resolve = (value: T) => {\r\n if(deferred.isFulfilled || deferred.isRejected) return;\r\n\r\n deferred.isFulfilled = true;\r\n resolve(value);\r\n };\r\n \r\n deferredHelper.reject = (...args: any[]) => {\r\n if(deferred.isRejected || deferred.isFulfilled) return;\r\n \r\n deferred.isRejected = true;\r\n reject(...args);\r\n };\r\n });\r\n\r\n // @ts-ignore\r\n /* deferred.then = (resolve: (value: T) => any, reject: (...args: any[]) => any) => {\r\n const n = deferredPromise<ReturnType<typeof resolve>>();\r\n \r\n }; */\r\n\r\n deferred.catch(noop).finally(() => {\r\n deferred.notify = deferred.notifyAll = deferred.lastNotify = null;\r\n deferred.listeners.length = 0;\r\n\r\n if(deferred.cancel) {\r\n deferred.cancel = () => {};\r\n }\r\n });\r\n\r\n Object.assign(deferred, deferredHelper);\r\n\r\n return deferred;\r\n}","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\n//import { MOUNT_CLASS_TO } from \"../config/debug\";\r\nimport type { ArgumentTypes, SuperReturnType } from \"../types\";\r\n\r\n// class EventSystem {\r\n// wm: WeakMap<any, Record<any, Set<any>>> = new WeakMap();\r\n\r\n// add(target: any, event: any, listener: any) {\r\n// let listeners = this.wm.get(target);\r\n// if (listeners === undefined) {\r\n// listeners = {};\r\n// }\r\n// let listenersForEvent = listeners[event];\r\n// if (listenersForEvent === undefined) {\r\n// listenersForEvent = new Set();\r\n// }\r\n// listenersForEvent.add(listener);\r\n// listeners[event] = listenersForEvent;\r\n// //target.addEventListener(event, listener);\r\n// this.wm.set(target, listeners);\r\n// };\r\n\r\n// remove(target: any, event: any, listener: any) {\r\n// let listeners = this.wm.get(target);\r\n// if (!listeners) return;\r\n// let listenersForEvent = listeners[event];\r\n// if (!listenersForEvent) return;\r\n// listenersForEvent.delete(listener);\r\n// };\r\n \r\n// /* fire(target, event) {\r\n// let listeners = this.wm.get(target);\r\n// if (!listeners) return;\r\n// let listenersForEvent = listeners[event];\r\n// if (!listenersForEvent) return;\r\n// for (let handler of handlers) {\r\n// setTimeout(handler, 0, event, target); // we use a setTimeout here because we want event triggering to be asynchronous. \r\n// }\r\n// }; */\r\n// }\r\n\r\n// console.log = () => {};\r\n\r\n// const e = new EventSystem();\r\n// MOUNT_CLASS_TO.e = e;\r\n\r\n/**\r\n * Better not to remove listeners during setting\r\n * Should add listener callback only once\r\n */\r\n\r\n// type EventLitenerCallback<T> = (data: T) => \r\n// export default class EventListenerBase<Listeners extends {[name: string]: Function}> {\r\nexport default class EventListenerBase<Listeners extends Record<string, Function>> {\r\n protected listeners: Partial<{\r\n [k in keyof Listeners]: Array<{callback: Listeners[k], options: boolean | AddEventListenerOptions}>\r\n }>;\r\n protected listenerResults: Partial<{\r\n [k in keyof Listeners]: ArgumentTypes<Listeners[k]>\r\n }>;\r\n\r\n private reuseResults: boolean;\r\n\r\n constructor(reuseResults?: boolean) {\r\n this._constructor(reuseResults);\r\n }\r\n\r\n public _constructor(reuseResults = false): any {\r\n this.reuseResults = reuseResults;\r\n this.listeners = {};\r\n this.listenerResults = {};\r\n }\r\n\r\n public addEventListener<T extends keyof Listeners>(name: T, callback: Listeners[T], options?: boolean | AddEventListenerOptions) {\r\n (this.listeners[name] ?? (this.listeners[name] = [])).push({callback, options}); // ! add before because if you don't, you won't be able to delete it from callback\r\n\r\n if(this.listenerResults.hasOwnProperty(name)) {\r\n callback(...this.listenerResults[name]);\r\n \r\n if((options as AddEventListenerOptions)?.once) {\r\n this.listeners[name].pop();\r\n return;\r\n }\r\n }\r\n \r\n //e.add(this, name, {callback, once});\r\n }\r\n\r\n public addMultipleEventsListeners(obj: {\r\n [name in keyof Listeners]?: Listeners[name]\r\n }) {\r\n for(const i in obj) {\r\n this.addEventListener(i, obj[i]);\r\n }\r\n }\r\n\r\n public removeEventListener<T extends keyof Listeners>(name: T, callback: Listeners[T], options?: boolean | AddEventListenerOptions) {\r\n if(this.listeners[name]) {\r\n this.listeners[name].findAndSplice(l => l.callback === callback);\r\n }\r\n //e.remove(this, name, callback);\r\n }\r\n\r\n // * must be protected, but who cares\r\n public dispatchEvent<T extends keyof Listeners>(name: T, ...args: ArgumentTypes<Listeners[T]>) {\r\n if(this.reuseResults) {\r\n this.listenerResults[name] = args;\r\n }\r\n\r\n const arr: Array<SuperReturnType<Listeners[typeof name]>> = [];\r\n\r\n /* let a = e.wm.get(this)[name];\r\n if(!a) return arr;\r\n const listeners = [...a]; */\r\n const listeners = this.listeners[name];\r\n if(listeners) {\r\n // ! this one will guarantee execution even if delete another listener during setting\r\n const left = listeners.slice();\r\n left.forEach((listener) => {\r\n const index = listeners.findIndex((l) => l.callback === listener.callback);\r\n if(index === -1) {\r\n return;\r\n }\r\n\r\n arr.push(listener.callback(...args));\r\n\r\n if((listener.options as AddEventListenerOptions)?.once) {\r\n this.removeEventListener(name, listener.callback);\r\n }\r\n });\r\n\r\n /* for(let i = 0, length = listeners.length; i < length; ++i) {\r\n const listener = listeners[i];\r\n arr.push(listener.callback(...args));\r\n\r\n if(listener.once) {\r\n listeners.splice(i, 1);\r\n --i;\r\n --length;\r\n }\r\n } */\r\n }\r\n\r\n return arr;\r\n }\r\n\r\n public cleanup() {\r\n this.listeners = {}; \r\n this.listenerResults = {};\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nexport const isWebWorker = typeof WorkerGlobalScope !== 'undefined' && self instanceof WorkerGlobalScope;\r\nexport const isServiceWorker = typeof ServiceWorkerGlobalScope !== 'undefined' && self instanceof ServiceWorkerGlobalScope;\r\nexport const isWorker = isWebWorker || isServiceWorker;\r\n\r\n// в SW может быть сразу две переменных TRUE, поэтому проверяю по последней\r\n\r\nexport const getWindowClients = () => {\r\n return (self as any as ServiceWorkerGlobalScope)\r\n .clients\r\n .matchAll({ includeUncontrolled: false, type: 'window' });\r\n};\r\n\r\nconst notifyServiceWorker = (all: boolean, ...args: any[]) => {\r\n (self as any as ServiceWorkerGlobalScope)\r\n .clients\r\n .matchAll({ includeUncontrolled: false, type: 'window' })\r\n .then((listeners) => {\r\n if(!listeners.length) {\r\n //console.trace('no listeners?', self, listeners);\r\n return;\r\n }\r\n\r\n listeners.slice(all ? 0 : -1).forEach(listener => {\r\n // @ts-ignore\r\n listener.postMessage(...args);\r\n });\r\n });\r\n};\r\n\r\nconst notifyWorker = (...args: any[]) => {\r\n // @ts-ignore\r\n (self as any as DedicatedWorkerGlobalScope).postMessage(...args);\r\n};\r\n\r\nconst noop = () => {};\r\n\r\nexport const notifySomeone = isServiceWorker ? notifyServiceWorker.bind(null, false) : (isWebWorker ? notifyWorker : noop);\r\nexport const notifyAll = isServiceWorker ? notifyServiceWorker.bind(null, true) : (isWebWorker ? notifyWorker : noop);\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport Modes from '../config/modes';\r\nimport { notifySomeone, isWorker } from '../helpers/context';\r\nimport { WorkerTaskTemplate } from '../types';\r\n//import { stringify } from '../helpers/json';\r\n\r\nclass LocalStorage<Storage extends Record<string, any>> {\r\n private prefix = '';\r\n private cache: Partial<Storage> = {};\r\n private useStorage = true;\r\n\r\n constructor(/* private preserveKeys: (keyof Storage)[] */) {\r\n if(Modes.test) {\r\n this.prefix = 't_';\r\n }\r\n }\r\n\r\n public get<T extends keyof Storage>(key: T, useCache = true): Storage[T] {\r\n if(this.cache.hasOwnProperty(key) && useCache) {\r\n return this.cache[key];\r\n } else if(this.useStorage) {\r\n let value: Storage[T];\r\n try {\r\n value = localStorage.getItem(this.prefix + key as string) as any;\r\n } catch(err) {\r\n this.useStorage = false;\r\n }\r\n\r\n if(value !== null) {\r\n try {\r\n value = JSON.parse(value);\r\n } catch(err) {\r\n //console.error(err);\r\n }\r\n } else {\r\n value = undefined;\r\n }\r\n\r\n return value;\r\n }/* else {\r\n throw 'something went wrong';\r\n } */\r\n }\r\n\r\n public set(obj: Partial<Storage>, onlyLocal = false) {\r\n for(const key in obj) {\r\n if(obj.hasOwnProperty(key)) {\r\n const value = obj[key];\r\n this.cache[key] = value;\r\n\r\n if(this.useStorage && !onlyLocal) {\r\n try {\r\n const stringified = JSON.stringify(value);\r\n localStorage.setItem(this.prefix + key, stringified);\r\n } catch(err) {\r\n this.useStorage = false;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n public delete(key: keyof Storage, saveLocal = false) {\r\n // ! it is needed here\r\n key = '' + key;\r\n\r\n if(!saveLocal) {\r\n delete this.cache[key];\r\n }\r\n \r\n //if(this.useStorage) {\r\n try {\r\n localStorage.removeItem(this.prefix + key);\r\n } catch(err) {\r\n \r\n }\r\n //}\r\n }\r\n\r\n /* public clear(preserveKeys: (keyof Storage)[] = this.preserveKeys) {\r\n // if(this.useStorage) {\r\n try {\r\n let obj: Partial<Storage> = {};\r\n if(preserveKeys) {\r\n preserveKeys.forEach(key => {\r\n const value = this.get(key);\r\n if(value !== undefined) {\r\n obj[key] = value;\r\n }\r\n });\r\n }\r\n \r\n localStorage.clear();\r\n\r\n if(preserveKeys) {\r\n this.set(obj);\r\n }\r\n } catch(err) {\r\n\r\n }\r\n // }\r\n } */\r\n\r\n public clear() {\r\n const keys: string[] = ['dc', 'server_time_offset', 'xt_instance', 'user_auth', 'state_id'];\r\n for(let i = 1; i <= 5; ++i) {\r\n keys.push(`dc${i}_server_salt`);\r\n keys.push(`dc${i}_auth_key`);\r\n }\r\n\r\n for(let key of keys) {\r\n this.delete(key, true);\r\n }\r\n }\r\n\r\n public toggleStorage(enabled: boolean) {\r\n this.useStorage = enabled;\r\n\r\n if(!enabled) {\r\n this.clear();\r\n } else {\r\n return this.set(this.cache);\r\n }\r\n }\r\n}\r\n\r\nexport interface LocalStorageProxyTask extends WorkerTaskTemplate {\r\n type: 'localStorageProxy',\r\n payload: {\r\n type: 'set' | 'get' | 'delete' | 'clear' | 'toggleStorage',\r\n args: any[]\r\n }\r\n};\r\n\r\nexport interface LocalStorageProxyTaskResponse extends WorkerTaskTemplate {\r\n type: 'localStorageProxy',\r\n payload: any\r\n};\r\n\r\nexport default class LocalStorageController<Storage extends Record<string, any>> {\r\n private static STORAGES: LocalStorageController<any>[] = [];\r\n private taskId = 0;\r\n private tasks: {[taskID: number]: (result: any) => void} = {};\r\n //private log = (...args: any[]) => console.log('[SW LS]', ...args);\r\n //private log = (...args: any[]) => {};\r\n\r\n private storage: LocalStorage<Storage>;\r\n\r\n constructor(/* private preserveKeys: (keyof Storage)[] = [] */) {\r\n LocalStorageController.STORAGES.push(this);\r\n\r\n if(!isWorker) {\r\n this.storage = new LocalStorage(/* preserveKeys */);\r\n }\r\n }\r\n\r\n public finishTask(taskId: number, result: any) {\r\n //this.log('finishTask:', taskID, result, Object.keys(this.tasks));\r\n\r\n if(!this.tasks.hasOwnProperty(taskId)) {\r\n //this.log('no such task:', taskID, result);\r\n return;\r\n }\r\n\r\n this.tasks[taskId](result);\r\n delete this.tasks[taskId];\r\n }\r\n\r\n private proxy<T>(type: LocalStorageProxyTask['payload']['type'], ...args: LocalStorageProxyTask['payload']['args']) {\r\n return new Promise<T>((resolve, reject) => {\r\n if(isWorker) {\r\n const taskId = this.taskId++;\r\n\r\n this.tasks[taskId] = resolve;\r\n const task: LocalStorageProxyTask = {\r\n type: 'localStorageProxy', \r\n id: taskId,\r\n payload: {\r\n type,\r\n args\r\n }\r\n };\r\n\r\n notifySomeone(task);\r\n } else {\r\n args = Array.prototype.slice.call(args);\r\n\r\n // @ts-ignore\r\n const result: any = this.storage[type].apply(this.storage, args as any);\r\n resolve(result);\r\n }\r\n });\r\n }\r\n\r\n public get<T extends keyof Storage>(key: T, useCache?: boolean) {\r\n return this.proxy<Storage[T]>('get', key, useCache);\r\n }\r\n\r\n public set(obj: Partial<Storage>, onlyLocal?: boolean) {\r\n return this.proxy<void>('set', obj, onlyLocal);\r\n }\r\n\r\n public delete(key: keyof Storage, saveLocal?: boolean) {\r\n return this.proxy<void>('delete', key, saveLocal);\r\n }\r\n\r\n public clear(/* preserveKeys?: (keyof Storage)[] */) {\r\n return this.proxy<void>('clear'/* , preserveKeys */);\r\n }\r\n\r\n public toggleStorage(enabled: boolean) {\r\n return this.proxy<void>('toggleStorage', enabled);\r\n }\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport type { AppInstance } from './mtproto/singleInstance';\r\nimport type { UserAuth } from './mtproto/mtproto_config';\r\nimport type { DcId } from '../types';\r\nimport { MOUNT_CLASS_TO } from '../config/debug';\r\nimport LocalStorageController from './localStorage';\r\n\r\nconst sessionStorage = new LocalStorageController<{\r\n dc: DcId,\r\n user_auth: UserAuth,\r\n state_id: number,\r\n dc1_auth_key: string,\r\n dc2_auth_key: string,\r\n dc3_auth_key: string,\r\n dc4_auth_key: string,\r\n dc5_auth_key: string,\r\n dc1_server_salt: string,\r\n dc2_server_salt: string,\r\n dc3_server_salt: string,\r\n dc4_server_salt: string,\r\n dc5_server_salt: string,\r\n server_time_offset: number,\r\n xt_instance: AppInstance,\r\n kz_version: 'K' | 'Z',\r\n tgme_sync: {\r\n canRedirect: boolean,\r\n ts: number\r\n }\r\n}>(/* ['kz_version'] */);\r\nMOUNT_CLASS_TO.appStorage = sessionStorage;\r\nexport default sessionStorage;\r\n","/*\n * https://github.com/morethanwords/tweb\n * Copyright (C) 2019-2021 Eduard Kuzmenko\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\n */\n\nconst arrays = {\n 8: new Uint8Array(1),\n 16: new Uint16Array(1),\n 32: new Uint32Array(1),\n};\nexport function nextRandomUint(bits: 8 | 16 | 32) {\n const array = arrays[bits];\n crypto.getRandomValues(array);\n return array[0];\n}\n\nexport function randomLong() {\n return '' + nextRandomUint(32) + nextRandomUint(32) % 0xFFFFFF;\n}\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nconst Modes = {\r\n test: location.search.indexOf('test=1') > 0/* || true */,\r\n debug: location.search.indexOf('debug=1') > 0,\r\n http: false, //location.search.indexOf('http=1') > 0,\r\n ssl: true, // location.search.indexOf('ssl=1') > 0 || location.protocol === 'https:' && location.search.indexOf('ssl=0') === -1,\r\n multipleConnections: true,\r\n asServiceWorker: false\r\n};\r\n\r\n \r\n \r\n \r\n\r\nexport default Modes;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n */\r\n\r\nimport type { ChatSavedPosition } from './appManagers/appImManager';\r\nimport type { State } from './appManagers/appStateManager';\r\nimport type { AppDraftsManager } from './appManagers/appDraftsManager';\r\nimport { MOUNT_CLASS_TO } from '../config/debug';\r\nimport { LangPackDifference } from '../layer';\r\nimport AppStorage from './storage';\r\nimport DATABASE_STATE from '../config/databases/state';\r\n\r\nconst stateStorage = new AppStorage<{\r\n chatPositions: {\r\n [peerId_threadId: string]: ChatSavedPosition\r\n },\r\n langPack: LangPackDifference,\r\n drafts: AppDraftsManager['drafts'],\r\n user_auth: any, // support old webk format\r\n} & State, typeof DATABASE_STATE>(DATABASE_STATE, 'session');\r\nMOUNT_CLASS_TO.stateStorage = stateStorage;\r\nexport default stateStorage;\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nexport function readBlobAs(blob: Blob, method: 'readAsText'): Promise<string>;\r\nexport function readBlobAs(blob: Blob, method: 'readAsDataURL'): Promise<string>;\r\nexport function readBlobAs(blob: Blob, method: 'readAsArrayBuffer'): Promise<ArrayBuffer>;\r\nexport function readBlobAs(blob: Blob, method: 'readAsArrayBuffer' | 'readAsText' | 'readAsDataURL'): Promise<any> {\r\n return new Promise<any>((resolve) => {\r\n const reader = new FileReader();\r\n reader.addEventListener('loadend', (e) => resolve(e.target.result));\r\n reader[method](blob);\r\n });\r\n}\r\n\r\nexport function readBlobAsText(blob: Blob) {\r\n return readBlobAs(blob, 'readAsText');\r\n}\r\n\r\nexport function readBlobAsDataURL(blob: Blob) {\r\n return readBlobAs(blob, 'readAsDataURL');\r\n}\r\n\r\nexport function readBlobAsArrayBuffer(blob: Blob) {\r\n return readBlobAs(blob, 'readAsArrayBuffer');\r\n}\r\n\r\nexport function readBlobAsUint8Array(blob: Blob) {\r\n return readBlobAsArrayBuffer(blob).then(buffer => new Uint8Array(buffer));\r\n}\r\n\r\nexport function blobConstruct(blobParts: any, mimeType: string = ''): Blob {\r\n let blob;\r\n const safeMimeType = blobSafeMimeType(mimeType);\r\n try {\r\n blob = new Blob(blobParts, {type: safeMimeType});\r\n } catch(e) {\r\n // @ts-ignore\r\n let bb = new BlobBuilder;\r\n blobParts.forEach((blobPart: any) => {\r\n bb.append(blobPart);\r\n });\r\n blob = bb.getBlob(safeMimeType);\r\n }\r\n return blob;\r\n}\r\n\r\n// https://www.iana.org/assignments/media-types/media-types.xhtml\r\nexport function blobSafeMimeType(mimeType: string) {\r\n if([\r\n 'image/jpeg',\r\n 'image/png',\r\n 'image/gif',\r\n 'image/webp',\r\n 'image/bmp',\r\n 'video/mp4',\r\n 'video/webm',\r\n 'video/quicktime',\r\n 'audio/ogg',\r\n 'audio/mpeg',\r\n 'audio/mp4',\r\n 'application/json',\r\n 'application/pdf'\r\n ].indexOf(mimeType) === -1) {\r\n return 'application/octet-stream';\r\n }\r\n\r\n return mimeType;\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport { Database } from '../config/databases';\r\nimport Modes from '../config/modes';\r\nimport { blobConstruct } from '../helpers/blob';\r\nimport { safeAssign } from '../helpers/object';\r\nimport { logger } from './logger';\r\n\r\n/**\r\n * https://developer.mozilla.org/en-US/docs/Web/API/IDBObjectStore/createIndex\r\n */\r\nexport type IDBIndex = {\r\n indexName: string,\r\n keyPath: string,\r\n objectParameters: IDBIndexParameters\r\n};\r\n\r\nexport type IDBStore = {\r\n name: string, \r\n indexes?: IDBIndex[]\r\n};\r\n\r\nexport type IDBOptions = {\r\n name?: string,\r\n storeName: string,\r\n stores?: IDBStore[],\r\n version?: number\r\n};\r\n\r\nconst DEBUG = false;\r\n\r\nexport default class IDBStorage<T extends Database<any>> {\r\n private static STORAGES: IDBStorage<Database<any>>[] = [];\r\n private openDbPromise: Promise<IDBDatabase>;\r\n private db: IDBDatabase;\r\n private storageIsAvailable = true;\r\n\r\n private log: ReturnType<typeof logger>;\r\n \r\n private name: string;\r\n private version: number;\r\n private stores: IDBStore[];\r\n private storeName: T['stores'][0]['name'];\r\n\r\n constructor(db: T, storeName: typeof db['stores'][0]['name']) {\r\n safeAssign(this, db);\r\n\r\n if(Modes.test) {\r\n this.name += '_test';\r\n }\r\n\r\n this.storeName = storeName;\r\n\r\n this.log = logger('IDB-' + this.storeName);\r\n\r\n this.openDatabase(true);\r\n\r\n IDBStorage.STORAGES.push(this);\r\n }\r\n\r\n public static closeDatabases(preserve?: IDBStorage<Database<any>>) {\r\n this.STORAGES.forEach(storage => {\r\n if(preserve && preserve === storage) {\r\n return;\r\n }\r\n\r\n const db = storage.db;\r\n if(db) {\r\n db.onclose = () => {};\r\n db.close();\r\n }\r\n });\r\n }\r\n\r\n /**\r\n * ! WARNING ! function requires at least one opened connection\r\n */\r\n /* public static clearObjectStores() {\r\n const storage = this.STORAGES[0];\r\n this.closeDatabases(storage);\r\n\r\n const names = Array.from(storage.db.objectStoreNames);\r\n const promises = names.map(name => storage.clear(name));\r\n return Promise.all(promises);\r\n } */\r\n\r\n /* public static deleteDatabase() {\r\n this.closeDatabases();\r\n\r\n const storages = this.STORAGES;\r\n const dbNames = Array.from(new Set(storages.map(storage => storage.name)));\r\n const promises = dbNames.map(dbName => {\r\n return new Promise<void>((resolve, reject) => {\r\n const deleteRequest = indexedDB.deleteDatabase(dbName);\r\n \r\n deleteRequest.onerror = () => {\r\n reject();\r\n };\r\n \r\n deleteRequest.onsuccess = () => {\r\n resolve();\r\n };\r\n });\r\n });\r\n\r\n return Promise.all(promises);\r\n } */\r\n\r\n public isAvailable() {\r\n return this.storageIsAvailable;\r\n }\r\n\r\n public openDatabase(createNew = false): Promise<IDBDatabase> {\r\n if(this.openDbPromise && !createNew) {\r\n return this.openDbPromise;\r\n }\r\n\r\n const createObjectStore = (db: IDBDatabase, store: IDBStore) => {\r\n const os = db.createObjectStore(store.name);\r\n\r\n if(store.indexes?.length) {\r\n for(const index of store.indexes) {\r\n os.createIndex(index.indexName, index.keyPath, index.objectParameters);\r\n }\r\n }\r\n };\r\n\r\n try {\r\n var request = indexedDB.open(this.name, this.version);\r\n\r\n if(!request) {\r\n return Promise.reject();\r\n }\r\n } catch(error) {\r\n this.log.error('error opening db', (error as Error).message);\r\n this.storageIsAvailable = false;\r\n return Promise.reject(error);\r\n }\r\n\r\n let finished = false;\r\n setTimeout(() => {\r\n if(!finished) {\r\n request.onerror({type: 'IDB_CREATE_TIMEOUT'} as Event);\r\n }\r\n }, 3000);\r\n\r\n return this.openDbPromise = new Promise<IDBDatabase>((resolve, reject) => {\r\n request.onsuccess = (event) => {\r\n finished = true;\r\n const db = request.result;\r\n let calledNew = false;\r\n\r\n this.log('Opened');\r\n \r\n db.onerror = (error) => {\r\n this.storageIsAvailable = false;\r\n this.log.error('Error creating/accessing IndexedDB database', error);\r\n reject(error);\r\n };\r\n\r\n db.onclose = (e) => {\r\n this.log.error('closed:', e);\r\n !calledNew && this.openDatabase();\r\n };\r\n\r\n db.onabort = (e) => {\r\n this.log.error('abort:', e);\r\n const transaction = e.target as IDBTransaction;\r\n \r\n this.openDatabase(calledNew = true);\r\n\r\n if(transaction.onerror) {\r\n transaction.onerror(e);\r\n }\r\n\r\n db.close();\r\n };\r\n\r\n db.onversionchange = (e) => {\r\n this.log.error('onversionchange, lol?');\r\n };\r\n\r\n resolve(this.db = db);\r\n };\r\n \r\n request.onerror = (event) => {\r\n finished = true;\r\n this.storageIsAvailable = false;\r\n this.log.error('Error creating/accessing IndexedDB database', event);\r\n reject(event);\r\n };\r\n \r\n request.onupgradeneeded = (event) => {\r\n finished = true;\r\n this.log.warn('performing idb upgrade from', event.oldVersion, 'to', event.newVersion);\r\n\r\n // @ts-ignore\r\n var db = event.target.result as IDBDatabase;\r\n this.stores.forEach((store) => {\r\n /* if(db.objectStoreNames.contains(store.name)) {\r\n //if(event.oldVersion === 1) {\r\n db.deleteObjectStore(store.name);\r\n //}\r\n } */\r\n \r\n if(!db.objectStoreNames.contains(store.name)) {\r\n createObjectStore(db, store);\r\n }\r\n });\r\n };\r\n });\r\n }\r\n\r\n public delete(entryName: string | string[]): Promise<void> {\r\n //return Promise.resolve();\r\n if(!Array.isArray(entryName)) {\r\n entryName = [].concat(entryName);\r\n }\r\n\r\n return this.getObjectStore('readwrite', (objectStore) => {\r\n return (entryName as string[]).map((entryName) => objectStore.delete(entryName));\r\n }, DEBUG ? 'delete: ' + entryName.join(', ') : '');\r\n }\r\n\r\n public clear(storeName?: IDBStorage<T>['storeName']) {\r\n return this.getObjectStore('readwrite', (objectStore) => objectStore.clear(), DEBUG ? 'clear' : '', storeName);\r\n }\r\n\r\n public save(entryName: string | string[], value: any | any[]) {\r\n // const handleError = (error: Error) => {\r\n // this.log.error('save: transaction error:', entryName, value, db, error, error && error.name);\r\n // if((!error || error.name === 'InvalidStateError')/* && false */) {\r\n // setTimeout(() => {\r\n // this.save(entryName, value);\r\n // }, 2e3);\r\n // } else {\r\n // //console.error('IndexedDB saveFile transaction error:', error, error && error.name);\r\n // }\r\n // };\r\n\r\n if(!Array.isArray(entryName)) {\r\n entryName = [].concat(entryName);\r\n value = [].concat(value);\r\n }\r\n \r\n return this.getObjectStore('readwrite', (objectStore) => {\r\n return (entryName as string[]).map((entryName, idx) => objectStore.put(value[idx], entryName));\r\n }, DEBUG ? 'save: ' + entryName.join(', ') : '');\r\n }\r\n\r\n public saveFile(fileName: string, blob: Blob | Uint8Array) {\r\n //return Promise.resolve(blobConstruct([blob]));\r\n if(!(blob instanceof Blob)) {\r\n blob = blobConstruct([blob]) as Blob;\r\n }\r\n\r\n return this.save(fileName, blob);\r\n }\r\n\r\n /* public saveFileBase64(db: IDBDatabase, fileName: string, blob: Blob | any): Promise<Blob> {\r\n if(this.getBlobSize(blob) > 10 * 1024 * 1024) {\r\n return Promise.reject();\r\n }\r\n\r\n if(!(blob instanceof Blob)) {\r\n var safeMimeType = blobSafeMimeType(blob.type || 'image/jpeg');\r\n var address = 'data:' + safeMimeType + ';base64,' + bytesToBase64(blob);\r\n return this.storagePutB64String(db, fileName, address).then(() => {\r\n return blob;\r\n });\r\n }\r\n\r\n try {\r\n var reader = new FileReader();\r\n } catch (e) {\r\n this.storageIsAvailable = false;\r\n return Promise.reject();\r\n }\r\n\r\n let promise = new Promise<Blob>((resolve, reject) => {\r\n reader.onloadend = () => {\r\n this.storagePutB64String(db, fileName, reader.result as string).then(() => {\r\n resolve(blob);\r\n }, reject);\r\n }\r\n \r\n reader.onerror = reject;\r\n });\r\n \r\n\r\n try {\r\n reader.readAsDataURL(blob);\r\n } catch (e) {\r\n this.storageIsAvailable = false;\r\n return Promise.reject();\r\n }\r\n\r\n return promise;\r\n }\r\n\r\n public storagePutB64String(db: IDBDatabase, fileName: string, b64string: string) {\r\n try {\r\n var objectStore = db.transaction([this.storeName], 'readwrite')\r\n .objectStore(this.storeName);\r\n var request = objectStore.put(b64string, fileName);\r\n } catch(error) {\r\n this.storageIsAvailable = false;\r\n return Promise.reject(error);\r\n }\r\n\r\n return new Promise((resolve, reject) => {\r\n request.onsuccess = function(event) {\r\n resolve();\r\n };\r\n \r\n request.onerror = reject;\r\n });\r\n }\r\n\r\n public getBlobSize(blob: any) {\r\n return blob.size || blob.byteLength || blob.length;\r\n } */\r\n\r\n public get<T>(entryName: string[]): Promise<T[]>;\r\n public get<T>(entryName: string): Promise<T>;\r\n public get<T>(entryName: string | string[]): Promise<T> | Promise<T[]> {\r\n //return Promise.reject();\r\n\r\n if(!Array.isArray(entryName)) {\r\n entryName = [].concat(entryName);\r\n }\r\n\r\n return this.getObjectStore<T>('readonly', (objectStore) => {\r\n return (entryName as string[]).map((entryName) => objectStore.get(entryName));\r\n }, DEBUG ? 'get: ' + entryName.join(', ') : '');\r\n }\r\n\r\n private getObjectStore<T>(mode: IDBTransactionMode, objectStore: (objectStore: IDBObjectStore) => IDBRequest | IDBRequest[], log?: string, storeName = this.storeName) {\r\n let perf: number;\r\n\r\n if(log) {\r\n perf = performance.now();\r\n this.log(log + ': start');\r\n }\r\n\r\n return this.openDatabase().then((db) => {\r\n return new Promise<T>((resolve, reject) => {\r\n /* if(mode === 'readwrite') {\r\n return;\r\n } */\r\n\r\n const transaction = db.transaction([storeName], mode);\r\n\r\n transaction.onerror = (e) => {\r\n clearTimeout(timeout);\r\n reject(transaction.error);\r\n };\r\n \r\n transaction.oncomplete = (e) => {\r\n clearTimeout(timeout);\r\n\r\n if(log) {\r\n this.log(log + ': end', performance.now() - perf);\r\n }\r\n\r\n const results = r.map(r => r.result);\r\n resolve(isArray ? results : results[0]);\r\n };\r\n \r\n const timeout = setTimeout(() => {\r\n this.log.error('transaction not finished', transaction);\r\n }, 10000);\r\n \r\n /* transaction.addEventListener('abort', (e) => {\r\n //handleError();\r\n this.log.error('IndexedDB: transaction abort!', transaction.error);\r\n }); */\r\n \r\n const requests = objectStore(transaction.objectStore(storeName));\r\n\r\n const isArray = Array.isArray(requests);\r\n const r: IDBRequest[] = isArray ? requests : [].concat(requests) as any;\r\n\r\n // const length = r.length;\r\n // /* let left = length;\r\n\r\n // const onRequestFinished = (error?: Error) => {\r\n // if(!--left) {\r\n // resolve(result);\r\n // clearTimeout(timeout);\r\n // }\r\n // }; */\r\n\r\n // for(let i = 0; i < length; ++i) {\r\n // const request = r[i];\r\n // request.onsuccess = () => {\r\n // onRequestFinished();\r\n // };\r\n\r\n // request.onerror = (e) => {\r\n // onRequestFinished(transaction.error);\r\n // };\r\n // }\r\n });\r\n });\r\n }\r\n\r\n public getAll<T>(): Promise<T[]> {\r\n return this.getObjectStore<T[]>('readonly', (objectStore) => objectStore.getAll(), DEBUG ? 'getAll' : '');\r\n }\r\n\r\n /* public getAllKeys(): Promise<Array<string>> {\r\n console.time('getAllEntries');\r\n return this.openDatabase().then((db) => {\r\n var objectStore = db.transaction([this.storeName], 'readonly')\r\n .objectStore(this.storeName);\r\n var request = objectStore.getAllKeys();\r\n\r\n return new Promise((resolve, reject) => {\r\n request.onsuccess = function(event) {\r\n // @ts-ignore\r\n var result = event.target.result;\r\n resolve(result);\r\n console.timeEnd('getAllEntries');\r\n }\r\n \r\n request.onerror = reject;\r\n });\r\n });\r\n } */\r\n\r\n /* public isFileExists(fileName: string): Promise<boolean> {\r\n console.time('isFileExists');\r\n return this.openDatabase().then((db) => {\r\n var objectStore = db.transaction([this.storeName], 'readonly')\r\n .objectStore(this.storeName);\r\n var request = objectStore.openCursor(fileName);\r\n\r\n return new Promise((resolve, reject) => {\r\n request.onsuccess = function(event) {\r\n // @ts-ignore\r\n var cursor = event.target.result;\r\n resolve(!!cursor);\r\n console.timeEnd('isFileExists');\r\n }\r\n \r\n request.onerror = reject;\r\n });\r\n });\r\n } */\r\n\r\n /* public getFileWriter(fileName: string, mimeType: string) {\r\n var fakeWriter = FileManager.getFakeFileWriter(mimeType, (blob) => {\r\n return this.saveFile(fileName, blob);\r\n });\r\n\r\n return Promise.resolve(fakeWriter);\r\n } */\r\n}\r\n","/*\r\n * https://github.com/morethanwords/tweb\r\n * Copyright (C) 2019-2021 Eduard Kuzmenko\r\n * https://github.com/morethanwords/tweb/blob/master/LICENSE\r\n * \r\n * Originally from:\r\n * https://github.com/zhukov/webogram\r\n * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>\r\n * https://github.com/zhukov/webogram/blob/master/LICENSE\r\n */\r\n\r\nimport { Database } from \"../config/databases\";\r\n//import DATABASE_SESSION from \"../config/databases/session\";\r\nimport { CancellablePromise, deferredPromise } from \"../helpers/cancellablePromise\";\r\nimport throttle from \"../helpers/schedulers/throttle\";\r\n//import { WorkerTaskTemplate } from \"../types\";\r\nimport IDBStorage from \"./idb\";\r\n\r\nfunction noop() {}\r\n\r\n/* export interface LocalStorageProxySetTask extends WorkerTaskTemplate {\r\n type: 'localStorageProxy',\r\n payload: {\r\n type: 'set',\r\n keys: string[],\r\n values: any[]\r\n }\r\n};\r\n\r\nexport interface LocalStorageProxyDeleteTask extends WorkerTaskTemplate {\r\n type: 'localStorageProxy',\r\n payload: {\r\n type: 'delete',\r\n keys: string[]\r\n }\r\n}; */\r\n\r\nexport default class AppStorage<Storage extends Record<string, any>, T extends Database<any>/* Storage extends {[name: string]: any} *//* Storage extends Record<string, any> */> {\r\n private static STORAGES: AppStorage<any, Database<any>>[] = [];\r\n private storage: IDBStorage<T>;//new CacheStorageController('session');\r\n\r\n //private cache: Partial<{[key: string]: Storage[typeof key]}> = {};\r\n private cache: Partial<Storage> = {};\r\n private useStorage = true;\r\n\r\n private getPromises: Map<keyof Storage, CancellablePromise<Storage[keyof Storage]>> = new Map();\r\n private getThrottled: () => void;\r\n\r\n private keysToSet: Set<keyof Storage> = new Set();\r\n private saveThrottled: () => void;\r\n private saveDeferred = deferredPromise<void>();\r\n\r\n private keysToDelete: Set<keyof Storage> = new Set();\r\n private deleteThrottled: () => void;\r\n private deleteDeferred = deferredPromise<void>();\r\n\r\n constructor(private db: T, private storeName: typeof db['stores'][number]['name']) {\r\n this.storage = new IDBStorage<T>(db, storeName);\r\n\r\n if(AppStorage.STORAGES.length) {\r\n this.useStorage = AppStorage.STORAGES[0].useStorage;\r\n }\r\n\r\n AppStorage.STORAGES.push(this);\r\n\r\n this.saveThrottled = throttle(async() => {\r\n const deferred = this.saveDeferred;\r\n this.saveDeferred = deferredPromise<void>();\r\n\r\n const set = this.keysToSet;\r\n if(set.size) {\r\n const keys = Array.from(set.values()) as string[];\r\n set.clear();\r\n\r\n try {\r\n //console.log('setItem: will set', key/* , value */);\r\n //await this.cacheStorage.delete(key); // * try to prevent memory leak in Chrome leading to 'Unexpected internal error.'\r\n //await this.storage.save(key, new Response(value, {headers: {'Content-Type': 'application/json'}}));\r\n\r\n const values = keys.map(key => this.cache[key]);\r\n /* if(db === DATABASE_SESSION && !('localStorage' in self)) { // * support legacy Webogram's localStorage\r\n self.postMessage({\r\n type: 'localStorageProxy', \r\n payload: {\r\n type: 'set',\r\n keys,\r\n values\r\n }\r\n } as LocalStorageProxySetTask);\r\n } */\r\n\r\n await this.storage.save(keys, values);\r\n //console.log('setItem: have set', key/* , value */);\r\n } catch(e) {\r\n //this.useCS = false;\r\n console.error('[AS]: set error:', e, keys/* , value */);\r\n }\r\n }\r\n\r\n deferred.resolve();\r\n\r\n if(set.size) {\r\n this.saveThrottled();\r\n }\r\n }, 16, false);\r\n\r\n this.deleteThrottled = throttle(async() => {\r\n const deferred = this.deleteDeferred;\r\n this.deleteDeferred = deferredPromise<void>();\r\n\r\n const set = this.keysToDelete;\r\n if(set.size) {\r\n const keys = Array.from(set.values()) as string[];\r\n set.clear();\r\n\r\n try {\r\n /* if(db === DATABASE_SESSION && !('localStorage' in self)) { // * support legacy Webogram's localStorage\r\n self.postMessage({\r\n type: 'localStorageProxy', \r\n payload: {\r\n type: 'delete',\r\n keys\r\n }\r\n } as LocalStorageProxyDeleteTask);\r\n } */\r\n\r\n await this.storage.delete(keys);\r\n } catch(e) {\r\n console.error('[AS]: delete error:', e, keys);\r\n }\r\n }\r\n\r\n deferred.resolve();\r\n\r\n if(set.size) {\r\n this.deleteThrottled();\r\n }\r\n }, 16, false);\r\n\r\n this.getThrottled = throttle(async() => {\r\n const keys = Array.from(this.getPromises.keys());\r\n\r\n this.storage.get(keys as string[]).then(values => {\r\n for(let i = 0, length = keys.length; i < length; ++i) {\r\n const key = keys[i];\r\n const deferred = this.getPromises.get(key);\r\n if(deferred) {\r\n // @ts-ignore\r\n deferred.resolve(this.cache[key] = values[i]);\r\n this.getPromises.delete(key);\r\n }\r\n }\r\n }, (error) => {\r\n if(!['NO_ENTRY_FOUND', 'STORAGE_OFFLINE'].includes(error)) {\r\n this.useStorage = false;\r\n console.error('[AS]: get error:', error, keys, storeName);\r\n }\r\n\r\n for(let i = 0, length = keys.length; i < length; ++i) {\r\n const key = keys[i];\r\n const deferred = this.getPromises.get(key);\r\n if(deferred) {\r\n //deferred.reject(error);\r\n deferred.resolve(undefined);\r\n this.getPromises.delete(key);\r\n }\r\n }\r\n }).finally(() => {\r\n if(this.getPromises.size) {\r\n this.getThrottled();\r\n }\r\n });\r\n }, 16, false);\r\n }\r\n\r\n public isAvailable() {\r\n return this.useStorage;\r\n }\r\n\r\n public getCache() {\r\n return this.cache;\r\n }\r\n\r\n public getFromCache<T extends keyof Storage>(key: T) {\r\n return this.cache[key];\r\n }\r\n\r\n public setToCache(key: keyof Storage, value: Storage[typeof key]) {\r\n return this.cache[key] = value;\r\n }\r\n\r\n public async get<T extends keyof Storage>(key: T, useCache = true): Promise<Storage[T]> {\r\n if(this.cache.hasOwnProperty(key) && useCache) {\r\n return this.getFromCache(key);\r\n } else if(this.useStorage) {\r\n const r = this.getPromises.get(key);\r\n if(r) return r as any;\r\n\r\n const p = deferredPromise<Storage[T]>();\r\n this.getPromises.set(key, p as any);\r\n\r\n this.getThrottled();\r\n\r\n return p;\r\n }/* else {\r\n throw 'something went wrong';\r\n } */\r\n }\r\n\r\n public getAll() {\r\n return this.storage.getAll().catch(() => []);\r\n }\r\n\r\n public set(obj: Partial<Storage>, onlyLocal = false) {\r\n //console.log('storageSetValue', obj, callback, arguments);\r\n\r\n for(const key in obj) {\r\n if(obj.hasOwnProperty(key)) {\r\n const value = obj[key];\r\n this.setToCache(key, value);\r\n\r\n // let perf = /* DEBUG */false ? performance.now() : 0;\r\n // value = JSON.stringify(value);\r\n\r\n // if(perf) {\r\n // let elapsedTime = performance.now() - perf;\r\n // if(elapsedTime > 10) {\r\n // console.warn('LocalStorage set: stringify time by JSON.stringify:', elapsedTime, key);\r\n // }\r\n // }\r\n \r\n /* perf = performance.now();\r\n value = stringify(value);\r\n console.log('LocalStorage set: stringify time by own stringify:', performance.now() - perf); */\r\n\r\n if(this.useStorage && !onlyLocal) {\r\n this.keysToSet.add(key);\r\n this.keysToDelete.delete(key);\r\n this.saveThrottled();\r\n }\r\n }\r\n }\r\n\r\n return this.useStorage ? this.saveDeferred : Promise.resolve();\r\n }\r\n\r\n public delete(key: keyof Storage, saveLocal = false) {\r\n /* if(!this.cache.hasOwnProperty(key)) {\r\n return;\r\n } */\r\n\r\n // ! it is needed here\r\n key = '' + key;\r\n\r\n if(!saveLocal) {\r\n delete this.cache[key];\r\n }\r\n \r\n if(this.useStorage) {\r\n this.keysToSet.delete(key);\r\n this.keysToDelete.add(key);\r\n this.deleteThrottled();\r\n }\r\n\r\n return this.useStorage ? this.deleteDeferred : Promise.resolve();\r\n }\r\n\r\n public clear(saveLocal = false) {\r\n if(!saveLocal) {\r\n for(const i in this.cache) {\r\n delete this.cache[i];\r\n }\r\n }\r\n\r\n return this.storage.clear().catch(noop);\r\n }\r\n\r\n public static toggleStorage(enabled: boolean) {\r\n return Promise.all(this.STORAGES.map(storage => {\r\n storage.useStorage = enabled;\r\n \r\n if(!enabled) {\r\n storage.keysToSet.clear();\r\n storage.keysToDelete.clear();\r\n storage.getPromises.forEach((deferred) => deferred.resolve(undefined));\r\n storage.getPromises.clear();\r\n return storage.clear(true);\r\n } else {\r\n return storage.set(storage.cache);\r\n }\r\n })).catch(noop);\r\n }\r\n\r\n /* public deleteDatabase() {\r\n return IDBStorage.deleteDatabase().catch(noop);\r\n } */\r\n}\r\n"],"sourceRoot":""}