Browse Source

Keep me signed in

Input autofill styles
master
morethanwords 4 years ago
parent
commit
3842392cb5
  1. 2
      src/components/lazyLoadQueue.ts
  2. 4
      src/helpers/object.ts
  3. 2
      src/lib/appManagers/appStateManager.ts
  4. 24
      src/lib/cacheStorage.ts
  5. 3
      src/lib/idb.ts
  6. 4
      src/lib/mtproto/apiFileManager.ts
  7. 9
      src/lib/mtproto/mtproto.worker.ts
  8. 4
      src/lib/mtproto/mtprotoworker.ts
  9. 17
      src/lib/storage.ts
  10. 3
      src/pages/pageAuthCode.ts
  11. 16
      src/pages/pageSignIn.ts
  12. 24
      src/scss/partials/_input.scss
  13. 7
      src/scss/style.scss

2
src/components/lazyLoadQueue.ts

@ -87,7 +87,7 @@ export class LazyLoadQueueBase {
//await item.load(item.div); //await item.load(item.div);
await this.loadItem(item); await this.loadItem(item);
} catch(err) { } catch(err) {
if(err !== 'NO_ENTRY_FOUND') { if(!['NO_ENTRY_FOUND', 'STORAGE_OFFLINE'].includes(err)) {
this.log.error('loadMediaQueue error:', err/* , item */); this.log.error('loadMediaQueue error:', err/* , item */);
} }
} }

4
src/helpers/object.ts

@ -116,6 +116,10 @@ export function getDeepProperty(object: any, key: string) {
const splitted = key.split('.'); const splitted = key.split('.');
let o: any = object; let o: any = object;
splitted.forEach(key => { splitted.forEach(key => {
if(!key) {
return;
}
// @ts-ignore // @ts-ignore
o = o[key]; o = o[key];
}); });

2
src/lib/appManagers/appStateManager.ts

@ -84,6 +84,7 @@ export type State = Partial<{
}, },
nightTheme?: boolean, // ! DEPRECATED nightTheme?: boolean, // ! DEPRECATED
}, },
keepSigned: boolean,
drafts: AppDraftsManager['drafts'] drafts: AppDraftsManager['drafts']
}>; }>;
@ -146,6 +147,7 @@ export const STATE_INIT: State = {
sound: false sound: false
} }
}, },
keepSigned: true,
drafts: {} drafts: {}
}; };

24
src/lib/cacheStorage.ts

