diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d70b51e..ec5e556 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -46,9 +46,6 @@ jobs: build-macos: if: ${{ github.event_name == 'push' || inputs.platform == 'all' || inputs.platform == 'macos' }} runs-on: macos-latest - strategy: - matrix: - arch: [x64, arm64] steps: - uses: actions/checkout@v4 @@ -63,10 +60,10 @@ jobs: - name: Build Electron app run: npm run electron:build - - name: Package for macOS (${{ matrix.arch }}) + - name: Package for macOS (x64 + arm64) env: GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: npx electron-builder --mac --${{ matrix.arch }} --config electron-builder.yml --publish always + run: npx electron-builder --mac --config electron-builder.yml --publish always build-linux: if: ${{ github.event_name == 'push' || inputs.platform == 'all' || inputs.platform == 'linux' }} diff --git a/electron-builder.yml b/electron-builder.yml index 7cbb8db..ea92e17 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -49,6 +49,9 @@ mac: artifactName: "${productName}-${version}-${arch}.${ext}" target: - target: dmg + arch: [x64, arm64] + - target: zip + arch: [x64, arm64] win: icon: build/icon.ico target: diff --git a/src/components/layout/AppShell.tsx b/src/components/layout/AppShell.tsx index 8f42ce6..9bda39b 100644 --- a/src/components/layout/AppShell.tsx +++ b/src/components/layout/AppShell.tsx @@ -225,6 +225,7 @@ export function AppShell({ children }: { children: React.ReactNode }) { downloadProgress: null, readyToInstall: false, isNativeUpdate: false, + lastError: null, }; setUpdateInfo(info); @@ -244,6 +245,7 @@ export function AppShell({ children }: { children: React.ReactNode }) { // --- Electron native updater check --- const checkForUpdatesNative = useCallback(async () => { setChecking(true); + setUpdateInfo((prev) => prev ? { ...prev, lastError: null } : prev); try { await window.electronAPI?.updater?.checkForUpdates(); } catch { @@ -280,6 +282,7 @@ export function AppShell({ children }: { children: React.ReactNode }) { downloadProgress: prev?.downloadProgress ?? null, readyToInstall: prev?.readyToInstall ?? false, isNativeUpdate: true, + lastError: null, }; return newInfo; }); @@ -300,6 +303,7 @@ export function AppShell({ children }: { children: React.ReactNode }) { setUpdateInfo((prev) => prev ? { ...prev, downloadProgress: event.progress?.percent ?? null, + lastError: null, } : prev); break; @@ -310,6 +314,7 @@ export function AppShell({ children }: { children: React.ReactNode }) { ...prev, readyToInstall: true, downloadProgress: 100, + lastError: null, }; }); break; @@ -317,7 +322,11 @@ export function AppShell({ children }: { children: React.ReactNode }) { case 'error': setChecking(false); // Reset download progress so the download button re-appears - setUpdateInfo((prev) => prev ? { ...prev, downloadProgress: null } : prev); + setUpdateInfo((prev) => prev ? { + ...prev, + downloadProgress: null, + lastError: event.error ?? 'Update failed', + } : prev); console.warn('[updater] Error:', event.error); break; } @@ -340,13 +349,18 @@ export function AppShell({ children }: { children: React.ReactNode }) { const downloadUpdate = useCallback(async () => { // Immediately show downloading state so user gets feedback - setUpdateInfo((prev) => prev ? { ...prev, downloadProgress: 0 } : prev); + setUpdateInfo((prev) => prev ? { ...prev, downloadProgress: 0, lastError: null } : prev); try { await window.electronAPI?.updater?.downloadUpdate(); } catch (err) { console.warn('[updater] Download failed:', err); + const message = err instanceof Error ? err.message : String(err); // Reset progress so the download button re-appears - setUpdateInfo((prev) => prev ? { ...prev, downloadProgress: null } : prev); + setUpdateInfo((prev) => prev ? { + ...prev, + downloadProgress: null, + lastError: message, + } : prev); } }, []); diff --git a/src/components/layout/UpdateDialog.tsx b/src/components/layout/UpdateDialog.tsx index b060578..05cd703 100644 --- a/src/components/layout/UpdateDialog.tsx +++ b/src/components/layout/UpdateDialog.tsx @@ -84,6 +84,12 @@ export function UpdateDialog() { )} + {updateInfo.lastError && ( +

+ {updateInfo.lastError} +

+ )} +