"use client"; const APP_HISTORY_KEY = "boss.app.history.v1"; const NATIVE_SESSION_KEY = "boss.native.session.v1"; const MAX_HISTORY_ENTRIES = 48; export type NativeSessionSnapshot = { restoreToken: string; account: string; displayName: string; expiresAt: string; lastSyncedAt: string; }; export type AppBackAction = | { mode: "history" } | { mode: "replace"; target: string } | { mode: "noop" }; function isBrowser() { return typeof window !== "undefined"; } function readJsonStorage(key: string, storage: Storage): T | null { try { const raw = storage.getItem(key); return raw ? (JSON.parse(raw) as T) : null; } catch { return null; } } function writeJsonStorage(key: string, value: unknown, storage: Storage) { try { storage.setItem(key, JSON.stringify(value)); } catch { // Ignore storage write failures in constrained webviews. } } function basePathFor(input: string) { return input.split("#")[0]?.split("?")[0] || "/"; } function fallbackForPath(input: string) { const pathname = basePathFor(input); if (pathname === "/auth/login") return null; if (pathname.startsWith("/auth/")) return "/auth/login"; if (pathname === "/conversations") return null; if (pathname.startsWith("/conversations/")) return "/conversations"; if (pathname === "/devices") { return input.includes("?") ? "/devices" : "/conversations"; } if (pathname.startsWith("/devices/")) return "/devices"; if (pathname === "/me") return "/conversations"; if (pathname.startsWith("/me/")) return "/me"; return "/conversations"; } export function currentAppLocation() { if (!isBrowser()) return "/"; return `${window.location.pathname}${window.location.search}${window.location.hash}`; } export function pushAppHistoryEntry(path: string) { if (!isBrowser()) return; const current = readJsonStorage(APP_HISTORY_KEY, window.sessionStorage) ?? []; const normalized = path || "/"; const next = current.filter((entry) => entry !== normalized); next.push(normalized); writeJsonStorage(APP_HISTORY_KEY, next.slice(-MAX_HISTORY_ENTRIES), window.sessionStorage); } export function popAppHistoryEntry(expectedPath?: string) { if (!isBrowser()) return; const current = readJsonStorage(APP_HISTORY_KEY, window.sessionStorage) ?? []; if (!current.length) return; if (expectedPath && current[current.length - 1] !== expectedPath) { writeJsonStorage( APP_HISTORY_KEY, current.filter((entry) => entry !== expectedPath), window.sessionStorage, ); return; } current.pop(); writeJsonStorage(APP_HISTORY_KEY, current, window.sessionStorage); } export function resolveAppBackAction(currentPath: string, explicitFallback?: string): AppBackAction { if (!isBrowser()) { return explicitFallback ? { mode: "replace", target: explicitFallback } : { mode: "noop" }; } const history = readJsonStorage(APP_HISTORY_KEY, window.sessionStorage) ?? []; const previous = [...history].reverse().find((entry) => entry !== currentPath); if (previous) { return { mode: "history" }; } const fallback = explicitFallback ?? fallbackForPath(currentPath); if (fallback && fallback !== currentPath) { return { mode: "replace", target: fallback }; } return { mode: "noop" }; } export async function isNativeBossApp() { if (!isBrowser()) return false; const { Capacitor } = await import("@capacitor/core"); return Capacitor.getPlatform() !== "web"; } async function preferencesApi() { if (!(await isNativeBossApp())) return null; const { Preferences } = await import("@capacitor/preferences"); return Preferences; } export async function persistNativeSessionSnapshot(snapshot: NativeSessionSnapshot) { const serialized = JSON.stringify(snapshot); const preferences = await preferencesApi(); if (preferences) { await preferences.set({ key: NATIVE_SESSION_KEY, value: serialized }); return; } if (isBrowser()) { window.localStorage.setItem(NATIVE_SESSION_KEY, serialized); } } export async function readNativeSessionSnapshot() { const preferences = await preferencesApi(); if (preferences) { const result = await preferences.get({ key: NATIVE_SESSION_KEY }); return result.value ? (JSON.parse(result.value) as NativeSessionSnapshot) : null; } if (!isBrowser()) return null; return readJsonStorage(NATIVE_SESSION_KEY, window.localStorage); } export async function clearNativeSessionSnapshot() { const preferences = await preferencesApi(); if (preferences) { await preferences.remove({ key: NATIVE_SESSION_KEY }); return; } if (isBrowser()) { window.localStorage.removeItem(NATIVE_SESSION_KEY); } }