@ -11,9 +11,12 @@ import FileManager from './filemanager';
//import { logger } from './polyfill'; //import { logger } from './polyfill';
export default class CacheStorageController { export default class CacheStorageController {
public static STORAGES: CacheStorageController[] = [];
//public dbName = 'cachedFiles'; //public dbName = 'cachedFiles';
public openDbPromise: Promise<Cache>; public openDbPromise: Promise<Cache>;
public useStorage = true;
//private log: ReturnType<typeof logger> = logger('CS'); //private log: ReturnType<typeof logger> = logger('CS');
constructor(public dbName: string) { constructor(public dbName: string) {
@ -22,6 +25,7 @@ export default class CacheStorageController {
} }
this.openDatabase(); this.openDatabase();
CacheStorageController.STORAGES.push(this);
} }
public openDatabase(): Promise<Cache> { public openDatabase(): Promise<Cache> {
@ -33,8 +37,8 @@ export default class CacheStorageController {
} }
public delete(entryName: string) { public delete(entryName: string) {
return this.timeoutOperation(async(cache) => { return this.timeoutOperation((cache) => {
const deleted = await cache.delete('/' + entryName); return cache.delete('/' + entryName);
}); });
} }
@ -43,12 +47,16 @@ export default class CacheStorageController {
} }
public save(entryName: string, response: Response) { public save(entryName: string, response: Response) {
if(!this.useStorage) return Promise.reject('STORAGE_OFFLINE');
return this.timeoutOperation((cache) => { return this.timeoutOperation((cache) => {
return cache.put('/' + entryName, response); return cache.put('/' + entryName, response);
}); });
} }
public saveFile(fileName: string, blob: Blob | Uint8Array) { public saveFile(fileName: string, blob: Blob | Uint8Array) {
if(!this.useStorage) return Promise.reject('STORAGE_OFFLINE');
//return Promise.resolve(blobConstruct([blob])); //return Promise.resolve(blobConstruct([blob]));
if(!(blob instanceof Blob)) { if(!(blob instanceof Blob)) {
blob = blobConstruct(blob) as Blob; blob = blobConstruct(blob) as Blob;
@ -64,6 +72,8 @@ export default class CacheStorageController {
} */ } */
public getFile(fileName: string, method: 'blob' | 'json' | 'text' = 'blob'): Promise<any> { public getFile(fileName: string, method: 'blob' | 'json' | 'text' = 'blob'): Promise<any> {
if(!this.useStorage) return Promise.reject('STORAGE_OFFLINE');
/* if(method === 'blob') { /* if(method === 'blob') {
return Promise.reject(); return Promise.reject();
} */ } */
@ -120,6 +130,16 @@ export default class CacheStorageController {
return Promise.resolve(fakeWriter); 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(); //const cacheStorage = new CacheStorageController();

3
src/lib/idb.ts

@ -36,6 +36,7 @@ export type IDBOptions = {
}; };
export default class IDBStorage { export default class IDBStorage {
//public static STORAGES: IDBStorage[] = [];
public openDbPromise: Promise<IDBDatabase>; public openDbPromise: Promise<IDBDatabase>;
public storageIsAvailable = true; public storageIsAvailable = true;
@ -51,6 +52,8 @@ export default class IDBStorage {
safeAssign(this, options); safeAssign(this, options);
this.openDatabase(true); this.openDatabase(true);
//IDBStorage.STORAGES.push(this);
} }
public isAvailable() { public isAvailable() {

4
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) { for(let i = 0, length = Math.min(maxRequests, delayed.length); i < length; ++i) {
superpuper(); superpuper();
} }
}).catch((err) => {
if(!['STORAGE_OFFLINE'].includes(err)) {
this.log.error('saveFile error:', err);
}
}); });
}); });

9
src/lib/mtproto/mtproto.worker.ts

