import { useCallback, useEffect, useState } from "react"; import { Trans, useTranslation } from "react-i18next"; import { Link, useNavigate } from "react-router-dom"; import useSWR from "swr"; import axios from "axios"; import { AlertTriangle, CheckCircle2, XCircle } from "lucide-react"; import { LuExternalLink } from "react-icons/lu"; import ActivityIndicator from "@/components/indicators/activity-indicator"; import { Button } from "@/components/ui/button"; import Heading from "@/components/ui/heading"; import { SettingsGroupCard, SplitCardRow, } from "@/components/card/SettingsGroupCard"; import FrigatePlusCurrentModelSummary from "@/views/settings/components/FrigatePlusCurrentModelSummary"; import { useDocDomain } from "@/hooks/use-doc-domain"; import { CameraNameLabel } from "@/components/camera/FriendlyNameLabel"; import { FrigateConfig } from "@/types/frigateConfig"; import { isReplayCamera } from "@/utils/cameraUtil"; import type { SettingsPageProps } from "@/views/settings/SingleSectionPage"; import { getPrimaryModel } from "@/utils/modelUtil"; import { useIsAdmin } from "@/hooks/use-is-admin"; type PlusKeyStatus = "valid" | "invalid" | "unreachable" | "not_set"; type PlusValidateResponse = { success: boolean; status: PlusKeyStatus }; export default function FrigatePlusSettingsView(_props: SettingsPageProps) { const { t } = useTranslation("views/settings"); const { getLocaleDocUrl } = useDocDomain(); const { data: config } = useSWR("config"); const navigate = useNavigate(); const isAdmin = useIsAdmin(); const [isValidating, setIsValidating] = useState(false); const [keyStatus, setKeyStatus] = useState(); const validateKey = useCallback(async () => { setIsValidating(true); try { const response = await axios.post("plus/validate"); setKeyStatus(response.data.status); } catch { setKeyStatus("unreachable"); } finally { setIsValidating(false); } }, []); useEffect(() => { document.title = t("documentTitle.frigatePlus"); }, [t]); if (!config) { return ; } return (
{t("frigatePlus.title")}

{t("frigatePlus.description")}

{t("frigatePlus.apiKey.desc")}

{!getPrimaryModel(config)?.plus && (
{t("frigatePlus.apiKey.plusLink")}
)} } content={
{config?.plus?.enabled ? ( ) : ( )} {config?.plus?.enabled ? t("frigatePlus.apiKey.formatValid") : t("frigatePlus.apiKey.formatInvalid")}
{config?.plus?.enabled && isAdmin && (
{keyStatus && !isValidating && (
{keyStatus === "valid" ? ( ) : keyStatus === "unreachable" ? ( ) : ( )} {keyStatus === "valid" ? t("frigatePlus.apiKey.serverValid") : keyStatus === "unreachable" ? t("frigatePlus.apiKey.serverUnreachable") : t("frigatePlus.apiKey.serverInvalid")}
)}
)}
} />
{config?.plus?.enabled && ( navigate("/settings?page=systemDetectorsAndModel") } > {t("frigatePlus.changeInDetectorsAndModel")} } /> )}

frigatePlus.snapshotConfig.desc

{t("readTheDocumentation", { ns: "common" })}
} content={
{Object.entries(config.cameras) .filter(([name]) => !isReplayCamera(name)) .sort(([, a], [, b]) => a.ui.order - b.ui.order) .map(([name, camera]) => ( ))}
{t("frigatePlus.snapshotConfig.table.camera")} {t("frigatePlus.snapshotConfig.table.snapshots")}
{camera.snapshots.enabled ? ( ) : ( )}
} />
); }