import { useCallback } from "react"; import { ActivityIndicator, Image, Text, TextInput, View } from "react-native"; import * as Clipboard from "expo-clipboard"; import * as QRCode from "qrcode"; import { useQuery } from "@tanstack/react-query"; import { StyleSheet, useUnistyles } from "react-native-unistyles"; import { RotateCw, Copy, Check } from "lucide-react-native"; import { settingsStyles } from "@/styles/settings"; import { Button } from "@/components/ui/button"; import { getDesktopDaemonPairing, shouldUseDesktopDaemon } from "@/desktop/daemon/desktop-daemon"; import { useState } from "react"; export function PairDeviceSection() { const { theme } = useUnistyles(); const showSection = shouldUseDesktopDaemon(); const [copied, setCopied] = useState(false); const pairingQuery = useQuery({ queryKey: ["desktop-daemon-pairing"], queryFn: getDesktopDaemonPairing, enabled: showSection, staleTime: 5 * 60 * 1000, retry: 1, }); const qrQuery = useQuery({ queryKey: ["desktop-daemon-pairing-qr", pairingQuery.data?.url], queryFn: () => QRCode.toDataURL(pairingQuery.data!.url!, { errorCorrectionLevel: "M", margin: 1, width: 480, }), enabled: !!pairingQuery.data?.url, staleTime: Infinity, }); const handleCopyLink = useCallback(async () => { if (!pairingQuery.data?.url) return; await Clipboard.setStringAsync(pairingQuery.data.url); setCopied(true); setTimeout(() => setCopied(false), 2000); }, [pairingQuery.data?.url]); if (!showSection) return null; return ( {pairingQuery.isPending ? ( Loading pairing offer… ) : pairingQuery.isError ? ( {pairingQuery.error instanceof Error ? pairingQuery.error.message : "Failed to load pairing offer."} ) : !pairingQuery.data?.url ? ( {pairingQuery.data?.relayEnabled === false ? "Relay is not enabled. Enable relay to pair a device." : "Pairing offer unavailable."} ) : ( Scan this QR code with Paseo on your phone, or copy the link below. {qrQuery.data ? ( ) : qrQuery.isError ? ( QR code unavailable. ) : ( )} )} ); } const styles = StyleSheet.create((theme) => ({ centered: { alignItems: "center", justifyContent: "center", gap: theme.spacing[3], paddingVertical: theme.spacing[6], paddingHorizontal: theme.spacing[4], }, content: { gap: theme.spacing[3], padding: theme.spacing[4], }, hint: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.xs, textAlign: "center", }, qrContainer: { alignItems: "center", justifyContent: "center", alignSelf: "center", width: 320, height: 320, borderRadius: theme.borderRadius.lg, borderWidth: 1, borderColor: theme.colors.border, backgroundColor: theme.colors.surface0, padding: theme.spacing[2], }, qrImage: { width: "100%", height: "100%", }, linkRow: { flexDirection: "row", alignItems: "center", gap: theme.spacing[2], }, inputWrapper: { flex: 1, borderRadius: theme.borderRadius.md, borderWidth: 1, borderColor: theme.colors.border, backgroundColor: theme.colors.surface0, overflow: "hidden", }, linkInput: { color: theme.colors.foregroundMuted, fontSize: theme.fontSize.xs, paddingVertical: theme.spacing[2], paddingHorizontal: theme.spacing[3], outlineStyle: "none", } as any, }));