Tray icon with live transfer progress and tabs menu

- AppTray: template menu-bar icon (22pt, adapts to light/dark). While
  transfers run it swaps to pre-rendered frames — faded arrows + a fill bar
  showing aggregate doneBytes/totalBytes of the queue (nearest 5%, throttled
  500ms); back to the glyph when idle. No runtime image encoding.
- Menu: one entry per tab (checkmark on the active one) with live per-tab
  transfer count and percentage (jobs mapped via session ids), an overall
  progress row while transferring, Show <app>, Quit. Selecting a tab
  activates the window and switches to it.
- First use of webview->bun messages: PanelsService pushes workspacesSync
  (tab names, sessions, active id) via a new ready-gated send proxy; verified
  end-to-end in the running app.
- engine.aggregateProgress(): totals + per-session breakdown over non-terminal
  jobs (unit-verified idle/mid-transfer/idle).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jokin
2026-07-11 21:41:51 +02:00
co-authored by Claude Fable 5
parent c218cc2104
commit 42e5e5bb9a
10 changed files with 228 additions and 6 deletions
+9 -1
View File
@@ -15,7 +15,13 @@ import type {
// pulling in bun-only type modules.
//
// bun.requests = calls the webview makes, handled in src/bun/rpc-handlers.ts
// bun.messages = fire-and-forget pushes from the webview (tray state)
// webview.messages = push events from bun, handled in ui rpc.service.ts
export interface WorkspaceSyncInfo {
workspaces: { id: number; name: string; remote: boolean; sessionIds: string[] }[];
activeId: number;
}
export type AppRPC = {
bun: {
requests: {
@@ -97,7 +103,9 @@ export type AppRPC = {
};
clearEditLeftovers: { params: Record<string, never>; response: Result };
};
messages: Record<never, never>;
messages: {
workspacesSync: WorkspaceSyncInfo;
};
};
webview: {
requests: Record<never, never>;