diff --git a/src/index.ts b/src/index.ts index eae7b63..af84277 100644 --- a/src/index.ts +++ b/src/index.ts @@ -12,7 +12,7 @@ import { patchAssets, all, find, getAssetByID, getAssetByName, getAssetIDByName import initSettings from "@ui/settings"; import { fixTheme } from "@ui/fixTheme"; import { connectToDebugger, patchLogHook } from "@lib/debug"; -import { initPlugins, plugins, fetchPlugin, evalPlugin, stopPlugin, removePlugin, getSettings } from "@lib/plugins"; +import { plugins, fetchPlugin, evalPlugin, stopPlugin, removePlugin, getSettings } from "@lib/plugins"; console.log("Hello from Vendetta!"); @@ -58,7 +58,6 @@ async function init() { patchAssets(); patchLogHook(); fixTheme(); - initPlugins(); } catch (e: Error | any) { erroredOnLoad = true; alert(`Vendetta failed to initialize... ${e.stack || e.toString()}`); diff --git a/src/lib/plugins.ts b/src/lib/plugins.ts index 379fd90..66734cc 100644 --- a/src/lib/plugins.ts +++ b/src/lib/plugins.ts @@ -1,6 +1,6 @@ import { Indexable, PluginManifest, Plugin } from "@types"; -import { AsyncStorage } from "@metro/common"; import logger from "@lib/logger"; +import createStorage from "./storage"; type EvaledPlugin = { onLoad?(): void; @@ -8,31 +8,19 @@ type EvaledPlugin = { settings: JSX.Element; }; -const proxyValidator = { - get(target: object, key: string | symbol): any { - const orig = Reflect.get(target, key); +export const plugins = createStorage>("VENDETTA_PLUGINS", async function(parsed) { + for (let p of Object.keys(parsed)) { + const plugin: Plugin = parsed[p]; - if (typeof orig === "object" && orig !== null) { - return new Proxy(orig, proxyValidator); + if (parsed[p].update) { + await fetchPlugin(plugin.id); } else { - return orig; + plugins[p] = parsed[p]; } - }, - set(target: object, key: string | symbol, value: any) { - Reflect.set(target, key, value); - AsyncStorage.setItem("VENDETTA_PLUGINS", JSON.stringify(plugins)); - return true; - }, - - deleteProperty(target: object, key: string | symbol) { - Reflect.deleteProperty(target, key); - AsyncStorage.setItem("VENDETTA_PLUGINS", JSON.stringify(plugins)); - return true; + if (parsed[p].enabled && plugins[p]) startPlugin(p); } -} - -export const plugins: Indexable = new Proxy({}, proxyValidator); +}); const loadedPlugins: Indexable = {}; export async function fetchPlugin(id: string) { @@ -124,20 +112,3 @@ export function removePlugin(id: string) { } export const getSettings = (id: string) => loadedPlugins[id]?.settings; - -export const initPlugins = () => AsyncStorage.getItem("VENDETTA_PLUGINS").then(async function (v) { - if (!v) return; - const parsedPlugins: Indexable = JSON.parse(v); - - for (let p of Object.keys(parsedPlugins)) { - const plugin = parsedPlugins[p] - - if (parsedPlugins[p].update) { - await fetchPlugin(plugin.id); - } else { - plugins[p] = parsedPlugins[p]; - } - - if (parsedPlugins[p].enabled && plugins[p]) startPlugin(p); - } -}) diff --git a/src/lib/storage.ts b/src/lib/storage.ts new file mode 100644 index 0000000..818a80a --- /dev/null +++ b/src/lib/storage.ts @@ -0,0 +1,45 @@ +import { Indexable } from "@types"; +import { AsyncStorage } from "@metro/common"; + +// TODO: React hook? +// TODO: Clean up types, if necessary +export default function createStorage(storeName: string, onRestore?: (parsed: T) => void): T { + const internalStore: Indexable = {}; + + const proxyValidator = { + get(target: object, key: string | symbol): any { + const orig = Reflect.get(target, key); + + if (typeof orig === "object" && orig !== null) { + return new Proxy(orig, proxyValidator); + } else { + return orig; + } + }, + + set(target: object, key: string | symbol, value: any) { + Reflect.set(target, key, value); + AsyncStorage.setItem(storeName, JSON.stringify(internalStore)); + return true; + }, + + deleteProperty(target: object, key: string | symbol) { + Reflect.deleteProperty(target, key); + AsyncStorage.setItem(storeName, JSON.stringify(internalStore)); + return true; + } + } + + AsyncStorage.getItem(storeName).then(async function (v) { + if (!v) return; + const parsed: T & Indexable = JSON.parse(v); + + if (onRestore && typeof onRestore === "function") { + onRestore(parsed); + } else { + for (let p of Object.keys(parsed)) internalStore[p] = parsed[p]; + } + }) + + return new Proxy(internalStore, proxyValidator) as T; +} \ No newline at end of file