Skip to content

Fix the app bar (especially on Windows)#18

Open
nedtwigg wants to merge 21 commits intomainfrom
feat/win-app-bar
Open

Fix the app bar (especially on Windows)#18
nedtwigg wants to merge 21 commits intomainfrom
feat/win-app-bar

Conversation

@nedtwigg
Copy link
Copy Markdown
Member

No description provided.

nedtwigg and others added 20 commits April 16, 2026 15:21
The flex-1 grow was trapped inside the Tip wrapper, so the center
section never ate the slack and the right group (close button on
Windows/Linux) floated next to the project name instead of the
window edge. Hoist flex-1 to a direct child of the AppBar row and
add ml-auto on the trailing group for good measure.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Standalone always starts at ~, so there's no meaningful project
directory to show. Drop the display from the AppBar center, remove
the projectDir/homeDir props, and delete the get_project_dir Tauri
command. Center section becomes an empty draggable spacer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The plus button spawns a terminal with the currently selected
shell. The shell-name button opens a menu that picks which shell
is current — it doesn't spawn. The dropdown sizes to its widest
item (w-max + whitespace-nowrap) and the active shell gets a
leading check.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contribute two commands to the mouseterm.view title bar: [+] which
spawns a terminal using the currently selected shell, and a picker
that opens showQuickPick to change the selection (with a check on
the active shell). Selection persists "global unless trumped by
workspace": reads prefer workspaceState then fall back to
globalState; writes go to whichever scope the user chose after
picking.

The shell-picker reuses ptyManager.getAvailableShells() and posts
a new mouseterm:newTerminal message, which the webview's
VSCodeAdapter translates into the same mouseterm:new-terminal
CustomEvent that Pond.tsx already listens for — the spawn path is
identical to the standalone AppBar's [+] button.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Set view.description to the currently selected shell name — it
renders next to the view title in muted text, giving the user a
persistent indication of which shell [+] will spawn. Reorder the
title-bar icons so the shell picker ($(terminal)) sits left of the
[+] button, matching the intended [>_] powershell [+] layout.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
getAvailableShells and getCwd attached their response listener via
child?.on(...) *before* calling sendToChild — but on the first
invocation the module-level child is still null, so the listener
was never registered and the 5s timeout fired with an empty list.
The extension surfaced that as "MouseTerm: no shells detected."
Reorder so sendToChild() (which forks the child via ensureChild)
runs first, then the listener binds to the now non-null child.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Three compounding issues made getAvailableShells() time out at 5s
on Windows, surfacing as "MouseTerm: No shells detected" and a
multi-second stall on [+] (which then spawned the platform default
because the resolved shell was undefined):

- findSystemNode() had no Windows branch: it exhausted Unix paths,
  failed the /usr/bin/env fallback, and returned the literal
  "/usr/local/bin/node" as execPath. fork() with that path stalls
  for several seconds on Windows. Short-circuit to process.execPath
  (Electron's Node) — VSCode's own terminal uses node-pty against
  Electron, so it's the right choice.
- detectWindowsShells() runs a synchronous wsl.exe -l -q with a 5s
  internal timeout. Combined with the execPath stall, the outer 5s
  timeout fired first. Bump the outer timeout to 15s.
- The whole detection was re-run on every click. Cache the shells
  promise at module level; invalidate on child exit or on empty
  results (so a cold-start miss doesn't pin an empty list).

activate() kicks off getAvailableShells() fire-and-forget to warm
the cache before the user clicks anything.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Splits go through Pond.addSplitPanel which wasn't setting
pendingShellOpts, so new panes from a split always spawned the
platform default regardless of what the user had picked.

Introduce a shared "default shell" slot in terminal-registry
(setDefaultShellOpts/getDefaultShellOpts). addSplitPanel reads it
and seeds pendingShellOpts for the new pane. Writers:

- Standalone: AppBar.ShellDropdown syncs its selection into the
  slot via a useEffect on `selected`.
- VSCode: the extension sends a new mouseterm:selectedShell
  message on activate, after the shell picker, and whenever a
  webview re-initialises (so a re-opened view relearns the
  selection). The webview's VSCodeAdapter writes into the slot.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Pond had three spawn paths that skipped pendingShellOpts: restore
fallback, fresh-start, and the onDidRemovePanel auto-respawn when
the last pane is killed/detached. Factor an addTerminalPanel
helper that seeds pendingShellOpts from getDefaultShellOpts and
route all three through it.

For the labelled shell button: VSCode's view/title navigation is
icon-only, so a text-bearing button there isn't expressible. Move
the picker to a StatusBarItem ("$(terminal) Windows PowerShell")
bound to mouseterm.selectShell. Leave [+] in the view title.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
VSCode's view/title navigation is icon-only for extensions — the
built-in terminal renders text via internal UI primitives that
aren't exposed through the extension API. Revert to the native
compromise: icon button next to [+] in the view header, and the
current shell name shown via view.description right after the
view title ("MOUSETERM  Windows PowerShell  [>_] [+]"). Remove
the StatusBarItem added in a917ef7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
VSCodeAdapter.getState() preferred the injected __MOUSETERM_HOST_STATE__
(a frozen HTML blob set at resolveWebviewView time) over
vscode.getState() (VSCode's per-webview storage that setState writes
to and survives re-mount). When the user split panes after the view
was first resolved, the injected blob never updated — and on panel
collapse + re-expand the webview re-mounted from it, restoring the
pre-split layout and collapsing everything into a single tab group.

Flip the order: use vscode.getState() first, fall back to hostState
only for the very first load (before any setState has run).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two bugs, one commit because they share the webview-boot path:

1. reconnectLivePtys was returning paneIds without a layout. On
   panel close+reopen the PTYs stay alive, so reconnection took
   that path, Pond received restoredLayout=undefined, and fell
   into the fallback that creates panels positionless (stacked as
   tabs). Reload Window worked only because deactivate kills the
   PTYs and the cold-start restoreSession path DOES return layout.
   Pull saved.layout from platform.getState() and include it —
   but only when the live id set matches the saved set, otherwise
   dockview would create ghost panels for dead PTYs.

2. Shell detection is async, so the extension pushed
   mouseterm:selectedShell after the webview had already mounted
   and Pond had spawned its first pane — that spawn used the
   platform default. Inject __MOUSETERM_SELECTED_SHELL__ into the
   webview HTML alongside __MOUSETERM_HOST_STATE__; VSCodeAdapter's
   constructor reads it synchronously and seeds defaultShellOpts
   before Pond mounts. resolveWebviewView now awaits
   ptyManager.getAvailableShells() (cached) before serving the HTML
   so the injected value is always known.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Extract setDefaultShellOpts/getDefaultShellOpts into shell-defaults.ts to
  break circular dependency (terminal-registry → platform → vscode-adapter →
  terminal-registry) that caused all 34 alarm tests to fail.
- Update vscode-adapter.ts and standalone AppBar.tsx to import from
  shell-defaults.ts directly; terminal-registry.ts re-exports for API compat.
- Wrap onDidRemovePanel auto-spawn in setTimeout(0) to avoid re-entrant
  api.addPanel call which dockview silently drops.
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages bot commented Apr 20, 2026

Deploying mouseterm with  Cloudflare Pages  Cloudflare Pages

Latest commit: 6618a10
Status: ✅  Deploy successful!
Preview URL: https://4d7b5011.mouseterm.pages.dev
Branch Preview URL: https://feat-win-app-bar.mouseterm.pages.dev

View logs

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant