import { SNApplication, ApplicationIdentifier, Environment, LegacyRawKeychainValue, RawKeychainValue, TransferPayload, NamespacedRootKeyInKeychain, extendArray, WebOrDesktopDeviceInterface, } from '@standardnotes/snjs' import { Database } from '../Database' export abstract class WebOrDesktopDevice implements WebOrDesktopDeviceInterface { constructor(public appVersion: string) {} private databases: Database[] = [] abstract environment: Environment setApplication(application: SNApplication): void { const database = new Database(application.identifier, application.alertService) this.databases.push(database) } public async getJsonParsedRawStorageValue(key: string): Promise { const value = await this.getRawStorageValue(key) if (value == undefined) { return undefined } try { return JSON.parse(value) } catch (e) { return value } } private databaseForIdentifier(identifier: ApplicationIdentifier) { return this.databases.find((database) => database.databaseName === identifier) as Database } deinit() { for (const database of this.databases) { database.deinit() } this.databases = [] } async getRawStorageValue(key: string): Promise { const result = localStorage.getItem(key) if (result == undefined) { return undefined } return result } async getAllRawStorageKeyValues() { const results = [] for (const key of Object.keys(localStorage)) { results.push({ key: key, value: localStorage[key], }) } return results } async setRawStorageValue(key: string, value: string) { localStorage.setItem(key, value) } async removeRawStorageValue(key: string) { localStorage.removeItem(key) } async removeAllRawStorageValues() { localStorage.clear() } async openDatabase(identifier: ApplicationIdentifier) { this.databaseForIdentifier(identifier).unlock() return new Promise((resolve, reject) => { this.databaseForIdentifier(identifier) .openDatabase(() => { resolve({ isNewDatabase: true }) }) .then(() => { resolve({ isNewDatabase: false }) }) .catch((error) => { reject(error) }) }) as Promise<{ isNewDatabase?: boolean } | undefined> } async getAllRawDatabasePayloads(identifier: ApplicationIdentifier) { return this.databaseForIdentifier(identifier).getAllPayloads() } async saveRawDatabasePayload(payload: TransferPayload, identifier: ApplicationIdentifier) { return this.databaseForIdentifier(identifier).savePayload(payload) } async saveRawDatabasePayloads(payloads: TransferPayload[], identifier: ApplicationIdentifier) { return this.databaseForIdentifier(identifier).savePayloads(payloads) } async removeRawDatabasePayloadWithId(id: string, identifier: ApplicationIdentifier) { return this.databaseForIdentifier(identifier).deletePayload(id) } async removeAllRawDatabasePayloads(identifier: ApplicationIdentifier) { return this.databaseForIdentifier(identifier).clearAllPayloads() } async getNamespacedKeychainValue(identifier: ApplicationIdentifier) { const keychain = await this.getKeychainValue() if (!keychain) { return } return keychain[identifier] } async getDatabaseKeys(): Promise { const keys: string[] = [] for (const database of this.databases) { extendArray(keys, await database.getAllKeys()) } return keys } async setNamespacedKeychainValue(value: NamespacedRootKeyInKeychain, identifier: ApplicationIdentifier) { let keychain = await this.getKeychainValue() if (!keychain) { keychain = {} } return this.setKeychainValue({ ...keychain, [identifier]: value, }) } async clearNamespacedKeychainValue(identifier: ApplicationIdentifier) { const keychain = await this.getKeychainValue() if (!keychain) { return } delete keychain[identifier] return this.setKeychainValue(keychain) } setRawKeychainValue(value: unknown): Promise { return this.setKeychainValue(value) } openUrl(url: string) { const win = window.open(url, '_blank') if (win) { win.focus() } } setLegacyRawKeychainValue(value: LegacyRawKeychainValue): Promise { return this.setKeychainValue(value) } abstract getKeychainValue(): Promise abstract setKeychainValue(value: unknown): Promise abstract clearRawKeychainValue(): Promise abstract isDeviceDestroyed(): boolean abstract performHardReset(): Promise async performSoftReset(): Promise { window.location.reload() } }