forked from phenom/healer-man
64 lines
1.9 KiB
TypeScript
64 lines
1.9 KiB
TypeScript
import type { ShellPhase } from "./types";
|
|
|
|
const HANDOFF_KEY = "healer-man.memory-reset.v1";
|
|
|
|
export interface MemoryResetHandoff {
|
|
readonly ownerId: string;
|
|
readonly characterId: string;
|
|
readonly phase: Extract<ShellPhase, "characters" | "main-menu" | "class-hall">;
|
|
}
|
|
|
|
interface HandoffStorage {
|
|
getItem(key: string): string | null;
|
|
setItem(key: string, value: string): void;
|
|
removeItem(key: string): void;
|
|
}
|
|
|
|
function browserStorage(): HandoffStorage | null {
|
|
try {
|
|
return typeof window === "undefined" ? null : window.sessionStorage;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
/** A full page reload is the browser's boundary for releasing imported modules. */
|
|
export function requestMemoryReset(handoff: MemoryResetHandoff): boolean {
|
|
if (import.meta.env.MODE === "test") return false;
|
|
const storage = browserStorage();
|
|
if (!storage) return false;
|
|
try {
|
|
storage.setItem(HANDOFF_KEY, JSON.stringify(handoff));
|
|
window.location.reload();
|
|
return true;
|
|
} catch {
|
|
try { storage.removeItem(HANDOFF_KEY); } catch { /* Storage may be disabled. */ }
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/** Consume once so a later ordinary reload never replays an old navigation. */
|
|
export function consumeMemoryReset(
|
|
ownerId: string,
|
|
characterIds: readonly string[],
|
|
storage: HandoffStorage | null = browserStorage(),
|
|
): MemoryResetHandoff | null {
|
|
if (!storage) return null;
|
|
let raw: string | null;
|
|
try {
|
|
raw = storage.getItem(HANDOFF_KEY);
|
|
storage.removeItem(HANDOFF_KEY);
|
|
} catch {
|
|
return null;
|
|
}
|
|
if (!raw) return null;
|
|
try {
|
|
const value = JSON.parse(raw) as Partial<MemoryResetHandoff>;
|
|
if (value.ownerId !== ownerId || !value.characterId || !characterIds.includes(value.characterId)) return null;
|
|
if (value.phase !== "characters" && value.phase !== "main-menu" && value.phase !== "class-hall") return null;
|
|
return value as MemoryResetHandoff;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|