mirror of
https://github.com/k1tbyte/Wand-Enhancer.git
synced 2026-08-28 17:01:04 +00:00
refactor(web-panel): update architecture + cheat i18n
Reorganize the panel around product capabilities and integrate the remote i18n feature from origin/master into the new structure. - Restructure src into capability features (app, trainer, library, remote-session, appearance, shared); move the bridge to bridge/src. - Add lingui-based UI localization and wrap remaining user-facing strings (Trans / msg macros); fix the 'END В·' mojibake. - Port WeMod cheat-metadata i18n: capture the access token from the snapshot's renderer in the bridge and fetch localized trainer_meta in remote-session.i18n; guarantee snapshot sync on token failure. - Wire vitest to the app's lingui/preact pipeline (mergeConfig).
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
import type { TrainerSummary } from '../../protocol/messages';
|
||||
|
||||
type Reviver<T> = (raw: unknown) => T | null;
|
||||
|
||||
function getStore(): Storage | null {
|
||||
return typeof window === 'undefined' ? null : window.localStorage;
|
||||
}
|
||||
|
||||
export function getTrainerStorageId(trainer: TrainerSummary | null | undefined): string | null {
|
||||
if (!trainer) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const id = trainer.gameId?.trim() || trainer.titleId?.trim() || trainer.trainerId?.trim();
|
||||
return id || null;
|
||||
}
|
||||
|
||||
export function loadJson<T>(key: string | null, revive: Reviver<T>, fallback: T): T {
|
||||
const store = getStore();
|
||||
if (!key || !store) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
try {
|
||||
const raw = store.getItem(key);
|
||||
if (!raw) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
return revive(JSON.parse(raw) as unknown) ?? fallback;
|
||||
} catch {
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
export function saveJson(key: string | null, value: unknown, isEmpty: (value: unknown) => boolean): void {
|
||||
const store = getStore();
|
||||
if (!key || !store) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
if (isEmpty(value)) {
|
||||
store.removeItem(key);
|
||||
return;
|
||||
}
|
||||
|
||||
store.setItem(key, JSON.stringify(value));
|
||||
} catch {
|
||||
// localStorage quota / serialization errors are non-critical for this UI.
|
||||
}
|
||||
}
|
||||
|
||||
export function loadStringSet(key: string | null): Record<string, true> {
|
||||
return loadJson<Record<string, true>>(
|
||||
key,
|
||||
(raw) => {
|
||||
if (!Array.isArray(raw)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const result: Record<string, true> = {};
|
||||
for (const value of raw) {
|
||||
if (typeof value === 'string' && value.length > 0) {
|
||||
result[value] = true;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
},
|
||||
{},
|
||||
);
|
||||
}
|
||||
|
||||
export function saveStringSet(key: string | null, value: Record<string, true>): void {
|
||||
const ids = Object.keys(value);
|
||||
saveJson(key, ids, () => ids.length === 0);
|
||||
}
|
||||
Reference in New Issue
Block a user