1import { DEFAULT_RELAY_URL, normalizeRelayUrl } from "../shared/rendezvous";2import { setRelayUrlForAllPairedDevices } from "./paired-devices";3456789101112131415export type SyncMode = "public" | "private" | "off";1617export interface SyncSettings {18 mode: SyncMode;19 2021222324 relayUrl: string;25}2627const RELAY_URL_KEY = "peach_relay_url_v1";28const SYNC_MODE_KEY = "peach_sync_mode_v1";2930const LEGACY_LAN_ONLY_KEY = "peach_sync_lan_only_v1";3132export async function getSyncSettings(): Promise<SyncSettings> {33 try {34 const values = (await chrome.storage.local.get([35 RELAY_URL_KEY,36 SYNC_MODE_KEY,37 LEGACY_LAN_ONLY_KEY,38 ])) as Record<string, unknown>;3940 const storedUrl =41 typeof values[RELAY_URL_KEY] === "string"42 ? safeNormalize(values[RELAY_URL_KEY] as string)43 : DEFAULT_RELAY_URL;4445 const stored = values[SYNC_MODE_KEY];46 if (stored === "public" || stored === "private" || stored === "off") {47 return { mode: stored, relayUrl: relayFor(stored, storedUrl) };48 }4950 51 52 53 54 const mode: SyncMode =55 values[LEGACY_LAN_ONLY_KEY] === true56 ? "off"57 : storedUrl === DEFAULT_RELAY_URL58 ? "public"59 : "private";60 return { mode, relayUrl: relayFor(mode, storedUrl) };61 } catch {62 return { mode: "public", relayUrl: DEFAULT_RELAY_URL };63 }64}6566676869707172export function isPrivateRelayUnconfigured(settings: SyncSettings): boolean {73 return settings.mode === "private" && settings.relayUrl === DEFAULT_RELAY_URL;74}75767778798081export function relayInForce(settings: SyncSettings): string {82 if (settings.mode === "off") throw new Error("sync_disabled");83 if (isPrivateRelayUnconfigured(settings)) throw new Error("private_relay_unset");84 return settings.relayUrl;85}8687export async function setSyncMode(mode: SyncMode): Promise<SyncSettings> {88 const current = await getSyncSettings();89 const next: SyncSettings = { mode, relayUrl: relayFor(mode, current.relayUrl) };90 91 92 93 94 if (mode !== "off" && !isPrivateRelayUnconfigured(next)) {95 await setRelayUrlForAllPairedDevices(next.relayUrl);96 }97 await chrome.storage.local.set({ [SYNC_MODE_KEY]: mode, [RELAY_URL_KEY]: next.relayUrl });98 return next;99}100101102103104105106107108export async function setRelayUrl(input: string): Promise<SyncSettings> {109 const relayUrl = normalizeRelayUrl(input);110 const mode: SyncMode = relayUrl === DEFAULT_RELAY_URL ? "public" : "private";111 await setRelayUrlForAllPairedDevices(relayUrl);112 await chrome.storage.local.set({ [RELAY_URL_KEY]: relayUrl, [SYNC_MODE_KEY]: mode });113 return { mode, relayUrl };114}115116function relayFor(mode: SyncMode, configured: string): string {117 return mode === "public" ? DEFAULT_RELAY_URL : configured;118}119120function safeNormalize(input: string): string {121 try {122 return normalizeRelayUrl(input);123 } catch {124 return DEFAULT_RELAY_URL;125 }126}