Keep the phone's nav under Connections when nothing is running

The chrome stands down for a shell, and it was standing down for the whole
terminal surface. Those parted company when that surface gained a connect page:
with no tabs open it draws a box, a CONNECT button and the machines connected to
before, which is a page in everything but which enum it is in. A third of the
display is worth giving to a shell and is not worth giving to that. Worse, it is
the one screen somebody arrives at by closing their last tab — so the state the
collapsed bar was most likely to be seen in was the state where it left the
system back gesture as the only route to Hosts or Settings.

So RefreshChrome reads one more question. IsTerminalSurface with no tabs joins
the pages in both flags, which keeps the rail and the bar in step: above 600dp
the rail is the bar, and fixing only the narrow layout would leave an unfolded
device on the same screen with the same nothing. The vault header is deliberately
not part of it. The surface draws its own bar with back and the +, and a header
above that is the second row of chrome this head exists to avoid.

The Connections entry lights for the first time, on IsTerminalSurface. It was
left unbound on the argument that the bar was never drawn while that surface was
up, so a lit state was unreachable — that argument is now false, and the flag is
unambiguous on a control that is only drawn in two situations: false on every
page, true on the connect page, and never read while a shell is showing. A bar
sitting under a screen it does not point at is the entry looking broken instead.

Nothing here is testable on this head — the phone's rectangles have no coverage,
for the reasons Phase 8 of manual-checks records — so 11.7 gains the check that
the bar is there with Connections lit, and 11.1 keeps the one that it is gone
with a shell up, which is the half that pays for the arrangement.
This commit is contained in:
2026-08-06 07:38:31 +02:00
parent 174ef7c420
commit cddfeb1f55
6 changed files with 81 additions and 23 deletions
@@ -25,8 +25,9 @@
── a terminal gets the screen ─────────────────────────────────────────────────────────────────────────
Three of the four rows below stand down while a shell is showing: the header, the shells strip and the
bottom bar itself. All three are bound on IsShowingPages, which is the same question asked once — the
surface is either a page or a terminal, and these are the chrome a page has.
bottom bar itself. The strip asks IsShowingPages directly; the other two go through flags the control
computes, and the bar's is the one that differs — it stays up on Connections with nothing running, which
is the terminal surface drawing a page rather than a shell. See PhoneShell.RefreshChrome.
The arithmetic is why. Header 56, strip 46, bar 64, and the terminal's own two rows on top of that: at
360dp the shell was framed by about a third of the display, all of it about somewhere the user was not.
@@ -308,10 +309,15 @@
<!-- ============ navigation ============ -->
<!--
Gone while a terminal is showing, which is the whole of that surface's arrangement: the bar's three
Gone while a shell is showing, which is the whole of that surface's arrangement: the bar's three
destinations are replaced by a back arrow and a + that leads to all of them, both in the terminal's
own bar. See TerminalScreen.axaml.
◆ A shell rather than the surface, which are not the same question — Connections with nothing running
is that surface drawing a page, and the bar stays under it. The screen it stands down for is the one
that pays for the room; a box asking which machine to connect to does not, and taking the nav away
from somebody who has just closed their last tab left them with only the back gesture.
◆ It is no longer a single question — a wide surface takes the rail instead — so it reads one flag
the control computes rather than a condition here. See PhoneShell.ShowsBottomBar.
@@ -340,12 +346,15 @@
rather than the door. The enum member stays ShellSurface.Terminal, for the reason the keychain's
tab is not called Vault: the surface is a terminal, and the word a user reads is the product's.
The only entry here that never lights, and deliberately no longer tries: this bar is collapsed
while the terminal is showing, so IsCurrent could only ever be read as false. Binding it anyway
would be a rule about a state this control cannot be in. What marks it as current is the surface
filling the screen.
◆ It lights again, and IsTerminalSurface is the right question rather than a near miss. This bar
is drawn in exactly two situations — a page, and Connections with nothing running — and that flag
separates them: false for every page, true for the one screen where this is where you are. With a
shell up the bar is gone and nothing here is read at all. It was left unbound while the bar was
collapsed for the whole of the terminal surface, which made a lit state unreachable; a screen the
bar can now sit under and not point at is the entry looking broken instead.
-->
<views:NavButton Grid.Column="1" Label="Connections" Glyph="⌗"
IsCurrent="{Binding IsTerminalSurface}"
Command="{Binding ShowTerminalCommand}" />
<!--