Fix Electron update: Squirrel feed URL, version display, error details
- 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 <noreply@anthropic.com>
This commit is contained in:
parent
56ac2d0079
commit
9fd0992fc4
5 changed files with 66 additions and 10 deletions
|
|
@ -10,11 +10,19 @@ try {
|
||||||
}
|
}
|
||||||
|
|
||||||
const HUB_URL = process.env.GAMING_HUB_URL || 'https://hub.daddelolymp.de';
|
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() {
|
function setupAutoUpdater() {
|
||||||
if (process.platform !== 'win32') return;
|
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 {
|
try {
|
||||||
autoUpdater.setFeedURL({ url: updateURL });
|
autoUpdater.setFeedURL({ url: updateURL });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
|
|
@ -93,7 +101,7 @@ function createWindow() {
|
||||||
|
|
||||||
// Custom User-Agent to identify Electron app
|
// Custom User-Agent to identify Electron app
|
||||||
const currentUA = mainWindow.webContents.getUserAgent();
|
const currentUA = mainWindow.webContents.getUserAgent();
|
||||||
mainWindow.webContents.setUserAgent(currentUA + ' GamingHubDesktop/1.5.0');
|
mainWindow.webContents.setUserAgent(currentUA + ` GamingHubDesktop/${APP_VERSION}`);
|
||||||
|
|
||||||
mainWindow.loadURL(HUB_URL);
|
mainWindow.loadURL(HUB_URL);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "gaming-hub-desktop",
|
"name": "gaming-hub-desktop",
|
||||||
"productName": "Gaming Hub",
|
"productName": "Gaming Hub",
|
||||||
"version": "1.5.0",
|
"version": "1.5.8",
|
||||||
"description": "Gaming Hub Desktop App mit Ad-Blocker",
|
"description": "Gaming Hub Desktop App mit Ad-Blocker",
|
||||||
"author": "Gaming Hub",
|
"author": "Gaming Hub",
|
||||||
"main": "main.js",
|
"main": "main.js",
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,8 @@ const { contextBridge, ipcRenderer } = require('electron');
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('electronAPI', {
|
contextBridge.exposeInMainWorld('electronAPI', {
|
||||||
isElectron: true,
|
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),
|
onUpdateAvailable: (callback) => ipcRenderer.on('update-available', callback),
|
||||||
onUpdateReady: (callback) => ipcRenderer.on('update-ready', callback),
|
onUpdateReady: (callback) => ipcRenderer.on('update-ready', callback),
|
||||||
onUpdateNotAvailable: (callback) => ipcRenderer.on('update-not-available', callback),
|
onUpdateNotAvailable: (callback) => ipcRenderer.on('update-not-available', callback),
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ export default function App() {
|
||||||
const [connected, setConnected] = useState(false);
|
const [connected, setConnected] = useState(false);
|
||||||
const [plugins, setPlugins] = useState<PluginInfo[]>([]);
|
const [plugins, setPlugins] = useState<PluginInfo[]>([]);
|
||||||
const [updateState, setUpdateState] = useState<'idle' | 'checking' | 'downloading' | 'ready' | 'uptodate' | 'error'>('idle');
|
const [updateState, setUpdateState] = useState<'idle' | 'checking' | 'downloading' | 'ready' | 'uptodate' | 'error'>('idle');
|
||||||
|
const [updateError, setUpdateError] = useState<string>('');
|
||||||
const [activeTab, setActiveTabRaw] = useState<string>(() => localStorage.getItem('hub_activeTab') ?? '');
|
const [activeTab, setActiveTabRaw] = useState<string>(() => localStorage.getItem('hub_activeTab') ?? '');
|
||||||
|
|
||||||
const setActiveTab = (tab: string) => {
|
const setActiveTab = (tab: string) => {
|
||||||
|
|
@ -118,15 +119,22 @@ export default function App() {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
api.onUpdateNotAvailable?.(() => setUpdateState('uptodate'));
|
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 = () => {
|
const handleCheckForUpdates = () => {
|
||||||
setUpdateState('checking');
|
setUpdateState('checking');
|
||||||
|
setUpdateError('');
|
||||||
(window as any).electronAPI?.checkForUpdates?.();
|
(window as any).electronAPI?.checkForUpdates?.();
|
||||||
// Timeout: falls Electron nicht antwortet, nach 15s zurücksetzen
|
// Timeout: falls Electron nicht antwortet, nach 15s zurücksetzen
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
setUpdateState(prev => prev === 'checking' ? 'error' : prev);
|
setUpdateState(prev => prev === 'checking' ? 'error' : prev);
|
||||||
|
setUpdateError(prev => prev || 'Zeitüberschreitung — Server nicht erreichbar.');
|
||||||
}, 15000);
|
}, 15000);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -199,6 +207,10 @@ export default function App() {
|
||||||
<>
|
<>
|
||||||
<div className="hub-update-icon">{'\u{1F50D}'}</div>
|
<div className="hub-update-icon">{'\u{1F50D}'}</div>
|
||||||
<h2>Suche nach Updates...</h2>
|
<h2>Suche nach Updates...</h2>
|
||||||
|
<div className="hub-update-versions">
|
||||||
|
{electronVersion && <span>Desktop App: v{electronVersion}</span>}
|
||||||
|
<span>Server: v{version}</span>
|
||||||
|
</div>
|
||||||
<div className="hub-update-progress">
|
<div className="hub-update-progress">
|
||||||
<div className="hub-update-progress-bar" />
|
<div className="hub-update-progress-bar" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -210,8 +222,10 @@ export default function App() {
|
||||||
{updateState === 'downloading' && (
|
{updateState === 'downloading' && (
|
||||||
<>
|
<>
|
||||||
<div className="hub-update-icon">{'\u2B07\uFE0F'}</div>
|
<div className="hub-update-icon">{'\u2B07\uFE0F'}</div>
|
||||||
<h2>Update verfügbar</h2>
|
<h2>Update wird heruntergeladen...</h2>
|
||||||
<p>Update wird heruntergeladen...</p>
|
<div className="hub-update-versions">
|
||||||
|
{electronVersion && <span>Aktuell: v{electronVersion}</span>}
|
||||||
|
</div>
|
||||||
<div className="hub-update-progress">
|
<div className="hub-update-progress">
|
||||||
<div className="hub-update-progress-bar" />
|
<div className="hub-update-progress-bar" />
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -223,7 +237,10 @@ export default function App() {
|
||||||
<h2>Update bereit!</h2>
|
<h2>Update bereit!</h2>
|
||||||
<p>Die App wird neu gestartet, um das Update zu installieren.</p>
|
<p>Die App wird neu gestartet, um das Update zu installieren.</p>
|
||||||
<button className="hub-update-btn" onClick={() => (window as any).electronAPI?.installUpdate()}>
|
<button className="hub-update-btn" onClick={() => (window as any).electronAPI?.installUpdate()}>
|
||||||
OK
|
Jetzt installieren
|
||||||
|
</button>
|
||||||
|
<button className="hub-update-btn hub-update-btn-secondary" onClick={() => setUpdateState('idle')}>
|
||||||
|
Später
|
||||||
</button>
|
</button>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
|
@ -231,7 +248,11 @@ export default function App() {
|
||||||
<>
|
<>
|
||||||
<div className="hub-update-icon">{'\u2705'}</div>
|
<div className="hub-update-icon">{'\u2705'}</div>
|
||||||
<h2>Alles aktuell!</h2>
|
<h2>Alles aktuell!</h2>
|
||||||
<p>Du verwendest bereits die neueste Version (v{version}).</p>
|
<div className="hub-update-versions">
|
||||||
|
{electronVersion && <span>Desktop App: v{electronVersion}</span>}
|
||||||
|
<span>Server: v{version}</span>
|
||||||
|
</div>
|
||||||
|
<p>Du verwendest bereits die neueste Version.</p>
|
||||||
<button className="hub-update-btn" onClick={() => setUpdateState('idle')}>
|
<button className="hub-update-btn" onClick={() => setUpdateState('idle')}>
|
||||||
OK
|
OK
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -241,7 +262,11 @@ export default function App() {
|
||||||
<>
|
<>
|
||||||
<div className="hub-update-icon">{'\u274C'}</div>
|
<div className="hub-update-icon">{'\u274C'}</div>
|
||||||
<h2>Update fehlgeschlagen</h2>
|
<h2>Update fehlgeschlagen</h2>
|
||||||
<p>Das Update konnte nicht heruntergeladen werden.</p>
|
<div className="hub-update-versions">
|
||||||
|
{electronVersion && <span>Desktop App: v{electronVersion}</span>}
|
||||||
|
<span>Server: v{version}</span>
|
||||||
|
</div>
|
||||||
|
{updateError && <p className="hub-update-error-detail">{updateError}</p>}
|
||||||
<button className="hub-update-btn" onClick={() => setUpdateState('idle')}>
|
<button className="hub-update-btn" onClick={() => setUpdateState('idle')}>
|
||||||
Schließen
|
Schließen
|
||||||
</button>
|
</button>
|
||||||
|
|
|
||||||
|
|
@ -313,6 +313,28 @@ html, body {
|
||||||
.hub-update-btn:hover {
|
.hub-update-btn:hover {
|
||||||
opacity: 0.85;
|
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 ── */
|
/* ── Main Content Area ── */
|
||||||
.hub-content {
|
.hub-content {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue