Move settings into a standalone Settings window
The tab-bar popover had outgrown itself. Settings now open in their own native window (a fourth window kind, built like the connection manager but not modal): a sidebar with Appearance, Transfers, Editor, File list and About, holding every popover row plus the visible-columns choice. Each control is an ordinary settings save, so the other windows follow live while it stays open. The gear button in the tab bar, Ctrl+, and the macOS app menu's "Settings..." (Cmd+,) open it. On macOS Cmd+W arrives as the main window's close-tab menu action, so bun closes the focused Settings window first instead of a main-window tab. Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+29
-13
@@ -30,8 +30,8 @@ Each `BrowserWindow` MUST receive its own `defineRPC(...)` instance: binding a
|
||||
BrowserView calls `rpc.setTransport(...)`, so a shared instance would have its
|
||||
transport stolen by the most recent window. `createAppRPC` (main),
|
||||
`createEditorRPC` (per editor window, hooks close over that window's record),
|
||||
`createManagerRPC` (the single manager window). `rpc.send.*` on an instance
|
||||
targets exactly its own webview.
|
||||
`createManagerRPC` (the single manager window), `createSettingsRPC` (the single
|
||||
Settings window). `rpc.send.*` on an instance targets exactly its own webview.
|
||||
|
||||
### The `events` late-binding pattern
|
||||
|
||||
@@ -39,15 +39,15 @@ targets exactly its own webview.
|
||||
exist until after construction). `AppDeps.events` is a mutable object of
|
||||
no-op functions, reassigned in `src/bun/index.ts` after everything exists:
|
||||
`sessionClosed`, `connectionsChanged`, `openEditor`, `settingsChanged`,
|
||||
`openConnectionManager`, `showAbout`.
|
||||
`openConnectionManager`, `openSettings`, `showAbout`.
|
||||
|
||||
## Window kinds
|
||||
|
||||
`src/bun/windows.ts` — `buildPreload(mode, settings, ctx?)` injects
|
||||
`__APP_PLATFORM`, `__APP_MODE` (`main|editor|manager`), `__APP_CTX` before any
|
||||
page script, plus the persisted theme attributes and interface scale so the
|
||||
first paint is already right. `ui/src/main.ts` picks the root component from
|
||||
`APP_MODE`; all three roots use selector `app-root` (index.html hosts only that
|
||||
`__APP_PLATFORM`, `__APP_MODE` (`main|editor|manager|settings`), `__APP_CTX`
|
||||
before any page script, plus the persisted theme attributes and interface
|
||||
scale so the first paint is already right. `ui/src/main.ts` picks the root component from
|
||||
`APP_MODE`; all four roots use selector `app-root` (index.html hosts only that
|
||||
tag). `chromeOptions()` is the ONLY place the native frame is decided, spread by
|
||||
the main window and `openSecondaryWindow`: macOS `hiddenInset` +
|
||||
`trafficLightOffset {x:12,y:13}` (the UI renders an `h-10 pl-24` drag-region
|
||||
@@ -103,6 +103,20 @@ main's `ConnectionsService` reloads; a reload-retry in `App.findConnection`
|
||||
covers the save→connect race. `setAlwaysOnTop` is deliberately NOT used (it
|
||||
would float over editor windows).
|
||||
|
||||
### Settings window (`src/bun/settings-window.ts` + `ui/src/app/skins/shadlike/settings-window/`)
|
||||
|
||||
Single instance, centered over main, **not modal**: every control is a plain
|
||||
`SettingsService` setter, so each edit is an ordinary save that bun
|
||||
rebroadcasts — the other windows follow live while it stays open. Opened by
|
||||
the tab-bar gear and Ctrl+, (`openSettings` from main) and, on macOS, the app
|
||||
menu's "Settings…" (⌘,, which the menu intercepts first). Its RPC serves only
|
||||
`getSettings`/`saveSettings`/`pickEditorApp`/`showAbout`. ⌘W reaches bun as
|
||||
the main window's `close-tab` menu action, so bun checks the Settings window's
|
||||
focus FIRST and closes it (see gotchas). Sidebar sections: Appearance,
|
||||
Transfers, Editor, File list (visible columns — the column-header right-click
|
||||
menu toggles the same setting), About (opens the native About box). The
|
||||
native title is `options.title`, retitled on a locale switch.
|
||||
|
||||
## Bun modules
|
||||
|
||||
- `fs/provider.ts` — `FileSystemProvider` interface: uniform local/SFTP ops +
|
||||
@@ -152,8 +166,9 @@ would float over editor windows).
|
||||
atomic tmp+rename, 0600 + win32 `icacls` ACL. `store/settings.ts` — defaults
|
||||
spread-merge on load, so NEW SETTINGS KEYS need no backend change.
|
||||
- `menu.ts` — macOS-only app menu, rebuilt on every connections change (the
|
||||
Connect submenu mirrors the store). ⌘W is intercepted by the menu, so bun
|
||||
routes `close-tab` to the focused editor window first. Labels go through
|
||||
Connect submenu mirrors the store; "Settings…" carries ⌘,). ⌘W is intercepted
|
||||
by the menu, so bun routes `close-tab` to a focused Settings or editor window
|
||||
first. Labels go through
|
||||
backend `i18n.t` and the menu is rebuilt on a locale change too.
|
||||
- `i18n.ts` — backend translator (native menus + thrown error messages, which
|
||||
no Angular service can reach). `setLocale(setting)` caches the resolved
|
||||
@@ -175,7 +190,7 @@ would float over editor windows).
|
||||
ui/src/app/
|
||||
core/ app.config.ts, icons.ts, platform.ts, format.ts, file-icons.ts,
|
||||
metrics.ts and every *.service.ts — the non-visual layer
|
||||
skins/shadlike/ the component tree: three window roots (SHAD_ROOTS barrel,
|
||||
skins/shadlike/ the component tree: four window roots (SHAD_ROOTS barrel,
|
||||
picked by main.ts), dialogs, context menu
|
||||
```
|
||||
|
||||
@@ -220,8 +235,9 @@ component; tokens → `ui/src/styles.css`.
|
||||
(`applyTheme/DarkTone/Accent` set `data-*` attributes on `<html>`;
|
||||
`applyUiScale` sets its inline `font-size`); `applyAll` also serves the
|
||||
`settingsChanged` broadcast, so every window follows a save made in any
|
||||
other. All three window RPCs serve `saveSettings` (editor and manager windows
|
||||
save too — the scale shortcuts); bun's `settingsSaved()` in index.ts runs the
|
||||
other. Every window RPC serves `saveSettings` (editor and manager windows
|
||||
save too — the scale shortcuts — and the Settings window is nothing but
|
||||
saves); bun's `settingsSaved()` in index.ts runs the
|
||||
side effects once and rebroadcasts to every window **except the sender**, so
|
||||
there is no echo to fight a held Cmd+. `applyAll` never persists. New setting
|
||||
= five touches here + types.ts (backend merges automatically).
|
||||
@@ -316,7 +332,7 @@ pixel-identical to the old neutral hover. **Interface scale** (`settings.uiScale
|
||||
`html { font-size: 16px * scale }`, and since EVERY size in the app is rem
|
||||
(panel tokens like `--row-h`, all Tailwind utilities, ng-icon sizes), the
|
||||
whole UI scales, chrome included.
|
||||
Driven by the tab-bar stepper, Ctrl/Cmd +/−/0, and preload-baked for a
|
||||
Driven by the Settings window's stepper, Ctrl/Cmd +/−/0, and preload-baked for a
|
||||
flash-free first paint. It replaced the 3-tier `data-text` axis; the store
|
||||
migrates old `textSize` values. TS that measures rem-sized CSS converts through
|
||||
`@core/metrics` `remPx()` — never an assumed 16.
|
||||
|
||||
@@ -10,7 +10,7 @@ electrobun}`). It is regenerated by `postinstall` and at the start of every
|
||||
records, hence gitignored. Fresh checkouts fail `tsc` until `bun install` has
|
||||
run once (postinstall creates the file). `BRANDING.version` stays
|
||||
semver-shaped (`0.1.<n>`) for electrobun's config/updater; `BRANDING.buildLabel`
|
||||
("Build n") is what humans see (About box, options popover).
|
||||
("Build n") is what humans see (About box, Settings → About).
|
||||
|
||||
## Dev loop
|
||||
|
||||
|
||||
@@ -114,6 +114,11 @@ touching the adjacent code.
|
||||
app-level `before-quit` supports `event.response = {allow:false}`). All
|
||||
unsaved-state guards must either intercept app-controlled close paths
|
||||
(⌘W, buttons) or survive the close (editor draft mirroring).
|
||||
- **⌘W in any secondary window arrives as the MAIN window's `close-tab`
|
||||
menu action** (macOS: the app menu intercepts it before the webview sees
|
||||
the key). bun must check the focused secondary window first — the Settings
|
||||
window, then editors — and close THAT; a new window kind that skips this
|
||||
check makes ⌘W close a main-window tab behind it.
|
||||
- **One rpc instance per window** — BrowserView binding steals the rpc's
|
||||
transport; a shared instance silently sends to the wrong webview.
|
||||
- **RPC before socket open is silently lost.** Everything gates on the
|
||||
|
||||
@@ -17,7 +17,7 @@ macOS is the primary target; Windows 11+ x64 and Linux x64 are **beta** targets
|
||||
| Shell wording | `ui context-menu.service.ts` | Reveal in Finder / Move to Trash | Show in Explorer / Move to Recycle Bin | Show in File Manager |
|
||||
| Shortcut labels | `ui platform.ts MOD_LABEL/ALT_LABEL` | ⌘ / ⌥ | Ctrl+ / Alt+ | Ctrl+ / Alt+ |
|
||||
| Tray | `src/bun/tray.ts` | 22 pt template PNG | 16 px colored PNG | colored (needs AppIndicator, see below) |
|
||||
| App menu | `src/bun/menu.ts` | full menu incl. About | none (early return) — About lives in the options popover | none (unsupported upstream) |
|
||||
| App menu | `src/bun/menu.ts` | full menu incl. About | none (early return) — Settings opens from the tab-bar gear (Ctrl+,), About from its About section | none (unsupported upstream) |
|
||||
| connections.json protection | `store/connections.ts` | chmod 0600 | `icacls` current-user ACL (0600 is meaningless) | 0600 |
|
||||
| App data dir | `store/paths.ts` | ~/Library/Application Support | %APPDATA% | $XDG_CONFIG_HOME/.config |
|
||||
| ssh-agent | `fs/sftp.ts` | $SSH_AUTH_SOCK | `\\.\pipe\openssh-ssh-agent` fallback | $SSH_AUTH_SOCK |
|
||||
@@ -172,7 +172,7 @@ Code paths written blind (no Windows box was available); verify in order:
|
||||
7. Ctrl+T/W/F/S and Ctrl+digit tab jumps; tooltips read "Ctrl+…".
|
||||
8. connections.json ACL: `icacls connections.json` shows only the current
|
||||
user after saving a connection.
|
||||
9. Editor/manager windows open, modal bounce works, About shows from the
|
||||
options popover.
|
||||
9. Editor/manager/Settings windows open, modal bounce works, Ctrl+, opens
|
||||
Settings and About shows from its About section.
|
||||
10. Known-issue confirmation: HiDPI blur on a scaled display (expected until
|
||||
upstream fixes it).
|
||||
|
||||
Reference in New Issue
Block a user