Auto-Updater: Doppelstart verhindern + Download-Status sichtbar
- State-Tracking im Main-Prozess (idle/checking/downloading/ready) - Manueller Check gibt aktuellen Status zurück statt Squirrel-Doppelstart - Auto-Check nur wenn idle (kein Konflikt mit laufendem Download) - Frontend synchronisiert Status beim Mount und Modal-Öffnen - getUpdateStatus IPC für synchrone Status-Abfrage Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
2c6ac0745d
commit
d909909591
3 changed files with 61 additions and 13 deletions
|
|
@ -33,43 +33,75 @@ function setupAutoUpdater() {
|
|||
return;
|
||||
}
|
||||
|
||||
// State-Tracking: verhindert Doppelstarts und bewahrt Status
|
||||
let updateState = 'idle'; // idle | checking | downloading | ready
|
||||
|
||||
autoUpdater.on('checking-for-update', () => {
|
||||
console.log('[AutoUpdater] Checking for updates...');
|
||||
updateState = 'checking';
|
||||
});
|
||||
|
||||
autoUpdater.on('update-available', () => {
|
||||
console.log('[AutoUpdater] Update available, downloading...');
|
||||
updateState = 'downloading';
|
||||
if (mainWindow) mainWindow.webContents.send('update-available');
|
||||
});
|
||||
|
||||
autoUpdater.on('update-downloaded', (_event, releaseNotes, releaseName) => {
|
||||
console.log('[AutoUpdater] Update downloaded:', releaseName || 'new version');
|
||||
updateState = 'ready';
|
||||
if (mainWindow) mainWindow.webContents.send('update-ready');
|
||||
});
|
||||
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
console.log('[AutoUpdater] App is up to date.');
|
||||
updateState = 'idle';
|
||||
if (mainWindow) mainWindow.webContents.send('update-not-available');
|
||||
});
|
||||
|
||||
autoUpdater.on('error', (err) => {
|
||||
console.error('[AutoUpdater] Error:', err.message);
|
||||
updateState = 'idle';
|
||||
if (mainWindow) mainWindow.webContents.send('update-error', err.message);
|
||||
});
|
||||
|
||||
// Handle install-update request from renderer
|
||||
ipcMain.on('install-update', () => {
|
||||
autoUpdater.quitAndInstall();
|
||||
});
|
||||
|
||||
autoUpdater.on('update-not-available', () => {
|
||||
console.log('[AutoUpdater] App is up to date.');
|
||||
if (mainWindow) mainWindow.webContents.send('update-not-available');
|
||||
});
|
||||
|
||||
// Manual check from renderer
|
||||
// Manual check from renderer — gibt aktuellen Status zurück statt Doppelstart
|
||||
ipcMain.on('check-for-updates', () => {
|
||||
if (updateState === 'downloading') {
|
||||
if (mainWindow) mainWindow.webContents.send('update-available');
|
||||
return;
|
||||
}
|
||||
if (updateState === 'ready') {
|
||||
if (mainWindow) mainWindow.webContents.send('update-ready');
|
||||
return;
|
||||
}
|
||||
if (updateState === 'checking') {
|
||||
return; // bereits am Prüfen
|
||||
}
|
||||
try { autoUpdater.checkForUpdates(); } catch (e) { console.error('[AutoUpdater]', e.message); }
|
||||
});
|
||||
|
||||
autoUpdater.on('error', (err) => {
|
||||
console.error('[AutoUpdater] Error:', err.message);
|
||||
if (mainWindow) mainWindow.webContents.send('update-error', err.message);
|
||||
// Sync-Abfrage: Frontend kann aktuellen Status beim Modal-Öffnen abfragen
|
||||
ipcMain.on('get-update-status', (event) => {
|
||||
event.returnValue = updateState;
|
||||
});
|
||||
|
||||
// Check for updates after 5 seconds, then every 30 minutes
|
||||
// Auto-Check nach 5 Sek, dann alle 30 Min (nur wenn idle)
|
||||
setTimeout(() => {
|
||||
try { autoUpdater.checkForUpdates(); } catch (e) { console.error('[AutoUpdater]', e.message); }
|
||||
if (updateState === 'idle') {
|
||||
try { autoUpdater.checkForUpdates(); } catch (e) { console.error('[AutoUpdater]', e.message); }
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
setInterval(() => {
|
||||
try { autoUpdater.checkForUpdates(); } catch (e) { console.error('[AutoUpdater]', e.message); }
|
||||
if (updateState === 'idle') {
|
||||
try { autoUpdater.checkForUpdates(); } catch (e) { console.error('[AutoUpdater]', e.message); }
|
||||
}
|
||||
}, 30 * 60 * 1000);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ contextBridge.exposeInMainWorld('electronAPI', {
|
|||
onUpdateNotAvailable: (callback) => ipcRenderer.on('update-not-available', callback),
|
||||
onUpdateError: (callback) => ipcRenderer.on('update-error', (_e, msg) => callback(msg)),
|
||||
checkForUpdates: () => ipcRenderer.send('check-for-updates'),
|
||||
getUpdateStatus: () => ipcRenderer.sendSync('get-update-status'),
|
||||
installUpdate: () => ipcRenderer.send('install-update'),
|
||||
setStreaming: (active) => ipcRenderer.send('streaming-status', active),
|
||||
showNotification: (title, body) => ipcRenderer.send('show-notification', title, body),
|
||||
|
|
|
|||
|
|
@ -65,6 +65,11 @@ export default function App() {
|
|||
setUpdateStatus('error');
|
||||
setUpdateError(msg || 'Unbekannter Fehler');
|
||||
});
|
||||
// Sync initial status (Hintergrund-Download könnte bereits laufen)
|
||||
const currentState = api.getUpdateStatus?.();
|
||||
if (currentState === 'downloading') setUpdateStatus('downloading');
|
||||
else if (currentState === 'ready') setUpdateStatus('ready');
|
||||
else if (currentState === 'checking') setUpdateStatus('checking');
|
||||
}, [isElectron]);
|
||||
|
||||
// Fetch plugin list
|
||||
|
|
@ -185,7 +190,17 @@ export default function App() {
|
|||
)}
|
||||
<span
|
||||
className="hub-version hub-version-clickable"
|
||||
onClick={() => setShowVersionModal(true)}
|
||||
onClick={() => {
|
||||
// Status vom Main-Prozess synchronisieren bevor Modal öffnet
|
||||
if (isElectron) {
|
||||
const api = (window as any).electronAPI;
|
||||
const s = api.getUpdateStatus?.();
|
||||
if (s === 'downloading') setUpdateStatus('downloading');
|
||||
else if (s === 'ready') setUpdateStatus('ready');
|
||||
else if (s === 'checking') setUpdateStatus('checking');
|
||||
}
|
||||
setShowVersionModal(true);
|
||||
}}
|
||||
title="Versionsinformationen"
|
||||
>
|
||||
v{version}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue