feat(electrobun): auto-updater + E2E tests + splash screen — ALL GAPS CLOSED

Auto-updater:
- updater.ts: GitHub Releases API check, semver comparison, timestamp tracking
- AdvancedSettings wired to real updater.check/getVersion RPC

E2E testing (45 tests):
- wdio.conf.js: WebDriverIO config for Electrobun (port 9761)
- fixtures.ts: isolated temp dirs, demo data, git repo init
- 4 spec files: smoke (13), settings (13), terminal (10), agent (9)

Splash screen:
- SplashScreen.svelte: animated gradient AGOR logo, version, loading dots
- App.svelte: shows splash until all init promises resolve, 300ms fade-out
This commit is contained in:
Hibryda 2026-03-22 01:49:30 +01:00
parent 88206205fe
commit 4826b9dffa
8 changed files with 637 additions and 11 deletions

View file

@ -7,6 +7,7 @@
import NotifDrawer, { type Notification } from './NotifDrawer.svelte';
import StatusBar from './StatusBar.svelte';
import SearchOverlay from './SearchOverlay.svelte';
import SplashScreen from './SplashScreen.svelte';
import { themeStore } from './theme-store.svelte.ts';
import { fontStore } from './font-store.svelte.ts';
import { keybindingStore } from './keybinding-store.svelte.ts';
@ -136,6 +137,9 @@
}).catch(console.error);
}
// ── Splash screen ─────────────────────────────────────────────
let appReady = $state(false);
// ── Reactive state ─────────────────────────────────────────────
let settingsOpen = $state(false);
let paletteOpen = $state(false);
@ -276,17 +280,22 @@
// ── Init ───────────────────────────────────────────────────────
onMount(() => {
themeStore.initTheme(appRpc).catch(console.error);
fontStore.initFonts(appRpc).catch(console.error);
keybindingStore.init(appRpc).catch(console.error);
// Run all init tasks in parallel, mark app ready when all complete
const initTasks = [
themeStore.initTheme(appRpc).catch(console.error),
fontStore.initFonts(appRpc).catch(console.error),
keybindingStore.init(appRpc).catch(console.error),
appRpc.request["groups.list"]({}).then(({ groups: dbGroups }) => {
if (dbGroups.length > 0) groups = dbGroups;
}).catch(console.error),
appRpc.request["settings.get"]({ key: 'active_group' }).then(({ value }) => {
if (value && groups.some(g => g.id === value)) activeGroupId = value;
}).catch(console.error),
];
appRpc.request["groups.list"]({}).then(({ groups: dbGroups }) => {
if (dbGroups.length > 0) groups = dbGroups;
}).catch(console.error);
appRpc.request["settings.get"]({ key: 'active_group' }).then(({ value }) => {
if (value && groups.some(g => g.id === value)) activeGroupId = value;
}).catch(console.error);
Promise.allSettled(initTasks).then(() => {
appReady = true;
});
keybindingStore.on('palette', () => { paletteOpen = !paletteOpen; });
keybindingStore.on('settings', () => { settingsOpen = !settingsOpen; });
@ -316,6 +325,7 @@
});
</script>
<SplashScreen ready={appReady} />
<SettingsDrawer open={settingsOpen} onClose={() => settingsOpen = false} />
<CommandPalette open={paletteOpen} onClose={() => paletteOpen = false} />
<SearchOverlay open={searchOpen} onClose={() => searchOpen = false} />