From 9fd0992fc48b83420fd52fb8430a04c26ed2887f Mon Sep 17 00:00:00 2001 From: Daniel Date: Sat, 7 Mar 2026 19:23:30 +0100 Subject: [PATCH] Fix Electron update: Squirrel feed URL, version display, error details MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix: Squirrel.Windows feed URL /updates → /downloads (Squirrel appends /RELEASES) - Show Desktop App + Server version in update modal - Display actual error message in failed state - Dynamic Electron version via app.getVersion() instead of hardcoded - Sync electron/package.json version with VERSION file (1.5.8) - Add "Später" button on update-ready, timeout error message - Style: version info, error detail box, secondary button Co-Authored-By: Claude Opus 4.6 --- electron/main.js | 12 ++++++++++-- electron/package.json | 2 +- electron/preload.js | 3 ++- web/src/App.tsx | 37 +++++++++++++++++++++++++++++++------ web/src/styles.css | 22 ++++++++++++++++++++++ 5 files changed, 66 insertions(+), 10 deletions(-) diff --git a/electron/main.js b/electron/main.js index 44c2ff7..632f71b 100644 --- a/electron/main.js +++ b/electron/main.js @@ -10,11 +10,19 @@ try { } const HUB_URL = process.env.GAMING_HUB_URL || 'https://hub.daddelolymp.de'; +const APP_VERSION = app.getVersion(); + +// Sync IPC: preload reads app version from package.json +ipcMain.on('get-app-version', (event) => { + event.returnValue = APP_VERSION; +}); function setupAutoUpdater() { if (process.platform !== 'win32') return; - const updateURL = `${HUB_URL}/updates`; + // Squirrel.Windows appends /RELEASES to the feed URL, + // so point to /downloads where RELEASES + nupkg files live + const updateURL = `${HUB_URL}/downloads`; try { autoUpdater.setFeedURL({ url: updateURL }); } catch (e) { @@ -93,7 +101,7 @@ function createWindow() { // Custom User-Agent to identify Electron app const currentUA = mainWindow.webContents.getUserAgent(); - mainWindow.webContents.setUserAgent(currentUA + ' GamingHubDesktop/1.5.0'); + mainWindow.webContents.setUserAgent(currentUA + ` GamingHubDesktop/${APP_VERSION}`); mainWindow.loadURL(HUB_URL); diff --git a/electron/package.json b/electron/package.json index 6799a67..84b8567 100644 --- a/electron/package.json +++ b/electron/package.json @@ -1,7 +1,7 @@ { "name": "gaming-hub-desktop", "productName": "Gaming Hub", - "version": "1.5.0", + "version": "1.5.8", "description": "Gaming Hub Desktop App mit Ad-Blocker", "author": "Gaming Hub", "main": "main.js", diff --git a/electron/preload.js b/electron/preload.js index 62725b6..a53910d 100644 --- a/electron/preload.js +++ b/electron/preload.js @@ -2,7 +2,8 @@ const { contextBridge, ipcRenderer } = require('electron'); contextBridge.exposeInMainWorld('electronAPI', { isElectron: true, - version: '1.5.0', + // Version comes from main process (reads package.json via app.getVersion()) + version: ipcRenderer.sendSync('get-app-version'), onUpdateAvailable: (callback) => ipcRenderer.on('update-available', callback), onUpdateReady: (callback) => ipcRenderer.on('update-ready', callback), onUpdateNotAvailable: (callback) => ipcRenderer.on('update-not-available', callback), diff --git a/web/src/App.tsx b/web/src/App.tsx index 0ccfabc..d6dab8e 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -28,6 +28,7 @@ export default function App() { const [connected, setConnected] = useState(false); const [plugins, setPlugins] = useState([]); const [updateState, setUpdateState] = useState<'idle' | 'checking' | 'downloading' | 'ready' | 'uptodate' | 'error'>('idle'); + const [updateError, setUpdateError] = useState(''); const [activeTab, setActiveTabRaw] = useState(() => localStorage.getItem('hub_activeTab') ?? ''); const setActiveTab = (tab: string) => { @@ -118,15 +119,22 @@ export default function App() { } }); api.onUpdateNotAvailable?.(() => setUpdateState('uptodate')); - api.onUpdateError?.(() => setUpdateState('error')); + api.onUpdateError?.((msg: string) => { + setUpdateError(msg || 'Unbekannter Fehler'); + setUpdateState('error'); + }); }, []); + const electronVersion = (window as any).electronAPI?.version ?? null; + const handleCheckForUpdates = () => { setUpdateState('checking'); + setUpdateError(''); (window as any).electronAPI?.checkForUpdates?.(); // Timeout: falls Electron nicht antwortet, nach 15s zurücksetzen setTimeout(() => { setUpdateState(prev => prev === 'checking' ? 'error' : prev); + setUpdateError(prev => prev || 'Zeitüberschreitung — Server nicht erreichbar.'); }, 15000); }; @@ -199,6 +207,10 @@ export default function App() { <>
{'\u{1F50D}'}

Suche nach Updates...

+
+ {electronVersion && Desktop App: v{electronVersion}} + Server: v{version} +
@@ -210,8 +222,10 @@ export default function App() { {updateState === 'downloading' && ( <>
{'\u2B07\uFE0F'}
-

Update verfügbar

-

Update wird heruntergeladen...

+

Update wird heruntergeladen...

+
+ {electronVersion && Aktuell: v{electronVersion}} +
@@ -223,7 +237,10 @@ export default function App() {

Update bereit!

Die App wird neu gestartet, um das Update zu installieren.

+ )} @@ -231,7 +248,11 @@ export default function App() { <>
{'\u2705'}

Alles aktuell!

-

Du verwendest bereits die neueste Version (v{version}).

+
+ {electronVersion && Desktop App: v{electronVersion}} + Server: v{version} +
+

Du verwendest bereits die neueste Version.

@@ -241,7 +262,11 @@ export default function App() { <>
{'\u274C'}

Update fehlgeschlagen

-

Das Update konnte nicht heruntergeladen werden.

+
+ {electronVersion && Desktop App: v{electronVersion}} + Server: v{version} +
+ {updateError &&

{updateError}

} diff --git a/web/src/styles.css b/web/src/styles.css index 07909e2..062fb67 100644 --- a/web/src/styles.css +++ b/web/src/styles.css @@ -313,6 +313,28 @@ html, body { .hub-update-btn:hover { opacity: 0.85; } +.hub-update-btn-secondary { + background: var(--bg-tertiary); + color: var(--text-secondary); + margin-top: 4px; +} +.hub-update-versions { + display: flex; + flex-direction: column; + gap: 2px; + margin: 8px 0; + font-size: 12px; + color: var(--text-muted); +} +.hub-update-error-detail { + font-size: 11px; + color: #ef4444; + background: rgba(239, 68, 68, 0.1); + border-radius: var(--radius); + padding: 6px 10px; + word-break: break-word; + max-width: 300px; +} /* ── Main Content Area ── */ .hub-content {