import { useTranslation } from "react-i18next"; import { Card, CardContent } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; import ActivityIndicator from "@/components/indicators/activity-indicator"; import { FaCopy, FaCheck } from "react-icons/fa"; import { LuX } from "react-icons/lu"; import { CiCircleAlert } from "react-icons/ci"; import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"; import { useState } from "react"; import { toast } from "sonner"; import type { OnvifProbeResponse, OnvifRtspCandidate, TestResult, CandidateTestMap, } from "@/types/cameraWizard"; import { FaCircleCheck } from "react-icons/fa6"; import { cn } from "@/lib/utils"; type OnvifProbeResultsProps = { isLoading: boolean; isError: boolean; error?: string; probeResult?: OnvifProbeResponse; onRetry: () => void; selectedUris?: string[]; testCandidate?: (uri: string) => void; candidateTests?: CandidateTestMap; testingCandidates?: Record; }; export default function OnvifProbeResults({ isLoading, isError, error, probeResult, onRetry, selectedUris, testCandidate, candidateTests, testingCandidates, }: OnvifProbeResultsProps) { const { t } = useTranslation(["views/settings"]); const [copiedUri, setCopiedUri] = useState(null); const handleCopyUri = (uri: string) => { navigator.clipboard.writeText(uri); setCopiedUri(uri); toast.success(t("cameraWizard.step2.uriCopied")); setTimeout(() => setCopiedUri(null), 2000); }; if (isLoading) { return (

{t("cameraWizard.step2.probingDevice")}

); } if (isError) { return (
{t("cameraWizard.step2.probeError")} {error && {error}}
); } if (!probeResult?.success) { return (
{t("cameraWizard.step2.probeNoSuccess")} {probeResult?.message && ( {probeResult.message} )}
); } const rtspCandidates = (probeResult.rtsp_candidates || []).filter( (c) => c.source === "GetStreamUri", ); if (probeResult?.success && rtspCandidates.length === 0) { return (
{t("cameraWizard.step2.noRtspCandidates")}
); } return ( <>
{probeResult?.success && (
{t("cameraWizard.step2.probeSuccessful")}
)}
{t("cameraWizard.step2.deviceInfo")}
{probeResult.manufacturer && (
{t("cameraWizard.step2.manufacturer")}: {" "} {probeResult.manufacturer}
)} {probeResult.model && (
{t("cameraWizard.step2.model")}: {" "} {probeResult.model}
)} {probeResult.firmware_version && (
{t("cameraWizard.step2.firmware")}: {" "} {probeResult.firmware_version}
)} {probeResult.profiles_count !== undefined && (
{t("cameraWizard.step2.profiles")}: {" "} {probeResult.profiles_count}
)} {probeResult.ptz_supported !== undefined && (
{t("cameraWizard.step2.ptzSupport")}: {" "} {probeResult.ptz_supported ? t("yes", { ns: "common" }) : t("no", { ns: "common" })}
)} {probeResult.ptz_supported && probeResult.autotrack_supported && (
{t("cameraWizard.step2.autotrackingSupport")}: {" "} {t("yes", { ns: "common" })}
)} {probeResult.ptz_supported && probeResult.presets_count !== undefined && (
{t("cameraWizard.step2.presets")}: {" "} {probeResult.presets_count}
)}
{rtspCandidates.length > 0 && (
{t("cameraWizard.step2.rtspCandidates")}
{t("cameraWizard.step2.rtspCandidatesDescription")}
{rtspCandidates.map((candidate, idx) => { const isSelected = !!selectedUris?.includes(candidate.uri); const candidateTest = candidateTests?.[candidate.uri]; const isTesting = testingCandidates?.[candidate.uri]; return ( handleCopyUri(candidate.uri)} isSelected={isSelected} testCandidate={testCandidate} candidateTest={candidateTest} isTesting={isTesting} /> ); })}
)}
); } type CandidateItemProps = { candidate: OnvifRtspCandidate; index?: number; copiedUri: string | null; onCopy: () => void; isSelected?: boolean; testCandidate?: (uri: string) => void; candidateTest?: TestResult | { success: false; error: string }; isTesting?: boolean; }; function CandidateItem({ index, candidate, copiedUri, onCopy, isSelected, testCandidate, candidateTest, isTesting, }: CandidateItemProps) { const { t } = useTranslation(["views/settings"]); const [showFull, setShowFull] = useState(false); const maskUri = (uri: string) => { const match = uri.match(/rtsp:\/\/([^:]+):([^@]+)@(.+)/); if (match) return `rtsp://${match[1]}:••••@${match[3]}`; return uri; }; return (

{t("cameraWizard.step2.candidateStreamTitle", { number: (index ?? 0) + 1, })}

{candidateTest?.success && (
{[ candidateTest.resolution, candidateTest.fps ? `${candidateTest.fps} ${t( "cameraWizard.testResultLabels.fps", )}` : null, candidateTest.videoCodec, candidateTest.audioCodec, ] .filter(Boolean) .join(" · ")}
)}
{candidateTest?.success && (
{t("cameraWizard.step2.connected")}
)} {candidateTest && !candidateTest.success && (
{t("cameraWizard.step2.notConnected")}
)}

setShowFull((s) => !s)} title={t("cameraWizard.step2.toggleUriView")} > {showFull ? candidate.uri : maskUri(candidate.uri)}

); }