Public Access
Give the phone its pins: an editor section and chips on Files
The data was never the gap — HostSecret.PinnedPaths syncs and merges on both heads, and the desktop's drawer has staged it since v5 — the phone just had nowhere to add, remove or use a pin. Now it has both halves. The host editor page gains a QUICK ACCESS section over the same shared staging the drawer binds (EditorPinnedPaths, AddEditorPin, RemoveEditorPin), with the remove target at this head's 44dp touch floor rather than the desktop's 22-pixel close box, and no folder glyph because this head embeds no icon font for one. The page also gains a Status line of its own: the add command's five refusals speak through Status, and this page covers the screen that normally draws it — a refusal nothing shows is no refusal at all. The Files screen draws the connected host's pins as chips between the breadcrumb and the listing, each running GoRemoteCommand exactly as a crumb does. They are captured at connect, like ConnectedTo and the session facts before them; a bucket gets none, having no HostSecret to pin anything on. Covered headlessly in ShellFlowTests — connect populates, disconnect clears, a bucket stays empty — and by manual checks 8.18 and 8.19, whose phase preamble also stops claiming thirteen checks when it lists twenty-one.
This commit is contained in:
@@ -637,6 +637,31 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
[ObservableProperty]
|
||||
private string? connectedIdentityLabel;
|
||||
|
||||
/// <summary>
|
||||
/// The paths pinned on the connected host, for the phone's Files-screen chip row — the desktop draws
|
||||
/// the same list in its QUICK ACCESS sidebar, over the terminal surface rather than this one. See
|
||||
/// <see cref="VaultViewModel.EditorPinnedPaths"/> for where a pin is actually added or removed; this is
|
||||
/// a read of what was already saved there.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Captured at connect, the same moment <see cref="ConnectedTo"/> is, rather than followed live off the
|
||||
/// host row's own <c>PinnedPaths</c>. A pin edited while this session stays open shows up on the next
|
||||
/// connect rather than mid-session — the same lag <see cref="ConnectedTo"/> itself already carries for
|
||||
/// a relabel — because this screen reads the vault once, at the moment it dials, rather than staying
|
||||
/// wired to a collection it otherwise never has a reason to watch. A bucket has no pins at all:
|
||||
/// <see cref="OpenBucketAsync"/> leaves this empty rather than reading as "not yet known", which is what
|
||||
/// empty already means for a host that connected with none pinned.
|
||||
/// </remarks>
|
||||
internal ObservableCollection<string> ConnectedPinnedPaths { get; } = [];
|
||||
|
||||
/// <summary>Whether the connected host or bucket has any pins to draw as chips.</summary>
|
||||
/// <remarks>
|
||||
/// A read of <see cref="ConnectedPinnedPaths"/> rather than an <c>[ObservableProperty]</c> of its own,
|
||||
/// so it is raised by hand at each of the three places that collection is repopulated or cleared —
|
||||
/// <see cref="MarkHostConnected"/>, <see cref="OpenBucketAsync"/> and <see cref="CloseSessionAsync"/>.
|
||||
/// </remarks>
|
||||
internal bool HasConnectedPins => ConnectedPinnedPaths.Count > 0;
|
||||
|
||||
[ObservableProperty]
|
||||
private HostKeyPresentation? pendingHostKey;
|
||||
|
||||
@@ -947,6 +972,10 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
ConnectedHostKeyAlgorithm = null;
|
||||
ConnectedIdentityLabel = null;
|
||||
|
||||
// And no pins either — see ConnectedPinnedPaths's own remark.
|
||||
ConnectedPinnedPaths.Clear();
|
||||
OnPropertyChanged(nameof(HasConnectedPins));
|
||||
|
||||
connected = (ConnectedTo, row.Label, row.EntityId, TimeProvider.System.GetUtcNow());
|
||||
|
||||
await ListRemoteAsync(session.HomeDirectory, cancellationToken).ConfigureAwait(true);
|
||||
@@ -1033,6 +1062,15 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
ConnectedHostKeyAlgorithm = opened.HostKey.Algorithm;
|
||||
ConnectedIdentityLabel = identityLabel;
|
||||
|
||||
// See ConnectedPinnedPaths's own remark for why this is a snapshot rather than a live follow.
|
||||
ConnectedPinnedPaths.Clear();
|
||||
foreach (var path in row.Host.PinnedPaths)
|
||||
{
|
||||
ConnectedPinnedPaths.Add(path);
|
||||
}
|
||||
|
||||
OnPropertyChanged(nameof(HasConnectedPins));
|
||||
|
||||
// Recorded, and not hidden because it is "only" the file browser. Opening this is a second login as
|
||||
// far as the remote's own auth.log is concerned, so a log of ours that omitted it would disagree with
|
||||
// the host's — and anybody comparing the two would be right to believe the host.
|
||||
@@ -1811,6 +1849,8 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
ConnectedCipher = null;
|
||||
ConnectedHostKeyAlgorithm = null;
|
||||
ConnectedIdentityLabel = null;
|
||||
ConnectedPinnedPaths.Clear();
|
||||
OnPropertyChanged(nameof(HasConnectedPins));
|
||||
RemotePath = string.Empty;
|
||||
RemoteEntries.Clear();
|
||||
RemoteTrail.Clear();
|
||||
|
||||
Reference in New Issue
Block a user