diff --git a/bun.lockb b/bun.lockb index f707626..e09c2e0 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index 14b09d9..5fcebaf 100644 --- a/package.json +++ b/package.json @@ -24,10 +24,10 @@ "@radix-ui/react-separator": "^1.1.1", "@radix-ui/react-slot": "^1.1.1", "@radix-ui/react-switch": "^1.1.2", - "@tanstack/react-query": "^5.62.11", - "@tanstack/react-query-devtools": "^5.62.11", + "@tanstack/react-query": "^5.62.14", + "@tanstack/react-query-devtools": "^5.62.14", "@tanstack/react-table": "^8.20.6", - "@trivago/prettier-plugin-sort-imports": "^5.2.0", + "@trivago/prettier-plugin-sort-imports": "^5.2.1", "@types/d3-geo": "^3.1.0", "@types/luxon": "^3.4.2", "class-variance-authority": "^0.7.1", @@ -51,7 +51,7 @@ }, "devDependencies": { "@eslint/js": "^9.17.0", - "@types/node": "^22.10.3", + "@types/node": "^22.10.5", "@types/react": "^19.0.2", "@types/react-dom": "^19.0.2", "@vitejs/plugin-react-swc": "^3.7.2", @@ -64,6 +64,6 @@ "tailwindcss": "^3.4.17", "typescript": "~5.6.3", "typescript-eslint": "^8.19.0", - "vite": "^6.0.6" + "vite": "^6.0.7" } } diff --git a/src/components/GroupSwitch.tsx b/src/components/GroupSwitch.tsx index 9446785..0298634 100644 --- a/src/components/GroupSwitch.tsx +++ b/src/components/GroupSwitch.tsx @@ -37,6 +37,13 @@ export default function GroupSwitch({ } }, []) + useEffect(() => { + const savedGroup = sessionStorage.getItem("selectedGroup") + if (savedGroup && tabs.includes(savedGroup)) { + setCurrentTab(savedGroup) + } + }, [tabs, setCurrentTab]) + useEffect(() => { const currentTagRef = tagRefs.current[tabs.indexOf(currentTab)] diff --git a/src/components/Header.tsx b/src/components/Header.tsx index 0408c1e..a657556 100644 --- a/src/components/Header.tsx +++ b/src/components/Header.tsx @@ -60,7 +60,13 @@ function Header() { return (
-
navigate("/")} className="cursor-pointer flex items-center sm:text-base text-sm font-medium"> +
{ + sessionStorage.removeItem("selectedGroup") + navigate("/") + }} + className="cursor-pointer flex items-center sm:text-base text-sm font-medium" + >
diff --git a/src/components/ServerCard.tsx b/src/components/ServerCard.tsx index 9a723e9..e88699f 100644 --- a/src/components/ServerCard.tsx +++ b/src/components/ServerCard.tsx @@ -20,6 +20,11 @@ export default function ServerCard({ now, serverInfo }: { now: number; serverInf serverInfo, ) + const cardClick = () => { + sessionStorage.setItem("fromMainPage", "true") + navigate(`/server/${serverInfo.id}`) + } + const showFlag = true const customBackgroundImage = @@ -46,7 +51,7 @@ export default function ServerCard({ now, serverInfo }: { now: number; serverInf "bg-card/70": customBackgroundImage, }, )} - onClick={() => navigate(`/server/${serverInfo.id}`)} + onClick={cardClick} >
navigate(`/server/${serverInfo.id}`, { replace: true })} + onClick={cardClick} >
{ + sessionStorage.setItem("fromMainPage", "true") + navigate(`/server/${serverInfo.id}`) + } + const showFlag = true const customBackgroundImage = @@ -37,7 +42,7 @@ export default function ServerCardInline({ now, serverInfo }: { now: number; ser "bg-card/70": customBackgroundImage, }, )} - onClick={() => navigate(`/server/${serverInfo.id}`)} + onClick={cardClick} >
@@ -97,7 +102,7 @@ export default function ServerCardInline({ now, serverInfo }: { now: number; ser

{t("serverCard.download")}

- {down >= 1024 ? `${(down / 1024).toFixed(2)}G/s` : up >= 1 ? `${down.toFixed(2)}M/s` : `${(down * 1024).toFixed(2)}K/s`} + {down >= 1024 ? `${(down / 1024).toFixed(2)}G/s` : down >= 1 ? `${down.toFixed(2)}M/s` : `${(down * 1024).toFixed(2)}K/s`}
@@ -121,7 +126,7 @@ export default function ServerCardInline({ now, serverInfo }: { now: number; ser "bg-card/70": customBackgroundImage, }, )} - onClick={() => navigate(`/server/${serverInfo.id}`)} + onClick={cardClick} >
diff --git a/src/components/ServerDetailOverview.tsx b/src/components/ServerDetailOverview.tsx index 8b3966a..facc583 100644 --- a/src/components/ServerDetailOverview.tsx +++ b/src/components/ServerDetailOverview.tsx @@ -7,6 +7,7 @@ import { useWebSocketContext } from "@/hooks/use-websocket-context" import { formatBytes } from "@/lib/format" import { cn, formatNezhaInfo } from "@/lib/utils" import { NezhaWebsocketResponse } from "@/types/nezha-api" +import { useEffect, useState } from "react" import { useTranslation } from "react-i18next" import { useNavigate } from "react-router-dom" @@ -16,12 +17,29 @@ export default function ServerDetailOverview({ server_id }: { server_id: string const { t } = useTranslation() const navigate = useNavigate() + const [hasHistory, setHasHistory] = useState(false) + + useEffect(() => { + const previousPath = sessionStorage.getItem("fromMainPage") + if (previousPath) { + setHasHistory(true) + } + }, []) + const { lastMessage, connected } = useWebSocketContext() if (!connected && !lastMessage) { return } + const linkClick = () => { + if (hasHistory) { + navigate(-1) + } else { + navigate("/") + } + } + const nezhaWsData = lastMessage ? (JSON.parse(lastMessage.data) as NezhaWebsocketResponse) : null if (!nezhaWsData) { @@ -66,7 +84,7 @@ export default function ServerDetailOverview({ server_id }: { server_id: string })} >
navigate("/")} + onClick={linkClick} className="flex flex-none cursor-pointer font-semibold leading-none items-center break-all tracking-tight gap-1 text-xl server-name" > diff --git a/src/locales/de/translation.json b/src/locales/de/translation.json index d5c5230..4cf9c43 100644 --- a/src/locales/de/translation.json +++ b/src/locales/de/translation.json @@ -115,5 +115,6 @@ }, "footer": { "themeBy": "Design von " - } + }, + "login": "Login" } diff --git a/src/pages/Server.tsx b/src/pages/Server.tsx index 08e0e16..15060b9 100644 --- a/src/pages/Server.tsx +++ b/src/pages/Server.tsx @@ -17,7 +17,7 @@ import { NezhaWebsocketResponse } from "@/types/nezha-api" import { ServerGroup } from "@/types/nezha-api" import { ArrowDownIcon, ArrowUpIcon, ArrowsUpDownIcon, ChartBarSquareIcon, MapIcon, ViewColumnsIcon } from "@heroicons/react/20/solid" import { useQuery } from "@tanstack/react-query" -import { useEffect, useState } from "react" +import { useEffect, useRef, useState } from "react" import { useTranslation } from "react-i18next" export default function Servers() { @@ -32,6 +32,7 @@ export default function Servers() { const [showServices, setShowServices] = useState("0") const [showMap, setShowMap] = useState("0") const [inline, setInline] = useState("0") + const containerRef = useRef(null) const [settingsOpen, setSettingsOpen] = useState(false) const [currentGroup, setCurrentGroup] = useState("All") @@ -39,6 +40,19 @@ export default function Servers() { // @ts-expect-error CustomBackgroundImage is a global variable (window.CustomBackgroundImage as string) !== "" ? window.CustomBackgroundImage : undefined + const restoreScrollPosition = () => { + const savedPosition = sessionStorage.getItem("scrollPosition") + if (savedPosition && containerRef.current) { + containerRef.current.scrollTop = Number(savedPosition) + } + } + + const handleTagChange = (newGroup: string) => { + setCurrentGroup(newGroup) + sessionStorage.setItem("selectedGroup", newGroup) + sessionStorage.setItem("scrollPosition", String(containerRef.current?.scrollTop || 0)) + } + useEffect(() => { const showServicesState = localStorage.getItem("showServices") if (showServicesState !== null) { @@ -53,6 +67,13 @@ export default function Servers() { } }, []) + useEffect(() => { + const savedGroup = sessionStorage.getItem("selectedGroup") || "All" + setCurrentGroup(savedGroup) + + restoreScrollPosition() + }, []) + const groupTabs = ["All", ...(groupData?.data?.map((item: ServerGroup) => item.group.name) || [])] if (!connected && !lastMessage) { @@ -233,7 +254,7 @@ export default function Servers() { > - +
@@ -306,14 +327,14 @@ export default function Servers() { {showMap === "1" && } {showServices === "1" && } {inline === "1" && ( -
+
{filteredServers.map((serverInfo) => ( ))}
)} {inline === "0" && ( -
+
{filteredServers.map((serverInfo) => ( ))}