diff --git a/src/components/lazyLoadQueue.ts b/src/components/lazyLoadQueue.ts index 8f471c14..8201b53a 100644 --- a/src/components/lazyLoadQueue.ts +++ b/src/components/lazyLoadQueue.ts @@ -87,7 +87,7 @@ export class LazyLoadQueueBase { //await item.load(item.div); await this.loadItem(item); } catch(err) { - if(err !== 'NO_ENTRY_FOUND') { + if(!['NO_ENTRY_FOUND', 'STORAGE_OFFLINE'].includes(err)) { this.log.error('loadMediaQueue error:', err/* , item */); } } diff --git a/src/helpers/object.ts b/src/helpers/object.ts index 8cccf63e..d1f7b38f 100644 --- a/src/helpers/object.ts +++ b/src/helpers/object.ts @@ -116,6 +116,10 @@ export function getDeepProperty(object: any, key: string) { const splitted = key.split('.'); let o: any = object; splitted.forEach(key => { + if(!key) { + return; + } + // @ts-ignore o = o[key]; }); diff --git a/src/lib/appManagers/appStateManager.ts b/src/lib/appManagers/appStateManager.ts index 46ed0229..ff147361 100644 --- a/src/lib/appManagers/appStateManager.ts +++ b/src/lib/appManagers/appStateManager.ts @@ -84,6 +84,7 @@ export type State = Partial<{ }, nightTheme?: boolean, // ! DEPRECATED }, + keepSigned: boolean, drafts: AppDraftsManager['drafts'] }>; @@ -146,6 +147,7 @@ export const STATE_INIT: State = { sound: false } }, + keepSigned: true, drafts: {} }; diff --git a/src/lib/cacheStorage.ts b/src/lib/cacheStorage.ts index 8c362b38..b675d4bc 100644 --- a/src/lib/cacheStorage.ts +++ b/src/lib/cacheStorage.ts @@ -11,9 +11,12 @@ import FileManager from './filemanager'; //import { logger } from './polyfill'; export default class CacheStorageController { + public static STORAGES: CacheStorageController[] = []; //public dbName = 'cachedFiles'; public openDbPromise: Promise; + public useStorage = true; + //private log: ReturnType = logger('CS'); constructor(public dbName: string) { @@ -22,6 +25,7 @@ export default class CacheStorageController { } this.openDatabase(); + CacheStorageController.STORAGES.push(this); } public openDatabase(): Promise { @@ -33,8 +37,8 @@ export default class CacheStorageController { } public delete(entryName: string) { - return this.timeoutOperation(async(cache) => { - const deleted = await cache.delete('/' + entryName); + return this.timeoutOperation((cache) => { + return cache.delete('/' + entryName); }); } @@ -43,12 +47,16 @@ export default class CacheStorageController { } public save(entryName: string, response: Response) { + if(!this.useStorage) return Promise.reject('STORAGE_OFFLINE'); + return this.timeoutOperation((cache) => { return cache.put('/' + entryName, response); }); } public saveFile(fileName: string, blob: Blob | Uint8Array) { + if(!this.useStorage) return Promise.reject('STORAGE_OFFLINE'); + //return Promise.resolve(blobConstruct([blob])); if(!(blob instanceof Blob)) { blob = blobConstruct(blob) as Blob; @@ -64,6 +72,8 @@ export default class CacheStorageController { } */ public getFile(fileName: string, method: 'blob' | 'json' | 'text' = 'blob'): Promise { + if(!this.useStorage) return Promise.reject('STORAGE_OFFLINE'); + /* if(method === 'blob') { return Promise.reject(); } */ @@ -120,6 +130,16 @@ export default class CacheStorageController { return Promise.resolve(fakeWriter); } + + public static toggleStorage(enabled: boolean) { + return Promise.all(this.STORAGES.map(storage => { + storage.useStorage = enabled; + + if(!enabled) { + return storage.deleteAll(); + } + })); + } } //const cacheStorage = new CacheStorageController(); diff --git a/src/lib/idb.ts b/src/lib/idb.ts index 7216a5eb..2e5d4b61 100644 --- a/src/lib/idb.ts +++ b/src/lib/idb.ts @@ -36,6 +36,7 @@ export type IDBOptions = { }; export default class IDBStorage { + //public static STORAGES: IDBStorage[] = []; public openDbPromise: Promise; public storageIsAvailable = true; @@ -51,6 +52,8 @@ export default class IDBStorage { safeAssign(this, options); this.openDatabase(true); + + //IDBStorage.STORAGES.push(this); } public isAvailable() { diff --git a/src/lib/mtproto/apiFileManager.ts b/src/lib/mtproto/apiFileManager.ts index 71b49937..787937d6 100644 --- a/src/lib/mtproto/apiFileManager.ts +++ b/src/lib/mtproto/apiFileManager.ts @@ -363,6 +363,10 @@ export class ApiFileManager { for(let i = 0, length = Math.min(maxRequests, delayed.length); i < length; ++i) { superpuper(); } + }).catch((err) => { + if(!['STORAGE_OFFLINE'].includes(err)) { + this.log.error('saveFile error:', err); + } }); }); diff --git a/src/lib/mtproto/mtproto.worker.ts b/src/lib/mtproto/mtproto.worker.ts index 1eb5dbc5..c88ced03 100644 --- a/src/lib/mtproto/mtproto.worker.ts +++ b/src/lib/mtproto/mtproto.worker.ts @@ -15,6 +15,8 @@ import type { ServiceWorkerTask, ServiceWorkerTaskResponse } from './mtproto.ser import { ctx } from '../../helpers/userAgent'; import { socketsProxied } from './dcConfigurator'; import { notifyAll } from '../../helpers/context'; +import AppStorage from '../storage'; +import CacheStorageController from '../cacheStorage'; let webpSupported = false; export const isWebpSupported = () => { @@ -121,6 +123,13 @@ const onMessage = async(e: any) => { break; } + + case 'toggleStorage': { + const enabled = task.args[0]; + AppStorage.toggleStorage(enabled); + CacheStorageController.toggleStorage(enabled); + break; + } default: { try { diff --git a/src/lib/mtproto/mtprotoworker.ts b/src/lib/mtproto/mtprotoworker.ts index 9a9842e9..63b7eeb0 100644 --- a/src/lib/mtproto/mtprotoworker.ts +++ b/src/lib/mtproto/mtprotoworker.ts @@ -478,6 +478,10 @@ export class ApiManagerProxy extends CryptoWorkerMethods { public uploadFile(options: {file: Blob | File, fileName: string}) { return this.performTaskWorker('uploadFile', options); } + + public toggleStorage(enabled: boolean) { + return this.performTaskWorker('toggleStorage', enabled); + } } const apiManagerProxy = new ApiManagerProxy(); diff --git a/src/lib/storage.ts b/src/lib/storage.ts index f4ae86d5..85a95a52 100644 --- a/src/lib/storage.ts +++ b/src/lib/storage.ts @@ -13,6 +13,7 @@ import { DatabaseStore, DatabaseStoreName } from "../config/database"; import IDBStorage, { IDBOptions } from "./idb"; export default class AppStorage/* Storage extends {[name: string]: any} *//* Storage extends Record */> { + public static STORAGES: AppStorage[] = []; private storage: IDBStorage;//new CacheStorageController('session'); //private cache: Partial<{[key: string]: Storage[typeof key]}> = {}; @@ -21,6 +22,8 @@ export default class AppStorage/* Storage ex constructor(storageOptions: Omit & {stores?: DatabaseStore[], storeName: DatabaseStoreName}) { this.storage = new IDBStorage(storageOptions); + + AppStorage.STORAGES.push(this); } public getCache() { @@ -45,7 +48,7 @@ export default class AppStorage/* Storage ex //console.log('[AS]: get result:', key, value); //value = JSON.parse(value); } catch(e) { - if(e !== 'NO_ENTRY_FOUND') { + if(!['NO_ENTRY_FOUND', 'STORAGE_OFFLINE'].includes(e)) { this.useStorage = false; console.error('[AS]: get error:', e, key, value); } @@ -117,4 +120,16 @@ export default class AppStorage/* Storage ex public clear() { return this.storage.deleteAll(); } + + public static toggleStorage(enabled: boolean) { + return Promise.all(this.STORAGES.map(storage => { + storage.useStorage = enabled; + + if(!enabled) { + return storage.clear(); + } else { + return storage.set(storage.cache); + } + })); + } } diff --git a/src/pages/pageAuthCode.ts b/src/pages/pageAuthCode.ts index ccc1e39a..1731648e 100644 --- a/src/pages/pageAuthCode.ts +++ b/src/pages/pageAuthCode.ts @@ -97,6 +97,9 @@ let onFirstMount = (): Promise => { good = true; err.handled = true; await pagePassword.mount(); + setTimeout(() => { + codeInput.value = ''; + }, 300); break; case 'PHONE_CODE_EXPIRED': codeInput.classList.add('error'); diff --git a/src/pages/pageSignIn.ts b/src/pages/pageSignIn.ts index 417beb23..75d4369d 100644 --- a/src/pages/pageSignIn.ts +++ b/src/pages/pageSignIn.ts @@ -27,6 +27,8 @@ import { ripple } from "../components/ripple"; import findUpTag from "../helpers/dom/findUpTag"; import findUpClassName from "../helpers/dom/findUpClassName"; import { randomLong } from "../helpers/random"; +import AppStorage from "../lib/storage"; +import CacheStorageController from "../lib/cacheStorage"; type Country = _Country & { li?: HTMLLIElement[] @@ -315,7 +317,19 @@ let onFirstMount = () => { name: 'keepSession', withRipple: true }); - signedCheckboxField.input.checked = true; + + signedCheckboxField.input.addEventListener('change', () => { + const keepSigned = signedCheckboxField.checked; + appStateManager.pushToState('keepSigned', keepSigned); + + AppStorage.toggleStorage(keepSigned); + CacheStorageController.toggleStorage(keepSigned); + apiManager.toggleStorage(keepSigned); + }); + + appStateManager.getState().then(state => { + signedCheckboxField.checked = state.keepSigned; + }); btnNext = Button('btn-primary btn-color-primary', {text: 'Login.Next'}); btnNext.style.visibility = 'hidden'; diff --git a/src/scss/partials/_input.scss b/src/scss/partials/_input.scss index 533ebd7e..1079adbc 100644 --- a/src/scss/partials/_input.scss +++ b/src/scss/partials/_input.scss @@ -74,6 +74,7 @@ opacity: 0; border-radius: var(--border-radius); pointer-events: none; + z-index: 1; @include animation-level(2) { transition: opacity .2s; @@ -86,7 +87,7 @@ --border-width: 1px; border: var(--border-width) solid var(--input-search-border-color); border-radius: var(--border-radius); - background-color: transparent; + background-color: var(--surface-color); //padding: 0 1rem; padding: calc(var(--padding) - var(--border-width)); box-sizing: border-box; @@ -97,6 +98,27 @@ z-index: 1; line-height: var(--line-height); + /* &:-internal-autofill-selected { + -webkit-box-shadow: 0 0 0px 1000px var(--surface-color) inset; + } */ + + &:-webkit-autofill, + &:-webkit-autofill:hover, + &:-webkit-autofill:focus, + &:-webkit-autofill:active { + //transition: background-color 5000s ease-in-out 0s; + -webkit-box-shadow: 0 0 0px 1000px var(--surface-color) inset; + } + + &:-webkit-autofill::first-line, + &:-webkit-autofill, + &:-webkit-autofill:hover, + &:-webkit-autofill:focus, + &:-webkit-autofill:active { + font-family: "Roboto", -apple-system, apple color emoji, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif !important; + font-size: 1rem !important; + } + @include respond-to(handhelds) { --padding: .9375rem; } diff --git a/src/scss/style.scss b/src/scss/style.scss index 3a1cd570..75af3b87 100644 --- a/src/scss/style.scss +++ b/src/scss/style.scss @@ -477,6 +477,13 @@ input, textarea { -webkit-appearance: none; } +/* input:-webkit-autofill, +input:-webkit-autofill:hover, +input:-webkit-autofill:focus, +input:-webkit-autofill:active { + transition: background-color 5000s ease-in-out 0s; +} */ + .subtitle { /* font-weight: 500; */ color: var(--secondary-text-color);