feat(electron): onboarding at first launch logic for client and web (#5183)

- Added a simple abstraction of persistent storage class.
- Different persistence solutions are provided for web and client.
    - web: stored in localStorage
    - client: stored in the application directory as `.json` file
- Define persistent app-config schema
- Add a new hook that can interactive with persistent-app-config reactively
This commit is contained in:
Cats Juice
2023-12-19 07:17:54 +00:00
parent e0d328676d
commit 15dd20ef48
32 changed files with 470 additions and 29 deletions

View File

@@ -0,0 +1,83 @@
import {
type AppConfigSchema,
AppConfigStorage,
defaultAppConfig,
} from '@toeverything/infra/app-config-storage';
import { type Dispatch, useEffect, useState } from 'react';
import { useMemo } from 'react';
/**
* Helper class to get/set app config from main process
*/
class AppConfigProxy {
value: AppConfigSchema = defaultAppConfig;
async getSync(): Promise<AppConfigSchema> {
return (this.value = await window.apis.configStorage.get());
}
async setSync(): Promise<void> {
await window.apis.configStorage.set(this.value);
}
get(): AppConfigSchema {
return this.value;
}
set(data: AppConfigSchema) {
this.value = data;
this.setSync().catch(console.error);
}
}
export const appConfigProxy = new AppConfigProxy();
const storage = environment.isDesktop
? new AppConfigStorage({
config: defaultAppConfig,
get: () => appConfigProxy.get(),
set: v => appConfigProxy.set(v),
})
: new AppConfigStorage({
config: defaultAppConfig,
get: () => JSON.parse(localStorage.getItem('app_config') ?? 'null'),
set: config => localStorage.setItem('app_config', JSON.stringify(config)),
});
export const appConfigStorage = storage;
export function useAppConfigStorage(): [
AppConfigSchema,
Dispatch<AppConfigSchema>,
];
export function useAppConfigStorage(
key: keyof AppConfigSchema
): [AppConfigSchema[typeof key], Dispatch<AppConfigSchema[typeof key]>];
/**
* Get reactive app config
* @param key
* @returns
*/
export function useAppConfigStorage(key?: keyof AppConfigSchema) {
const [_config, _setConfig] = useState(storage.get());
useEffect(() => {
storage.set(_config);
}, [_config]);
const value = useMemo(() => (key ? _config[key] : _config), [_config, key]);
const setValue = useMemo(() => {
if (key) {
return (value: AppConfigSchema[typeof key]) => {
_setConfig(cfg => ({ ...cfg, [key]: value }));
};
} else {
return (config: AppConfigSchema) => {
_setConfig(config);
};
}
}, [_setConfig, key]);
return [value, setValue];
}