diff --git a/webui/src/components/Header.tsx b/webui/src/components/Header.tsx index 1c1d8fc..782af27 100644 --- a/webui/src/components/Header.tsx +++ b/webui/src/components/Header.tsx @@ -1,19 +1,60 @@ import React from 'react'; -import { Terminal, Globe, Menu, Moon, SunMedium } from 'lucide-react'; +import { Terminal, Globe, Github, Menu, Moon, RefreshCw, SunMedium } from 'lucide-react'; import { useTranslation } from 'react-i18next'; import { useAppContext } from '../context/AppContext'; import { useUI } from '../context/UIContext'; +const REPO_URL = 'https://github.com/YspCoder/clawgo'; + +function normalizeVersion(value: string) { + return String(value || '').trim().replace(/^v/i, ''); +} + const Header: React.FC = () => { const { t, i18n } = useTranslation(); - const { isGatewayOnline, setSidebarOpen, sidebarCollapsed } = useAppContext(); - const { theme, toggleTheme } = useUI(); + const { isGatewayOnline, setSidebarOpen, sidebarCollapsed, gatewayVersion, webuiVersion } = useAppContext(); + const { theme, toggleTheme, notify } = useUI(); + const [checkingVersion, setCheckingVersion] = React.useState(false); const toggleLang = () => { const nextLang = i18n.language === 'en' ? 'zh' : 'en'; i18n.changeLanguage(nextLang); }; + const checkVersion = async () => { + setCheckingVersion(true); + try { + const response = await fetch('https://api.github.com/repos/YspCoder/clawgo/releases/latest', { + headers: { Accept: 'application/vnd.github+json' }, + }); + if (!response.ok) { + throw new Error(`GitHub API ${response.status}`); + } + const data = await response.json(); + const latest = normalizeVersion(data?.tag_name || ''); + const currentGateway = normalizeVersion(gatewayVersion); + const currentWebUI = normalizeVersion(webuiVersion); + const isCurrent = latest && latest === currentGateway && latest === currentWebUI; + await notify({ + title: isCurrent ? t('versionCheckUpToDateTitle') : t('versionCheckUpdateTitle'), + message: isCurrent + ? t('versionCheckUpToDateMessage', { version: latest || '-' }) + : t('versionCheckUpdateMessage', { + latest: latest || '-', + gateway: currentGateway || '-', + webui: currentWebUI || '-', + }), + }); + } catch (error) { + await notify({ + title: t('versionCheckFailedTitle'), + message: t('versionCheckFailedMessage', { error: error instanceof Error ? error.message : String(error) }), + }); + } finally { + setCheckingVersion(false); + } + }; + return (
@@ -52,6 +93,25 @@ const Header: React.FC = () => {
+ + + + + +