@ -15,6 +15,8 @@ import type { ServiceWorkerTask, ServiceWorkerTaskResponse } from './mtproto.ser
import { ctx } from '../../helpers/userAgent'; import { ctx } from '../../helpers/userAgent';
import { socketsProxied } from './dcConfigurator'; import { socketsProxied } from './dcConfigurator';
import { notifyAll } from '../../helpers/context'; import { notifyAll } from '../../helpers/context';
import AppStorage from '../storage';
import CacheStorageController from '../cacheStorage';
let webpSupported = false; let webpSupported = false;
export const isWebpSupported = () => { export const isWebpSupported = () => {
@ -121,6 +123,13 @@ const onMessage = async(e: any) => {
break; break;
} }
case 'toggleStorage': {
const enabled = task.args[0];
AppStorage.toggleStorage(enabled);
CacheStorageController.toggleStorage(enabled);
break;
}
default: { default: {
try { try {

4
src/lib/mtproto/mtprotoworker.ts

@ -478,6 +478,10 @@ export class ApiManagerProxy extends CryptoWorkerMethods {
public uploadFile(options: {file: Blob | File, fileName: string}) { public uploadFile(options: {file: Blob | File, fileName: string}) {
return this.performTaskWorker('uploadFile', options); return this.performTaskWorker('uploadFile', options);
} }
public toggleStorage(enabled: boolean) {
return this.performTaskWorker('toggleStorage', enabled);
}
} }
const apiManagerProxy = new ApiManagerProxy(); const apiManagerProxy = new ApiManagerProxy();

17
src/lib/storage.ts

@ -13,6 +13,7 @@ import { DatabaseStore, DatabaseStoreName } from "../config/database";
import IDBStorage, { IDBOptions } from "./idb"; import IDBStorage, { IDBOptions } from "./idb";
export default class AppStorage<Storage extends Record<string, any>/* Storage extends {[name: string]: any} *//* Storage extends Record<string, any> */> { export default class AppStorage<Storage extends Record<string, any>/* Storage extends {[name: string]: any} *//* Storage extends Record<string, any> */> {
public static STORAGES: AppStorage<any>[] = [];
private storage: IDBStorage;//new CacheStorageController('session'); private storage: IDBStorage;//new CacheStorageController('session');
//private cache: Partial<{[key: string]: Storage[typeof key]}> = {}; //private cache: Partial<{[key: string]: Storage[typeof key]}> = {};
@ -21,6 +22,8 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
constructor(storageOptions: Omit<IDBOptions, 'storeName' | 'stores'> & {stores?: DatabaseStore[], storeName: DatabaseStoreName}) { constructor(storageOptions: Omit<IDBOptions, 'storeName' | 'stores'> & {stores?: DatabaseStore[], storeName: DatabaseStoreName}) {
this.storage = new IDBStorage(storageOptions); this.storage = new IDBStorage(storageOptions);
AppStorage.STORAGES.push(this);
} }
public getCache() { public getCache() {
@ -45,7 +48,7 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
//console.log('[AS]: get result:', key, value); //console.log('[AS]: get result:', key, value);
//value = JSON.parse(value); //value = JSON.parse(value);
} catch(e) { } catch(e) {
if(e !== 'NO_ENTRY_FOUND') { if(!['NO_ENTRY_FOUND', 'STORAGE_OFFLINE'].includes(e)) {
this.useStorage = false; this.useStorage = false;
console.error('[AS]: get error:', e, key, value); console.error('[AS]: get error:', e, key, value);
} }
@ -117,4 +120,16 @@ export default class AppStorage<Storage extends Record<string, any>/* Storage ex
public clear() { public clear() {
return this.storage.deleteAll(); 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);
}
}));
}
} }

3
src/pages/pageAuthCode.ts

@ -97,6 +97,9 @@ let onFirstMount = (): Promise<any> => {
good = true; good = true;
err.handled = true; err.handled = true;
await pagePassword.mount(); await pagePassword.mount();
setTimeout(() => {
codeInput.value = '';
}, 300);
break; break;
case 'PHONE_CODE_EXPIRED': case 'PHONE_CODE_EXPIRED':
codeInput.classList.add('error'); codeInput.classList.add('error');

16
src/pages/pageSignIn.ts

@ -27,6 +27,8 @@ import { ripple } from "../components/ripple";
import findUpTag from "../helpers/dom/findUpTag"; import findUpTag from "../helpers/dom/findUpTag";
import findUpClassName from "../helpers/dom/findUpClassName"; import findUpClassName from "../helpers/dom/findUpClassName";
import { randomLong } from "../helpers/random"; import { randomLong } from "../helpers/random";
import AppStorage from "../lib/storage";
import CacheStorageController from "../lib/cacheStorage";
type Country = _Country & { type Country = _Country & {
li?: HTMLLIElement[] li?: HTMLLIElement[]
@ -315,7 +317,19 @@ let onFirstMount = () => {
name: 'keepSession', name: 'keepSession',
withRipple: true 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 = Button('btn-primary btn-color-primary', {text: 'Login.Next'});
btnNext.style.visibility = 'hidden'; btnNext.style.visibility = 'hidden';

24
src/scss/partials/_input.scss

@ -74,6 +74,7 @@
opacity: 0; opacity: 0;
border-radius: var(--border-radius); border-radius: var(--border-radius);
pointer-events: none; pointer-events: none;
z-index: 1;
@include animation-level(2) { @include animation-level(2) {
transition: opacity .2s; transition: opacity .2s;
@ -86,7 +87,7 @@
--border-width: 1px; --border-width: 1px;
border: var(--border-width) solid var(--input-search-border-color); border: var(--border-width) solid var(--input-search-border-color);
border-radius: var(--border-radius); border-radius: var(--border-radius);
background-color: transparent; background-color: var(--surface-color);
//padding: 0 1rem; //padding: 0 1rem;
padding: calc(var(--padding) - var(--border-width)); padding: calc(var(--padding) - var(--border-width));
box-sizing: border-box; box-sizing: border-box;
@ -97,6 +98,27 @@
z-index: 1; z-index: 1;
line-height: var(--line-height); 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) { @include respond-to(handhelds) {
--padding: .9375rem; --padding: .9375rem;
} }

7
src/scss/style.scss

@ -477,6 +477,13 @@ input, textarea {
-webkit-appearance: none; -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 { .subtitle {
/* font-weight: 500; */ /* font-weight: 500; */
color: var(--secondary-text-color); color: var(--secondary-text-color);

Loading…
Cancel
Save