Public Access
Give the user menu one door into settings instead of three
Settings, Vaults and Preferences all opened the same full-window settings mode and differed only in which of its seven pages they landed on. SettingsNav, which lists every one of those pages including Vaults and Preferences, is on screen the whole time you are in there — so two of the three rows were deep links into a place the third one opens. They saved one click and cost a menu that read as though it offered three destinations. It was three rows for a reason that had stopped applying. Until v5c, "Settings" and "Preferences" were two doors onto the same bare Preferences screen, and splitting them was the fix for something real; Vaults arrived beside them when VaultsScreen became a settings page too. Folding those two back in is not a return to that state. They are pages now, with a rail of their own, and what a menu at the foot of the nav rail is for is getting into settings at all. Nothing became unreachable — both are one click deeper, from the rail that was always going to be the way to them. ◆ WHAT STAYS, AND WHY IT IS NOT THE SAME ARGUMENT. Logout stays and still lands on the Account page rather than on General, because its confirmation card is drawn inline on that one page while the vault is unlocked; arming it from anywhere else would raise a card nobody could see. The vault switches and New vault above the divider stay too — neither is a page of the settings mode, and the switches have no other home. ◆ THE ROWS ARE REMOVED FROM THE MARKUP, NOT UNWIRED. NavRailTests asserts their absence rather than only asserting that Settings still works, because the failure that guards against is silent: a row left in the markup with its handler deleted is a menu entry that does nothing when pressed, which reads as a broken application rather than a tidied menu. The helper it asserts through excludes the vault switches by their data context and not by their label — a vault is free to be called "Vaults", and a test that a menu entry is absent must not be defeatable by what somebody named a vault. Two facts go, one comes back plus the absence check; the layout suite is 166. Manual check 1.8 walked a reader through all three rows in turn and now walks them through the one, then through SettingsNav's seven — which is where the two went. design-import-gaps.md gains a v5c-5 section rather than an edit to the v5c table: what that table records is what shipped in that pass, and it did. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c270f3fe39
commit
ed936380b3
5 files changed
+94
-78
No files matched your search
@@ -741,3 +741,27 @@ to a 34-pixel rail carrying the chevron that brings it back — a rail rather th
|
|||||||
that vanishes without trace is one people report as lost. The choice is written through to
|
that vanishes without trace is one people report as lost. The choice is written through to
|
||||||
`ClientSettings.SessionSidebarOpen` rather than held for the session: it is a decision about how much of the
|
`ClientSettings.SessionSidebarOpen` rather than held for the session: it is a decision about how much of the
|
||||||
window a terminal gets, and one that had to be made again on every launch would not really be on offer.
|
window a terminal gets, and one that had to be made again on every launch would not really be on offer.
|
||||||
|
|
||||||
|
## v5c-5 — one door to settings, not three
|
||||||
|
|
||||||
|
**The user-chip popover keeps its Settings row and has lost Vaults and Preferences.** v5c gave it three, and
|
||||||
|
the table above records why: until that pass "Settings" and "Preferences" had been two doors onto the same
|
||||||
|
bare screen, so splitting them was a real fix, and Vaults arrived beside them when `VaultsScreen` became a
|
||||||
|
settings page too.
|
||||||
|
|
||||||
|
Living with it made the shape of the mistake clear. All three opened the same full-window mode and differed
|
||||||
|
only in which of its seven pages they landed on — and `SettingsNav`, which lists every one of those pages
|
||||||
|
including Vaults and Preferences, is on screen the entire time you are in there. So two of the three rows
|
||||||
|
were deep links into a place the third one opens, saving one click and costing a menu that read as though it
|
||||||
|
offered three destinations. A menu at the foot of the rail is for getting into settings at all; which page
|
||||||
|
you want is a question that has a rail of its own once you are there.
|
||||||
|
|
||||||
|
Nothing became unreachable: both pages are one click deeper, from the rail that was always going to be the
|
||||||
|
way to them. `NavRailTests` asserts the rows are gone from the markup rather than merely unwired, because a
|
||||||
|
row left behind with no handler is a menu entry that does nothing when pressed — which reads as a broken
|
||||||
|
application rather than a tidied menu.
|
||||||
|
|
||||||
|
Logout stays, and still lands on a page rather than on General: its confirmation card is drawn inline on the
|
||||||
|
Account page and nowhere else, so arming it from anywhere else would be a card raised where nobody could see
|
||||||
|
it. The vault switches and **New vault** above the divider stay too — they are what the popover is for
|
||||||
|
besides settings, and neither is a page of the settings mode.
|
||||||
+12
-9
@@ -118,15 +118,17 @@ view models — this check is the version with a real connection on the end of i
|
|||||||
|
|
||||||
### 1.8 Entering and leaving settings mode
|
### 1.8 Entering and leaving settings mode
|
||||||
|
|
||||||
From HOSTS, press the user chip at the foot of the nav rail and choose **Settings**. Then repeat from a
|
From HOSTS, press the user chip at the foot of the nav rail and choose **Settings** — which is the menu's
|
||||||
fresh open, choosing **Vaults**, and again choosing **Preferences**.
|
only way in now; the Vaults and Preferences rows beside it were folded back into it, because all three
|
||||||
|
opened this same mode and differed only in which page they landed on.
|
||||||
|
|
||||||
**Pass:** each of the three swaps the whole window's chrome — the titlebar becomes the 53px "Back to
|
**Pass:** it swaps the whole window's chrome — the titlebar becomes the 53px "Back to application" bar, the
|
||||||
application" bar, the ordinary nav rail is replaced by the 340px SettingsNav, and the status bar and the
|
ordinary nav rail is replaced by the 340px SettingsNav, and the status bar and the update banner (if either
|
||||||
update banner (if either was showing) are both gone. **Settings** lands on General; **Vaults** and
|
was showing) are both gone. It lands on **General**, with SettingsNav's own list beside it —
|
||||||
**Preferences** land on their own pages, each lit in SettingsNav's own list — General/Vaults/Account under
|
General/Vaults/Account under SETTINGS, Security/Preferences/Groups/Tags under CUSTOMIZE, Logout pinned below
|
||||||
SETTINGS, Security/Preferences/Groups/Tags under CUSTOMIZE, Logout pinned below both. Click every one of the
|
both. Click every one of the seven rows in turn: each swaps the content column without leaving settings mode
|
||||||
seven rows in turn: each swaps the content column without leaving settings mode or touching the titlebar.
|
or touching the titlebar, and Vaults and Preferences are among them — which is the whole reason the popover
|
||||||
|
no longer carries its own rows for those two.
|
||||||
|
|
||||||
Now open a terminal, leave it showing, and open Settings from the user chip again. Press **Back to
|
Now open a terminal, leave it showing, and open Settings from the user chip again. Press **Back to
|
||||||
application** — or, without touching anything else, press Esc.
|
application** — or, without touching anything else, press Esc.
|
||||||
@@ -134,7 +136,8 @@ application** — or, without touching anything else, press Esc.
|
|||||||
**Pass:** both return to exactly the screen that was showing before Settings was opened — the terminal,
|
**Pass:** both return to exactly the screen that was showing before Settings was opened — the terminal,
|
||||||
still running, rather than HOSTS or anywhere else. Switching between settings pages first (General → Vaults
|
still running, rather than HOSTS or anywhere else. Switching between settings pages first (General → Vaults
|
||||||
→ Preferences) does not change what "back" goes back to; only the screen open the moment Settings was
|
→ Preferences) does not change what "back" goes back to; only the screen open the moment Settings was
|
||||||
**first** entered does.
|
**first** entered does. The other doors into this mode — the palette, and the Preferences page's own two
|
||||||
|
importer rows — behave the same way, so the popover having one row rather than three changes nothing here.
|
||||||
|
|
||||||
**Failure means:** a return to HOSTS regardless of where Settings was opened from is
|
**Failure means:** a return to HOSTS regardless of where Settings was opened from is
|
||||||
`MainWindowViewModel.settingsReturnScreen` being recaptured on every `EnterSettings` call rather than only on
|
`MainWindowViewModel.settingsReturnScreen` being recaptured on every `EnterSettings` call rather than only on
|
||||||
|
|||||||
@@ -252,13 +252,23 @@
|
|||||||
<Border Height="1" Margin="11,4" Background="{StaticResource BorderMid}" />
|
<Border Height="1" Margin="11,4" Background="{StaticResource BorderMid}" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
v5c: Settings, Vaults and Preferences now each land on their own page of the settings mode —
|
◆ ONE ROW, WHERE v5c PUT THREE.
|
||||||
see MainWindowViewModel.EnterSettings and SettingsView.axaml. Settings opens on General, the
|
|
||||||
mode's own default landing page; Vaults and Preferences open directly on the page they name,
|
Settings, Vaults and Preferences all opened the same full-window settings mode — see
|
||||||
which is also what anything that used to navigate to ShellScreen.Vaults or
|
MainWindowViewModel.EnterSettings and SettingsView.axaml — differing only in which of its
|
||||||
ShellScreen.Preferences now does — see ShowScreen. Three handlers rather than the two rows
|
seven pages they landed on. Two of the three were therefore deep links into a place the third
|
||||||
sharing one before this wave: the mock's Settings area was a family of screens that did not
|
one opens, and SettingsNav is already on screen the whole time listing every page including
|
||||||
exist yet, and now that it does, "Settings" and "Preferences" are no longer the same click.
|
those two, so the shortcut saved one click and cost a menu that read as though it offered
|
||||||
|
three destinations.
|
||||||
|
|
||||||
|
It was three rows because settings mode had only just been built out of what used to be two
|
||||||
|
bare ShellScreens: "Settings" and "Preferences" were the same click before that wave, and
|
||||||
|
splitting them was the fix for a real thing. Folding the other two back in is not a return to
|
||||||
|
that state — Vaults and Preferences are pages now, reached from the rail inside settings, and
|
||||||
|
what this menu is for is getting there at all.
|
||||||
|
|
||||||
|
What still lands on a page rather than on General is Logout below, and it has to: its
|
||||||
|
confirmation card is drawn inline on the Account page and nowhere else.
|
||||||
-->
|
-->
|
||||||
<Button Classes="poprow" Click="OnPopoverSettingsPressed">
|
<Button Classes="poprow" Click="OnPopoverSettingsPressed">
|
||||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
<StackPanel Orientation="Horizontal" Spacing="10">
|
||||||
@@ -268,29 +278,6 @@
|
|||||||
</StackPanel>
|
</StackPanel>
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
<!--
|
|
||||||
◆ THE SAME TREATMENT AS SETTINGS ABOVE AND LOGOUT BELOW, which these two did not have: their
|
|
||||||
label was TextGhost where the other two rows' was Text, so a menu of five equally live
|
|
||||||
destinations drew two of them in the colour this window uses for something switched off. The
|
|
||||||
icons stay one step quieter than the words — the idiom the nav rail's own rows already follow
|
|
||||||
— but "quieter than the word beside it" and "dimmed" are not the same statement.
|
|
||||||
-->
|
|
||||||
<Button Classes="poprow" Click="OnPopoverVaultsPressed">
|
|
||||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
||||||
<TextBlock FontFamily="{StaticResource IconFont}" Text="" FontSize="12"
|
|
||||||
Foreground="{StaticResource TextGhost}" />
|
|
||||||
<TextBlock Text="Vaults" FontSize="10" Foreground="{StaticResource Text}" />
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Button Classes="poprow" Click="OnPopoverPreferencesPressed">
|
|
||||||
<StackPanel Orientation="Horizontal" Spacing="10">
|
|
||||||
<TextBlock FontFamily="{StaticResource IconFont}" Text="" FontSize="12"
|
|
||||||
Foreground="{StaticResource TextGhost}" />
|
|
||||||
<TextBlock Text="Preferences" FontSize="10" Foreground="{StaticResource Text}" />
|
|
||||||
</StackPanel>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Border Height="1" Margin="11,4" Background="{StaticResource BorderMid}" />
|
<Border Height="1" Margin="11,4" Background="{StaticResource BorderMid}" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
|
|||||||
@@ -59,28 +59,6 @@ internal sealed partial class NavRail : UserControl
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Opens settings mode on its Preferences page.</summary>
|
|
||||||
private void OnPopoverPreferencesPressed(object? sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
ClosePopover();
|
|
||||||
|
|
||||||
if (DataContext is MainWindowViewModel shell)
|
|
||||||
{
|
|
||||||
shell.EnterSettingsCommand.Execute(SettingsPage.Preferences);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>Opens settings mode on its Vaults page.</summary>
|
|
||||||
private void OnPopoverVaultsPressed(object? sender, RoutedEventArgs e)
|
|
||||||
{
|
|
||||||
ClosePopover();
|
|
||||||
|
|
||||||
if (DataContext is MainWindowViewModel shell)
|
|
||||||
{
|
|
||||||
shell.EnterSettingsCommand.Execute(SettingsPage.Vaults);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Starts a sign-out, through the Account settings page so the confirmation card has somewhere to be
|
/// Starts a sign-out, through the Account settings page so the confirmation card has somewhere to be
|
||||||
/// seen — see <see cref="MainWindowViewModel.SignOutFromPopover"/>.
|
/// seen — see <see cref="MainWindowViewModel.SignOutFromPopover"/>.
|
||||||
|
|||||||
@@ -210,32 +210,38 @@ public sealed class NavRailTests : IAsyncLifetime
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Settings, Vaults and Preferences each enter settings mode on the page they promise, and shut the
|
/// Settings enters settings mode on its landing page, and shuts the popover behind it.
|
||||||
/// popover behind them.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// <para>
|
/// v5c gave this menu three navigation rows — Settings, Vaults and Preferences — because settings mode
|
||||||
/// v5c: these three used to land on a bare <c>ShellScreen</c> — Settings and Preferences on the very
|
/// had just been built out of what were two bare <c>ShellScreen</c>s, and "Settings" and "Preferences"
|
||||||
/// same one, since the mock's own Settings area did not exist yet. Now that it does, each opens the
|
/// had been the same click until then. All three opened the same mode and differed only in which page
|
||||||
/// settings mode on its own page — see <see cref="MainWindowViewModel.EnterSettings"/> — and "Settings"
|
/// they landed on, which made two of them deep links into a place the third one opens, past a
|
||||||
/// and "Preferences" are no longer the same click.
|
/// <c>SettingsNav</c> that lists every page anyway. One row now; see <c>NavRail.axaml</c>'s own remark.
|
||||||
/// </para>
|
|
||||||
/// <para>
|
|
||||||
/// Three <see cref="Fact"/>s over one private body rather than a <see cref="Theory"/>: <c>SettingsPage</c>
|
|
||||||
/// is <c>internal</c>, and a public theory method may not carry an internal type in its signature.
|
|
||||||
/// </para>
|
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
[Fact]
|
[Fact]
|
||||||
public Task ThePopoversSettingsRow_EntersSettingsOnGeneralAndClosesThePopover() =>
|
public Task ThePopoversSettingsRow_EntersSettingsOnGeneralAndClosesThePopover() =>
|
||||||
APopoverRowLandsOnAsync("Settings", SettingsPage.General);
|
APopoverRowLandsOnAsync("Settings", SettingsPage.General);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The two rows that were folded into it are gone from the menu rather than merely unwired.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Worth a test of its own because the failure it guards is silent: a row left in the markup and
|
||||||
|
/// stripped of its handler is a menu entry that does nothing when pressed, which reads as a broken
|
||||||
|
/// application rather than as a tidied menu. Both destinations are still reachable — one click deeper,
|
||||||
|
/// from <c>SettingsNav</c> — which is the whole argument for removing them from here.
|
||||||
|
/// </remarks>
|
||||||
[Fact]
|
[Fact]
|
||||||
public Task ThePopoversVaultsRow_EntersSettingsOnVaultsAndClosesThePopover() =>
|
public Task ThePopoverNoLongerOffersVaultsOrPreferencesOfItsOwn() =>
|
||||||
APopoverRowLandsOnAsync("Vaults", SettingsPage.Vaults);
|
OnTheRailAsync((rail, window) =>
|
||||||
|
{
|
||||||
|
Click(UserChip(rail), window);
|
||||||
|
|
||||||
[Fact]
|
PopoverRows(window).ShouldNotContain("Vaults");
|
||||||
public Task ThePopoversPreferencesRow_EntersSettingsOnPreferencesAndClosesThePopover() =>
|
PopoverRows(window).ShouldNotContain("Preferences");
|
||||||
APopoverRowLandsOnAsync("Preferences", SettingsPage.Preferences);
|
PopoverRows(window).ShouldContain("Settings");
|
||||||
|
});
|
||||||
|
|
||||||
private Task APopoverRowLandsOnAsync(string label, SettingsPage target) =>
|
private Task APopoverRowLandsOnAsync(string label, SettingsPage target) =>
|
||||||
OnTheRailAsync((rail, window) =>
|
OnTheRailAsync((rail, window) =>
|
||||||
@@ -369,6 +375,24 @@ public sealed class NavRailTests : IAsyncLifetime
|
|||||||
.OfType<TextBlock>()
|
.OfType<TextBlock>()
|
||||||
.Any(text => string.Equals(text.Text, label, StringComparison.Ordinal)));
|
.Any(text => string.Equals(text.Text, label, StringComparison.Ordinal)));
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Every word the open popover offers as a place to go.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The vault switches are excluded by their data context rather than by their label, because a vault is
|
||||||
|
/// free to be called anything — including "Vaults" — and a test asserting that a menu entry is absent
|
||||||
|
/// must not be satisfiable or defeatable by what somebody named a vault.
|
||||||
|
/// </remarks>
|
||||||
|
private static IReadOnlyList<string> PopoverRows(Visual window) =>
|
||||||
|
[.. window.GetVisualDescendants()
|
||||||
|
.OfType<Button>()
|
||||||
|
.Where(button => button.Classes.Contains("poprow")
|
||||||
|
&& button.DataContext is not VaultToggleViewModel)
|
||||||
|
.SelectMany(button => button.GetVisualDescendants().OfType<TextBlock>())
|
||||||
|
.Select(text => text.Text)
|
||||||
|
.Where(text => !string.IsNullOrEmpty(text))
|
||||||
|
.Select(text => text!)];
|
||||||
|
|
||||||
/// <summary>Whether a vault row's magenta check square is drawn, for whether it is currently shown.</summary>
|
/// <summary>Whether a vault row's magenta check square is drawn, for whether it is currently shown.</summary>
|
||||||
private static bool HasVisibleCheck(Button row) =>
|
private static bool HasVisibleCheck(Button row) =>
|
||||||
row.GetVisualDescendants().OfType<Border>().Any(
|
row.GetVisualDescendants().OfType<Border>().Any(
|
||||||
|
|||||||
Reference in new issue
Block a user