import { ModeToggle } from "@/components/ThemeSwitcher" import { Separator } from "@/components/ui/separator" import { Skeleton } from "@/components/ui/skeleton" import { useBackground } from "@/hooks/use-background" import { useWebSocketContext } from "@/hooks/use-websocket-context" import { fetchLoginUser, fetchSetting } from "@/lib/nezha-api" import { cn } from "@/lib/utils" import { useQuery } from "@tanstack/react-query" import { AnimatePresence, m } from "framer-motion" import { ImageMinus } from "lucide-react" import { DateTime } from "luxon" import { useEffect, useRef, useState } from "react" import { useTranslation } from "react-i18next" import { useNavigate } from "react-router-dom" import { LanguageSwitcher } from "./LanguageSwitcher" import { Loader, LoadingSpinner } from "./loading/Loader" import { Button } from "./ui/button" function Header() { const { t } = useTranslation() const navigate = useNavigate() const { backgroundImage, updateBackground } = useBackground() const { data: settingData, isLoading } = useQuery({ queryKey: ["setting"], queryFn: () => fetchSetting(), refetchOnMount: true, refetchOnWindowFocus: true, }) const { lastMessage, connected } = useWebSocketContext() const onlineCount = connected ? (lastMessage ? JSON.parse(lastMessage.data).online || 0 : 0) : "..." const siteName = settingData?.data?.config?.site_name // @ts-expect-error CustomLogo is a global variable const customLogo = window.CustomLogo || "/apple-touch-icon.png" // @ts-expect-error CustomDesc is a global variable const customDesc = window.CustomDesc || t("nezha") useEffect(() => { const link = document.querySelector("link[rel*='icon']") || document.createElement("link") // @ts-expect-error set link.type link.type = "image/x-icon" // @ts-expect-error set link.rel link.rel = "shortcut icon" // @ts-expect-error set link.href link.href = customLogo document.getElementsByTagName("head")[0].appendChild(link) }, [customLogo]) useEffect(() => { document.title = siteName || "CZL SVR" }, [siteName]) const handleBackgroundToggle = () => { if (window.CustomBackgroundImage) { // Store the current background image before removing it sessionStorage.setItem("savedBackgroundImage", window.CustomBackgroundImage) updateBackground(undefined) } else { // Restore the saved background image const savedImage = sessionStorage.getItem("savedBackgroundImage") if (savedImage) { updateBackground(savedImage) } } } const customBackgroundImage = backgroundImage return (
{ sessionStorage.removeItem("selectedGroup") navigate("/") }} className="cursor-pointer flex items-center sm:text-base text-sm font-medium" >
apple-touch-icon
{isLoading ? : siteName || "CZL SVR"}

{customDesc}

{(customBackgroundImage || sessionStorage.getItem("savedBackgroundImage")) && ( )}
) } type links = { link: string name: string } function Links() { // @ts-expect-error CustomLinks is a global variable const customLinks = window.CustomLinks as string const links: links[] | null = customLinks ? JSON.parse(customLinks) : null if (!links) return null return (
{links.map((link, index) => { return ( {link.name} ) })}
) } export function RefreshToast() { const { t } = useTranslation() const navigate = useNavigate() const { needReconnect } = useWebSocketContext() if (!needReconnect) { return null } if (needReconnect) { sessionStorage.removeItem("needRefresh") setTimeout(() => { navigate(0) }, 1000) } return (

{t("refreshing")}...

) } function DashboardLink() { const { t } = useTranslation() const { setNeedReconnect } = useWebSocketContext() const previousLoginState = useRef(null) const { data: userData, isFetched, isLoadingError, isError, refetch, } = useQuery({ queryKey: ["login-user"], queryFn: () => fetchLoginUser(), refetchOnMount: false, refetchOnWindowFocus: true, refetchIntervalInBackground: true, refetchInterval: 1000 * 30, retry: 0, }) const isLogin = isError ? false : userData ? !!userData?.data?.id && !!document.cookie : false if (isLoadingError) { previousLoginState.current = isLogin } useEffect(() => { refetch() }, [document.cookie]) useEffect(() => { if (isFetched || isError) { // 只有当登录状态发生变化时才设置needReconnect if (previousLoginState.current !== null && previousLoginState.current !== isLogin) { setNeedReconnect(true) } previousLoginState.current = isLogin } }, [isLogin]) return (
{!isLogin && t("login")} {isLogin && t("dashboard")}
) } function Overview() { const { t } = useTranslation() const [mouted, setMounted] = useState(false) useEffect(() => { setMounted(true) }, []) const timeOption = DateTime.TIME_WITH_SECONDS timeOption.hour12 = true const [timeString, setTimeString] = useState(DateTime.now().setLocale("en-US").toLocaleString(timeOption)) useEffect(() => { const updateTime = () => { const now = DateTime.now().setLocale("en-US").toLocaleString(timeOption) setTimeString(now) requestAnimationFrame(updateTime) } requestAnimationFrame(updateTime) }, []) return (

👋 {t("overview")}

{t("whereTheTimeIs")}

{mouted ? (

{timeString}

) : ( )}
) } export default Header