diff --git a/electron/main.ts b/electron/main.ts index 81e0c5d..4e331bc 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -552,6 +552,11 @@ function registerIpcHandlers() { } }) + ipcMain.handle('app:ignoreUpdate', async (_, version: string) => { + configService?.set('ignoredUpdateVersion', version) + return { success: true } + }) + // 窗口控制 ipcMain.on('window:minimize', (event) => { BrowserWindow.fromWebContents(event.sender)?.minimize() @@ -1159,7 +1164,16 @@ function checkForUpdatesOnStartup() { if (result && result.updateInfo) { const currentVersion = app.getVersion() const latestVersion = result.updateInfo.version + + // 检查是否有新版本 if (latestVersion !== currentVersion && mainWindow) { + // 检查该版本是否被用户忽略 + const ignoredVersion = configService?.get('ignoredUpdateVersion') + if (ignoredVersion === latestVersion) { + console.log(`版本 ${latestVersion} 已被用户忽略,跳过更新提示`) + return + } + // 通知渲染进程有新版本 mainWindow.webContents.send('app:updateAvailable', { version: latestVersion, diff --git a/electron/preload.ts b/electron/preload.ts index 2c259eb..c0bfb69 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -34,6 +34,7 @@ contextBridge.exposeInMainWorld('electronAPI', { getVersion: () => ipcRenderer.invoke('app:getVersion'), checkForUpdates: () => ipcRenderer.invoke('app:checkForUpdates'), downloadAndInstall: () => ipcRenderer.invoke('app:downloadAndInstall'), + ignoreUpdate: (version: string) => ipcRenderer.invoke('app:ignoreUpdate', version), onDownloadProgress: (callback: (progress: any) => void) => { ipcRenderer.on('app:downloadProgress', (_, progress) => callback(progress)) return () => ipcRenderer.removeAllListeners('app:downloadProgress') diff --git a/electron/services/config.ts b/electron/services/config.ts index 621ca08..34f1fb8 100644 --- a/electron/services/config.ts +++ b/electron/services/config.ts @@ -33,6 +33,9 @@ interface ConfigSchema { authEnabled: boolean authPassword: string // SHA-256 hash authUseHello: boolean + + // 更新相关 + ignoredUpdateVersion: string } export class ConfigService { @@ -67,7 +70,9 @@ export class ConfigService { authEnabled: false, authPassword: '', - authUseHello: false + authUseHello: false, + + ignoredUpdateVersion: '' } }) } diff --git a/src/App.tsx b/src/App.tsx index 95d9e9d..dff779a 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -203,6 +203,18 @@ function App() { } } + const handleIgnoreUpdate = async () => { + if (!updateInfo || !updateInfo.version) return + + try { + await window.electronAPI.app.ignoreUpdate(updateInfo.version) + setShowUpdateDialog(false) + setUpdateInfo(null) + } catch (e: any) { + console.error('忽略更新失败:', e) + } + } + const dismissUpdate = () => { setUpdateInfo(null) } @@ -383,6 +395,7 @@ function App() { updateInfo={updateInfo} onClose={() => setShowUpdateDialog(false)} onUpdate={handleUpdateNow} + onIgnore={handleIgnoreUpdate} isDownloading={isDownloading} progress={downloadProgress} /> diff --git a/src/components/UpdateDialog.scss b/src/components/UpdateDialog.scss index 452447a..f12a6d8 100644 --- a/src/components/UpdateDialog.scss +++ b/src/components/UpdateDialog.scss @@ -171,6 +171,29 @@ .actions { display: flex; justify-content: center; + gap: 12px; + + .btn-ignore { + background: transparent; + color: #666666; + border: 1px solid #d0d0d0; + padding: 16px 32px; + border-radius: 20px; + font-size: 16px; + font-weight: 600; + cursor: pointer; + transition: all 0.2s; + + &:hover { + background: #f5f5f5; + border-color: #999999; + color: #333333; + } + + &:active { + transform: scale(0.98); + } + } .btn-update { background: #000000; diff --git a/src/components/UpdateDialog.tsx b/src/components/UpdateDialog.tsx index 78f3db5..bafdb18 100644 --- a/src/components/UpdateDialog.tsx +++ b/src/components/UpdateDialog.tsx @@ -12,6 +12,7 @@ interface UpdateDialogProps { updateInfo: UpdateInfo | null onClose: () => void onUpdate: () => void + onIgnore?: () => void isDownloading: boolean progress: number | { percent: number @@ -27,6 +28,7 @@ const UpdateDialog: React.FC = ({ updateInfo, onClose, onUpdate, + onIgnore, isDownloading, progress }) => { @@ -118,6 +120,11 @@ const UpdateDialog: React.FC = ({ ) : (
+ {onIgnore && ( + + )} diff --git a/src/pages/SettingsPage.tsx b/src/pages/SettingsPage.tsx index f4603b3..f746c87 100644 --- a/src/pages/SettingsPage.tsx +++ b/src/pages/SettingsPage.tsx @@ -316,6 +316,19 @@ function SettingsPage() { } } + const handleIgnoreUpdate = async () => { + if (!updateInfo || !updateInfo.version) return + + try { + await window.electronAPI.app.ignoreUpdate(updateInfo.version) + setShowUpdateDialog(false) + setUpdateInfo(null) + showMessage(`已忽略版本 ${updateInfo.version}`, true) + } catch (e: any) { + showMessage(`操作失败: ${e}`, false) + } + } + const showMessage = (text: string, success: boolean) => { diff --git a/src/services/config.ts b/src/services/config.ts index e0a20c2..01b5cb7 100644 --- a/src/services/config.ts +++ b/src/services/config.ts @@ -35,7 +35,10 @@ export const CONFIG_KEYS = { // 安全 AUTH_ENABLED: 'authEnabled', AUTH_PASSWORD: 'authPassword', - AUTH_USE_HELLO: 'authUseHello' + AUTH_USE_HELLO: 'authUseHello', + + // 更新 + IGNORED_UPDATE_VERSION: 'ignoredUpdateVersion' } as const export interface WxidConfig { @@ -399,3 +402,17 @@ export async function getAuthUseHello(): Promise { export async function setAuthUseHello(useHello: boolean): Promise { await config.set(CONFIG_KEYS.AUTH_USE_HELLO, useHello) } + +// === 更新相关 === + +// 获取被忽略的更新版本 +export async function getIgnoredUpdateVersion(): Promise { + const value = await config.get(CONFIG_KEYS.IGNORED_UPDATE_VERSION) + return (value as string) || null +} + +// 设置被忽略的更新版本 +export async function setIgnoredUpdateVersion(version: string): Promise { + await config.set(CONFIG_KEYS.IGNORED_UPDATE_VERSION, version) +} + diff --git a/src/types/electron.d.ts b/src/types/electron.d.ts index 67b1097..aeff9dd 100644 --- a/src/types/electron.d.ts +++ b/src/types/electron.d.ts @@ -32,6 +32,7 @@ export interface ElectronAPI { getVersion: () => Promise checkForUpdates: () => Promise<{ hasUpdate: boolean; version?: string; releaseNotes?: string }> downloadAndInstall: () => Promise + ignoreUpdate: (version: string) => Promise<{ success: boolean }> onDownloadProgress: (callback: (progress: number) => void) => () => void onUpdateAvailable: (callback: (info: { version: string; releaseNotes: string }) => void) => () => void }