import { createSignal, For, onCleanup, onMount, Show } from "solid-js"; import { sendMessage } from "../App"; import type { DiscoveredPeer, PairedDevice, PairingStep } from "../../shared/sync-types"; interface SyncPairingProps { onClose: () => void; onPaired: (device: PairedDevice) => void; } function Spinner() { return ; } export function SyncPairingView(props: SyncPairingProps) { const [step, setStep] = createSignal({ stage: "idle" }); const [discoveredPeers, setDiscoveredPeers] = createSignal([]); const [discoveryActive, setDiscoveryActive] = createSignal(false); const [discoveryError, setDiscoveryError] = createSignal(null); const [pairingPeerId, setPairingPeerId] = createSignal(null); onMount(() => { void startDiscovery(); }); onCleanup(() => { if (discoveryActive()) void sendMessage({ type: "STOP_PEER_DISCOVERY" }); }); function handleRuntimeMessage(msg: unknown) { const m = msg as { type?: string; peer?: DiscoveredPeer; deviceId?: string }; if (m?.type === "SYNC_PEER_DISCOVERED" && m.peer) { const peer = m.peer; setDiscoveredPeers((prev) => { if (prev.some((p) => p.deviceId === peer.deviceId)) return prev; return [...prev, peer]; }); } if (m?.type === "SYNC_PEER_LOST" && m.deviceId) { const id = m.deviceId; setDiscoveredPeers((prev) => prev.filter((p) => p.deviceId !== id)); } } async function startDiscovery() { chrome.runtime.onMessage.addListener(handleRuntimeMessage); onCleanup(() => chrome.runtime.onMessage.removeListener(handleRuntimeMessage)); const res = await sendMessage({ type: "START_PEER_DISCOVERY" }); const response = res as { ok: boolean; error?: string }; if (response.ok) { setDiscoveryActive(true); setDiscoveryError(null); } else { setDiscoveryError(response.error ?? "discovery_failed"); } } async function handlePairWithPeer(peer: DiscoveredPeer) { setPairingPeerId(peer.deviceId); setStep({ stage: "connecting", peerName: peer.deviceName }); const res = await sendMessage({ type: "INITIATE_PAIR_WITH_PEER", payload: { peer }, }); const response = res as { ok: boolean; error?: string }; setPairingPeerId(null); if (!response.ok) { setStep({ stage: "error", message: response.error ?? "pair_failed" }); return; } const paired: PairedDevice = { deviceId: peer.deviceId, displayName: peer.deviceName, x25519PublicKey: peer.x25519PublicKey, pairedAt: Date.now(), }; setStep({ stage: "done", device: paired }); props.onPaired(paired); } return (
add a device

Add a device

{discoveryError() === "pro_required" ? "Sync requires Peach Pro." : "Native sync host is not installed yet."}

Searching for Peach on your local network…

{(peer) => (
{peer.deviceName} {peer.alreadyPaired ? "Already paired ✓" : "Found on network"}
)}

Open Peach on the other device. Both devices need to be on the same WiFi network.

{step().stage === "connecting" ? "Connecting…" : "Verifying…"}

Paired!

{(step() as { stage: "done"; device: PairedDevice }).device.displayName}

Pairing failed

{(step() as { stage: "error"; message: string }).message}

); }