From d45ae46fb4d437ddb0724a99f5053d294be881d7 Mon Sep 17 00:00:00 2001 From: Bot Date: Fri, 1 May 2026 13:54:37 +0800 Subject: [PATCH] feat: add scheduled theme mode and domain translations --- src/components/DomainStatus.tsx | 32 ++++++++---------------------- src/components/ServerOverview.tsx | 4 ++-- src/components/ThemeProvider.tsx | 20 ++++++++++++++++--- src/components/ThemeSwitcher.tsx | 9 +++++++++ src/locales/en/translation.json | 15 +++++++++++--- src/locales/zh-CN/translation.json | 15 +++++++++++--- src/locales/zh-TW/translation.json | 13 ++++++++++-- 7 files changed, 71 insertions(+), 37 deletions(-) diff --git a/src/components/DomainStatus.tsx b/src/components/DomainStatus.tsx index d3ab5b2..923fe2d 100644 --- a/src/components/DomainStatus.tsx +++ b/src/components/DomainStatus.tsx @@ -1,15 +1,11 @@ -// src/components/DomainStatus.tsx (最终完整版) - import { useQuery } from '@tanstack/react-query'; import { getDomains, Domain } from '@/api/domain'; import { CalendarDays, DollarSign } from 'lucide-react'; import { cn } from '@/lib/utils'; import { useEffect, useState } from 'react'; +import { useTranslation } from 'react-i18next'; import RemainPercentBar from "./RemainPercentBar"; -// ======================================================= -// 彩色备注标签组件 -// ======================================================= const DomainNoteTags = ({ notes }: { notes?: string }) => { if (!notes) { return null; @@ -42,11 +38,8 @@ const DomainNoteTags = ({ notes }: { notes?: string }) => { ); }; - -// ======================================================= -// 行内模式卡片 (Inline Mode Card) -// ======================================================= const DomainCardInline = ({ domain }: { domain: Domain }) => { + const { t } = useTranslation(); const expiresIn = domain.expires_in_days; const billingData = domain.BillingData || {}; const customBackgroundImage = (window as any).CustomBackgroundImage !== "" ? (window as any).CustomBackgroundImage : undefined; @@ -75,13 +68,13 @@ const DomainCardInline = ({ domain }: { domain: Domain }) => { {billingData.registrar || 'N/A'}
- 到期: {billingData.endDate ? new Date(billingData.endDate).toLocaleDateString() : 'N/A'} + {t('domain.expiryPrefix')}: {billingData.endDate ? new Date(billingData.endDate).toLocaleDateString() : 'N/A'}
{billingData.renewalPrice || 'N/A'}
- {expiresIn !== undefined ? `${expiresIn} 天` : 'N/A'} + {expiresIn !== undefined ? `${expiresIn} ${t('domain.days')}` : 'N/A'} @@ -90,17 +83,12 @@ const DomainCardInline = ({ domain }: { domain: Domain }) => { ); }; - -// ======================================================= -// 卡片模式 (Card Mode) -// ======================================================= const DomainCard = ({ domain }: { domain: Domain }) => { + const { t } = useTranslation(); const expiresIn = domain.expires_in_days; const billingData = domain.BillingData || {}; const customBackgroundImage = (window as any).CustomBackgroundImage !== "" ? (window as any).CustomBackgroundImage : undefined; - - return (
{

{domain.Domain}

- {billingData.registrar || '未知注册商'} + {billingData.registrar || t('domain.unknownRegistrar')}
{billingData.endDate ? new Date(billingData.endDate).toLocaleDateString() : 'N/A'} @@ -125,7 +113,7 @@ const DomainCard = ({ domain }: { domain: Domain }) => {
- {expiresIn !== undefined ? `${expiresIn}天` : 'N/A'} + {expiresIn !== undefined ? `${expiresIn}${t('domain.days')}` : 'N/A'}
@@ -135,10 +123,6 @@ const DomainCard = ({ domain }: { domain: Domain }) => { ); }; - -// ======================================================= -// 主组件 (Main Component) -// ======================================================= export const DomainStatus = () => { const { data: domains, isLoading, error } = useQuery({ queryKey: ['domains'], @@ -196,4 +180,4 @@ export const DomainStatus = () => { ))}
); -}; \ No newline at end of file +}; diff --git a/src/components/ServerOverview.tsx b/src/components/ServerOverview.tsx index e427da9..2f3b2df 100644 --- a/src/components/ServerOverview.tsx +++ b/src/components/ServerOverview.tsx @@ -151,7 +151,7 @@ export default function ServerOverview({ >
-

总域名数

+

{t("serverOverview.totalDomains")}

{totalDomains}
@@ -195,7 +195,7 @@ export default function ServerOverview({
{!disableAnimatedMan && ( {"animated-man"} (localStorage.getItem(storageKey) as Theme) || "system", ); + const [isSystemDark, setIsSystemDark] = useState( + () => window.matchMedia("(prefers-color-scheme: dark)").matches, + ); + const [hour, setHour] = useState(() => DateTime.now().hour); useEffect(() => { const timer = setInterval(() => { setHour(DateTime.now().hour); }, 60000); - return () => clearInterval(timer); + + const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)"); + const handler = (e: MediaQueryListEvent) => setIsSystemDark(e.matches); + mediaQuery.addEventListener("change", handler); + + return () => { + clearInterval(timer); + mediaQuery.removeEventListener("change", handler); + }; }, []); useEffect(() => { @@ -46,6 +58,8 @@ export function ThemeProvider({ let effectiveTheme = theme; if (theme === "system") { + effectiveTheme = isSystemDark ? "dark" : "light"; + } else if (theme === "scheduled") { // Time-based theme: 18:00 - 06:00 is dark const isNight = hour >= 18 || hour < 6; effectiveTheme = isNight ? "dark" : "light"; @@ -62,7 +76,7 @@ export function ThemeProvider({ root.classList.remove("disable-transitions"); }, 0); return () => window.clearTimeout(timeoutId); - }, [theme, hour]); + }, [theme, hour, isSystemDark]); const value = { theme, diff --git a/src/components/ThemeSwitcher.tsx b/src/components/ThemeSwitcher.tsx index fdd7fe9..f402b64 100644 --- a/src/components/ThemeSwitcher.tsx +++ b/src/components/ThemeSwitcher.tsx @@ -70,6 +70,15 @@ export function ModeToggle() { {t("theme.system")} {theme === "system" && } + handleSelect(e, "scheduled")} + > + {t("theme.scheduled")} + {theme === "scheduled" && } + ); diff --git a/src/locales/en/translation.json b/src/locales/en/translation.json index e2d4f4d..4c971f0 100644 --- a/src/locales/en/translation.json +++ b/src/locales/en/translation.json @@ -19,7 +19,8 @@ "offlineServers": "Offline Servers", "totalBandwidth": "Total Bandwidth", "speed": "Speed", - "network": "Network" + "network": "Network", + "totalDomains": "Total Domains" }, "map": { "Distributions": "Servers are distributed in", @@ -100,7 +101,8 @@ "theme": { "light": "Light", "dark": "Dark", - "system": "System" + "system": "System", + "scheduled": "Scheduled" }, "error": { "pageNotFound": "Page not found", @@ -144,5 +146,12 @@ "ToggleLightMode": "Toggle Light Mode", "ToggleDarkMode": "Toggle Dark Mode", "ToggleSystemMode": "Toggle System Mode", - "Home": "Home" + "Home": "Home", + "domain": { + "registrar": "Registrar", + "expiryDate": "Expiry Date", + "expiryPrefix": "Expires", + "days": "Days", + "unknownRegistrar": "Unknown Registrar" + } } diff --git a/src/locales/zh-CN/translation.json b/src/locales/zh-CN/translation.json index 8a71686..ee4bf98 100644 --- a/src/locales/zh-CN/translation.json +++ b/src/locales/zh-CN/translation.json @@ -19,7 +19,8 @@ "offlineServers": "离线服务器", "totalBandwidth": "总流量", "speed": "速率", - "network": "网络" + "network": "网络", + "totalDomains": "总域名数" }, "map": { "Distributions": "服务器分布在", @@ -101,7 +102,8 @@ "theme": { "light": "亮色", "dark": "暗色", - "system": "跟随系统" + "system": "跟随系统", + "scheduled": "定时切换" }, "error": { "pageNotFound": "页面不存在", @@ -145,5 +147,12 @@ "ToggleLightMode": "切换亮色模式", "ToggleDarkMode": "切换暗色模式", "ToggleSystemMode": "切换系统模式", - "Home": "首页" + "Home": "首页", + "domain": { + "registrar": "注册商", + "expiryDate": "到期日期", + "expiryPrefix": "到期", + "days": "天", + "unknownRegistrar": "未知注册商" + } } diff --git a/src/locales/zh-TW/translation.json b/src/locales/zh-TW/translation.json index 2a56a48..e4bcfa8 100644 --- a/src/locales/zh-TW/translation.json +++ b/src/locales/zh-TW/translation.json @@ -19,7 +19,8 @@ "offlineServers": "離線伺服器", "totalBandwidth": "總帶寬", "speed": "速率", - "network": "網路" + "network": "網路", + "totalDomains": "總域名數" }, "map": { "Distributions": "伺服器分布在", @@ -94,7 +95,8 @@ "theme": { "light": "亮色", "dark": "暗色", - "system": "跟隨系統" + "system": "跟隨系統", + "scheduled": "定時切換" }, "error": { "pageNotFound": "頁面不存在", @@ -136,6 +138,13 @@ "ToggleDarkMode": "切換暗色模式", "ToggleSystemMode": "切換系統模式", "Home": "首頁", + "domain": { + "registrar": "註冊商", + "expiryDate": "到期日期", + "expiryPrefix": "到期", + "days": "天", + "unknownRegistrar": "未知註冊商" + }, "pwa": { "offlineReady": "可離線使用之應用程式", "newContent": "有新内容可用",