From d2a921a75db8d7c4010b47211dce9d7323506ad1 Mon Sep 17 00:00:00 2001 From: Michael Neale Date: Sun, 21 Jun 2026 08:41:30 +1000 Subject: [PATCH] feat: add option to disable automatic update downloads (#9872) Signed-off-by: Douwe Osinga Co-authored-by: Crazyop757 <83007860+Crazyop757@users.noreply.github.com> Co-authored-by: Douwe Osinga --- .../components/settings/app/UpdateSection.tsx | 112 +++++++++++++++++- ui/desktop/src/i18n/messages/en.json | 15 +++ ui/desktop/src/i18n/messages/es.json | 15 +++ ui/desktop/src/i18n/messages/hi.json | 15 +++ ui/desktop/src/i18n/messages/ja.json | 15 +++ ui/desktop/src/i18n/messages/ko.json | 15 +++ ui/desktop/src/i18n/messages/ru.json | 15 +++ ui/desktop/src/i18n/messages/tr.json | 15 +++ ui/desktop/src/i18n/messages/zh-CN.json | 15 +++ ui/desktop/src/main.ts | 10 ++ ui/desktop/src/preload.ts | 4 + ui/desktop/src/utils/autoUpdater.ts | 58 +++++++-- ui/desktop/src/utils/settings.ts | 2 + 13 files changed, 289 insertions(+), 17 deletions(-) diff --git a/ui/desktop/src/components/settings/app/UpdateSection.tsx b/ui/desktop/src/components/settings/app/UpdateSection.tsx index 37e9dd177..d295f1f9d 100644 --- a/ui/desktop/src/components/settings/app/UpdateSection.tsx +++ b/ui/desktop/src/components/settings/app/UpdateSection.tsx @@ -5,6 +5,28 @@ import { errorMessage } from '../../../utils/conversionUtils'; import { defineMessages, useIntl } from '../../../i18n'; const i18n = defineMessages({ + disableAutoDownload: { + id: 'updateSection.disableAutoDownload', + defaultMessage: 'Disable automatic update downloads', + }, + disableAutoDownloadDesc: { + id: 'updateSection.disableAutoDownloadDesc', + defaultMessage: + 'When enabled, Goose will notify you of new versions but will not download them automatically.', + }, + autoDownloadDisabledByEnv: { + id: 'updateSection.autoDownloadDisabledByEnv', + defaultMessage: + 'Automatic downloads are disabled via the GOOSE_DISABLE_AUTO_DOWNLOAD environment variable.', + }, + downloadNow: { + id: 'updateSection.downloadNow', + defaultMessage: 'Download Now', + }, + autoDownloadDisabledNote: { + id: 'updateSection.autoDownloadDisabledNote', + defaultMessage: 'Automatic download is disabled. Click "Download Now" to download manually.', + }, loading: { id: 'updateSection.loading', defaultMessage: 'Loading...', @@ -116,6 +138,8 @@ export default function UpdateSection() { }); const [progress, setProgress] = useState(0); const [isUsingGitHubFallback, setIsUsingGitHubFallback] = useState(false); + const [disableAutoDownload, setDisableAutoDownload] = useState(false); + const [autoDownloadForcedByEnv, setAutoDownloadForcedByEnv] = useState(false); const progressTimeoutRef = React.useRef | null>(null); const lastProgressRef = React.useRef(0); // Track last progress to prevent backward jumps @@ -140,6 +164,16 @@ export default function UpdateSection() { setIsUsingGitHubFallback(isGitHub); }); + window.electron.getSetting('disableAutoDownload').then((stored) => { + setDisableAutoDownload(!!stored); + }); + window.electron.getAutoDownloadDisabled().then((effective) => { + window.electron.getSetting('disableAutoDownload').then((stored) => { + // If effective is true but user setting is false, env var is forcing it + setAutoDownloadForcedByEnv(effective && !stored); + }); + }); + // Listen for updater events window.electron.onUpdaterEvent((event) => { @@ -249,6 +283,30 @@ export default function UpdateSection() { window.electron.installUpdate(); }; + const downloadUpdate = async () => { + setUpdateStatus('downloading'); + setProgress(0); + lastProgressRef.current = 0; + try { + const result = await window.electron.downloadUpdate(); + if (result.error) { + throw new Error(result.error); + } + } catch (error) { + setUpdateInfo((prev) => ({ + ...prev, + error: errorMessage(error, 'Failed to download update'), + })); + setUpdateStatus('error'); + setTimeout(() => setUpdateStatus('idle'), 5000); + } + }; + + const toggleAutoDownload = async (disabled: boolean) => { + setDisableAutoDownload(disabled); + await window.electron.setSetting('disableAutoDownload', disabled); + }; + const getStatusMessage = () => { switch (updateStatus) { case 'checking': @@ -287,6 +345,8 @@ export default function UpdateSection() { } }; + const autoDownloadEffectivelyDisabled = disableAutoDownload || autoDownloadForcedByEnv; + return (
@@ -315,6 +375,12 @@ export default function UpdateSection() { {intl.formatMessage(i18n.checkForUpdates)} + {updateInfo.isUpdateAvailable && updateStatus === 'idle' && autoDownloadEffectivelyDisabled && ( + + )} + {updateStatus === 'ready' && (
)}
+ + {/* Auto-download toggle */} +
+ {autoDownloadForcedByEnv ? ( +

+ {intl.formatMessage(i18n.autoDownloadDisabledByEnv)} +

+ ) : ( + + )} +
); } diff --git a/ui/desktop/src/i18n/messages/en.json b/ui/desktop/src/i18n/messages/en.json index b107ff79f..167e5697d 100644 --- a/ui/desktop/src/i18n/messages/en.json +++ b/ui/desktop/src/i18n/messages/en.json @@ -4760,6 +4760,12 @@ "updateSection.autoDownload": { "defaultMessage": "Update will be downloaded automatically in the background." }, + "updateSection.autoDownloadDisabledByEnv": { + "defaultMessage": "Automatic downloads are disabled via the GOOSE_DISABLE_AUTO_DOWNLOAD environment variable." + }, + "updateSection.autoDownloadDisabledNote": { + "defaultMessage": "Automatic download is disabled. Click \"Download Now\" to download manually." + }, "updateSection.autoInstallNote": { "defaultMessage": "The update will be installed automatically when you quit the app." }, @@ -4772,6 +4778,15 @@ "updateSection.currentVersion": { "defaultMessage": "Current version" }, + "updateSection.disableAutoDownload": { + "defaultMessage": "Disable automatic update downloads" + }, + "updateSection.disableAutoDownloadDesc": { + "defaultMessage": "When enabled, Goose will notify you of new versions but will not download them automatically." + }, + "updateSection.downloadNow": { + "defaultMessage": "Download Now" + }, "updateSection.downloadReady": { "defaultMessage": "Update downloaded and ready to install!" }, diff --git a/ui/desktop/src/i18n/messages/es.json b/ui/desktop/src/i18n/messages/es.json index feb924c9f..c94ceb5a4 100644 --- a/ui/desktop/src/i18n/messages/es.json +++ b/ui/desktop/src/i18n/messages/es.json @@ -4760,6 +4760,12 @@ "updateSection.autoDownload": { "defaultMessage": "La actualización se descargará automáticamente en segundo plano." }, + "updateSection.autoDownloadDisabledByEnv": { + "defaultMessage": "Las descargas automáticas están desactivadas mediante la variable de entorno GOOSE_DISABLE_AUTO_DOWNLOAD." + }, + "updateSection.autoDownloadDisabledNote": { + "defaultMessage": "La descarga automática está desactivada. Haz clic en «Descargar ahora» para descargar manualmente." + }, "updateSection.autoInstallNote": { "defaultMessage": "La actualización se instalará automáticamente cuando cierres la app." }, @@ -4772,6 +4778,15 @@ "updateSection.currentVersion": { "defaultMessage": "Versión actual" }, + "updateSection.disableAutoDownload": { + "defaultMessage": "Desactivar la descarga automática de actualizaciones" + }, + "updateSection.disableAutoDownloadDesc": { + "defaultMessage": "Cuando está activado, Goose te avisará de nuevas versiones pero no las descargará automáticamente." + }, + "updateSection.downloadNow": { + "defaultMessage": "Descargar ahora" + }, "updateSection.downloadReady": { "defaultMessage": "¡Actualización descargada y lista para instalar!" }, diff --git a/ui/desktop/src/i18n/messages/hi.json b/ui/desktop/src/i18n/messages/hi.json index 3dcb53891..bd81c1e60 100644 --- a/ui/desktop/src/i18n/messages/hi.json +++ b/ui/desktop/src/i18n/messages/hi.json @@ -4760,6 +4760,12 @@ "updateSection.autoDownload": { "defaultMessage": "अपडेट बैकग्राउंड में अपने आप डाउनलोड हो जाएगा." }, + "updateSection.autoDownloadDisabledByEnv": { + "defaultMessage": "स्वचालित डाउनलोड GOOSE_DISABLE_AUTO_DOWNLOAD पर्यावरण चर के माध्यम से अक्षम हैं।" + }, + "updateSection.autoDownloadDisabledNote": { + "defaultMessage": "स्वचालित डाउनलोड अक्षम है। मैन्युअल रूप से डाउनलोड करने के लिए \"अभी डाउनलोड करें\" पर क्लिक करें।" + }, "updateSection.autoInstallNote": { "defaultMessage": "जब आप ऐप छोड़ देंगे तो अपडेट अपने आप इंस्टॉल हो जाएगा।" }, @@ -4772,6 +4778,15 @@ "updateSection.currentVersion": { "defaultMessage": "वर्तमान संस्करण" }, + "updateSection.disableAutoDownload": { + "defaultMessage": "स्वचालित अपडेट डाउनलोड अक्षम करें" + }, + "updateSection.disableAutoDownloadDesc": { + "defaultMessage": "सक्षम होने पर, Goose आपको नई संस्करणों की सूचना देगा लेकिन उन्हें स्वचालित रूप से डाउनलोड नहीं करेगा।" + }, + "updateSection.downloadNow": { + "defaultMessage": "अभी डाउनलोड करें" + }, "updateSection.downloadReady": { "defaultMessage": "अपडेट डाउनलोड हो गया है और इंस्टॉल करने के लिए तैयार है!" }, diff --git a/ui/desktop/src/i18n/messages/ja.json b/ui/desktop/src/i18n/messages/ja.json index 661645b53..cdf2ada5f 100644 --- a/ui/desktop/src/i18n/messages/ja.json +++ b/ui/desktop/src/i18n/messages/ja.json @@ -4760,6 +4760,12 @@ "updateSection.autoDownload": { "defaultMessage": "アップデートはバックグラウンドで自動的にダウンロードされます。" }, + "updateSection.autoDownloadDisabledByEnv": { + "defaultMessage": "自動ダウンロードは GOOSE_DISABLE_AUTO_DOWNLOAD 環境変数によって無効になっています。" + }, + "updateSection.autoDownloadDisabledNote": { + "defaultMessage": "自動ダウンロードは無効です。手動でダウンロードするには「今すぐダウンロード」をクリックしてください。" + }, "updateSection.autoInstallNote": { "defaultMessage": "アプリを終了すると、アップデートが自動的にインストールされます。" }, @@ -4772,6 +4778,15 @@ "updateSection.currentVersion": { "defaultMessage": "現在のバージョン" }, + "updateSection.disableAutoDownload": { + "defaultMessage": "アップデートの自動ダウンロードを無効にする" + }, + "updateSection.disableAutoDownloadDesc": { + "defaultMessage": "有効にすると、Goose は新しいバージョンを通知しますが、自動的にはダウンロードしません。" + }, + "updateSection.downloadNow": { + "defaultMessage": "今すぐダウンロード" + }, "updateSection.downloadReady": { "defaultMessage": "アップデートのダウンロードが完了し、インストールの準備ができました!" }, diff --git a/ui/desktop/src/i18n/messages/ko.json b/ui/desktop/src/i18n/messages/ko.json index 285ac637b..70d5805d0 100644 --- a/ui/desktop/src/i18n/messages/ko.json +++ b/ui/desktop/src/i18n/messages/ko.json @@ -4760,6 +4760,12 @@ "updateSection.autoDownload": { "defaultMessage": "업데이트는 백그라운드에서 자동으로 다운로드됩니다." }, + "updateSection.autoDownloadDisabledByEnv": { + "defaultMessage": "자동 다운로드는 GOOSE_DISABLE_AUTO_DOWNLOAD 환경 변수를 통해 비활성화되어 있습니다." + }, + "updateSection.autoDownloadDisabledNote": { + "defaultMessage": "자동 다운로드가 비활성화되어 있습니다. 수동으로 다운로드하려면 \"지금 다운로드\"를 클릭하세요." + }, "updateSection.autoInstallNote": { "defaultMessage": "앱을 종료하면 업데이트가 자동으로 설치됩니다." }, @@ -4772,6 +4778,15 @@ "updateSection.currentVersion": { "defaultMessage": "현재 버전" }, + "updateSection.disableAutoDownload": { + "defaultMessage": "자동 업데이트 다운로드 비활성화" + }, + "updateSection.disableAutoDownloadDesc": { + "defaultMessage": "활성화하면 Goose가 새 버전을 알려주지만 자동으로 다운로드하지는 않습니다." + }, + "updateSection.downloadNow": { + "defaultMessage": "지금 다운로드" + }, "updateSection.downloadReady": { "defaultMessage": "업데이트가 다운로드되었으며 설치 준비가 완료되었습니다!" }, diff --git a/ui/desktop/src/i18n/messages/ru.json b/ui/desktop/src/i18n/messages/ru.json index ea1a3fcdf..3e06cbf03 100644 --- a/ui/desktop/src/i18n/messages/ru.json +++ b/ui/desktop/src/i18n/messages/ru.json @@ -4760,6 +4760,12 @@ "updateSection.autoDownload": { "defaultMessage": "Обновление будет автоматически скачано в фоновом режиме." }, + "updateSection.autoDownloadDisabledByEnv": { + "defaultMessage": "Автоматическая загрузка отключена через переменную окружения GOOSE_DISABLE_AUTO_DOWNLOAD." + }, + "updateSection.autoDownloadDisabledNote": { + "defaultMessage": "Автоматическая загрузка отключена. Нажмите «Скачать сейчас», чтобы загрузить вручную." + }, "updateSection.autoInstallNote": { "defaultMessage": "Обновление будет установлено автоматически при выходе из приложения." }, @@ -4772,6 +4778,15 @@ "updateSection.currentVersion": { "defaultMessage": "Текущая версия" }, + "updateSection.disableAutoDownload": { + "defaultMessage": "Отключить автоматическую загрузку обновлений" + }, + "updateSection.disableAutoDownloadDesc": { + "defaultMessage": "Когда включено, Goose будет уведомлять о новых версиях, но не будет загружать их автоматически." + }, + "updateSection.downloadNow": { + "defaultMessage": "Скачать сейчас" + }, "updateSection.downloadReady": { "defaultMessage": "Обновление скачано и готово к установке!" }, diff --git a/ui/desktop/src/i18n/messages/tr.json b/ui/desktop/src/i18n/messages/tr.json index 7dcd1ca03..af5b66864 100644 --- a/ui/desktop/src/i18n/messages/tr.json +++ b/ui/desktop/src/i18n/messages/tr.json @@ -4760,6 +4760,12 @@ "updateSection.autoDownload": { "defaultMessage": "Güncelleme arka planda otomatik olarak indirilecektir." }, + "updateSection.autoDownloadDisabledByEnv": { + "defaultMessage": "Otomatik indirmeler GOOSE_DISABLE_AUTO_DOWNLOAD ortam değişkeni aracılığıyla devre dışı bırakılmıştır." + }, + "updateSection.autoDownloadDisabledNote": { + "defaultMessage": "Otomatik indirme devre dışı. Manuel olarak indirmek için \"Şimdi İndir\"e tıklayın." + }, "updateSection.autoInstallNote": { "defaultMessage": "Uygulamadan çıktığınızda güncelleme otomatik olarak yüklenecektir." }, @@ -4772,6 +4778,15 @@ "updateSection.currentVersion": { "defaultMessage": "Güncel sürüm" }, + "updateSection.disableAutoDownload": { + "defaultMessage": "Otomatik güncelleme indirmelerini devre dışı bırak" + }, + "updateSection.disableAutoDownloadDesc": { + "defaultMessage": "Etkinleştirildiğinde, Goose yeni sürümleri bildirir ancak bunları otomatik olarak indirmez." + }, + "updateSection.downloadNow": { + "defaultMessage": "Şimdi İndir" + }, "updateSection.downloadReady": { "defaultMessage": "Güncelleme indirildi ve kuruluma hazır!" }, diff --git a/ui/desktop/src/i18n/messages/zh-CN.json b/ui/desktop/src/i18n/messages/zh-CN.json index aba52dd19..f2534e317 100644 --- a/ui/desktop/src/i18n/messages/zh-CN.json +++ b/ui/desktop/src/i18n/messages/zh-CN.json @@ -4760,6 +4760,12 @@ "updateSection.autoDownload": { "defaultMessage": "更新将在后台自动下载。" }, + "updateSection.autoDownloadDisabledByEnv": { + "defaultMessage": "自动下载已通过 GOOSE_DISABLE_AUTO_DOWNLOAD 环境变量禁用。" + }, + "updateSection.autoDownloadDisabledNote": { + "defaultMessage": "自动下载已禁用。点击\"立即下载\"以手动下载。" + }, "updateSection.autoInstallNote": { "defaultMessage": "退出应用时将自动安装更新。" }, @@ -4772,6 +4778,15 @@ "updateSection.currentVersion": { "defaultMessage": "当前版本" }, + "updateSection.disableAutoDownload": { + "defaultMessage": "禁用自动更新下载" + }, + "updateSection.disableAutoDownloadDesc": { + "defaultMessage": "启用后,Goose 会通知你有新版本,但不会自动下载。" + }, + "updateSection.downloadNow": { + "defaultMessage": "立即下载" + }, "updateSection.downloadReady": { "defaultMessage": "更新已下载,可以安装!" }, diff --git a/ui/desktop/src/main.ts b/ui/desktop/src/main.ts index def607497..cd8b69ac3 100644 --- a/ui/desktop/src/main.ts +++ b/ui/desktop/src/main.ts @@ -41,6 +41,7 @@ import windowStateKeeper from 'electron-window-state'; import { getUpdateAvailable, registerUpdateIpcHandlers, + setAutoDownloadDisabled, setTrayRef, setupAutoUpdater, updateTrayMenu, @@ -1736,6 +1737,7 @@ const validSettingKeys: Set = new Set([ 'showPricing', 'sessionSharing', 'seenAnnouncementIds', + 'disableAutoDownload', ]); ipcMain.handle('set-setting', (_event, key: SettingKey, value: unknown) => { @@ -1763,6 +1765,10 @@ ipcMain.handle('set-setting', (_event, key: SettingKey, value: unknown) => { if (key === 'keyboardShortcuts') { registerGlobalShortcuts(); } + + if (key === 'disableAutoDownload') { + setAutoDownloadDisabled(value as boolean); + } }); ipcMain.handle('get-secret-key', () => { @@ -2301,6 +2307,10 @@ async function appMain() { if (shouldSetupUpdater()) { log.info('Setting up auto-updater after window creation...'); try { + const settings = getSettings(); + if (settings.disableAutoDownload) { + setAutoDownloadDisabled(true); + } setupAutoUpdater(); } catch (error) { log.error('Error setting up auto-updater:', error); diff --git a/ui/desktop/src/preload.ts b/ui/desktop/src/preload.ts index eca1e0ea0..9f0bda06d 100644 --- a/ui/desktop/src/preload.ts +++ b/ui/desktop/src/preload.ts @@ -181,6 +181,7 @@ type ElectronAPI = { onUpdaterEvent: (callback: (event: UpdaterEvent) => void) => void; getUpdateState: () => Promise<{ updateAvailable: boolean; latestVersion?: string } | null>; isUsingGitHubFallback: () => Promise; + getAutoDownloadDisabled: () => Promise; // Recipe warning functions closeWindow: () => void; hasAcceptedRecipeBefore: (recipe: Recipe) => Promise; @@ -338,6 +339,9 @@ const electronAPI: ElectronAPI = { isUsingGitHubFallback: (): Promise => { return ipcRenderer.invoke('is-using-github-fallback'); }, + getAutoDownloadDisabled: (): Promise => { + return ipcRenderer.invoke('get-auto-download-disabled'); + }, closeWindow: () => ipcRenderer.send('close-window'), hasAcceptedRecipeBefore: (recipe: Recipe) => ipcRenderer.invoke('has-accepted-recipe-before', recipe), diff --git a/ui/desktop/src/utils/autoUpdater.ts b/ui/desktop/src/utils/autoUpdater.ts index 91a3cc281..abb1c2d25 100644 --- a/ui/desktop/src/utils/autoUpdater.ts +++ b/ui/desktop/src/utils/autoUpdater.ts @@ -46,6 +46,18 @@ let lastReportedProgress = 0; // Track if IPC handlers have been registered let ipcUpdateHandlersRegistered = false; +let autoDownloadDisabled = false; + +export function setAutoDownloadDisabled(disabled: boolean) { + autoDownloadDisabled = disabled; + autoUpdater.autoDownload = !disabled; + log.info(`Auto-download ${disabled ? 'disabled' : 'enabled'}`); +} + +export function getAutoDownloadDisabled(): boolean { + return autoDownloadDisabled; +} + // Register IPC handlers (only once) export function registerUpdateIpcHandlers() { if (ipcUpdateHandlersRegistered) { @@ -154,9 +166,12 @@ export function registerUpdateIpcHandlers() { updateTrayIcon(true); sendStatusToWindow('update-available', { version: result.latestVersion }); - // Auto-download for GitHub fallback (matching autoDownload behavior) - log.info('Auto-downloading update via GitHub fallback...'); - await githubAutoDownload(result.downloadUrl!, result.latestVersion!, 'manual check'); + if (!autoDownloadDisabled) { + log.info('Auto-downloading update via GitHub fallback...'); + await githubAutoDownload(result.downloadUrl!, result.latestVersion!, 'manual check'); + } else { + log.info('Auto-download disabled — skipping GitHub fallback download'); + } } else { trackUpdateCheckCompleted('not_available', currentVersion, { latestVersion: result.latestVersion, @@ -333,6 +348,10 @@ export function registerUpdateIpcHandlers() { ipcMain.handle('is-using-github-fallback', () => { return isUsingGitHubFallback; }); + + ipcMain.handle('get-auto-download-disabled', () => { + return autoDownloadDisabled; + }); } // Configure auto-updater @@ -368,8 +387,17 @@ export function setupAutoUpdater(tray?: Tray) { log.error('Error getting feed URL:', e); } + // Respect GOOSE_DISABLE_AUTO_DOWNLOAD env var (takes precedence over user setting) + const envDisabled = + process.env.GOOSE_DISABLE_AUTO_DOWNLOAD === '1' || + process.env.GOOSE_DISABLE_AUTO_DOWNLOAD === 'true'; + if (envDisabled) { + autoDownloadDisabled = true; + log.info('Auto-download disabled via GOOSE_DISABLE_AUTO_DOWNLOAD environment variable'); + } + // Configure auto-updater settings - autoUpdater.autoDownload = true; // Automatically download updates when available + autoUpdater.autoDownload = !autoDownloadDisabled; autoUpdater.autoInstallOnAppQuit = true; // Enable updates in development mode for testing @@ -485,9 +513,12 @@ export function setupAutoUpdater(tray?: Tray) { updateTrayIcon(true); sendStatusToWindow('update-available', { version: result.latestVersion }); - // Auto-download for GitHub fallback (matching autoDownload behavior) - log.info('Auto-downloading update via GitHub fallback on startup...'); - await githubAutoDownload(result.downloadUrl!, result.latestVersion!, 'on startup'); + if (!autoDownloadDisabled) { + log.info('Auto-downloading update via GitHub fallback on startup...'); + await githubAutoDownload(result.downloadUrl!, result.latestVersion!, 'on startup'); + } else { + log.info('Auto-download disabled — skipping GitHub fallback download on startup'); + } } else { trackUpdateCheckCompleted('not_available', currentVersion, { latestVersion: result.latestVersion, @@ -533,7 +564,9 @@ export function setupAutoUpdater(tray?: Tray) { latestVersion: info.version, usingFallback: false, }); - trackUpdateDownloadStarted(info.version, 'electron-updater'); + if (!autoDownloadDisabled) { + trackUpdateDownloadStarted(info.version, 'electron-updater'); + } updateAvailable = true; lastUpdateState = { updateAvailable: true, latestVersion: info.version }; updateTrayIcon(true); @@ -591,9 +624,12 @@ export function setupAutoUpdater(tray?: Tray) { updateTrayIcon(true); sendStatusToWindow('update-available', { version: result.latestVersion }); - // Auto-download for GitHub fallback (matching autoDownload behavior) - log.info('Auto-downloading update via GitHub fallback after error...'); - await githubAutoDownload(result.downloadUrl!, result.latestVersion!, 'after error'); + if (!autoDownloadDisabled) { + log.info('Auto-downloading update via GitHub fallback after error...'); + await githubAutoDownload(result.downloadUrl!, result.latestVersion!, 'after error'); + } else { + log.info('Auto-download disabled — skipping GitHub fallback download after error'); + } } else { updateAvailable = false; updateTrayIcon(false); diff --git a/ui/desktop/src/utils/settings.ts b/ui/desktop/src/utils/settings.ts index 0f23ac8e1..2d3765e1f 100644 --- a/ui/desktop/src/utils/settings.ts +++ b/ui/desktop/src/utils/settings.ts @@ -33,6 +33,7 @@ export type LanguageSetting = 'system' | 'en' | 'es' | 'hi' | 'ja' | 'ko' | 'ru' export interface Settings { // Desktop app settings showMenuBarIcon: boolean; + disableAutoDownload: boolean; showDockIcon: boolean; enableWakelock: boolean; enableNotifications: boolean; @@ -70,6 +71,7 @@ export const defaultKeyboardShortcuts: DefaultKeyboardShortcuts = { export const defaultSettings: Settings = { // Desktop app settings showMenuBarIcon: true, + disableAutoDownload: false, showDockIcon: true, enableWakelock: false, enableNotifications: true,