From c05d7e99e2bc7df58ea0b4d26cda957ca8bad2a0 Mon Sep 17 00:00:00 2001 From: Jon Staab Date: Tue, 11 Nov 2025 17:49:22 -0800 Subject: [PATCH] remove old icon picker --- src/app/components/WalletConnect.svelte | 2 +- src/app/core/commands.ts | 8 +- src/app/core/storage.ts | 52 + src/app/util/notifications.ts | 6 +- src/app/util/storage.ts | 353 +++--- src/app/util/theme.ts | 4 +- src/assets/icons/index.html | 1353 ----------------------- src/lib/indexeddb.ts | 170 +++ src/lib/storage.ts | 108 -- src/routes/+layout.svelte | 22 +- 10 files changed, 435 insertions(+), 1643 deletions(-) create mode 100644 src/app/core/storage.ts delete mode 100644 src/assets/icons/index.html create mode 100644 src/lib/indexeddb.ts delete mode 100644 src/lib/storage.ts diff --git a/src/app/components/WalletConnect.svelte b/src/app/components/WalletConnect.svelte index b8c6a38..1489a4d 100644 --- a/src/app/components/WalletConnect.svelte +++ b/src/app/components/WalletConnect.svelte @@ -21,7 +21,7 @@ import {pushToast} from "@app/util/toast" import {pushModal} from "@app/util/modal" import WalletAsReceivingAddress from "@app/components/WalletAsReceivingAddress.svelte" - import Divider from "@src/lib/components/Divider.svelte" + import Divider from "@lib/components/Divider.svelte" const back = () => history.back() diff --git a/src/app/core/commands.ts b/src/app/core/commands.ts index e2feb3c..d82241b 100644 --- a/src/app/core/commands.ts +++ b/src/app/core/commands.ts @@ -93,7 +93,8 @@ import { userBlossomServers, shouldUnwrap, } from "@welshman/app" -import {compressFile} from "@src/lib/html" +import {compressFile} from "@lib/html" +import {kv, db} from "@app/core/storage" import type {SettingsValues, Alert} from "@app/core/state" import { SETTINGS, @@ -111,7 +112,6 @@ import { } from "@app/core/state" import {loadAlertStatuses} from "@app/core/requests" import {platform, platformName, getPushInfo} from "@app/util/push" -import {preferencesStorageProvider, Collection} from "@src/lib/storage" // Utils @@ -156,8 +156,8 @@ export const logout = async () => { localStorage.clear() - await preferencesStorageProvider.clear() - await Collection.clearAll() + await kv.clear() + await db.clear() } // Synchronization diff --git a/src/app/core/storage.ts b/src/app/core/storage.ts new file mode 100644 index 0000000..44e2241 --- /dev/null +++ b/src/app/core/storage.ts @@ -0,0 +1,52 @@ +import {reject, call, identity} from "@welshman/lib" +import {Preferences} from "@capacitor/preferences" +import {Encoding, Filesystem, Directory} from "@capacitor/filesystem" +import {IDB} from "@lib/indexeddb" + +export const kv = call(() => { + let p = Promise.resolve() + + const get = async (key: string): Promise => { + const result = await Preferences.get({key}) + if (!result.value) return undefined + try { + return JSON.parse(result.value) + } catch (e) { + return undefined + } + } + + const set = async (key: string, value: T): Promise => { + p = p.then(() => Preferences.set({key, value: JSON.stringify(value)})) + + await p + } + + const clear = async () => { + p = p.then(() => Preferences.clear()) + + await p + } + + return {get, set, clear} +}) + +export const db = new IDB({name: "flotilla-9gl", version: 1}) + +// Migration - we used to use capacitor's filesystem for storage, clear it out since we're +// going back to indexeddb +call(async () => { + const res = await Filesystem.readdir({ + path: "", + directory: Directory.Data, + }) + + await Promise.all( + res.files.map(file => + Filesystem.deleteFile({ + path: file.name, + directory: Directory.Data, + }), + ), + ) +}) diff --git a/src/app/util/notifications.ts b/src/app/util/notifications.ts index 3f29698..acd2c96 100644 --- a/src/app/util/notifications.ts +++ b/src/app/util/notifications.ts @@ -1,4 +1,5 @@ import {derived, get} from "svelte/store" +import {Badge} from "@capawesome/capacitor-badge" import {synced, throttled} from "@welshman/store" import {pubkey, relaysByUrl} from "@welshman/app" import {prop, spec, identity, now, groupBy} from "@welshman/lib" @@ -23,15 +24,14 @@ import { getSpaceUrlsFromGroupSelections, getSpaceRoomsFromGroupSelections, } from "@app/core/state" -import {preferencesStorageProvider} from "@src/lib/storage" -import {Badge} from "@capawesome/capacitor-badge" +import {kv} from "@app/core/storage" // Checked state export const checked = synced>({ key: "checked", defaultValue: {}, - storage: preferencesStorageProvider, + storage: kv, }) export const deriveChecked = (key: string) => derived(checked, prop(key)) diff --git a/src/app/util/storage.ts b/src/app/util/storage.ts index ed8bded..1e9efe8 100644 --- a/src/app/util/storage.ts +++ b/src/app/util/storage.ts @@ -48,35 +48,16 @@ import { onZapper, onHandle, wrapManager, + onRelay, } from "@welshman/app" -import {Collection} from "@lib/storage" import {isMobile} from "@lib/html" +import type {IDBTable} from "@lib/indexeddb" -const syncEvents = async () => { - const collection = new Collection({table: "events", getId: prop("id")}) - - const initialEvents = await collection.get() - - // Mark events verified to avoid re-verification of signatures - for (const event of initialEvents) { - event[verifiedSymbol] = true - } - - repository.load(initialEvents) - - const metaKinds = [ - PROFILE, - FOLLOWS, - MUTES, - RELAYS, - BLOSSOM_SERVERS, - INBOX_RELAYS, - APP_DATA, - ROOMS, - ] - const alertKinds = [ALERT_STATUS, ALERT_EMAIL, ALERT_WEB, ALERT_IOS, ALERT_ANDROID] - const spaceKinds = [RELAY_ADD_MEMBER, RELAY_REMOVE_MEMBER, RELAY_MEMBERS, RELAY_JOIN, RELAY_LEAVE] - const roomKinds = [ +const kinds = { + meta: [PROFILE, FOLLOWS, MUTES, RELAYS, BLOSSOM_SERVERS, INBOX_RELAYS, APP_DATA, ROOMS], + alert: [ALERT_STATUS, ALERT_EMAIL, ALERT_WEB, ALERT_IOS, ALERT_ANDROID], + space: [RELAY_ADD_MEMBER, RELAY_REMOVE_MEMBER, RELAY_MEMBERS, RELAY_JOIN, RELAY_LEAVE], + room: [ ROOM_META, ROOM_DELETE, ROOM_ADMINS, @@ -84,178 +65,222 @@ const syncEvents = async () => { ROOM_ADD_MEMBER, ROOM_REMOVE_MEMBER, ROOM_CREATE_PERMISSION, - ] - const contentKinds = [EVENT_TIME, THREAD, MESSAGE, ZAP_GOAL, DIRECT_MESSAGE, DIRECT_MESSAGE_FILE] + ], + content: [EVENT_TIME, THREAD, MESSAGE, ZAP_GOAL, DIRECT_MESSAGE, DIRECT_MESSAGE_FILE], +} - const rankEvent = (event: TrustedEvent) => { - if (metaKinds.includes(event.kind)) return 9 - if (alertKinds.includes(event.kind)) return 8 - if (spaceKinds.includes(event.kind)) return 7 - if (roomKinds.includes(event.kind)) return 6 - if (!isMobile && contentKinds.includes(event.kind)) return 5 - return 0 - } +const rankEvent = (event: TrustedEvent) => { + if (kinds.meta.includes(event.kind)) return 9 + if (kinds.alert.includes(event.kind)) return 8 + if (kinds.space.includes(event.kind)) return 7 + if (kinds.room.includes(event.kind)) return 6 + if (!isMobile && kinds.content.includes(event.kind)) return 5 + return 0 +} - return on( - repository, - "update", - batch(3000, async (updates: RepositoryUpdate[]) => { - const add: TrustedEvent[] = [] - const remove = new Set() +const eventsAdapter = { + name: "events", + keyPath: ["id"], + init: async (table: IDBTable) => { + const initialEvents = await table.getAll() - for (const update of updates) { - for (const event of update.added) { - if (rankEvent(event) > 0) { - add.push(event) - remove.delete(event.id) + // Mark events verified to avoid re-verification of signatures + for (const event of initialEvents) { + event[verifiedSymbol] = true + } + + repository.load(initialEvents) + + return on( + repository, + "update", + batch(3000, async (updates: RepositoryUpdate[]) => { + const add: TrustedEvent[] = [] + const remove = new Set() + + for (const update of updates) { + for (const event of update.added) { + if (rankEvent(event) > 0) { + add.push(event) + remove.delete(event.id) + } + } + + for (const id of update.removed) { + remove.add(id) } } - for (const id of update.removed) { - remove.add(id) + if (add.length > 0) { + await table.bulkPut(add) } + + if (remove.size > 0) { + await table.bulkDelete(remove) + } + }), + ) + }, +} + +type TrackerItem = {id: string; relays: string[]} + +const trackerAdapter = { + name: "tracker", + keyPath: ["id"], + init: async (table: IDBTable) => { + const relaysById = new Map>() + + for (const {id, relays} of await table.getAll()) { + relaysById.set(id, new Set(relays)) + } + + tracker.load(relaysById) + + const _onAdd = async (ids: Iterable) => { + const items: TrackerItem[] = [] + + for (const id of ids) { + const event = repository.getEvent(id) + + if (!event || rankEvent(event) === 0) continue + + const relays = Array.from(tracker.getRelays(id)) + + if (relays.length === 0) continue + + items.push({id, relays}) } - await collection.update({add, remove}) - }), - ) + await table.bulkPut(items) + } + + const _onRemove = async (ids: Iterable) => { + await table.bulkDelete(Array.from(ids)) + } + + const onAdd = batch(3000, _onAdd) + + const onRemove = batch(3000, _onRemove) + + const onLoad = () => _onAdd(tracker.relaysById.keys()) + + const onClear = () => _onRemove(tracker.relaysById.keys()) + + tracker.on("add", onAdd) + tracker.on("remove", onRemove) + tracker.on("load", onLoad) + tracker.on("clear", onClear) + + return () => { + tracker.off("add", onAdd) + tracker.off("remove", onRemove) + tracker.off("load", onLoad) + tracker.off("clear", onClear) + } + }, } -type TrackerItem = [string, string[]] +const relaysAdapter = { + name: "relays", + keyPath: ["url"], + init: async (table: IDBTable) => { + relays.set(await table.getAll()) -const syncTracker = async () => { - const collection = new Collection({ - table: "tracker", - getId: (item: TrackerItem) => item[0], - }) - - const relaysById = new Map>() - - for (const [id, relays] of await collection.get()) { - relaysById.set(id, new Set(relays)) - } - - tracker.load(relaysById) - - const updateOne = batch(3000, (ids: string[]) => { - collection.add(ids.map(id => [id, Array.from(tracker.getRelays(id))])) - }) - - const updateAll = throttle(3000, () => { - collection.set( - Array.from(tracker.relaysById.entries()).map(([id, relays]) => [id, Array.from(relays)]), - ) - }) - - tracker.on("add", updateOne) - tracker.on("remove", updateOne) - tracker.on("load", updateAll) - tracker.on("clear", updateAll) - - return () => { - tracker.off("add", updateOne) - tracker.off("remove", updateOne) - tracker.off("load", updateAll) - tracker.off("clear", updateAll) - } + return onRelay(batch(3000, table.bulkPut)) + }, } -const syncRelays = async () => { - const collection = new Collection({table: "relays", getId: prop("url")}) +const relayStatsAdapter = { + name: "relayStats", + keyPath: ["url"], + init: async (table: IDBTable) => { + relayStats.set(await table.getAll()) - relays.set(await collection.get()) - - return throttled(3000, relays).subscribe(collection.set) + return throttled(3000, relayStats).subscribe(table.bulkPut) + }, } -const syncRelayStats = async () => { - const collection = new Collection({table: "relayStats", getId: prop("url")}) +const handlesAdapter = { + name: "handles", + keyPath: ["nip05"], + init: async (table: IDBTable) => { + handles.set(await table.getAll()) - relayStats.set(await collection.get()) - - return throttled(3000, relayStats).subscribe(collection.set) + return onHandle(batch(3000, table.bulkPut)) + }, } -const syncHandles = async () => { - const collection = new Collection({table: "handles", getId: prop("nip05")}) +const zappersAdapter = { + name: "zappers", + keyPath: ["lnurl"], + init: async (table: IDBTable) => { + zappers.set(await table.getAll()) - handles.set(await collection.get()) - - return onHandle(batch(3000, collection.add)) + return onZapper(batch(3000, table.bulkPut)) + }, } -const syncZappers = async () => { - const collection = new Collection({table: "zappers", getId: prop("lnurl")}) +type FreshnessItem = {key: string; value: number} - zappers.set(await collection.get()) +const freshnessAdapter = { + name: "freshness", + keyPath: ["key"], + init: async (table: IDBTable) => { + const initialRecords = await table.getAll() - return onZapper(batch(3000, collection.add)) + freshness.set(fromPairs(initialRecords.map(({key, value}) => [key, value]))) + + return throttled(3000, freshness).subscribe($freshness => { + table.bulkPut(Object.entries($freshness).map(([key, value]) => ({key, value}))) + }) + }, } -type FreshnessItem = [string, number] +type PlaintextItem = {key: string; value: string} -const syncFreshness = async () => { - const collection = new Collection({ - table: "freshness", - getId: (item: FreshnessItem) => item[0], - }) +const plaintextAdapter = { + name: "plaintext", + keyPath: ["key"], + init: async (table: IDBTable) => { + const initialRecords = await table.getAll() - freshness.set(fromPairs(await collection.get())) + plaintext.set(fromPairs(initialRecords.map(({key, value}) => [key, value]))) - return throttled(3000, freshness).subscribe($freshness => { - collection.set(Object.entries($freshness)) - }) + return throttled(3000, plaintext).subscribe($plaintext => { + table.bulkPut(Object.entries($plaintext).map(([key, value]) => ({key, value}))) + }) + }, } -type PlaintextItem = [string, string] +const wrapManagerAdapter = { + name: "wrapManager", + keyPath: ["id"], + init: async (table: IDBTable) => { + wrapManager.load(await table.getAll()) -const syncPlaintext = async () => { - const collection = new Collection({ - table: "plaintext", - getId: (item: PlaintextItem) => item[0], - }) + const addOne = batch(3000, table.bulkPut) - plaintext.set(fromPairs(await collection.get())) + const removeOne = throttle(3000, table.bulkDelete) - return throttled(3000, plaintext).subscribe($plaintext => { - collection.set(Object.entries($plaintext)) - }) + wrapManager.on("add", addOne) + wrapManager.on("remove", removeOne) + + return () => { + wrapManager.off("add", addOne) + wrapManager.off("remove", removeOne) + } + }, } -const syncWrapManager = async () => { - const collection = new Collection({table: "wraps", getId: prop("id")}) - - wrapManager.load(await collection.get()) - - const addOne = batch(3000, (wrapItems: WrapItem[]) => collection.add(wrapItems)) - - const updateAll = throttle(3000, () => collection.set(wrapManager.dump())) - - wrapManager.on("add", addOne) - wrapManager.on("remove", updateAll) - - return () => { - wrapManager.off("add", addOne) - wrapManager.off("remove", updateAll) - } -} - -export const syncDataStores = async () => { - const promises = [ - syncEvents(), - syncTracker(), - syncRelays(), - syncHandles(), - syncZappers(), - syncPlaintext(), - syncWrapManager(), - ] - - if (!isMobile) { - promises.push(syncFreshness(), syncRelayStats()) - } - - const unsubscribers = await Promise.all(promises) - - return () => unsubscribers.forEach(call) -} +export const adapters = [ + eventsAdapter, + trackerAdapter, + relaysAdapter, + relayStatsAdapter, + handlesAdapter, + zappersAdapter, + freshnessAdapter, + plaintextAdapter, + wrapManagerAdapter, +] diff --git a/src/app/util/theme.ts b/src/app/util/theme.ts index 35c1f9b..66371b2 100644 --- a/src/app/util/theme.ts +++ b/src/app/util/theme.ts @@ -1,8 +1,8 @@ -import {preferencesStorageProvider} from "@src/lib/storage" +import {kv} from "@app/core/storage" import {synced} from "@welshman/store" export const theme = synced({ key: "theme", defaultValue: window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light", - storage: preferencesStorageProvider, + storage: kv, }) diff --git a/src/assets/icons/index.html b/src/assets/icons/index.html deleted file mode 100644 index c4a2df4..0000000 --- a/src/assets/icons/index.html +++ /dev/null @@ -1,1353 +0,0 @@ - - - - - - Icon Gallery - - - - - -
-

Icon Gallery

-
- -
-
-
- - - - diff --git a/src/lib/indexeddb.ts b/src/lib/indexeddb.ts new file mode 100644 index 0000000..ce1efd8 --- /dev/null +++ b/src/lib/indexeddb.ts @@ -0,0 +1,170 @@ +import {openDB, deleteDB} from "idb" +import type {IDBPDatabase} from "idb" +import {writable} from "svelte/store" +import type {Unsubscriber} from "svelte/store" +import {call, defer} from "@welshman/lib" +import type {Maybe} from "@welshman/lib" +import {withGetter} from "@welshman/store" + +export type IDBAdapter = { + name: string + keyPath: string[] + init: (table: IDBTable) => Promise +} + +export type IDBAdapters = IDBAdapter[] + +export enum IDBStatus { + Ready = "ready", + Closed = "closed", + Opening = "opening", + Closing = "closing", + Initial = "initial", +} + +export type IDBOptions = { + name: string + version: number +} + +export class IDB { + idbp: Maybe> + ready: Maybe> + unsubscribers: Maybe + status = IDBStatus.Initial + + constructor(readonly options: IDBOptions) {} + + init(adapters: IDBAdapters) { + if (this.status !== IDBStatus.Initial) { + throw new Error(`Database re-initialized while ${this.status}`) + } + + this.status = IDBStatus.Opening + + this.idbp = openDB(this.options.name, this.options.version, { + upgrade(idbDb: IDBPDatabase) { + const names = new Set(adapters.map(a => a.name)) + + for (const table of idbDb.objectStoreNames) { + if (!names.has(table)) { + idbDb.deleteObjectStore(table) + } + } + + for (const {name, keyPath} of adapters) { + try { + idbDb.createObjectStore(name, {keyPath}) + } catch (e) { + console.warn(e) + } + } + }, + blocked() {}, + blocking() {}, + }) + + this.ready = this.idbp.then(async idbp => { + window.addEventListener("beforeunload", () => idbp.close()) + + this.unsubscribers = await Promise.all(adapters.map(({name, init}) => init(this.table(name)))) + + this.status = IDBStatus.Ready + }) + } + + table = (name: string) => new IDBTable(this, name) + + _withIDBP = async (f: (db: IDBPDatabase) => Promise) => { + if (this.status === IDBStatus.Initial) { + throw new Error("Database was accessed in initial state") + } + + // If we're closing, ignore any lingering requests + if ([IDBStatus.Closed, IDBStatus.Closing].includes(this.status)) return + + return f(await this.idbp) + } + + getAll = async (table: string): Promise => + this._withIDBP(async idbp => { + const tx = idbp.transaction(table, "readwrite") + const store = tx.objectStore(table) + const result = await store.getAll() + + await tx.done + + return result + }) + + bulkPut = async (table: string, data: Iterable) => + this._withIDBP(async idbp => { + const tx = idbp.transaction(table, "readwrite") + const store = tx.objectStore(table) + + await Promise.all( + Array.from(data).map(item => { + try { + store.put(item) + } catch (e) { + console.error(e, item) + } + }), + ) + + await tx.done + }) + + bulkDelete = async (table: string, ids: Iterable) => + this._withIDBP(async idbp => { + const tx = idbp.transaction(table, "readwrite") + const store = tx.objectStore(table) + + await Promise.all(Array.from(ids).map(id => store.delete(id))) + await tx.done + }) + + close = () => + this._withIDBP(async idbp => { + this.unsubscribers!.forEach(call) + this.status = IDBStatus.Closing + + await idbp.close() + + // Allow the caller to call reset and re-init immediately + if (this.status === IDBStatus.Closing) { + this.idbp = undefined + this.ready = undefined + this.unsubscribers = undefined + this.status = IDBStatus.Closed + } + }) + + clear = async () => { + await this.close() + await deleteDB(this.options.name, { + blocked() {}, + }) + } + + reset = () => { + if (![IDBStatus.Closing, IDBStatus.Closed].includes(this.status)) { + throw new Error("Database reset when not closed") + } + + this.status = IDBStatus.Initial + } +} + +export class IDBTable { + constructor( + readonly db: IDB, + readonly name: string, + ) {} + + getAll = () => this.db.getAll(this.name) + + bulkPut = (data: Iterable) => this.db.bulkPut(this.name, data) + + bulkDelete = (ids: Iterable) => this.db.bulkDelete(this.name, ids) +} diff --git a/src/lib/storage.ts b/src/lib/storage.ts deleted file mode 100644 index d0cad00..0000000 --- a/src/lib/storage.ts +++ /dev/null @@ -1,108 +0,0 @@ -import {reject, identity} from "@welshman/lib" -import {type StorageProvider} from "@welshman/store" -import {Preferences} from "@capacitor/preferences" -import {Encoding, Filesystem, Directory} from "@capacitor/filesystem" - -export class PreferencesStorageProvider implements StorageProvider { - p = Promise.resolve() - - get = async (key: string): Promise => { - const result = await Preferences.get({key}) - if (!result.value) return undefined - try { - return JSON.parse(result.value) - } catch (e) { - return undefined - } - } - - set = async (key: string, value: T): Promise => { - this.p = this.p.then(() => Preferences.set({key, value: JSON.stringify(value)})) - - await this.p - } - - clear = async () => { - this.p = this.p.then(() => Preferences.clear()) - - await this.p - } -} - -export const preferencesStorageProvider = new PreferencesStorageProvider() - -export type CollectionOptions = { - table: string - getId: (item: T) => string -} - -export class Collection { - constructor(readonly options: CollectionOptions) {} - - static clearAll = async (): Promise => { - const res = await Filesystem.readdir({ - path: "", - directory: Directory.Data, - }) - - await Promise.all( - res.files.map(file => - Filesystem.deleteFile({ - path: file.name, - directory: Directory.Data, - }), - ), - ) - } - - #path = () => `collection_${this.options.table}.json` - - get = async (): Promise => { - try { - const file = await Filesystem.readFile({ - path: this.#path(), - directory: Directory.Data, - encoding: Encoding.UTF8, - }) - - // Speed things up by parsing only once - return JSON.parse("[" + file.data.toString().split("\n").filter(identity).join(",") + "]") - } catch (err) { - // file doesn't exist, or isn't valid json - return [] - } - } - - set = (items: T[]) => - Filesystem.writeFile({ - path: this.#path(), - directory: Directory.Data, - encoding: Encoding.UTF8, - data: items.map(v => JSON.stringify(v)).join("\n"), - }) - - add = (items: T[]) => - Filesystem.appendFile({ - path: this.#path(), - directory: Directory.Data, - encoding: Encoding.UTF8, - data: "\n" + items.map(v => JSON.stringify(v)).join("\n"), - }) - - remove = async (ids: Set) => - this.set(reject(item => ids.has(this.options.getId(item)), await this.get())) - - update = async ({add, remove}: {add?: T[]; remove?: Set}) => { - if (remove && remove.size > 0) { - const items = reject(item => remove.has(this.options.getId(item)), await this.get()) - - if (add) { - items.push(...add) - } - - await this.set(items) - } else if (add && add.length > 0) { - await this.add(add) - } - } -} diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 3a5ab44..7dad0e2 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -20,21 +20,21 @@ import * as welshmanSigner from "@welshman/signer" import * as net from "@welshman/net" import * as app from "@welshman/app" - import {preferencesStorageProvider} from "@lib/storage" import AppContainer from "@app/components/AppContainer.svelte" import ModalContainer from "@app/components/ModalContainer.svelte" import {setupHistory} from "@app/util/history" import {setupTracking} from "@app/util/tracking" import {setupAnalytics} from "@app/util/analytics" import {authPolicy, trustPolicy, mostlyRestrictedPolicy} from "@app/util/policies" + import {kv, db} from "@app/core/storage" import {userSettingsValues} from "@app/core/state" import {syncApplicationData} from "@app/core/sync" - import {theme} from "@app/util/theme" - import {toast, pushToast} from "@app/util/toast" - import {initializePushNotifications} from "@app/util/push" import * as commands from "@app/core/commands" import * as requests from "@app/core/requests" import * as appState from "@app/core/state" + import {theme} from "@app/util/theme" + import {toast, pushToast} from "@app/util/toast" + import {initializePushNotifications} from "@app/util/push" import * as notifications from "@app/util/notifications" import * as storage from "@app/util/storage" import NewNotificationSound from "@src/app/components/NewNotificationSound.svelte" @@ -96,22 +96,28 @@ sync({ key: "pubkey", store: pubkey, - storage: preferencesStorageProvider, + storage: kv, }), sync({ key: "sessions", store: sessions, - storage: preferencesStorageProvider, + storage: kv, }), sync({ key: "shouldUnwrap", store: shouldUnwrap, - storage: preferencesStorageProvider, + storage: kv, }), ]) // Wait until data storage is initialized before syncing other stuff - unsubscribers.push(await storage.syncDataStores()) + await db.init(storage.adapters) + + // Close DB and restart when we're done + unsubscribers.push(() => { + db.close() + db.reset() + }) // Add our extra policies now that we're set up defaultSocketPolicies.push(...policies)