Public Access
Merge main into the desktop redesign branch
Four conflicts. Three were two people adding to the same spot, and one was a real collision: main gave the connect bar a REMEMBER tick in the same pass that this branch took the connect bar off the hosts screen. REMEMBER is now in the drawer, beside the password box it qualifies. Nothing about the feature changed — RemembersConnectPassword, its refusal to fire until the remote has accepted the password, and the six tests over it are main's untouched — only where it is drawn. The move improves it slightly and it is worth saying why rather than claiming a merge was neutral: the bar had one row and had to fit the box, the tick, the authentication note and CONNECT along it, which is why the tick was a bare "REMEMBER" in tracked capitals. A column has room to put it under the box as a sentence, where it reads as a property of the password rather than as a fourth control in a row. MainWindowViewModel: both sides added members after ShowTerminal — the desktop's three fixed tabs here, the phone's connect menu on main. They do not interact, so both are kept, each under its own heading. TeamsScreen: main added the team's own RENAME, HAND OVER and ARCHIVE, a member's LastActive, the role a new member arrives as, and the KEY HOLDERS list. This branch had only bumped the file's font sizes a point. Resolved by taking main's file whole and re-running the bump over it, so the new controls join the scale rather than sitting a point below everything around them. README: both sides described a different head's third pass in the same paragraph. Both kept. Two things checked rather than assumed, because this branch moved the furniture the merged commits sit on. The chrome heights main's terminal work touched are the phone's, not the desktop's — 44, 42 and 24 are unchanged, so the layout harness's budget still describes the window. And main's keychain DELETE did not reach VaultScreen.axaml, whose header this branch rearranged, so the five buttons that overflowed at the larger type are still five. 2415 tests pass, up from 2369 by the 46 main brought.
This commit is contained in:
@@ -73,7 +73,7 @@ internal enum ShellScreen
|
||||
/// <summary>Everything in the vault that is not a host.</summary>
|
||||
Vault = 2,
|
||||
|
||||
/// <summary>Shared vaults and the people in them. Nothing implements it yet.</summary>
|
||||
/// <summary>Shared vaults and the people in them. Both heads draw it.</summary>
|
||||
Team = 3,
|
||||
|
||||
/// <summary>Preferences.</summary>
|
||||
@@ -418,25 +418,21 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Two defaults, because the two audiences never overlap. A release build is installed by somebody
|
||||
/// signing in to the hosted deployment, and typing its address is the only thing standing between
|
||||
/// them and a working application. A debug build is run from a clone, next to
|
||||
/// <c>dotnet run --project src/DodoSSH.Api</c>, and shipping the hosted address there would point
|
||||
/// every development launch at production — which is worse than an inconvenience, since sign-in is
|
||||
/// the step that enrolls a device.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Note the schemes. <c>http</c> locally is not an oversight: the API's first launch profile — the
|
||||
/// one a plain <c>dotnet run</c> and the README both select — is plaintext on 5233, and pointing an
|
||||
/// HTTPS client at a plaintext port fails as "The SSL connection could not be established", which
|
||||
/// One default for every build. The hosted deployment is what all but a handful of launches are
|
||||
/// aiming at, and typing its address is the only thing standing between an installed application and
|
||||
/// a working one. Running against a clone means replacing this with
|
||||
/// <c>http://localhost:5233</c> by hand — note the scheme, because the API's first launch profile —
|
||||
/// the one a plain <c>dotnet run</c> and the README both select — is plaintext on 5233, and pointing
|
||||
/// an HTTPS client at a plaintext port fails as "The SSL connection could not be established", which
|
||||
/// sends people looking for a certificate problem. See <see cref="ExplainSignInFailure" />.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// This was once split on <c>DEBUG</c> so a development launch could not enroll a device against
|
||||
/// production by accident. That protection is gone: a debug build now offers the hosted address like
|
||||
/// any other, and the first sign-in accepted unread lands there.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
#if DEBUG
|
||||
internal const string DefaultServerUrl = "http://localhost:5233";
|
||||
#else
|
||||
internal const string DefaultServerUrl = "https://ssh.dodotech.cloud";
|
||||
#endif
|
||||
|
||||
[ObservableProperty]
|
||||
private string serverUrl = DefaultServerUrl;
|
||||
@@ -781,14 +777,18 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
/// The hub and everything behind it, because a bottom bar that went dark the moment you opened one of
|
||||
/// its destinations would be a bar that only ever lights three of its four entries. This is the one
|
||||
/// place where "which tab" and "which screen" are deliberately not the same question — the other three
|
||||
/// tabs are each exactly one screen, and this one is six.
|
||||
/// tabs are each exactly one screen, and this one is seven.
|
||||
///
|
||||
/// Preferences is in the list because the phone reaches it through the hub. The desktop reaches it from
|
||||
/// the rail and never asks this.
|
||||
/// the rail and never asks this. <see cref="ShellScreen.Team"/> is in it for the same reason and no
|
||||
/// other: the desktop has a rail entry for teams and the phone reaches them through MORE, so a screen
|
||||
/// missing here is one whose arrival darkens the tab that led to it and brings the shell's own header
|
||||
/// back over a screen that already has one.
|
||||
/// </remarks>
|
||||
internal bool IsMoreSurface =>
|
||||
IsShowingPages && Screen is ShellScreen.More or ShellScreen.Snippets or ShellScreen.Logs
|
||||
or ShellScreen.Transfers or ShellScreen.Buckets or ShellScreen.Preferences;
|
||||
or ShellScreen.Transfers or ShellScreen.Buckets or ShellScreen.Preferences
|
||||
or ShellScreen.Team;
|
||||
|
||||
/// <summary>
|
||||
/// Whether the terminal's WebView may be on screen at this instant.
|
||||
@@ -799,8 +799,15 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
/// and a child window composites above everything its parent paints — so whatever Avalonia draws in the
|
||||
/// same rectangle is drawn underneath it and its buttons cannot be clicked. Anything that covers the
|
||||
/// terminal's area has to collapse the terminal instead, and that is every one of the conditions here: a
|
||||
/// locked vault (the unlock card), the page area (every screen uses the full width), and the
|
||||
/// quick-connect palette.
|
||||
/// locked vault (the unlock card), the page area (every screen uses the full width), the quick-connect
|
||||
/// palette, and the phone's connect sheet.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>The sheet is here rather than in <see cref="IsTerminalSurface"/>, and the palette is not.</b> The
|
||||
/// palette replaces the whole surface, so collapsing everything the terminal half draws is right. The
|
||||
/// sheet is raised from the terminal's own top bar and that bar has to stay on screen behind it —
|
||||
/// dropping the surface would take the bar, the tabs and the phone's whole chrome with it and leave the
|
||||
/// sheet floating over the page underneath. So only the renderer's rectangle is given up.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>The terminal and the pages are exclusive, and that is the whole of the rule.</b> They share one
|
||||
@@ -829,7 +836,8 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
/// safe — that detaches it and destroys the whole WebView2 process tree.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
internal bool IsTerminalShowing => IsTerminalSurface && SelectedTab is { HasSession: true };
|
||||
internal bool IsTerminalShowing =>
|
||||
IsTerminalSurface && !IsConnectSheetOpen && SelectedTab is { HasSession: true };
|
||||
|
||||
/// <summary>
|
||||
/// Whether the terminal half of the window is the half being shown, pane or no pane.
|
||||
@@ -945,6 +953,54 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
[RelayCommand]
|
||||
private void ShowVaults() => ShowScreen(vaultsScreen);
|
||||
|
||||
// ---- The phone's connect menu ----
|
||||
|
||||
/// <summary>
|
||||
/// Whether the phone's connect menu is open over the terminal.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Drawn by the Android head alone, and shell state rather than something that view could hold on its
|
||||
/// own for the reason <see cref="IsSearching"/> is: it has to collapse the renderer while it is up. See
|
||||
/// <see cref="IsTerminalShowing"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// It exists because the phone gives a terminal the whole screen. The bottom bar and the vault header
|
||||
/// are gone while a shell is showing, so the three things that bar was the way to — a host, a host's
|
||||
/// files, a bucket — need a way back that is not "leave the terminal first and remember what you were
|
||||
/// doing". The menu is that, and every entry on it is one of the two navigation commands above.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[ObservableProperty]
|
||||
private bool isConnectSheetOpen;
|
||||
|
||||
/// <summary>Raises the connect menu over the terminal.</summary>
|
||||
/// <remarks>
|
||||
/// Gated on the terminal surface rather than merely trusting its only button to be off screen otherwise.
|
||||
/// The flag collapses the renderer, so one set while a page was showing would be a sheet nobody can see
|
||||
/// holding a terminal hidden that nothing would put back.
|
||||
/// </remarks>
|
||||
[RelayCommand]
|
||||
private void OpenConnectSheet()
|
||||
{
|
||||
if (!IsTerminalSurface)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
IsConnectSheetOpen = true;
|
||||
}
|
||||
|
||||
/// <summary>Lowers the connect menu, leaving the terminal where it was.</summary>
|
||||
/// <remarks>
|
||||
/// The scrim, the CANCEL row and the system back gesture all come here. Choosing an entry does not, and
|
||||
/// does not need to: every entry navigates, and leaving the terminal surface lowers the sheet on its own
|
||||
/// — see <see cref="OnSurfaceChanged"/>, which is what makes "the sheet is only ever up over a terminal"
|
||||
/// true of routes nobody wrote it for.
|
||||
/// </remarks>
|
||||
[RelayCommand]
|
||||
private void CloseConnectSheet() => IsConnectSheetOpen = false;
|
||||
|
||||
// ---- Open terminals ----
|
||||
|
||||
/// <summary>
|
||||
@@ -2595,7 +2651,22 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="OnScreenChanged" />
|
||||
partial void OnSurfaceChanged(ShellSurface value) => RaiseSurfaceState();
|
||||
/// <remarks>
|
||||
/// <b>The one place the connect sheet is lowered by something other than a tap.</b> Every way out of a
|
||||
/// terminal ends here — a rail or bottom-bar destination, the files screen, the palette connecting to a
|
||||
/// host, closing the last tab, a lock — and each of them would otherwise leave the flag set on a shell
|
||||
/// showing a page. That is not merely untidy: the flag collapses the renderer, so the next return to the
|
||||
/// terminal would draw the sheet again over a rectangle held blank by it.
|
||||
/// </remarks>
|
||||
partial void OnSurfaceChanged(ShellSurface value)
|
||||
{
|
||||
if (value is not ShellSurface.Terminal)
|
||||
{
|
||||
IsConnectSheetOpen = false;
|
||||
}
|
||||
|
||||
RaiseSurfaceState();
|
||||
}
|
||||
|
||||
/// <remarks>
|
||||
/// Both changes raise the same set, and they have to: <see cref="IsHostsShowing"/> and its four siblings
|
||||
@@ -2659,6 +2730,9 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
|
||||
partial void OnIsSearchingChanged(bool value) => RaiseTerminalState();
|
||||
|
||||
/// <inheritdoc cref="OnIsSearchingChanged" />
|
||||
partial void OnIsConnectSheetOpenChanged(bool value) => RaiseTerminalState();
|
||||
|
||||
/// <remarks>
|
||||
/// The unlock card and the confirmation swap, so arming one has to hide the other — see
|
||||
/// <see cref="IsAskingForThePassphrase"/>.
|
||||
|
||||
Reference in New Issue
Block a user