Add: Check-for-Updates Button in Electron App

- Manueller Update-Check per Button im Header
- Modal-Zustaende: checking, downloading, ready, uptodate, error
- IPC: check-for-updates, update-not-available Events
This commit is contained in:
Daniel 2026-03-07 14:27:09 +01:00
parent c2942737bd
commit ce2a26ddeb
4 changed files with 65 additions and 1 deletions

View file

@ -27,7 +27,7 @@ export function registerTab(pluginName: string, component: React.FC<{ data: any
export default function App() {
const [connected, setConnected] = useState(false);
const [plugins, setPlugins] = useState<PluginInfo[]>([]);
const [updateState, setUpdateState] = useState<'idle' | 'downloading' | 'ready' | 'error'>('idle');
const [updateState, setUpdateState] = useState<'idle' | 'checking' | 'downloading' | 'ready' | 'uptodate' | 'error'>('idle');
const [activeTab, setActiveTabRaw] = useState<string>(() => localStorage.getItem('hub_activeTab') ?? '');
const setActiveTab = (tab: string) => {
@ -100,9 +100,15 @@ export default function App() {
if (!api?.onUpdateAvailable) return;
api.onUpdateAvailable(() => setUpdateState('downloading'));
api.onUpdateReady(() => setUpdateState('ready'));
api.onUpdateNotAvailable?.(() => setUpdateState('uptodate'));
api.onUpdateError?.(() => setUpdateState('error'));
}, []);
const handleCheckForUpdates = () => {
setUpdateState('checking');
(window as any).electronAPI?.checkForUpdates();
};
// Tab icon mapping
const tabIcons: Record<string, string> = {
radio: '\u{1F30D}',
@ -151,6 +157,16 @@ export default function App() {
<span className="hub-download-label">Desktop App</span>
</a>
)}
{(window as any).electronAPI && (
<button
className="hub-check-update-btn"
onClick={handleCheckForUpdates}
disabled={updateState !== 'idle'}
title="Nach Updates suchen"
>
{'\u{1F504}'}
</button>
)}
<span className="hub-version">v{version}</span>
</div>
</header>
@ -158,6 +174,15 @@ export default function App() {
{updateState !== 'idle' && (
<div className="hub-update-overlay">
<div className="hub-update-modal">
{updateState === 'checking' && (
<>
<div className="hub-update-icon">{'\u{1F50D}'}</div>
<h2>Suche nach Updates...</h2>
<div className="hub-update-progress">
<div className="hub-update-progress-bar" />
</div>
</>
)}
{updateState === 'downloading' && (
<>
<div className="hub-update-icon">{'\u2B07\uFE0F'}</div>
@ -178,6 +203,16 @@ export default function App() {
</button>
</>
)}
{updateState === 'uptodate' && (
<>
<div className="hub-update-icon">{'\u2705'}</div>
<h2>Alles aktuell!</h2>
<p>Du verwendest bereits die neueste Version (v{version}).</p>
<button className="hub-update-btn" onClick={() => setUpdateState('idle')}>
OK
</button>
</>
)}
{updateState === 'error' && (
<>
<div className="hub-update-icon">{'\u274C'}</div>

View file

@ -226,6 +226,27 @@ html, body {
border-radius: 4px;
}
/* ── Check for Updates Button ── */
.hub-check-update-btn {
background: none;
border: 1px solid var(--border);
border-radius: var(--radius);
color: var(--text-secondary);
font-size: 14px;
padding: 2px 8px;
cursor: pointer;
transition: all var(--transition);
line-height: 1;
}
.hub-check-update-btn:hover:not(:disabled) {
color: var(--accent);
border-color: var(--accent);
}
.hub-check-update-btn:disabled {
opacity: 0.4;
cursor: default;
}
/* ── Update Modal ── */
.hub-update-overlay {
position: fixed;