IGDB-Integration für Game Library + Electron Update-Button im Version-Modal
- Neues IGDB-Service-Modul (igdb.ts): Token-Management, Rate-Limiting, Game-Lookup per Steam-AppID/Name, Batch-Enrichment mit In-Memory-Cache - Server: 2 neue Routes (/igdb/enrich/:steamId, /igdb/game/:appid), Auto-Enrichment bei Steam-Login und Refresh - Frontend: IGDB-Cover, Genre-Tags, Plattform-Badges, farbcodiertes Rating, IGDB-Anreichern-Button - Version-Modal: Update-Button für Electron-App (checkForUpdates/installUpdate), Desktop-App-Version anzeigen - CSS: Styles für IGDB-Elemente und Update-UI Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
aec1142bff
commit
b404c20eca
6 changed files with 785 additions and 25 deletions
|
|
@ -26,6 +26,8 @@ export function registerTab(pluginName: string, component: React.FC<{ data: any
|
|||
tabComponents[pluginName] = component;
|
||||
}
|
||||
|
||||
type UpdateStatus = 'idle' | 'checking' | 'available' | 'downloading' | 'ready' | 'upToDate' | 'error';
|
||||
|
||||
export default function App() {
|
||||
const [connected, setConnected] = useState(false);
|
||||
const [plugins, setPlugins] = useState<PluginInfo[]>([]);
|
||||
|
|
@ -37,6 +39,12 @@ export default function App() {
|
|||
};
|
||||
const [showVersionModal, setShowVersionModal] = useState(false);
|
||||
const [pluginData, setPluginData] = useState<Record<string, any>>({});
|
||||
|
||||
// Electron auto-update state
|
||||
const isElectron = !!(window as any).electronAPI?.isElectron;
|
||||
const electronVersion = isElectron ? (window as any).electronAPI.version : null;
|
||||
const [updateStatus, setUpdateStatus] = useState<UpdateStatus>('idle');
|
||||
const [updateError, setUpdateError] = useState<string>('');
|
||||
const eventSourceRef = useRef<EventSource | null>(null);
|
||||
|
||||
// Request notification permission
|
||||
|
|
@ -46,6 +54,19 @@ export default function App() {
|
|||
}
|
||||
}, []);
|
||||
|
||||
// Electron auto-update listeners
|
||||
useEffect(() => {
|
||||
if (!isElectron) return;
|
||||
const api = (window as any).electronAPI;
|
||||
api.onUpdateAvailable(() => setUpdateStatus('downloading'));
|
||||
api.onUpdateReady(() => setUpdateStatus('ready'));
|
||||
api.onUpdateNotAvailable(() => setUpdateStatus('upToDate'));
|
||||
api.onUpdateError((msg: string) => {
|
||||
setUpdateStatus('error');
|
||||
setUpdateError(msg || 'Unbekannter Fehler');
|
||||
});
|
||||
}, [isElectron]);
|
||||
|
||||
// Fetch plugin list
|
||||
useEffect(() => {
|
||||
fetch('/api/plugins')
|
||||
|
|
@ -184,9 +205,15 @@ export default function App() {
|
|||
</div>
|
||||
<div className="hub-version-modal-body">
|
||||
<div className="hub-version-modal-row">
|
||||
<span className="hub-version-modal-label">Version</span>
|
||||
<span className="hub-version-modal-label">Hub-Version</span>
|
||||
<span className="hub-version-modal-value">v{version}</span>
|
||||
</div>
|
||||
{isElectron && (
|
||||
<div className="hub-version-modal-row">
|
||||
<span className="hub-version-modal-label">Desktop-App</span>
|
||||
<span className="hub-version-modal-value">v{electronVersion}</span>
|
||||
</div>
|
||||
)}
|
||||
<div className="hub-version-modal-row">
|
||||
<span className="hub-version-modal-label">Server</span>
|
||||
<span className="hub-version-modal-value">
|
||||
|
|
@ -194,6 +221,65 @@ export default function App() {
|
|||
{connected ? 'Verbunden' : 'Getrennt'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{isElectron && (
|
||||
<div className="hub-version-modal-update">
|
||||
{updateStatus === 'idle' && (
|
||||
<button
|
||||
className="hub-version-modal-update-btn"
|
||||
onClick={() => {
|
||||
setUpdateStatus('checking');
|
||||
setUpdateError('');
|
||||
(window as any).electronAPI.checkForUpdates();
|
||||
}}
|
||||
>
|
||||
{'\u{1F504}'} Nach Updates suchen
|
||||
</button>
|
||||
)}
|
||||
{updateStatus === 'checking' && (
|
||||
<div className="hub-version-modal-update-status">
|
||||
<span className="hub-update-spinner" />
|
||||
Suche nach Updates…
|
||||
</div>
|
||||
)}
|
||||
{updateStatus === 'downloading' && (
|
||||
<div className="hub-version-modal-update-status">
|
||||
<span className="hub-update-spinner" />
|
||||
Update wird heruntergeladen…
|
||||
</div>
|
||||
)}
|
||||
{updateStatus === 'ready' && (
|
||||
<button
|
||||
className="hub-version-modal-update-btn ready"
|
||||
onClick={() => (window as any).electronAPI.installUpdate()}
|
||||
>
|
||||
{'\u2705'} Jetzt installieren & neu starten
|
||||
</button>
|
||||
)}
|
||||
{updateStatus === 'upToDate' && (
|
||||
<div className="hub-version-modal-update-status success">
|
||||
{'\u2705'} App ist aktuell
|
||||
<button
|
||||
className="hub-version-modal-update-retry"
|
||||
onClick={() => setUpdateStatus('idle')}
|
||||
>
|
||||
Erneut prüfen
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
{updateStatus === 'error' && (
|
||||
<div className="hub-version-modal-update-status error">
|
||||
{'\u274C'} {updateError}
|
||||
<button
|
||||
className="hub-version-modal-update-retry"
|
||||
onClick={() => setUpdateStatus('idle')}
|
||||
>
|
||||
Erneut versuchen
|
||||
</button>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue