From cd9a1746c1de87795b2ccee3dc689aa8eab197b6 Mon Sep 17 00:00:00 2001 From: korjwl1 Date: Tue, 11 Aug 2026 00:49:21 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix(update):=20'Update=20Now'=20can=20no=20?= =?UTF-8?q?longer=20succeed=20silently=20=E2=80=94=20verify=20install,=20s?= =?UTF-8?q?how=20phases,=20surface=20errors=20inline=20(Refs=20#38)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Three holes made the button untrustworthy: - Success was defined as 'brew exited 0'. Every skip/no-op path exits 0, so RunUpdate reported success while the bundle never changed. Now: if brew returns without the cask postflight having killed us (a real install kills this process first), read the installed bundle's version and fail loudly when it isn't the target. - Zero feedback for the whole run — the tap refresh alone was observed taking 75 s with a static 'Updating…' label. RunUpdate now emits update_progress (refresh/install) and the banner + About show the phase. - Failures surfaced only as a toast, which renders under the Settings modal. handleUpdate rethrows; the banner and About render the error inline next to the button that failed. Co-Authored-By: Claude Fable 5 --- frontend/src/App.svelte | 4 +++ frontend/src/i18n/en.json | 5 ++- frontend/src/i18n/ja.json | 5 ++- frontend/src/i18n/ko.json | 5 ++- frontend/src/lib/Settings.svelte | 5 +++ frontend/src/lib/UpdateNotice.svelte | 48 ++++++++++++++++++++++++++-- internal/app/settings_ops.go | 39 ++++++++++++++++++++++ internal/gui/gui.go | 1 + 8 files changed, 107 insertions(+), 5 deletions(-) diff --git a/frontend/src/App.svelte b/frontend/src/App.svelte index a27b3a8..2be240c 100644 --- a/frontend/src/App.svelte +++ b/frontend/src/App.svelte @@ -633,6 +633,10 @@ await TunnelService.RunUpdate(updateInfo); } catch (e) { showToast('Update failed: ' + (e?.message || e)); + // Rethrow: modal-context callers (Settings → About, the banner) + // render the failure inline — a toast alone can sit underneath an + // open modal where it is never seen. + throw e; } } diff --git a/frontend/src/i18n/en.json b/frontend/src/i18n/en.json index 2ce05ef..d8c6599 100644 --- a/frontend/src/i18n/en.json +++ b/frontend/src/i18n/en.json @@ -196,7 +196,10 @@ "time_hours_ago": "{n}h ago", "time_days_ago": "{n}d ago", "dev_build_hint": "Automatic checks are disabled in development builds. Use the button above to check manually.", - "auto_off_hint": "Automatic checks are turned off in Settings. Use the button above to check manually." + "auto_off_hint": "Automatic checks are turned off in Settings. Use the button above to check manually.", + "install_failed": "Update failed", + "progress_refresh": "Checking the package repository…", + "progress_install": "Downloading and installing…" }, "wifi_permission": { "title": "Location Services required", diff --git a/frontend/src/i18n/ja.json b/frontend/src/i18n/ja.json index b508dbc..46d6a88 100644 --- a/frontend/src/i18n/ja.json +++ b/frontend/src/i18n/ja.json @@ -196,7 +196,10 @@ "time_hours_ago": "{n}時間前", "time_days_ago": "{n}日前", "dev_build_hint": "開発ビルドでは自動確認が無効化されています。上のボタンで手動確認してください。", - "auto_off_hint": "設定で自動確認がオフになっています。上のボタンで手動確認してください。" + "auto_off_hint": "設定で自動確認がオフになっています。上のボタンで手動確認してください。", + "install_failed": "アップデート失敗", + "progress_refresh": "パッケージリポジトリを確認中…", + "progress_install": "ダウンロードとインストール中…" }, "wifi_permission": { "title": "位置情報サービスの許可が必要", diff --git a/frontend/src/i18n/ko.json b/frontend/src/i18n/ko.json index 988e1b9..3d46045 100644 --- a/frontend/src/i18n/ko.json +++ b/frontend/src/i18n/ko.json @@ -196,7 +196,10 @@ "time_hours_ago": "{n}시간 전", "time_days_ago": "{n}일 전", "dev_build_hint": "개발 빌드에서는 자동 확인이 비활성화되어 있습니다. 위 버튼으로 수동 확인하세요.", - "auto_off_hint": "설정에서 자동 확인이 꺼져 있습니다. 위 버튼으로 수동 확인하세요." + "auto_off_hint": "설정에서 자동 확인이 꺼져 있습니다. 위 버튼으로 수동 확인하세요.", + "install_failed": "업데이트 실패", + "progress_refresh": "패키지 저장소 확인 중…", + "progress_install": "다운로드 및 설치 중…" }, "wifi_permission": { "title": "위치 서비스 권한 필요", diff --git a/frontend/src/lib/Settings.svelte b/frontend/src/lib/Settings.svelte index 2963bc2..9bb803f 100644 --- a/frontend/src/lib/Settings.svelte +++ b/frontend/src/lib/Settings.svelte @@ -116,8 +116,13 @@ async function doAboutUpdate() { aboutShowVpnWarn = false; aboutUpdating = true; + aboutCheckResult = ''; try { if (onInstall) await onInstall(); + } catch (e) { + // Inline, next to the button that failed — the toast alone renders + // under this modal. + aboutCheckResult = ($t('update.install_failed') || 'Update failed') + ': ' + (e?.message || e); } finally { aboutUpdating = false; } diff --git a/frontend/src/lib/UpdateNotice.svelte b/frontend/src/lib/UpdateNotice.svelte index 49b7b6b..b8412de 100644 --- a/frontend/src/lib/UpdateNotice.svelte +++ b/frontend/src/lib/UpdateNotice.svelte @@ -1,4 +1,6 @@