import { Button } from "@/components/ui/button"; import { DropdownMenu, DropdownMenuContent, DropdownMenuLabel, DropdownMenuRadioGroup, DropdownMenuRadioItem, DropdownMenuSeparator, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu"; import Heading from "@/components/ui/heading"; import copy from "copy-to-clipboard"; import { useCallback, useMemo, useRef, useState } from "react"; import useSWR from "swr"; const logTypes = ["frigate", "go2rtc", "nginx"] as const; type LogType = (typeof logTypes)[number]; function Logs() { const [logService, setLogService] = useState("frigate"); const { data: frigateLogs } = useSWR("logs/frigate", { refreshInterval: 1000, }); const { data: go2rtcLogs } = useSWR("logs/go2rtc", { refreshInterval: 1000 }); const { data: nginxLogs } = useSWR("logs/nginx", { refreshInterval: 1000 }); const logs = useMemo(() => { if (logService == "frigate") { return frigateLogs; } else if (logService == "go2rtc") { return go2rtcLogs; } else if (logService == "nginx") { return nginxLogs; } else { return "unknown logs"; } }, [logService, frigateLogs, go2rtcLogs, nginxLogs]); const handleCopyLogs = useCallback(() => { copy(logs); }, [logs]); // scroll to bottom button const contentRef = useRef(null); const [endVisible, setEndVisible] = useState(true); const observer = useRef(null); const endLogRef = useCallback( (node: HTMLElement | null) => { if (observer.current) observer.current.disconnect(); try { observer.current = new IntersectionObserver((entries) => { setEndVisible(entries[0].isIntersecting); }); if (node) observer.current.observe(node); } catch (e) { // no op } }, [setEndVisible] ); return (
Logs
Select Logs To View setLogService(type as LogType)} > {Object.values(logTypes).map((item) => ( {item} Logs ))}
{!endVisible && (
contentRef.current?.scrollTo({ top: contentRef.current?.scrollHeight, behavior: "smooth", }) } > Jump to Bottom
)}
{logs}
); } export default Logs;