[Global] Loader config and identity (#17)

* [TS] Add definition for DCDFileManager

* [Storage] Introduce backends

* [Settings] Add loader config

* [TS] Update storage definitions

* [TS] Update loader config and identity types

* [Loader] Expose loader config and identity

* [UI] Actually update UI for the new loader config fields
This commit is contained in:
redstonekasi 2023-02-06 08:48:55 +01:00 committed by GitHub
parent cfccd5f5b2
commit 1840577fb5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 154 additions and 19 deletions

View file

@ -1,5 +1,5 @@
import { Indexable, PluginManifest, Plugin } from "@types";
import { awaitSyncWrapper, createStorage, wrapSync } from "@lib/storage";
import { awaitSyncWrapper, createMMKVBackend, createStorage, wrapSync } from "@lib/storage";
import safeFetch from "@utils/safeFetch";
import logger from "@lib/logger";
@ -11,7 +11,7 @@ type EvaledPlugin = {
settings: JSX.Element;
};
export const plugins = wrapSync(createStorage<Indexable<Plugin>>("VENDETTA_PLUGINS"));
export const plugins = wrapSync(createStorage<Indexable<Plugin>>(createMMKVBackend("VENDETTA_PLUGINS")));
const loadedPlugins: Indexable<EvaledPlugin> = {};
export async function fetchPlugin(id: string) {
@ -61,7 +61,7 @@ export async function evalPlugin(plugin: Plugin) {
plugin: {
manifest: plugin.manifest,
// Wrapping this with wrapSync is NOT an option.
storage: await createStorage<Indexable<any>>(plugin.id),
storage: await createStorage<Indexable<any>>(createMMKVBackend(plugin.id)),
}
};
const pluginString = `vendetta=>{return ${plugin.js}}\n//# sourceURL=${plugin.id}`;

View file

@ -1,4 +1,5 @@
import { createStorage, wrapSync } from "@lib/storage";
import { Settings } from "@types";
import { createFileBackend, createMMKVBackend, createStorage, wrapSync } from "@lib/storage";
import { LoaderConfig, Settings } from "@types";
export default wrapSync(createStorage<Settings>("VENDETTA_SETTINGS"));
export default wrapSync(createStorage<Settings>(createMMKVBackend("VENDETTA_SETTINGS")));
export const loaderConfig = wrapSync(createStorage<LoaderConfig>(createFileBackend("vendetta_loader.json")));

View file

@ -0,0 +1,24 @@
import { DCDFileManager, MMKVManager, StorageBackend } from "@types";
import { ReactNative as RN } from "@metro/hoist";
const MMKVManager = RN.NativeModules.MMKVManager as MMKVManager;
const DCDFileManager = RN.NativeModules.DCDFileManager as DCDFileManager;
const filePathFixer: (file: string) => string = RN.Platform.select({
default: (f) => f,
ios: (f) => `Documents/${f}`,
});
export const createMMKVBackend = (store: string): StorageBackend => ({
get: async function() {
return JSON.parse((await MMKVManager.getItem(store)) ?? "{}");
},
set: (data) => MMKVManager.setItem(store, JSON.stringify(data)),
});
export const createFileBackend = (file: string): StorageBackend => ({
get: async function() {
return JSON.parse((await DCDFileManager.readFile(`${DCDFileManager.getConstants().DocumentsDirPath}/${file}`, "utf8")) ?? "{}");
},
set: (data) => void DCDFileManager.writeFile("documents", filePathFixer(file), JSON.stringify(data), "utf8"),
});

View file

@ -1,6 +1,6 @@
import { Emitter, MMKVManager } from "@types";
import { Emitter, MMKVManager, StorageBackend } from "@types";
import { ReactNative as RN } from "@metro/hoist";
import createEmitter from "./emitter";
import createEmitter from "../emitter";
const MMKVManager = RN.NativeModules.MMKVManager as MMKVManager;
@ -79,11 +79,11 @@ export function useProxy<T>(storage: T): T {
return storage;
}
export async function createStorage<T>(storeName: string): Promise<Awaited<T>> {
const data = JSON.parse((await MMKVManager.getItem(storeName)) ?? "{}");
export async function createStorage<T>(backend: StorageBackend): Promise<Awaited<T>> {
const data = await backend.get();
const { proxy, emitter } = createProxy(data);
const handler = () => MMKVManager.setItem(storeName, JSON.stringify(proxy));
const handler = () => backend.set(proxy);
emitter.on("SET", handler);
emitter.on("DEL", handler);
@ -115,3 +115,5 @@ export function wrapSync<T extends Promise<any>>(store: T): Awaited<T> {
}
export const awaitSyncWrapper = (store: any) => new Promise<void>((res) => store[syncAwaitSymbol](res));
export * from "./backends";

View file

@ -1,7 +1,7 @@
import { VendettaObject } from "@types";
import patcher from "@lib/patcher";
import logger from "@lib/logger";
import settings from "@lib/settings";
import settings, { loaderConfig } from "@lib/settings";
import * as constants from "@lib/constants";
import * as debug from "@lib/debug";
import * as plugins from "@lib/plugins";
@ -37,6 +37,10 @@ export default async function windowObject(unloads: any[]): Promise<VendettaObje
commands: without(commands, "patchCommands"),
storage,
settings,
loader: {
identity: window.__vendetta_loader,
config: loaderConfig,
},
logger,
version: debug.versionHash,
unload: () => {
@ -45,4 +49,4 @@ export default async function windowObject(unloads: any[]): Promise<VendettaObje
delete window.vendetta;
}
}
}
}