0a0c7081409db2f67a8395149b54cec85a55c967
19
Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
0a0c708140 |
Reduce the synthesized resize to the bottom-right grip only
The handles are invisible and paint above the frame, so the north strip ran the full window width across the caption buttons and the north-east square sat on the close button's own top-right corner. Crossing one dropped that button's :hover mid-glow, which reads as the Aero glow flickering or sticking — an artifact with nothing wrong in the CSS at all. Only the bottom-right corner overlaps nothing: it lands in the 6px gutter that .window-body's margin leaves below and right of the content. That is also where Win7 put its own resize gripper, so one grip is the more faithful answer anyway. Bumped to 1rem from 0.75rem since it is now the only way to resize. resizeFrame stays general and the probe still exercises all eight edges: the origin-moving cases are the subtle ones and are worth keeping proven, so restoring a side later is one entry in the component against tested math. Both the component and gotchas.md now spell out which edges are safe to restore (south, east, west) and which are not (north and both top corners). Harness diffs 0; math, hover and menu probes clean. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
4605a481f1 |
Synthesize window resize for the frameless win7 skin (a documented stopgap)
The win7 skin is frameless so 7.css can draw the Aero caption, and on GTK that means undecorated, which takes the window manager's resize borders and corner grips with it. All three win7 windows were completely unresizable. electrobun 1.18.1 offers nothing to re-enable, verified against the shipped binary rather than assumed: libNativeWrapper exports startWindowMove/ stopWindowMove with no resize counterpart, imports gtk_window_begin_move_drag but not gtk_window_begin_resize_drag, dragRegions.ts implements moving only, and BrowserWindow has neither setResizable nor min-size options. But the window is still programmatically resizable, so only the input affordance is missing: eight handles overlay the frame and drag it through a new windowGetFrame/windowSetFrame pair on the shared windowControlHandlers factory, which gives all three window kinds resize with no per-window wiring. Three things that would have made this quietly wrong: - dragRegions.ts starts a window MOVE from a mousedown listener on document, never checks defaultPrevented, and is not suppressed by a pointerdown handler either (the compatibility mousedown still fires). Every handle carries app-region-no-drag, which short-circuits its check first. - deltas come from screenX, not clientX: a north/west resize moves the window origin under a stationary pointer, so client coords feed that back into the next delta and the window runs away. - the min-size clamp re-anchors the opposite edge; clamping width alone lets x keep tracking the pointer, walking the window off-screen while it looks frozen. This is a stopgap and the point is that it is removable on sight. The frame math is a dependency-free module so scripts/resize-math-probe.ts asserts all eight edges without a window (verified it catches the unanchored-clamp bug: x jumps to 5100 instead of parking at 460). scripts/check-electrobun-resize.ts scans the installed electrobun for the primitives this is waiting on and prints the removal checklist when they appear; it runs from postinstall so a version bump surfaces it, never fails an install, and is silent otherwise. Both trigger paths were simulated. The component header carries the full checklist; docs cover the platform consequence and the dragRegions traps. Harness diffs exactly 0 in both themes; hover and menu probes still clean. Not yet exercised with a real pointer — that needs a live window. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
5ed029a2b8 |
Flatten the selection and the menu highlight; kill the Aero afterglow
Three things looked wrong, three different causes. The selected row carried a border. 7.css outlines tr.highlighted (#aaddfa) on top of its fill, and we had been restating that outline in the new blue — so the band had an edge, and on the cursor row the dotted focus rect made three concentric outlines around a single row. The reserved 1px border stays (it is what stops selection from shifting rows) but is transparent in every state; the fill paints under it, since background-clip is border-box. --w7-sel-bd and --w7-sel-bd-idle are gone with it. The context menu highlighted items with 7.css's translucent gradient wash — the same gradient the ListView selection just dropped. It now uses --w7-sel-bg, so selection reads identically wherever it appears. The hover-off animation was button.css bleeding into menu items, which ARE buttons: button::before is a glow overlay that fades out over a full second, and menu.css suppresses it with content:none on the :hover arm ONLY — so leaving an item brought the pseudo back with opacity animating 1 -> 0, a ghost trailing the pointer. Killing content in every state removes it. Same family, also fixed: button:focus runs pulse-anim infinitely, and this menu moves real focus between items for keyboard nav. menu-probe.ts now checks the highlight too, using hover-probe's :hover -> .simhover rewrite: it measures colour spread down a text-free strip of a force-hovered item, so "is it flat?" is a measurement. Verified the check can fail by injecting the old wash into the built stylesheet — spread 9, exit 2; the flat fill reads spread 0 at exactly #cbe8f6. The harness lost its selection outlines and nothing else, in both themes. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
c4364c1051 |
Fix the dead win7 context menu, flatten the selection, add a tab menu
Right-click did nothing under the win7 skin, and then swallowed the next
click. 7.css declares `position: relative` on ul[role=menu] and the `skin`
layer outranks `utilities`, so Tailwind's `.fixed` lost: [style.left/top.px]
became flow offsets from the menu's static position — the last child of the
h-screen frame — and every menu rendered below the viewport, unreachable
behind overflow:hidden. Its backdrop is a plain <div>, unmatched by 7.css, so
that stayed genuinely fixed and ate the following click. Regressed in
|
||
|
|
9c54a441a9 |
Scale stage 3: shortcuts service + Ctrl/Cmd +/-/0 for the scale
Groundwork for the vim-style bindings planned next: the app previously had NO
keyboard abstraction — `event.metaKey || event.ctrlKey` copy-pasted inline in
six places, no typing-target guard anywhere, every window root matching keys
by hand.
New @core/shortcuts.service.ts owns:
- isMod() (also accepts MouseEvent — Mod+click toggle-select uses the same
rule) and isTypingTarget();
- ONE declarative keymap: resolve(event, scope) -> ShortcutId | null, scoped
main / editor / manager. Layout rules are encoded once: digits, +/- and
Alt-letter chords match on event.code (AZERTY digit rows, layouts where '+'
needs Shift, macOS Option-Z producing Ω); plain letter chords match on
event.key so they follow the user's layout.
Both app.ts, both editor-window.ts and both connection-manager.ts now resolve
through the service and switch on ids — behaviour-preserving for every
existing shortcut, including the deliberate quirks (Ctrl+Tab never meta
because Cmd-Tab is the macOS app switcher; Cmd+9 = last tab; editor Mod+W is
the Windows/Linux arm, macOS routes via the app menu). Escape and Tab stay
component-local on purpose: their meaning is per-window state (find bar open?
close prompt up? caret in the textarea?), not a global binding. The file
panels keep their contextual key state machine but delegate modifier tests.
On top of the table: Ctrl/Cmd +/-/0 steps/resets the interface scale in every
window kind, all three previously unclaimed. isTypingTarget is applied
per-shortcut, not globally in resolve(): the scale keys must not fire while
typing ('-' in a rename prompt must type '-'), but the editor WANTS Mod+S
mid-typing and the tab shortcuts keep their existing reach.
Docs: architecture.md's density prose now describes the uiScale lever;
gotchas.md gains the scale section — the disassembly evidence that native
page zoom is an empty stub on Linux (so nobody tries it again), the
everything-must-be-rem rule, the skinfix-outranks-variants trap the harness
caught (48px close button silently 29px), and the px-mirrors-in-TS class of
bug with the remPx() remedy.
Verified: tsc + build clean; live boot with the user's real legacy settings
file migrates textSize:large -> uiScale 1.2 and renders scaled. Not verified
here (needs interaction): the stepper clicks and the shortcut keys themselves.
Co-Authored-By: Claude <noreply@anthropic.com>
|
||
|
|
c8ccc6b918 |
Skin is a launch-time choice; stop applying it to a live window
Switching Modern -> Win7 at runtime broke the UI. SettingsService.applySkin toggled the `.win7` class the moment the setting changed — harmless when there was one component tree, and a broken window as soon as there were two. The tree is bootstrapped once from the preload-baked __APP_SKIN, so the live flip painted 7.css onto shadlike markup that has no .window.glass, no .title-bar, no menu[role=tablist] and no <table> ListView. The CSS landed on a tree that cannot receive it. A reload would not have helped, and neither would anything short of a restart: - The preload is a persistent WebKitUserScript injected at DOCUMENT_START, so its string is frozen at webview construction — loadURL() re-runs it with the OLD __APP_SKIN. updatePreloadScriptToWebView exists in the FFI but is reachable only from electrobun's internal <electrobun-webview> handler. - titleBarStyle/transparent have no setters; a live window cannot be re-framed. win7 -> modern is the dangerous direction — the modern tree draws no title bar, so it would land in a frameless transparent window with no way to move, minimize or close it. - Recreating the main window is also out: exitOnLastWindowClosed is true, the main rpc is captured by six push closures, the tray captures `win`, and listeners cannot be removed. So: applySkin is deleted outright, from setSkin AND from applyAll — the latter matters independently, since applyAll runs on the settingsChanged push and was therefore breaking every open editor and manager window too. Clicking a skin now only persists it. Also fixed a second leak found while tracing this: manager-window and editor-windows build from `currentSettings()`, the LIVE snapshot, so a window opened after a pending change would boot the new tree and frame while main still ran the old one. `initSessionSkin` now freezes the skin at startup before any window exists, and buildPreload/chromeOptions read that pinned value — chromeOptions loses its parameter so no call site can get it wrong. The options row shows the saved value as pending (skinPending() compares settings.skin() against APP_SKIN) with the hint retexted in all 7 locales; it said "Reopen the window to change its frame", which described the deleted design. Verified: tsc + build:ui clean; both skins boot correctly from a persisted setting (win7 frameless, modern with the native frame). The live flip is now impossible by construction, which is the check that matters here — the UI bundle contains no classList write for win7 at all, the only writer is buildPreload, and sessionSkin has exactly one assignment site. Not verified: the click itself and the pending hint appearing, which need an interaction pass — no window automation is available here. Both are present in the built bundle. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
5bbfc2f475 |
Document the core/skins split
architecture.md gains a "UI layout: one core, two skin trees" section — the folder map, the barrel contract that lets main.ts stay ignorant of both trees, why duplicate selectors across trees are safe, and where a new rule belongs (core / a skin / shared tokens). Its "Window kinds" section now describes two-axis root selection, and the "Skins" section is no longer stale prose about a deleted design: it covers the stylesheet split and the two-phase nature of a skin change (CSS live, tree and frame at next window open). gotchas.md gains a section for the split, all of it earned during the work: `.win7` cannot be renamed because 7.scoped.css is precompiled against that literal; reach core through @core/* rather than relative paths, which is what let 67 imports survive two relocations; @font-face url() rebases when a stylesheet moves and fails silently; the @layer statement must stay first; duplicate selectors across trees are safe; and ngtsc type-checks components nothing imports, so a green build does say something about the inactive skin. Also corrected the component paths that moved under skins/, and the updater.service.ts link that moved under core/. Checked every ../ link in docs/ resolves. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
ab0bb4ef6f |
Pane command rows go flat, like the Connections button
The file panels' action verbs (Send/Edit/Rename/new folder/new file/ permissions/Delete) and the panel picker were wearing the full Aero slab, which is the dialog push-button treatment — wrong for what is really an Explorer command bar. Marked the session strip w7-toolbar so they get the flat-with-hover-glow treatment the Connections button already had from the tab-bar row. The path bar gets it too. Its up/refresh controls sit directly under the action row, so leaving them as slabs beside newly-flat neighbours would have read as arbitrary rather than deliberate. w7-toolbar only targets button, so the path <input> keeps its 7.css textbox border. Verified on a live single-instance capture: both rows flat, the path input unchanged. architecture.md's "three header rows" was now wrong and says "every command row" instead. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
06a14fb6a1 |
Make w7-flat actually flatten; document this round
The status bar's transfers summary is a text toggle, but 7.css painted it as a full Aero push button — a stray bordered slab sitting in the status line. Marked it w7-flat, the per-button escape hatch that existed for exactly this and had never been used. It did not work, for a reason worth keeping: 7.css restates border-color at `.win7 button:not(:disabled):not(:hover)` = (0,3,1), which outranks `.win7 .w7-flat` = (0,2,0). The .w7-toolbar arm of the same rule only ever won that fight by tying on specificity and landing later in the same layer — an accident w7-flat did not share. Split the rule: `background: revert-layer` stays in `skin` (it must land on `utilities`), and the paint-suppression literals move to `skinfix`, where layer order settles it instead of a specificity arms race. Docs updated in the same change per the working agreement — architecture.md gains the tabs contract, the w7-flat/w7-toolbar split and the frame transparency invariant; gotchas.md gains a win7-skin section (unlayered beats every layer, the (0,3,1) border-color restatement, overflow-x clipping the y-axis, 7.css's hardcoded light literals, exact selectors) plus the two Angular traps this round hit: a duplicate `class` attribute is silently dropped, and a backtick inside a component template's HTML comment terminates the TS template literal. Also recorded the verification trap that cost three wrong readings today: `bun run start` leaves the old instance running and `import -window` grabs the OLDEST match, so screenshots silently come from a stale build — this is what made the w7-flat fix above look like a no-op when it was already correct. Kill and count instances before capturing. And `pkill -f 'electrobun dev'` matches the shell running it and kills your own command. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
0ae2a62229 |
Stage 4a: context menu is pure 7.css; retire the lookalike and the false claim
The menu now renders 7.css's real contract — ul[role=menu] > li[role=menuitem] > button for actions, input[type=checkbox] + label for the checkable column toggles, and dividers as .has-divider on the PRECEDING item (7.css draws them as an ::after bevel, not as a node; the service's separator entries collapse onto their predecessor at render time). With the markup right, the framework supplies everything the hand-written version imitated or lacked: the left gutter stripe, bevelled separators, the gradient selection band, the checked box, and disabled/submenu styling we previously had none of. Deleted: the w7-menu lookalike (both the button-slab stripper in `skin` and the whole hand-authored Aero set in `skinfix`) and its w7-menu/w7-menu-sep hooks. The "7.css has no menu component" claims in styles.css and architecture.md were FALSE — dist/gui/menu.css is a full component; the old markup (div > button) simply matched none of it. Both corrected to state the real contract and the trap. Keyboard now follows the platform instead of a highlight class: arrows move REAL focus between items — 7.css styles :focus-visible identically to :hover, and keyboard-initiated programmatic focus counts — and Enter/Space activate buttons natively; only labels need a synthetic click. This also makes the menu honest to screen readers. Dark mode: menu.css hardcodes light literals (color:initial, white bevel halves, the #b3d3f9 checked-box ring); restated in skinfix's dark arm like the ListView's. Also fixed, caught BY the harness: the Stage 3 frame sizing rule was keyed on bare `.window`, forcing 100vh height onto every 7.css window (the harness's demo windows blew up to full page). It is now keyed on `w7-frame`, a hook only the three real window roots carry. Verified zoomed in light and dark against 7.css's reference markup: gutter, dividers, checkmark box, grey right-aligned accelerator all match; bundle 490.92 kB. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
6bb4c3cd7d |
Merge main into feat/7css-skin + give the HTML context menu an Aero skin
main retired electrobun's native context menu (a documented no-op on Linux) in favour of an HTML one on every platform. Merging that here needs the menu to look right under the Win7 skin as well. Conflicts, all resolved by keeping both sides: - src/bun/index.ts — createAppRPC keeps the branch's mainWindow getter, drops main's removed contextMenu dep. - ui/src/app/app.ts — imports both TitleBar and ContextMenu. - ui/src/app/platform.ts — kept the branch's version (its IS_MAC_CHROME accounts for the frameless win7 chrome, and MOD_LABEL correctly keys on the real platform rather than the chrome), plus exporting IS_MAC and adding IS_LINUX for the menu's per-OS shell wording. Aero menu (branch-only): 7.css has no menu component, so it is hand-authored across both layers — the row <button>s shed their push-button slab in `skin` (revert-layer only reaches `utilities` from there), and the square-cornered slab, hairline border and gradient selection band are stated in `skinfix`. Built strictly from existing --w7-* vars, never literal hex, so the hand-written dark Win7 palette recolours it for free. Hover and the keyboard cursor share one band (the component marks the cursor with `bg-accent`, which is overridden alongside :hover) as a real Win7 menu does. Also answers a question the merge raised: frameless windows DO work on Linux. The GTK wrapper honours titleBarStyle "hidden" — it calls gtk_window_set_decorated(false) and logs "GTK: Created window without decorations (custom titlebar)". Verified on GNOME/Wayland and documented in architecture.md. Verified: backend `tsc --noEmit` clean, `bun run build:ui` clean (492.52 kB initial, still under the 500 kB budget), app launches with the skin active, frameless, no console errors and no GBM failures. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
f7ebed5478 |
Make Linux a supported platform: HTML context menus + runtime deps + release target
`bun run start` died on Linux with ERR_DLOPEN_FAILED (missing libayatana-appindicator3.so.1). Fixing the environment exposed the real gap: electrobun's ContextMenu.showContextMenu is a documented no-op on Linux, and since the UI suppresses the webview's own right-click menu, EVERY panel context menu was silently dead there — Send to Other Panel, Open, Rename, Permissions, Delete, Copy Path, Reveal and the column picker all unreachable. Electrobun itself logs "Application menus are not supported on Linux. Implement menu UI in your webview HTML instead." at boot. - Context menus are now HTML on EVERY platform (ui/src/app/context-menu.ts + context-menu.service.ts), not just as a Linux fallback: one implementation cannot drift from a second one. The item builders are ported verbatim from the old bun menu, so ordering, per-platform labels and the Windows-local chmod hide are unchanged, and picks are emitted as the same `ctx-*` / `col:*` strings through RpcService.emitMenuAction — App.handleMenuAction is untouched and still the single dispatcher for both the macOS menubar and right-clicks. Adds what the native menu gave for free: arrow/Enter/Escape keys, viewport edge-flip, close on blur/resize/scroll. The Edit item now shows the real F4 hint instead of the native menu's "e" mnemonic. - New shellItemAction RPC replaces showRowMenu/showColumnsMenu — the only part the webview can't do itself (reveal, open-with-default, copy path). Deletes src/bun/context-menu.ts entirely. - release.ts gains a linux-x64 target. Electrobun emits only the .tar.zst updater blob on Linux, so the artifact is a .tar.gz of the assembled app folder, mirroring the Windows portable zip. - Docs: platform-notes gets a Linux runtime-dependency table (AppIndicator is linked HARD — a missing lib is a boot failure, not a degraded tray), the ldd diagnostic, GNOME tray caveat, known issues and a first-boot smoke test; gotchas gets the ERR_DLOPEN_FAILED trail and the benign GLX/GBM startup noise; architecture/build-and-release/README updated accordingly. Verified: backend `tsc --noEmit` clean, `bun run build:ui` clean (399 kB initial), app boots on Linux with no errors beyond the documented benign warnings. NOT verified on macOS/Windows — the native menu is retired on those platforms too, so the menus need eyeballing on a Mac before the next release. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
07825c1bd1 |
Add a toggleable Windows 7 (7.css) skin behind a new skin setting
Evaluation branch: a full Aero skin, including frameless windows with our own title bar, switchable against the existing modern look. The app already had a four-axis runtime skinning mechanism and zero component stylesheets, so the skin is one new setting plus one stylesheet section rather than a parallel UI. The key move is cascade order: 7.css is imported into a `skin` layer ABOVE Tailwind's `utilities`, so its bare element rules outrank the ~1900 inline utility classes already in the templates. Template changes are limited to additive, skin-inert hooks (ARIA roles, `has-scrollbar`, `w7-toolbar`, `w7-btn`). - styles.css: explicit layer order, `7.css/dist/7.scoped.css` via `layer(skin)`, a token bridge re-pointing the existing semantic tokens at Win7 values (no new tokens, so `@theme inline` is untouched), a hand-authored dark Win7 palette, and neutralizers that `revert-layer` 7.css's dialog-button metrics back to the utility layer. Neutralizers must live inside `skin`, not `skinfix` — `revert-layer` only reaches `utilities` from one layer up. - Frameless chrome: `chromeOptions(skin)` is now the single place either skin's frame is decided. `titleBarStyle: "hidden"` on every platform, which is also the only way to drop the macOS traffic lights. New `title-bar` component mounted by all three window roots. - Window controls over RPC (minimize/toggle-maximize/close/is-maximized), served per window kind so the X reuses each one's existing close path — editors still get their dirty prompt. electrobun has no maximize event, so the state is derived from `resize`; double-click-to-maximize is implemented here too. - Font: Noto Sans vendored (OFL-1.1) under ui/src/fonts, since Segoe UI is absent off Windows and not redistributable. Verified: backend `tsc --noEmit` clean, `bun run build:ui` clean (486 kB initial, under the 500 kB budget), app launches with the skin active and no console errors. The rendered result has not been eyeballed — screen capture and accessibility are both denied to the shell on this machine. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
fc03fa6216 |
Make the darker tone true-black AMOLED
The darker tone sat at #090908 for --background while --chrome was already pure black, which both inverted the elevation ramp (frame strips darker than the content beside them) and missed the point of an AMOLED tone — only a true #000000 pixel is actually off on OLED. --background now collapses into --chrome at pure black, so the main window, connection manager and editor all render black end to end: panes, bars, sidebar, gutter and textarea. Elevation is kept where it earns its place — dialogs, popovers and toasts stay #181817, hover and selection #272726 — and --border/--input go from 12%/15% to 16%/18% white, since on pure black those lines are the only thing left defining panes, bars and rows. No plumbing needed: buildPreload already bakes data-dark-tone onto every window pre-paint, and tone changes broadcast live to open windows. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
e4ba846719 |
Retone dark theme to warm gray #1a1a19 with layered surfaces
The dark palette was shadcn's cool zinc (#202023, hue ~286). Anchor it on #1a1a19 instead — cds gray-830, a warm near-neutral (hue 107) — and retone the whole dark neutral family to match, since a warm background under cool panels clashes. Lightness ramp is preserved; chromatic tokens (destructive, success, icon hues, accent formulas) and the light palette are untouched. Also introduce --chrome so the app isn't one flat tone: frame strips (tab bar, status bar, transfer bar, editor/manager header+footer, connection sidebar) now sit one step below the content panes, with popovers and hover above them — the standard dark-UI elevation order. Dark ramp: #151514 chrome, #1a1a19 content, #20201f card, #2e2e2d hover; the "darker" tone drops chrome to true black. Light gains only a zinc-50 chrome step. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
a40433b99e |
Add built-in auto-updater with tab-bar update pill
Wires electrobun's Updater to the /dl download host. The packaged app checks https://miniscp.com/dl on launch + every 6h; when a newer build exists, an accent-colored "update tool" appears next to Connections in the tab bar. It announces the update, becomes its own inline progress bar while downloading, then flips to "Restart to apply" (two-step: download, then user-triggered relaunch). - electrobun.config.ts: release.baseUrl = https://miniscp.com/dl (baked into version.json at build; miniscp.com fronted by an external proxy for TLS). - rpc.ts: checkForUpdate/downloadUpdate/applyUpdate requests + updateStatus push. - rpc-handlers.ts + index.ts: call Updater; poll on launch+6h; stream onStatusChange progress. checkForUpdate self-guards the dev channel. - rpc.service.ts + new updater.service.ts: signal-based state (available -> downloading -> ready, ready derived from downloadUpdate ok). - tab-bar.ts: single bg-primary pill; progress fills the pill itself. - icons.ts: register mynaDownload. i18n: tabBar + menu keys across all locales. - menu.ts + app.ts: "Check for Updates…" app-menu item -> UpdaterService.check(). - docs: build-and-release + architecture updated. Unsigned builds still update (applyUpdate strips the macOS quarantine xattr). Verified: tsc --noEmit (exit 0) + build:ui AOT (exit 0). Live pill + full download/apply flow require a two-build test on the host. Co-Authored-By: Claude <noreply@anthropic.com> |
||
|
|
a0f56822cd |
Internationalization: 7 languages with live switching
Custom signal-based runtime (no i18n dependency): shared src/shared/i18n dictionaries, ui I18nService.t() reactive by construction so language switches live, and a backend i18n.ts for native menus + thrown errors. Every user-facing string keyed across templates, toasts, dialogs, file kinds, columns, macOS menu/context menus, and errors. Language picker in Options (auto-detects OS locale, falls back to English); switching relabels the webview and native chrome instantly. English/Spanish/French/ German fully drafted; Chinese/Japanese/Basque drafted, flagged for native review. Docs updated. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |
||
|
|
ee5a9e13e6 |
Auto-refresh the active tab's panels (silent, non-disturbing)
Local panels are fs.watched (LocalDirWatcher + setWatchedDirs -> pathRefresh);
remote panels poll every 3s. New refresh({silent}) skips the loading/busy
flags and touches no DOM, snapshotting sessionId+cwd to discard results if the
user navigated mid-flight. Only the active tab is live; switching tabs
refreshes the new pair. A future on/off setting is left as commented
breadcrumbs. Docs updated.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
||
|
|
dc5cb1f707 |
Developer documentation: architecture, build/release, platforms, gotchas
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> |