// Copyright (C) 2023 Vaughn Nugent // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . import { defer } from "lodash"; import { RemovableRef, SerializerAsync, StorageLikeAsync, useStorageAsync, watchOnce } from "@vueuse/core"; import { type MaybeRefOrGetter, type WatchSource, isProxy, toRaw } from "vue"; import type { Watchable } from "./types"; export const waitForChange = []>>(source: [...T]):Promise => { return new Promise((resolve) => watchOnce(source, () => resolve())) } export const waitForChangeFn = []>>(source: [...T]) => { return (): Promise => { return new Promise((resolve) => watchOnce(source, () => resolve())) } } export const useStorage = (storage: any & chrome.storage.StorageArea, key: string, initialValue: MaybeRefOrGetter): RemovableRef => { const wrapper: StorageLikeAsync = { async getItem(key: string): Promise { const value = await storage.get(key) //pass the raw value to the serializer return value[key] as T; }, async setItem(key: string, value: any): Promise { //pass the raw value to storage await storage.set({ [key]: value }); }, async removeItem(key: string): Promise { await storage.remove(key); } } /** * Custom sealizer that passes the raw * values to the storage, the storage * wrapper above will store the raw values * as is. */ const serializer: SerializerAsync = { async read(value: any) { return value as T }, async write(value: any) { if (isProxy(value)) { return toRaw(value) } return value; } } return useStorageAsync(key, initialValue, wrapper, { serializer, deep: true, shallow: true }); } export const onWatchableChange = (watchable: Watchable, onChangeCallback: () => Promise, controls?: { immediate: boolean }) => { defer(async () => { if (controls?.immediate) { await onChangeCallback(); } while (true) { await watchable.waitForChange(); await onChangeCallback(); } }) }