feat(updater): implement auto-install countdown and cancellation for updates (#151)
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* Displays update status and allows manual update checking/installation
|
||||
*/
|
||||
import { useEffect, useCallback } from 'react';
|
||||
import { Download, RefreshCw, Loader2, Rocket } from 'lucide-react';
|
||||
import { Download, RefreshCw, Loader2, Rocket, XCircle } from 'lucide-react';
|
||||
import { Button } from '@/components/ui/button';
|
||||
import { Progress } from '@/components/ui/progress';
|
||||
import { useUpdateStore } from '@/stores/update';
|
||||
@@ -26,10 +26,12 @@ export function UpdateSettings() {
|
||||
progress,
|
||||
error,
|
||||
isInitialized,
|
||||
autoInstallCountdown,
|
||||
init,
|
||||
checkForUpdates,
|
||||
downloadUpdate,
|
||||
installUpdate,
|
||||
cancelAutoInstall,
|
||||
clearError,
|
||||
} = useUpdateStore();
|
||||
|
||||
@@ -60,6 +62,9 @@ export function UpdateSettings() {
|
||||
};
|
||||
|
||||
const renderStatusText = () => {
|
||||
if (status === 'downloaded' && autoInstallCountdown != null && autoInstallCountdown >= 0) {
|
||||
return t('updates.status.autoInstalling', { seconds: autoInstallCountdown });
|
||||
}
|
||||
switch (status) {
|
||||
case 'checking':
|
||||
return t('updates.status.checking');
|
||||
@@ -102,6 +107,14 @@ export function UpdateSettings() {
|
||||
</Button>
|
||||
);
|
||||
case 'downloaded':
|
||||
if (autoInstallCountdown != null && autoInstallCountdown >= 0) {
|
||||
return (
|
||||
<Button onClick={cancelAutoInstall} size="sm" variant="outline">
|
||||
<XCircle className="h-4 w-4 mr-2" />
|
||||
{t('updates.action.cancelAutoInstall')}
|
||||
</Button>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<Button onClick={installUpdate} size="sm" variant="default">
|
||||
<Rocket className="h-4 w-4 mr-2" />
|
||||
|
||||
@@ -72,13 +72,14 @@
|
||||
"description": "Keep ClawX up to date",
|
||||
"autoCheck": "Auto-check for updates",
|
||||
"autoCheckDesc": "Check for updates on startup",
|
||||
"autoDownload": "Auto-download updates",
|
||||
"autoDownloadDesc": "Download updates in the background",
|
||||
"autoDownload": "Auto-update",
|
||||
"autoDownloadDesc": "Automatically download and install updates",
|
||||
"status": {
|
||||
"checking": "Checking for updates...",
|
||||
"downloading": "Downloading update...",
|
||||
"available": "Update available: v{{version}}",
|
||||
"downloaded": "Ready to install: v{{version}}",
|
||||
"autoInstalling": "Restarting to install update in {{seconds}}s...",
|
||||
"failed": "Update check failed",
|
||||
"latest": "You have the latest version",
|
||||
"check": "Check for updates to get the latest features"
|
||||
@@ -88,13 +89,14 @@
|
||||
"downloading": "Downloading...",
|
||||
"download": "Download Update",
|
||||
"install": "Install & Restart",
|
||||
"cancelAutoInstall": "Cancel",
|
||||
"retry": "Retry",
|
||||
"check": "Check for Updates"
|
||||
},
|
||||
"currentVersion": "Current Version",
|
||||
"whatsNew": "What's New:",
|
||||
"errorDetails": "Error Details:",
|
||||
"help": "Updates are downloaded in the background and installed when you restart the app."
|
||||
"help": "When auto-update is enabled, updates are downloaded and installed automatically."
|
||||
},
|
||||
"advanced": {
|
||||
"title": "Advanced",
|
||||
|
||||
@@ -72,8 +72,31 @@
|
||||
"description": "ClawX を最新に保つ",
|
||||
"autoCheck": "自動更新チェック",
|
||||
"autoCheckDesc": "起動時に更新を確認",
|
||||
"autoDownload": "自動ダウンロード",
|
||||
"autoDownloadDesc": "バックグラウンドで更新をダウンロード"
|
||||
"autoDownload": "自動アップデート",
|
||||
"autoDownloadDesc": "更新を自動的にダウンロードしてインストール",
|
||||
"status": {
|
||||
"checking": "更新を確認中...",
|
||||
"downloading": "更新をダウンロード中...",
|
||||
"available": "更新あり: v{{version}}",
|
||||
"downloaded": "インストール準備完了: v{{version}}",
|
||||
"autoInstalling": "{{seconds}} 秒後に再起動して更新をインストールします...",
|
||||
"failed": "更新の確認に失敗しました",
|
||||
"latest": "最新バージョンです",
|
||||
"check": "更新を確認して最新の機能を入手"
|
||||
},
|
||||
"action": {
|
||||
"checking": "確認中...",
|
||||
"downloading": "ダウンロード中...",
|
||||
"download": "更新をダウンロード",
|
||||
"install": "インストールして再起動",
|
||||
"cancelAutoInstall": "キャンセル",
|
||||
"retry": "再試行",
|
||||
"check": "更新を確認"
|
||||
},
|
||||
"currentVersion": "現在のバージョン",
|
||||
"whatsNew": "更新内容:",
|
||||
"errorDetails": "エラー詳細:",
|
||||
"help": "自動アップデートが有効な場合、更新は自動的にダウンロードされインストールされます。"
|
||||
},
|
||||
"advanced": {
|
||||
"title": "詳細設定",
|
||||
|
||||
@@ -72,13 +72,14 @@
|
||||
"description": "保持 ClawX 最新",
|
||||
"autoCheck": "自动检查更新",
|
||||
"autoCheckDesc": "启动时检查更新",
|
||||
"autoDownload": "自动下载更新",
|
||||
"autoDownloadDesc": "在后台下载更新",
|
||||
"autoDownload": "自动更新",
|
||||
"autoDownloadDesc": "自动下载并安装更新",
|
||||
"status": {
|
||||
"checking": "正在检查更新...",
|
||||
"downloading": "正在下载更新...",
|
||||
"available": "可用更新:v{{version}}",
|
||||
"downloaded": "准备安装:v{{version}}",
|
||||
"autoInstalling": "将在 {{seconds}} 秒后重启并安装更新...",
|
||||
"failed": "检查更新失败",
|
||||
"latest": "您已拥有最新版本",
|
||||
"check": "检查更新以获取最新功能"
|
||||
@@ -88,13 +89,14 @@
|
||||
"downloading": "下载中...",
|
||||
"download": "下载更新",
|
||||
"install": "安装并重启",
|
||||
"cancelAutoInstall": "取消",
|
||||
"retry": "重试",
|
||||
"check": "检查更新"
|
||||
},
|
||||
"currentVersion": "当前版本",
|
||||
"whatsNew": "更新内容:",
|
||||
"errorDetails": "错误详情:",
|
||||
"help": "更新将在后台下载,并在您重启应用时安装。"
|
||||
"help": "开启自动更新后,更新将自动下载并安装。"
|
||||
},
|
||||
"advanced": {
|
||||
"title": "高级",
|
||||
|
||||
@@ -35,12 +35,15 @@ interface UpdateState {
|
||||
progress: ProgressInfo | null;
|
||||
error: string | null;
|
||||
isInitialized: boolean;
|
||||
/** Seconds remaining before auto-install, or null if inactive. */
|
||||
autoInstallCountdown: number | null;
|
||||
|
||||
// Actions
|
||||
init: () => Promise<void>;
|
||||
checkForUpdates: () => Promise<void>;
|
||||
downloadUpdate: () => Promise<void>;
|
||||
installUpdate: () => void;
|
||||
cancelAutoInstall: () => Promise<void>;
|
||||
setChannel: (channel: 'stable' | 'beta' | 'dev') => Promise<void>;
|
||||
setAutoDownload: (enable: boolean) => Promise<void>;
|
||||
clearError: () => void;
|
||||
@@ -53,6 +56,7 @@ export const useUpdateStore = create<UpdateState>((set, get) => ({
|
||||
progress: null,
|
||||
error: null,
|
||||
isInitialized: false,
|
||||
autoInstallCountdown: null,
|
||||
|
||||
init: async () => {
|
||||
if (get().isInitialized) return;
|
||||
@@ -101,6 +105,11 @@ export const useUpdateStore = create<UpdateState>((set, get) => ({
|
||||
});
|
||||
});
|
||||
|
||||
window.electron.ipcRenderer.on('update:auto-install-countdown', (data) => {
|
||||
const { seconds, cancelled } = data as { seconds: number; cancelled?: boolean };
|
||||
set({ autoInstallCountdown: cancelled ? null : seconds });
|
||||
});
|
||||
|
||||
set({ isInitialized: true });
|
||||
|
||||
// Apply persisted settings from the settings store
|
||||
@@ -180,6 +189,14 @@ export const useUpdateStore = create<UpdateState>((set, get) => ({
|
||||
window.electron.ipcRenderer.invoke('update:install');
|
||||
},
|
||||
|
||||
cancelAutoInstall: async () => {
|
||||
try {
|
||||
await window.electron.ipcRenderer.invoke('update:cancelAutoInstall');
|
||||
} catch (error) {
|
||||
console.error('Failed to cancel auto-install:', error);
|
||||
}
|
||||
},
|
||||
|
||||
setChannel: async (channel) => {
|
||||
try {
|
||||
await window.electron.ipcRenderer.invoke('update:setChannel', channel);
|
||||
|
||||
Reference in New Issue
Block a user