1234import { Preferences } from "@capacitor/preferences";56type Listener<T extends (...args: any[]) => void> = {7 addListener: (_listener: T) => void;8 removeListener: (_listener: T) => void;9};1011const sessionStore = new Map<string, unknown>();1213function noopListener<T extends (...args: any[]) => void>(): Listener<T> {14 return {15 addListener: () => {},16 removeListener: () => {},17 };18}1920async function keysFor(input: string | string[] | Record<string, unknown> | null): Promise<string[]> {21 if (input === null) {22 const result = await Preferences.keys();23 return result.keys;24 }25 if (Array.isArray(input)) return input;26 if (typeof input === "string") return [input];27 return Object.keys(input);28}2930async function localGet(keys: string | string[] | Record<string, unknown> | null): Promise<Record<string, unknown>> {31 const result: Record<string, unknown> = {};32 for (const key of await keysFor(keys)) {33 const { value } = await Preferences.get({ key });34 if (value === null) continue;35 try {36 result[key] = JSON.parse(value);37 } catch {38 result[key] = value;39 }40 }41 return result;42}4344async function localSet(items: Record<string, unknown>): Promise<void> {45 for (const [key, value] of Object.entries(items)) {46 await Preferences.set({ key, value: JSON.stringify(value) });47 }48}4950async function localRemove(keys: string | string[]): Promise<void> {51 const keyArray = Array.isArray(keys) ? keys : [keys];52 for (const key of keyArray) {53 await Preferences.remove({ key });54 }55}5657function sessionKeys(input: string | string[] | Record<string, unknown> | null): string[] {58 if (input === null) return [...sessionStore.keys()];59 if (Array.isArray(input)) return input;60 if (typeof input === "string") return [input];61 return Object.keys(input);62}6364const chromeShim = {65 runtime: {66 id: "peach-mobile",67 sendMessage: (_msg: unknown, cb?: (response: unknown) => void) => {68 const response = { ok: false, error: "NO_SERVICE_WORKER" };69 cb?.(response);70 return Promise.resolve(response);71 },72 onMessage: noopListener<(message: unknown) => void>(),73 connect: () => ({74 disconnect: () => {},75 onMessage: noopListener<(message: unknown) => void>(),76 onDisconnect: noopListener<() => void>(),77 postMessage: () => {},78 }),79 lastError: null,80 },81 storage: {82 local: {83 get: localGet,84 set: localSet,85 remove: localRemove,86 clear: () => Preferences.clear(),87 },88 session: {89 get: async (keys: string | string[] | Record<string, unknown> | null) => {90 const result: Record<string, unknown> = {};91 for (const key of sessionKeys(keys)) {92 if (sessionStore.has(key)) result[key] = sessionStore.get(key);93 }94 return result;95 },96 set: async (items: Record<string, unknown>) => {97 for (const [key, value] of Object.entries(items)) {98 sessionStore.set(key, value);99 }100 },101 remove: async (keys: string | string[]) => {102 const keyArray = Array.isArray(keys) ? keys : [keys];103 for (const key of keyArray) sessionStore.delete(key);104 },105 clear: async () => {106 sessionStore.clear();107 },108 },109 onChanged: noopListener<(changes: Record<string, unknown>, areaName: string) => void>(),110 },111 alarms: {112 clear: () => {},113 create: () => {},114 onAlarm: noopListener<(alarm: { name: string }) => void>(),115 },116 idle: {117 setDetectionInterval: () => {},118 onStateChanged: noopListener<(state: string) => void>(),119 },120 tabs: {121 query: (_query: unknown, cb?: (tabs: any[]) => void) => {122 cb?.([]);123 return Promise.resolve([]);124 },125 sendMessage: () => Promise.resolve(undefined),126 create: () => Promise.resolve(undefined),127 onActivated: noopListener<() => void>(),128 onUpdated: noopListener<() => void>(),129 },130 action: {131 openPopup: () => Promise.resolve(),132 setBadgeText: () => Promise.resolve(),133 setBadgeBackgroundColor: () => Promise.resolve(),134 },135 scripting: {136 executeScript: () => Promise.resolve(),137 },138};139140(window as any).chrome = chromeShim;