import { BLE } from "@components/PageComponents/Connect/BLE.tsx"; import { HTTP } from "@components/PageComponents/Connect/HTTP.tsx"; import { Serial } from "@components/PageComponents/Connect/Serial.tsx"; import { Dialog, DialogClose, DialogContent, DialogHeader, DialogTitle, } from "@components/UI/Dialog.tsx"; import { Tabs, TabsContent, TabsList, TabsTrigger, } from "@components/UI/Tabs.tsx"; import { type BrowserFeature, useBrowserFeatureDetection, } from "@core/hooks/useBrowserFeatureDetection.ts"; import { AlertCircle } from "lucide-react"; import { Trans, useTranslation } from "react-i18next"; import { Link } from "../UI/Typography/Link.tsx"; export interface TabElementProps { closeDialog: () => void; } export interface TabManifest { id: "HTTP" | "BLE" | "Serial"; label: string; element: React.FC; isDisabled: boolean; } export interface NewDeviceProps { open: boolean; onOpenChange: (open: boolean) => void; } interface FeatureErrorProps { missingFeatures: BrowserFeature[]; tabId: "HTTP" | "BLE" | "Serial"; } const errors: Record = { "Web Bluetooth": { href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_Bluetooth_API#browser_compatibility", i18nKey: "newDeviceDialog.validation.requiresWebBluetooth", }, "Web Serial": { href: "https://developer.mozilla.org/en-US/docs/Web/API/Web_Serial_API#browser_compatibility", i18nKey: "newDeviceDialog.validation.requiresWebSerial", }, "Secure Context": { href: "https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts", i18nKey: "newDeviceDialog.validation.requiresSecureContext", }, }; const ErrorMessage = ({ missingFeatures, tabId }: FeatureErrorProps) => { if (missingFeatures.length === 0) { return null; } const browserFeatures = missingFeatures.filter( (feature) => feature !== "Secure Context", ); const needsSecureContext = missingFeatures.includes("Secure Context"); const needsFeature = tabId === "BLE" && browserFeatures.includes("Web Bluetooth") ? "Web Bluetooth" : tabId === "Serial" && browserFeatures.includes("Web Serial") ? "Web Serial" : undefined; return (
{needsFeature && ( , ]} /> )} {needsFeature && needsSecureContext && " "} {needsSecureContext && ( 0 ? "newDeviceDialog.validation.additionallyRequiresSecureContext" : "newDeviceDialog.validation.requiresSecureContext" } components={{ "0": ( ), }} /> )}
); }; export const NewDeviceDialog = ({ open, onOpenChange }: NewDeviceProps) => { const { t } = useTranslation("dialog"); const { unsupported } = useBrowserFeatureDetection(); const tabs: TabManifest[] = [ { id: "HTTP", label: t("newDeviceDialog.tabHttp"), element: HTTP, isDisabled: false, }, { id: "BLE", label: t("newDeviceDialog.tabBluetooth"), element: BLE, isDisabled: unsupported.includes("Web Bluetooth") || unsupported.includes("Secure Context"), }, { id: "Serial", label: t("newDeviceDialog.tabSerial"), element: Serial, isDisabled: unsupported.includes("Web Serial") || unsupported.includes("Secure Context"), }, ]; return ( {t("newDeviceDialog.title")} {tabs.map((tab) => ( {tab.label} ))} {tabs.map((tab) => (
{tab.id !== "HTTP" && tab.isDisabled ? ( ) : ( onOpenChange(false)} /> )}
))}
); };