feat(desktop): mac zip auto-update

This commit is contained in:
zhayujie
2026-07-07 15:11:55 +08:00
parent 8df38a23d2
commit d531e14fbf
11 changed files with 254 additions and 80 deletions

View File

@@ -84,6 +84,7 @@ const translations: Record<string, Record<string, string>> = {
menu_website: '官网',
menu_docs: '文档中心',
menu_skill_hub: '技能广场',
menu_feedback: '反馈',
// onboarding
onboarding_welcome_title: '欢迎使用 CowAgent',
onboarding_welcome_desc: '你的私人超级 AI 助手。几步设置,即可开始对话。',
@@ -453,6 +454,7 @@ const translations: Record<string, Record<string, string>> = {
menu_website: 'Website',
menu_docs: 'Documentation',
menu_skill_hub: 'Skill Hub',
menu_feedback: 'Feedback',
// onboarding
onboarding_welcome_title: 'Welcome to CowAgent',
onboarding_welcome_desc: 'Your personal super AI assistant. A few quick steps and you are ready to chat.',

View File

@@ -20,6 +20,7 @@ import {
Globe,
FileText,
Store,
MessageSquareWarning,
} from 'lucide-react'
import type { LucideIcon } from 'lucide-react'
// The desktop app's own brand icon (transparent PNG), bundled by Vite.
@@ -41,6 +42,8 @@ const FALLBACK_VERSION = '2.1.3'
// English is the default (no suffix); Chinese gets a /zh suffix. Skill hub is
// language-agnostic.
const SKILL_HUB_URL = 'https://skills.cowagent.ai/'
// GitHub issues — where users report bugs / request features.
const FEEDBACK_URL = 'https://github.com/zhayujie/CowAgent/issues'
const websiteUrl = () => (getLang() === 'zh' ? 'https://cowagent.ai/zh' : 'https://cowagent.ai')
const docsUrl = () => (getLang() === 'zh' ? 'https://docs.cowagent.ai/zh' : 'https://docs.cowagent.ai')
@@ -324,6 +327,11 @@ const FooterMenu: React.FC<{
<MenuItem icon={<Store size={16} />} label={t('menu_skill_hub')} onClick={() => onOpenLink(SKILL_HUB_URL)} />
<MenuItem icon={<FileText size={16} />} label={t('menu_docs')} onClick={() => onOpenLink(docsUrl())} />
<MenuItem icon={<Globe size={16} />} label={t('menu_website')} onClick={() => onOpenLink(websiteUrl())} />
<MenuItem
icon={<MessageSquareWarning size={16} />}
label={t('menu_feedback')}
onClick={() => onOpenLink(FEEDBACK_URL)}
/>
<div className="my-1 border-t border-subtle" />

View File

@@ -1,5 +1,6 @@
import { create } from 'zustand'
import type { UpdateStatus } from '../types'
import { getLang } from '../i18n'
interface UpdateState {
status: UpdateStatus | null
@@ -57,10 +58,11 @@ export const useUpdateStore = create<UpdateState>((set, get) => ({
set({ dismissedVersion: null, panelOpen: true })
}
// Always kick a fresh check too (picks up newer versions / recovers errors).
window.electronAPI?.checkForUpdate?.()
// Pass the UI language so downloads route to the China CDN / R2 accordingly.
window.electronAPI?.checkForUpdate?.(getLang())
},
download: () => window.electronAPI?.downloadUpdate?.(),
download: () => window.electronAPI?.downloadUpdate?.(getLang()),
install: () => window.electronAPI?.installUpdate?.(),
}))

View File

@@ -21,9 +21,9 @@ export interface ElectronAPI {
onMenuAction?: (callback: (action: string) => void) => () => void
// Current app version string (e.g. "0.0.5").
getAppVersion?: () => Promise<string>
// Auto-update
checkForUpdate?: () => Promise<void>
downloadUpdate?: () => Promise<void>
// Auto-update. lang (e.g. "zh") routes installer downloads to the China CDN.
checkForUpdate?: (lang?: string) => Promise<void>
downloadUpdate?: (lang?: string) => Promise<void>
installUpdate?: () => Promise<void>
onUpdateStatus?: (callback: (status: UpdateStatus) => void) => () => void
platform: string