// Capacitor chrome shim. The mobile foreground imports background modules that // were written for MV3, so this supplies the small chrome.* surface they touch. import { Preferences } from "@capacitor/preferences"; declare const __APP_VERSION__: string; type Listener void> = { addListener: (_listener: T) => void; removeListener: (_listener: T) => void; }; const sessionStore = new Map(); function noopListener void>(): Listener { return { addListener: () => {}, removeListener: () => {}, }; } async function keysFor(input: string | string[] | Record | null): Promise { if (input === null) { const result = await Preferences.keys(); return result.keys; } if (Array.isArray(input)) return input; if (typeof input === "string") return [input]; return Object.keys(input); } async function localGet(keys: string | string[] | Record | null): Promise> { const result: Record = {}; for (const key of await keysFor(keys)) { const { value } = await Preferences.get({ key }); if (value === null) continue; try { result[key] = JSON.parse(value); } catch { result[key] = value; } } return result; } async function localSet(items: Record): Promise { for (const [key, value] of Object.entries(items)) { await Preferences.set({ key, value: JSON.stringify(value) }); } } async function localRemove(keys: string | string[]): Promise { const keyArray = Array.isArray(keys) ? keys : [keys]; for (const key of keyArray) { await Preferences.remove({ key }); } } function sessionKeys(input: string | string[] | Record | null): string[] { if (input === null) return [...sessionStore.keys()]; if (Array.isArray(input)) return input; if (typeof input === "string") return [input]; return Object.keys(input); } const chromeShim = { runtime: { id: "peach-mobile", getManifest: () => ({ name: "Peach", version: typeof __APP_VERSION__ !== "undefined" ? __APP_VERSION__ : "0.0.0", manifest_version: 3, }), sendMessage: (_msg: unknown, cb?: (response: unknown) => void) => { const response = { ok: false, error: "NO_SERVICE_WORKER" }; cb?.(response); return Promise.resolve(response); }, onMessage: noopListener<(message: unknown) => void>(), connect: () => ({ disconnect: () => {}, onMessage: noopListener<(message: unknown) => void>(), onDisconnect: noopListener<() => void>(), postMessage: () => {}, }), lastError: null, }, storage: { local: { get: localGet, set: localSet, remove: localRemove, clear: () => Preferences.clear(), }, session: { get: async (keys: string | string[] | Record | null) => { const result: Record = {}; for (const key of sessionKeys(keys)) { if (sessionStore.has(key)) result[key] = sessionStore.get(key); } return result; }, set: async (items: Record) => { for (const [key, value] of Object.entries(items)) { sessionStore.set(key, value); } }, remove: async (keys: string | string[]) => { const keyArray = Array.isArray(keys) ? keys : [keys]; for (const key of keyArray) sessionStore.delete(key); }, clear: async () => { sessionStore.clear(); }, }, onChanged: noopListener<(changes: Record, areaName: string) => void>(), }, alarms: { clear: () => {}, create: () => {}, onAlarm: noopListener<(alarm: { name: string }) => void>(), }, idle: { setDetectionInterval: () => {}, onStateChanged: noopListener<(state: string) => void>(), }, tabs: { query: (_query: unknown, cb?: (tabs: any[]) => void) => { cb?.([]); return Promise.resolve([]); }, sendMessage: () => Promise.resolve(undefined), create: () => Promise.resolve(undefined), onActivated: noopListener<() => void>(), onUpdated: noopListener<() => void>(), }, action: { openPopup: () => Promise.resolve(), setBadgeText: () => Promise.resolve(), setBadgeBackgroundColor: () => Promise.resolve(), }, scripting: { executeScript: () => Promise.resolve(), }, }; (window as any).chrome = chromeShim;