// 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();
}
})
}