mirror of
https://github.com/woodchen-ink/nezha-dash-v1.git
synced 2025-07-18 09:31:55 +08:00
commit
e1b7acaa07
16
src/App.tsx
16
src/App.tsx
@ -6,6 +6,7 @@ import { Route, BrowserRouter as Router, Routes } from "react-router-dom"
|
|||||||
import ErrorBoundary from "./components/ErrorBoundary"
|
import ErrorBoundary from "./components/ErrorBoundary"
|
||||||
import Footer from "./components/Footer"
|
import Footer from "./components/Footer"
|
||||||
import Header, { RefreshToast } from "./components/Header"
|
import Header, { RefreshToast } from "./components/Header"
|
||||||
|
import { useBackground } from "./hooks/use-background"
|
||||||
import { useTheme } from "./hooks/use-theme"
|
import { useTheme } from "./hooks/use-theme"
|
||||||
import { InjectContext } from "./lib/inject"
|
import { InjectContext } from "./lib/inject"
|
||||||
import { fetchSetting } from "./lib/nezha-api"
|
import { fetchSetting } from "./lib/nezha-api"
|
||||||
@ -25,11 +26,7 @@ const App: React.FC = () => {
|
|||||||
const { i18n } = useTranslation()
|
const { i18n } = useTranslation()
|
||||||
const { setTheme } = useTheme()
|
const { setTheme } = useTheme()
|
||||||
const [isCustomCodeInjected, setIsCustomCodeInjected] = useState(false)
|
const [isCustomCodeInjected, setIsCustomCodeInjected] = useState(false)
|
||||||
|
const { backgroundImage: customBackgroundImage } = useBackground()
|
||||||
// 检测是否强制指定了主题颜色
|
|
||||||
const forceTheme =
|
|
||||||
// @ts-expect-error ForceTheme is a global variable
|
|
||||||
(window.ForceTheme as string) !== "" ? window.ForceTheme : undefined
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (settingData?.data?.config?.custom_code) {
|
if (settingData?.data?.config?.custom_code) {
|
||||||
@ -38,6 +35,11 @@ const App: React.FC = () => {
|
|||||||
}
|
}
|
||||||
}, [settingData?.data?.config?.custom_code])
|
}, [settingData?.data?.config?.custom_code])
|
||||||
|
|
||||||
|
// 检测是否强制指定了主题颜色
|
||||||
|
const forceTheme =
|
||||||
|
// @ts-expect-error ForceTheme is a global variable
|
||||||
|
(window.ForceTheme as string) !== "" ? window.ForceTheme : undefined
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (forceTheme === "dark" || forceTheme === "light") {
|
if (forceTheme === "dark" || forceTheme === "light") {
|
||||||
setTheme(forceTheme)
|
setTheme(forceTheme)
|
||||||
@ -60,10 +62,6 @@ const App: React.FC = () => {
|
|||||||
i18n.changeLanguage(settingData?.data?.config?.language)
|
i18n.changeLanguage(settingData?.data?.config?.language)
|
||||||
}
|
}
|
||||||
|
|
||||||
const customBackgroundImage =
|
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const customMobileBackgroundImage =
|
const customMobileBackgroundImage =
|
||||||
// @ts-expect-error CustomMobileBackgroundImage is a global variable
|
// @ts-expect-error CustomMobileBackgroundImage is a global variable
|
||||||
(window.CustomMobileBackgroundImage as string) !== "" ? window.CustomMobileBackgroundImage : undefined
|
(window.CustomMobileBackgroundImage as string) !== "" ? window.CustomMobileBackgroundImage : undefined
|
||||||
|
@ -22,9 +22,7 @@ interface CycleTransferStatsClientProps {
|
|||||||
|
|
||||||
export const CycleTransferStatsClient: React.FC<CycleTransferStatsClientProps> = ({ name, from, to, max, serverStats, className }) => {
|
export const CycleTransferStatsClient: React.FC<CycleTransferStatsClientProps> = ({ name, from, to, max, serverStats, className }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
|
@ -13,9 +13,7 @@ export default function GlobalMap({ serverList, now }: { serverList: NezhaServer
|
|||||||
const countryList: string[] = []
|
const countryList: string[] = []
|
||||||
const serverCounts: { [key: string]: number } = {}
|
const serverCounts: { [key: string]: number } = {}
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
serverList.forEach((server) => {
|
serverList.forEach((server) => {
|
||||||
if (server.country_code) {
|
if (server.country_code) {
|
||||||
|
@ -11,9 +11,7 @@ export default function GroupSwitch({
|
|||||||
currentTab: string
|
currentTab: string
|
||||||
setCurrentTab: (tab: string) => void
|
setCurrentTab: (tab: string) => void
|
||||||
}) {
|
}) {
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const scrollRef = useRef<HTMLDivElement>(null)
|
const scrollRef = useRef<HTMLDivElement>(null)
|
||||||
const tagRefs = useRef(tabs.map(() => createRef<HTMLDivElement>()))
|
const tagRefs = useRef(tabs.map(() => createRef<HTMLDivElement>()))
|
||||||
|
@ -1,11 +1,13 @@
|
|||||||
import { ModeToggle } from "@/components/ThemeSwitcher"
|
import { ModeToggle } from "@/components/ThemeSwitcher"
|
||||||
import { Separator } from "@/components/ui/separator"
|
import { Separator } from "@/components/ui/separator"
|
||||||
import { Skeleton } from "@/components/ui/skeleton"
|
import { Skeleton } from "@/components/ui/skeleton"
|
||||||
|
import { useBackground } from "@/hooks/use-background"
|
||||||
import { useWebSocketContext } from "@/hooks/use-websocket-context"
|
import { useWebSocketContext } from "@/hooks/use-websocket-context"
|
||||||
import { fetchLoginUser, fetchSetting } from "@/lib/nezha-api"
|
import { fetchLoginUser, fetchSetting } from "@/lib/nezha-api"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { useQuery } from "@tanstack/react-query"
|
import { useQuery } from "@tanstack/react-query"
|
||||||
import { AnimatePresence, m } from "framer-motion"
|
import { AnimatePresence, m } from "framer-motion"
|
||||||
|
import { ImageMinus } from "lucide-react"
|
||||||
import { DateTime } from "luxon"
|
import { DateTime } from "luxon"
|
||||||
import { useEffect, useRef, useState } from "react"
|
import { useEffect, useRef, useState } from "react"
|
||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
@ -18,6 +20,7 @@ import { Button } from "./ui/button"
|
|||||||
function Header() {
|
function Header() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const navigate = useNavigate()
|
const navigate = useNavigate()
|
||||||
|
const { backgroundImage, updateBackground } = useBackground()
|
||||||
|
|
||||||
const { data: settingData, isLoading } = useQuery({
|
const { data: settingData, isLoading } = useQuery({
|
||||||
queryKey: ["setting"],
|
queryKey: ["setting"],
|
||||||
@ -38,10 +41,6 @@ function Header() {
|
|||||||
// @ts-expect-error CustomDesc is a global variable
|
// @ts-expect-error CustomDesc is a global variable
|
||||||
const customDesc = window.CustomDesc || t("nezha")
|
const customDesc = window.CustomDesc || t("nezha")
|
||||||
|
|
||||||
const customBackgroundImage =
|
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const link = document.querySelector("link[rel*='icon']") || document.createElement("link")
|
const link = document.querySelector("link[rel*='icon']") || document.createElement("link")
|
||||||
// @ts-expect-error set link.type
|
// @ts-expect-error set link.type
|
||||||
@ -57,6 +56,22 @@ function Header() {
|
|||||||
document.title = siteName || "CZL SVR"
|
document.title = siteName || "CZL SVR"
|
||||||
}, [siteName])
|
}, [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 (
|
return (
|
||||||
<div className="mx-auto w-full max-w-5xl">
|
<div className="mx-auto w-full max-w-5xl">
|
||||||
<section className="flex items-center justify-between header-top">
|
<section className="flex items-center justify-between header-top">
|
||||||
@ -87,6 +102,18 @@ function Header() {
|
|||||||
</div>
|
</div>
|
||||||
<LanguageSwitcher />
|
<LanguageSwitcher />
|
||||||
<ModeToggle />
|
<ModeToggle />
|
||||||
|
{(customBackgroundImage || sessionStorage.getItem("savedBackgroundImage")) && (
|
||||||
|
<Button
|
||||||
|
variant="outline"
|
||||||
|
size="sm"
|
||||||
|
onClick={handleBackgroundToggle}
|
||||||
|
className={cn("rounded-full px-[9px] bg-white dark:bg-black", {
|
||||||
|
"bg-white/70 dark:bg-black/70": customBackgroundImage,
|
||||||
|
})}
|
||||||
|
>
|
||||||
|
<ImageMinus className="w-4 h-4" />
|
||||||
|
</Button>
|
||||||
|
)}
|
||||||
<Button
|
<Button
|
||||||
variant="outline"
|
variant="outline"
|
||||||
size="sm"
|
size="sm"
|
||||||
@ -234,32 +261,23 @@ function DashboardLink() {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// https://github.com/streamich/react-use/blob/master/src/useInterval.ts
|
|
||||||
const useInterval = (callback: () => void, delay: number | null) => {
|
|
||||||
const savedCallback = useRef<() => void>(() => {})
|
|
||||||
useEffect(() => {
|
|
||||||
savedCallback.current = callback
|
|
||||||
})
|
|
||||||
useEffect(() => {
|
|
||||||
if (delay !== null) {
|
|
||||||
const interval = setInterval(() => savedCallback.current(), delay || 0)
|
|
||||||
return () => clearInterval(interval)
|
|
||||||
}
|
|
||||||
return undefined
|
|
||||||
}, [delay])
|
|
||||||
}
|
|
||||||
function Overview() {
|
function Overview() {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const [mouted, setMounted] = useState(false)
|
const [mouted, setMounted] = useState(false)
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setMounted(true)
|
setMounted(true)
|
||||||
}, [])
|
}, [])
|
||||||
const timeOption = DateTime.TIME_SIMPLE
|
const timeOption = DateTime.TIME_WITH_SECONDS
|
||||||
timeOption.hour12 = true
|
timeOption.hour12 = true
|
||||||
const [timeString, setTimeString] = useState(DateTime.now().setLocale("en-US").toLocaleString(timeOption))
|
const [timeString, setTimeString] = useState(DateTime.now().setLocale("en-US").toLocaleString(timeOption))
|
||||||
useInterval(() => {
|
useEffect(() => {
|
||||||
setTimeString(DateTime.now().setLocale("en-US").toLocaleString(timeOption))
|
const updateTime = () => {
|
||||||
}, 1000)
|
const now = DateTime.now().setLocale("en-US").toLocaleString(timeOption)
|
||||||
|
setTimeString(now)
|
||||||
|
requestAnimationFrame(updateTime)
|
||||||
|
}
|
||||||
|
requestAnimationFrame(updateTime)
|
||||||
|
}, [])
|
||||||
return (
|
return (
|
||||||
<section className={"mt-10 flex flex-col md:mt-16 header-timer"}>
|
<section className={"mt-10 flex flex-col md:mt-16 header-timer"}>
|
||||||
<p className="text-base font-semibold">👋 {t("overview")}</p>
|
<p className="text-base font-semibold">👋 {t("overview")}</p>
|
||||||
|
@ -9,9 +9,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
export function LanguageSwitcher() {
|
export function LanguageSwitcher() {
|
||||||
const { t, i18n } = useTranslation()
|
const { t, i18n } = useTranslation()
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const locale = i18n.languages[0]
|
const locale = i18n.languages[0]
|
||||||
|
|
||||||
|
@ -93,9 +93,7 @@ export const NetworkChartClient = React.memo(function NetworkChart({
|
|||||||
|
|
||||||
const defaultChart = "All"
|
const defaultChart = "All"
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const [activeChart, setActiveChart] = React.useState(defaultChart)
|
const [activeChart, setActiveChart] = React.useState(defaultChart)
|
||||||
const [isPeakEnabled, setIsPeakEnabled] = React.useState(false)
|
const [isPeakEnabled, setIsPeakEnabled] = React.useState(false)
|
||||||
|
@ -27,9 +27,7 @@ export default function ServerCard({ now, serverInfo }: { now: number; serverInf
|
|||||||
|
|
||||||
const showFlag = true
|
const showFlag = true
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
// @ts-expect-error ShowNetTransfer is a global variable
|
// @ts-expect-error ShowNetTransfer is a global variable
|
||||||
const showNetTransfer = window.ShowNetTransfer as boolean
|
const showNetTransfer = window.ShowNetTransfer as boolean
|
||||||
|
@ -27,9 +27,7 @@ export default function ServerCardInline({ now, serverInfo }: { now: number; ser
|
|||||||
|
|
||||||
const showFlag = true
|
const showFlag = true
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const parsedData = parsePublicNote(public_note)
|
const parsedData = parsePublicNote(public_note)
|
||||||
|
|
||||||
|
@ -128,9 +128,7 @@ function GpuChart({
|
|||||||
const hasInitialized = useRef(false)
|
const hasInitialized = useRef(false)
|
||||||
const [historyLoaded, setHistoryLoaded] = useState(false)
|
const [historyLoaded, setHistoryLoaded] = useState(false)
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
// 初始化历史数据
|
// 初始化历史数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -237,9 +235,7 @@ function CpuChart({ now, data, messageHistory }: { now: number; data: NezhaServe
|
|||||||
|
|
||||||
const { cpu } = formatNezhaInfo(now, data)
|
const { cpu } = formatNezhaInfo(now, data)
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
// 初始化历史数据
|
// 初始化历史数据
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -343,9 +339,7 @@ function ProcessChart({ now, data, messageHistory }: { now: number; data: NezhaS
|
|||||||
const hasInitialized = useRef(false)
|
const hasInitialized = useRef(false)
|
||||||
const [historyLoaded, setHistoryLoaded] = useState(false)
|
const [historyLoaded, setHistoryLoaded] = useState(false)
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const { process } = formatNezhaInfo(now, data)
|
const { process } = formatNezhaInfo(now, data)
|
||||||
|
|
||||||
@ -457,9 +451,7 @@ function MemChart({ now, data, messageHistory }: { now: number; data: NezhaServe
|
|||||||
const hasInitialized = useRef(false)
|
const hasInitialized = useRef(false)
|
||||||
const [historyLoaded, setHistoryLoaded] = useState(false)
|
const [historyLoaded, setHistoryLoaded] = useState(false)
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const { mem, swap } = formatNezhaInfo(now, data)
|
const { mem, swap } = formatNezhaInfo(now, data)
|
||||||
|
|
||||||
@ -602,9 +594,7 @@ function DiskChart({ now, data, messageHistory }: { now: number; data: NezhaServ
|
|||||||
const hasInitialized = useRef(false)
|
const hasInitialized = useRef(false)
|
||||||
const [historyLoaded, setHistoryLoaded] = useState(false)
|
const [historyLoaded, setHistoryLoaded] = useState(false)
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const { disk } = formatNezhaInfo(now, data)
|
const { disk } = formatNezhaInfo(now, data)
|
||||||
|
|
||||||
@ -715,9 +705,7 @@ function NetworkChart({ now, data, messageHistory }: { now: number; data: NezhaS
|
|||||||
const hasInitialized = useRef(false)
|
const hasInitialized = useRef(false)
|
||||||
const [historyLoaded, setHistoryLoaded] = useState(false)
|
const [historyLoaded, setHistoryLoaded] = useState(false)
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const { up, down } = formatNezhaInfo(now, data)
|
const { up, down } = formatNezhaInfo(now, data)
|
||||||
|
|
||||||
@ -858,9 +846,7 @@ function ConnectChart({ now, data, messageHistory }: { now: number; data: NezhaS
|
|||||||
const hasInitialized = useRef(false)
|
const hasInitialized = useRef(false)
|
||||||
const [historyLoaded, setHistoryLoaded] = useState(false)
|
const [historyLoaded, setHistoryLoaded] = useState(false)
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const { tcp, udp } = formatNezhaInfo(now, data)
|
const { tcp, udp } = formatNezhaInfo(now, data)
|
||||||
|
|
||||||
|
@ -75,9 +75,7 @@ export default function ServerDetailOverview({ server_id }: { server_id: string
|
|||||||
last_active_time_string,
|
last_active_time_string,
|
||||||
} = formatNezhaInfo(nezhaWsData.now, server)
|
} = formatNezhaInfo(nezhaWsData.now, server)
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
countries.registerLocale(enLocale)
|
countries.registerLocale(enLocale)
|
||||||
|
|
||||||
|
@ -25,9 +25,7 @@ export default function ServerOverview({ online, offline, total, up, down, upSpe
|
|||||||
// @ts-expect-error CustomIllustration is a global variable
|
// @ts-expect-error CustomIllustration is a global variable
|
||||||
const customIllustration = window.CustomIllustration || "/animated-man.webp"
|
const customIllustration = window.CustomIllustration || "/animated-man.webp"
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
|
@ -17,9 +17,7 @@ interface ServiceTrackerProps {
|
|||||||
|
|
||||||
export const ServiceTrackerClient: React.FC<ServiceTrackerProps> = ({ days, className, title, uptime = 100, avgDelay = 0 }) => {
|
export const ServiceTrackerClient: React.FC<ServiceTrackerProps> = ({ days, className, title, uptime = 100, avgDelay = 0 }) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className={cn(
|
className={cn(
|
||||||
|
@ -4,9 +4,7 @@ import { useTranslation } from "react-i18next"
|
|||||||
|
|
||||||
export default function TabSwitch({ tabs, currentTab, setCurrentTab }: { tabs: string[]; currentTab: string; setCurrentTab: (tab: string) => void }) {
|
export default function TabSwitch({ tabs, currentTab, setCurrentTab }: { tabs: string[]; currentTab: string; setCurrentTab: (tab: string) => void }) {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
return (
|
return (
|
||||||
<div className="z-50 flex flex-col items-start rounded-[50px] server-info-tab">
|
<div className="z-50 flex flex-col items-start rounded-[50px] server-info-tab">
|
||||||
<div
|
<div
|
||||||
|
@ -12,9 +12,7 @@ export function ModeToggle() {
|
|||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { setTheme, theme } = useTheme()
|
const { setTheme, theme } = useTheme()
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const handleSelect = (e: Event, newTheme: Theme) => {
|
const handleSelect = (e: Event, newTheme: Theme) => {
|
||||||
e.preventDefault()
|
e.preventDefault()
|
||||||
|
@ -106,28 +106,15 @@ export const WebSocketProvider: React.FC<WebSocketProviderProps> = ({ url, child
|
|||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
connect()
|
connect()
|
||||||
|
|
||||||
// 添加页面可见性变化监听
|
|
||||||
const handleVisibilityChange = () => {
|
|
||||||
if (document.hidden) {
|
|
||||||
// 页面隐藏时断开连接
|
|
||||||
cleanup()
|
|
||||||
} else {
|
|
||||||
// 页面可见时重新连接
|
|
||||||
connect()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 添加页面卸载事件监听
|
// 添加页面卸载事件监听
|
||||||
const handleBeforeUnload = () => {
|
const handleBeforeUnload = () => {
|
||||||
cleanup()
|
cleanup()
|
||||||
}
|
}
|
||||||
|
|
||||||
document.addEventListener("visibilitychange", handleVisibilityChange)
|
|
||||||
window.addEventListener("beforeunload", handleBeforeUnload)
|
window.addEventListener("beforeunload", handleBeforeUnload)
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
cleanup()
|
cleanup()
|
||||||
document.removeEventListener("visibilitychange", handleVisibilityChange)
|
|
||||||
window.removeEventListener("beforeunload", handleBeforeUnload)
|
window.removeEventListener("beforeunload", handleBeforeUnload)
|
||||||
}
|
}
|
||||||
}, [url])
|
}, [url])
|
||||||
|
55
src/hooks/use-background.ts
Normal file
55
src/hooks/use-background.ts
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
import { useEffect, useState } from "react"
|
||||||
|
|
||||||
|
declare global {
|
||||||
|
interface Window {
|
||||||
|
CustomBackgroundImage: string
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const BACKGROUND_CHANGE_EVENT = "backgroundChange"
|
||||||
|
|
||||||
|
export function useBackground() {
|
||||||
|
const [backgroundImage, setBackgroundImage] = useState<string | undefined>(undefined)
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
// 监听背景变化
|
||||||
|
const handleBackgroundChange = () => {
|
||||||
|
setBackgroundImage(window.CustomBackgroundImage || undefined)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 初始化检查
|
||||||
|
const checkInitialBackground = () => {
|
||||||
|
if (window.CustomBackgroundImage) {
|
||||||
|
setBackgroundImage(window.CustomBackgroundImage)
|
||||||
|
} else {
|
||||||
|
const savedImage = sessionStorage.getItem("savedBackgroundImage")
|
||||||
|
if (savedImage) {
|
||||||
|
window.CustomBackgroundImage = savedImage
|
||||||
|
setBackgroundImage(savedImage)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 设置一个轮询来检查初始背景
|
||||||
|
const intervalId = setInterval(() => {
|
||||||
|
if (window.CustomBackgroundImage || sessionStorage.getItem("savedBackgroundImage")) {
|
||||||
|
checkInitialBackground()
|
||||||
|
clearInterval(intervalId)
|
||||||
|
}
|
||||||
|
}, 100)
|
||||||
|
|
||||||
|
window.addEventListener(BACKGROUND_CHANGE_EVENT, handleBackgroundChange)
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
window.removeEventListener(BACKGROUND_CHANGE_EVENT, handleBackgroundChange)
|
||||||
|
clearInterval(intervalId)
|
||||||
|
}
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
const updateBackground = (newBackground: string | undefined) => {
|
||||||
|
window.CustomBackgroundImage = newBackground || ""
|
||||||
|
window.dispatchEvent(new Event(BACKGROUND_CHANGE_EVENT))
|
||||||
|
}
|
||||||
|
|
||||||
|
return { backgroundImage, updateBackground }
|
||||||
|
}
|
@ -36,9 +36,7 @@ export default function Servers() {
|
|||||||
const [settingsOpen, setSettingsOpen] = useState<boolean>(false)
|
const [settingsOpen, setSettingsOpen] = useState<boolean>(false)
|
||||||
const [currentGroup, setCurrentGroup] = useState<string>("All")
|
const [currentGroup, setCurrentGroup] = useState<string>("All")
|
||||||
|
|
||||||
const customBackgroundImage =
|
const customBackgroundImage = (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
||||||
// @ts-expect-error CustomBackgroundImage is a global variable
|
|
||||||
(window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined
|
|
||||||
|
|
||||||
const restoreScrollPosition = () => {
|
const restoreScrollPosition = () => {
|
||||||
const savedPosition = sessionStorage.getItem("scrollPosition")
|
const savedPosition = sessionStorage.getItem("scrollPosition")
|
||||||
|
Loading…
x
Reference in New Issue
Block a user