From 196363190dbca9ff0d478533e705791bef681a2b Mon Sep 17 00:00:00 2001 From: root Date: Wed, 15 Apr 2026 11:04:45 +0000 Subject: [PATCH] feat: add home view and simplify navigation --- ServerDeck/src/App.tsx | 110 +++++++++++++++++++++++----------- ServerDeck/src/lib/i18n.ts | 8 +++ ServerDeck/src/styles/app.css | 85 ++++++++++++++++++++++++++ 3 files changed, 168 insertions(+), 35 deletions(-) diff --git a/ServerDeck/src/App.tsx b/ServerDeck/src/App.tsx index 5471601..1535ca1 100644 --- a/ServerDeck/src/App.tsx +++ b/ServerDeck/src/App.tsx @@ -13,6 +13,7 @@ import { Activity, ArrowLeft, Bot, + Home, ChevronRight, Copy, Download, @@ -108,6 +109,7 @@ import { type TerminalThemePreset } from "./data/terminalThemes"; +const HOME_TAB_ID = "home"; const HOSTS_TAB_ID = "hosts"; const SFTP_TAB_ID = "sftp"; const AGENT_TAB_ID = "agent"; @@ -772,7 +774,7 @@ export default function App() { const detachedSettingsWindow = isSettingsWindowView(); const preferenceSyncSource = detachedSettingsWindow ? "settings" : "main"; - const [activeTabId, setActiveTabId] = useState(() => (detachedSettingsWindow ? SETTINGS_TAB_ID : HOSTS_TAB_ID)); + const [activeTabId, setActiveTabId] = useState(() => (detachedSettingsWindow ? SETTINGS_TAB_ID : HOME_TAB_ID)); const [terminalTabs, setTerminalTabs] = useState([]); const [monitorTabs, setMonitorTabs] = useState([]); const [hosts, setHosts] = useState([]); @@ -853,12 +855,13 @@ export default function App() { const fitAddonRef = useRef(null); const terminalDecodersRef = useRef>(new Map()); const terminalBuffersRef = useRef>(new Map()); - const activeTabIdRef = useRef(HOSTS_TAB_ID); - const previousTabIdRef = useRef(HOSTS_TAB_ID); + const activeTabIdRef = useRef(HOME_TAB_ID); + const previousTabIdRef = useRef(HOME_TAB_ID); const terminalTabsRef = useRef([]); const monitorTabsRef = useRef([]); const skipPreferenceSyncRef = useRef(false); + const isHomeView = activeTabId === HOME_TAB_ID; const isHostsView = activeTabId === HOSTS_TAB_ID; const isSftpView = activeTabId === SFTP_TAB_ID; const isAgentView = activeTabId === AGENT_TAB_ID; @@ -2454,7 +2457,7 @@ export default function App() { } function closeSettings() { - const fallbackTabId = previousTabIdRef.current === SETTINGS_TAB_ID ? HOSTS_TAB_ID : previousTabIdRef.current; + const fallbackTabId = previousTabIdRef.current === SETTINGS_TAB_ID ? HOME_TAB_ID : previousTabIdRef.current; setActiveTabId(fallbackTabId); } @@ -3286,7 +3289,7 @@ export default function App() { const nextTabs = currentTabs.filter((tab) => tab.id !== tabId); const nextActiveTabId = activeTabIdRef.current === tabId - ? nextTabs[targetIndex]?.id ?? nextTabs[targetIndex - 1]?.id ?? HOSTS_TAB_ID + ? nextTabs[targetIndex]?.id ?? nextTabs[targetIndex - 1]?.id ?? HOME_TAB_ID : activeTabIdRef.current; setTerminalTabs(nextTabs); @@ -3390,7 +3393,7 @@ export default function App() { const targetTab = currentTabs[targetIndex]; const nextTabs = currentTabs.filter((tab) => tab.id !== tabId); - const nextActiveTabId = activeTabIdRef.current === tabId ? HOSTS_TAB_ID : activeTabIdRef.current; + const nextActiveTabId = activeTabIdRef.current === tabId ? HOME_TAB_ID : activeTabIdRef.current; setMonitorTabs(nextTabs); setActiveTabId(nextActiveTabId); @@ -3484,33 +3487,6 @@ export default function App() { {sidebarCollapsed ? : } - - - - - - {terminalTabs.map((tab) => (
+ + ) : isHostsView ? (
diff --git a/ServerDeck/src/lib/i18n.ts b/ServerDeck/src/lib/i18n.ts index 3365c80..eb64d12 100644 --- a/ServerDeck/src/lib/i18n.ts +++ b/ServerDeck/src/lib/i18n.ts @@ -100,6 +100,8 @@ type Messages = { monitorInfoCopied: string; copied: string; copyServerInfo: string; + home: string; + homeDescription: string; hosts: string; sftp: string; newTab: string; @@ -425,6 +427,8 @@ export const messagesByLanguage: Record = { monitorInfoCopied: "Server info copied", copied: "Copied", copyServerInfo: "Copy Server Info", + home: "Home", + homeDescription: "Start from one clear place, then jump into hosts, SFTP, agent, or a local terminal.", hosts: "Hosts", sftp: "SFTP", newTab: "New Tab", @@ -748,6 +752,8 @@ export const messagesByLanguage: Record = { monitorInfoCopied: "已复制服务器信息", copied: "已复制", copyServerInfo: "一键复制配置信息", + home: "首页", + homeDescription: "先从一个清晰入口开始,再进入主机、SFTP、Agent 或本地终端。", hosts: "主机", sftp: "SFTP", newTab: "新标签页", @@ -1071,6 +1077,8 @@ export const messagesByLanguage: Record = { monitorInfoCopied: "サーバー情報をコピーしました", copied: "コピー済み", copyServerInfo: "設定情報をコピー", + home: "ホーム", + homeDescription: "まずは分かりやすい入口から始めて、そこから Hosts、SFTP、Agent、ローカルターミナルへ進みます。", hosts: "ホスト", sftp: "SFTP", newTab: "新しいタブ", diff --git a/ServerDeck/src/styles/app.css b/ServerDeck/src/styles/app.css index 114130f..d2985e7 100644 --- a/ServerDeck/src/styles/app.css +++ b/ServerDeck/src/styles/app.css @@ -546,6 +546,7 @@ select { overflow: hidden; } +.home-screen, .hosts-screen, .sftp-screen, .settings-screen, @@ -558,12 +559,88 @@ select { overflow: hidden; } +.home-screen, .hosts-screen, .sftp-screen, .settings-screen { padding: 0; } +.home-screen { + display: grid; + place-items: center; + padding: 32px; +} + +.home-screen__inner { + width: min(720px, 100%); + display: grid; + justify-items: center; + gap: 18px; + text-align: center; +} + +.home-screen__badge { + width: 72px; + height: 72px; + display: grid; + place-items: center; + border-radius: 20px; + background: var(--chrome-tab-active-bg); + border: 1px solid var(--chrome-tab-active-border); + color: var(--content-text); + font-size: 26px; + font-weight: 700; +} + +.home-screen__inner h1 { + margin: 0; + font-size: 34px; + line-height: 1.1; +} + +.home-screen__inner p { + margin: 0; + max-width: 560px; + color: var(--content-muted); + font-size: 14px; + line-height: 1.7; +} + +.home-screen__actions { + display: flex; + flex-wrap: wrap; + justify-content: center; + gap: 12px; +} + +.home-screen__stats { + width: 100%; + display: grid; + grid-template-columns: repeat(4, minmax(0, 1fr)); + gap: 12px; + margin-top: 8px; +} + +.home-stat-card { + display: grid; + gap: 6px; + padding: 18px 14px; + border-radius: 18px; + border: 1px solid var(--content-border); + background: var(--content-raised-bg); +} + +.home-stat-card strong { + font-size: 24px; + color: var(--content-text); +} + +.home-stat-card span { + color: var(--content-muted); + font-size: 12px; +} + .sftp-screen { display: grid; grid-template-rows: auto 1fr auto; @@ -4462,6 +4539,14 @@ select { align-items: stretch; } + .home-screen { + padding: 20px; + } + + .home-screen__stats { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .topbar__brand { min-width: auto; }