Skip to content

Commit

Permalink
add config to modconf
Browse files Browse the repository at this point in the history
  • Loading branch information
DerGoogler committed Feb 25, 2024
1 parent f16f1e1 commit 858457e
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 21 deletions.
2 changes: 1 addition & 1 deletion Website/src/activitys/ModConfPlaygroundActivity.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ const ModConfPlaygroundActivity = () => {
const { context, extra } = useActivity<PlaygroundExtra>();
const { strings } = useStrings();
const { modFS } = useModFS();
const [description, setDescription] = useNativeFileStorage(modFS("MODCONF_PLAYGROUND"), extra.defaultText || "", { json: false });
const [description, setDescription] = useNativeFileStorage(modFS("MODCONF_PLAYGROUND"), extra.defaultText || "");
const [errBoundKey, setErrBoundKey] = React.useState(0);

const isLargeScreen = useMediaQuery("(min-width:600px)");
Expand Down
1 change: 1 addition & 0 deletions Website/src/components/ConfigureView/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,7 @@ export const ConfigureView = React.forwardRef<any, { children: string; modid: st
parseCode(code),
true
)({
console: console,
log: log,
modid: props.modid,
modpath: (path: string) => `${format("MODULECWD")}/${path}`,
Expand Down
4 changes: 3 additions & 1 deletion Website/src/components/ConfigureView/libs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { Ansi } from "@Components/Ansi";
import { os } from "@Native/Os";
import { BuildConfig } from "@Native/BuildConfig";
import { useSettings } from "@Hooks/useSettings";
import { useNativeFileStorage } from "@Hooks/useNativeFileStorage";
import { ConfigProvider, useConfig, useNativeFileStorage } from "@Hooks/useNativeFileStorage";
import { useModFS } from "@Hooks/useModFS";
import PicturePreviewActivity from "@Activitys/PicturePreviewActivity";

Expand Down Expand Up @@ -76,6 +76,7 @@ export const libraries = [
{
name: "@mmrl/hooks",
__esModule: {
useConfig: useConfig,
useModFS: useModFS,
useActivity: useActivity,
useNativeProperties: useNativeProperties,
Expand All @@ -89,6 +90,7 @@ export const libraries = [
{
name: "@mmrl/providers",
__esModule: {
ConfigProvider: ConfigProvider,
StringsProvider: StringsProvider,
},
},
Expand Down
2 changes: 1 addition & 1 deletion Website/src/hooks/useModFS.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ export const useModFS = () => {
};

export const ModFSProvider = (props: React.PropsWithChildren) => {
const [modFS, setModFS] = useNativeFileStorage("/data/adb/mmrl/modfs.v7.json", INITIAL_MOD_CONF);
const [modFS, setModFS] = useNativeFileStorage("/data/adb/mmrl/modfs.v7.json", INITIAL_MOD_CONF, { loader: JSON });

const contextValue = React.useMemo(
() => ({
Expand Down
97 changes: 79 additions & 18 deletions Website/src/hooks/useNativeFileStorage.tsx
Original file line number Diff line number Diff line change
@@ -1,43 +1,52 @@
import { useCallback, useEffect, useState } from "react";
import { SetStateAction, useCallback, useEffect, useState } from "react";
import { useLog } from "./native/useLog";
import { SuFile } from "@Native/SuFile";
import { SetValue, parseJSON } from "./useNativeStorage";
import INI from "ini";
import YMAL from "yaml";
import { os } from "@Native/Os";
import { SetValue } from "./useNativeStorage";
import React from "react";

export function useNativeFileStorage<T>(key: string, initialValue: T, opt: { json: boolean } = { json: true }): [T, SetValue<T>] {
const log = useLog("useNativeStorage");
type Loader = typeof JSON | typeof INI | typeof YMAL | null;

const { json } = opt;
export function useNativeFileStorage<T = string>(
key: string,
initialValue: T,
opt: { loader: Loader } = { loader: null }
): [T, SetValue<T>] {
const { loader } = opt;

const file = new SuFile(key);

const readValue = useCallback((): T => {
if (typeof window === "undefined") {
return initialValue;
}

try {
return file.exist() ? (json ? (parseJSON(file.read()) as T) : (file.read() as T)) : initialValue;
if (file.exist()) {
if (loader) {
return loader.parse(file.read());
} else {
return file.read() as T;
}
} else {
return initialValue;
}
} catch (error) {
log.w(`Error reading file “${key}”: ${error}`);

return initialValue;
}
}, [initialValue, key]);

const [storedValue, setStoredValue] = useState<T>(readValue);

const setValue: SetValue<T> = (value) => {
if (typeof window === "undefined") {
log.w(`Tried setting localStorage key “${key}” even though environment is not a client`);
}

try {
const newValue = value instanceof Function ? value(storedValue) : value;
file.write(json ? JSON.stringify(newValue) : String(newValue));
if (loader) {
file.write((loader as any).stringify(newValue));
} else {
file.write(String(newValue));
}
setStoredValue(newValue);
} catch (error) {
log.w(`Error writing file “${key}”: ${error}`);
throw new Error(`Error writing file “${key}”: ${error}`);
}
};

Expand All @@ -47,3 +56,55 @@ export function useNativeFileStorage<T>(key: string, initialValue: T, opt: { jso

return [storedValue, setValue];
}

export interface ConfigContext {
config: object;
setConfig(key: string, state: SetStateAction<object>): void;
}

export const ConfigContext = React.createContext<ConfigContext>({
config: {},
setConfig(key: string, state: SetStateAction<object>) {},
});

export const useConfig = () => {
return React.useContext(ConfigContext);
};

export interface ConfigProvider extends React.PropsWithChildren {
loadFromFile: string;
loader: Loader;
initialConfig: object;
}

export const ConfigProvider = (props: ConfigProvider) => {
const { loadFromFile, loader = JSON, initialConfig } = props;

if (!loadFromFile) {
throw new TypeError('"loadFromFile" is undefined');
}

if (!initialConfig) {
throw new TypeError('"initialConfig" is undefined');
}

const [config, setConfig] = useNativeFileStorage<object>(loadFromFile, initialConfig, { loader: loader });

const contextValue = React.useMemo(
() => ({
config: config,
setConfig: (name, state) => {
setConfig((prev) => {
const newValue = state instanceof Function ? state(prev[name]) : state;
return {
...prev,
[name]: newValue,
};
});
},
}),
[config]
);

return <ConfigContext.Provider value={contextValue} children={props.children} />;
};

0 comments on commit 858457e

Please sign in to comment.