Editor opens in native windows (one per file)

Real BrowserWindow per edited file with its own RPC instance, deduped by
sessionId+path. The same Angular bundle boots an editor-only root via
preload globals. Native close isn't cancellable in electrobun, so the
editor mirrors its draft to bun; traffic-light closes get a native
Save/Discard prompt after the fact, and failed saves park the draft in
the edit-leftovers dir. In-window closes (Cmd+W, Close) use a styled
prompt; the quit guard now also counts unsaved editors.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Jokin
2026-07-13 22:36:11 +02:00
co-authored by Claude Fable 5
parent 70f3f2a2e6
commit 1652b9e298
18 changed files with 716 additions and 239 deletions
+28 -1
View File
@@ -11,12 +11,24 @@ import type {
TransferSnapshot,
} from "./types";
/** Everything an editor window needs to know about the file it hosts. */
export interface EditorOpenContext {
sessionId: string;
path: string;
name: string;
sessionTitle: string;
}
// Structurally equivalent to electrobun's ElectrobunRPCSchema, written in
// resolved form so this file stays importable from the Angular bundle without
// pulling in bun-only type modules.
//
// bun.requests = calls the webview makes, handled in src/bun/rpc-handlers.ts
// webview.messages = push events from bun, handled in ui rpc.service.ts
//
// ONE schema serves both window kinds (main + editor): electrobun allows
// partial handler sets, and messages nobody listens to are silently dropped,
// so each side only implements/hears what applies to it.
export type AppRPC = {
bun: {
requests: {
@@ -122,8 +134,17 @@ export type AppRPC = {
response: Result;
};
moveToTrash: { params: { path: string }; response: Result };
// editor windows
/** Main window only: open (or focus) a native editor window. */
openEditor: { params: EditorOpenContext; response: Result };
/** Editor windows only — handled by that window's own rpc closure. */
editorSave: { params: { content: string }; response: Result };
editorClose: { params: Record<string, never>; response: Result };
};
messages: {
/** Editor → bun draft mirror; safety net for the non-cancellable native close. */
editorState: { dirty: boolean; content: string };
};
messages: Record<never, never>;
};
webview: {
requests: Record<never, never>;
@@ -131,6 +152,12 @@ export type AppRPC = {
transferUpdate: TransferSnapshot;
sessionClosed: { sessionId: string; reason: string };
menuAction: { action: string };
/** bun → editor windows when the main window saves settings. */
settingsChanged: { settings: AppSettings };
/** bun → main after an editor save, so matching panels refresh. */
pathRefresh: { sessionId: string; dir: string };
/** bun → one editor: run the in-window close flow (dirty prompt). */
editorCloseRequest: Record<string, never>;
};
};
};