Public Access
Android: the redesign — a Vaults tab with hosts, keychain and snippets, card lists, a keychain that can add, and files that act on what is chosen
The bottom bar is Vaults · Connections · Settings, drawn as Material 3 pills with icons from the embedded Material font and a count of open sessions on Connections, which replaces the strip of shells above the bar. Vaults is the open vault: its header carries the name as a switch to the vaults screen, the sync light and a lock icon, and a Hosts · Keychain · Snippets segmented control sits under it. The keychain and snippets move there from Settings (IsVaultSurface lights the tab; IsMoreSurface no longer lists them), and back from either goes to the hosts. Settings becomes an account card and grouped sections: security, vaults and history, files, this app. Host rows are cards with a terminal tile and the live dot on its corner. The connect sheet names the host and its address, labels its box, focuses it as it opens, reveals the password on request, and puts CANCEL left and CONNECT right; every two-button row on the head now confirms on the right. While a hosts-screen sheet is up the header and bar are dimmed too and a tap on them lowers it, and the bar stands down while the software keyboard is up. The keychain gains a floating + and a sheet of the desktop's five adds (generate a key, paste a key, a password, a bucket, a tag) over the editors VaultViewModel already had, drawn as a full-screen page with labels above the boxes; a chosen item gets EDIT and COPY PUBLIC KEY beside MOVE and DELETE. Snippets get a floating + and cards that say RUNS or INSERTS. Files trade the seven-button block for a selection bar (save, and a ⋮ sheet with rename, move, permissions and a red delete), folder and file tiles, an upload button, and header actions for a terminal on the same host, refresh and close; a terminal's + sheet opens SFTP on that terminal's own host. The theme takes the audit's visual findings: Fluent's ClipToBounds is cleared on glowing buttons so the glow is no longer cut to a square (the desktop's Button.accent too), prose is Montserrat with mono kept for addresses and code, disabled secondary buttons are quieter than enabled ones, Fluent's dropdown, checkbox, switch, focus and selection brushes come from the palette, touch no longer leaves hover fills behind, and lists, nav entries and icon buttons carry names for TalkBack. Builds clean; checked on the emulator end to end: unlock, the three vault views, adding and deleting a password, connecting through the new sheet, files on the terminal's host with the selection bar and its sheet. App tests 727 of 733 pass with 5 skipped; the one failure, TheCountsAPhoneShows_ FollowEveryForwardsState, passes three runs of three alone and is untouched here. Layout tests pass.
This commit is contained in:
1 parent
6806e542f9
commit
5b32c76c95
24 files changed
+2022
-654
No files matched your search
@@ -941,6 +941,9 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
/// <summary>Whether the picker is showing hosts.</summary>
|
||||
internal bool ShowsHostPicker => Remote is RemoteKind.Host;
|
||||
|
||||
/// <summary>Whether a host — not a bucket — is open, so that a terminal could be opened beside it.</summary>
|
||||
internal bool IsHostConnected => IsConnected && Remote is RemoteKind.Host;
|
||||
|
||||
/// <summary>Whether the picker is showing buckets.</summary>
|
||||
internal bool ShowsBucketPicker => Remote is RemoteKind.Bucket;
|
||||
|
||||
@@ -1440,6 +1443,50 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
var many => $"{many} selected",
|
||||
};
|
||||
|
||||
/// <summary>Whether there is anything for an action to act on: a tick, or a chosen row.</summary>
|
||||
/// <remarks>
|
||||
/// The phone's question, and it is <see cref="RemoteBatch"/>'s own rule — ticks, or the selection when
|
||||
/// there are none — asked as a yes or no. It decides whether the files screen's selection bar is up,
|
||||
/// which is where that head keeps SAVE and the menu of the four things that change a file. Nothing on
|
||||
/// the desktop reads it.
|
||||
/// </remarks>
|
||||
internal bool HasRemoteBatch => HasCheckedRemote || SelectedRemoteEntry is not null;
|
||||
|
||||
/// <summary>What the phone's selection bar says: the count when rows are ticked, else the row's name.</summary>
|
||||
internal string RemoteBatchLabel =>
|
||||
HasCheckedRemote ? CheckedRemoteLabel : SelectedRemoteEntry?.Name ?? string.Empty;
|
||||
|
||||
/// <summary>Whether the phone's menu of things to do to the chosen rows is up.</summary>
|
||||
/// <remarks>
|
||||
/// The phone moved RENAME, MOVE, PERMS and DELETE off a permanent block of buttons — seven of them over
|
||||
/// half the screen, live with nothing chosen (audit M11) — and into a sheet raised from the selection
|
||||
/// bar's ⋮. The sheet's openness is kept here rather than in the view so the system back gesture, which
|
||||
/// the shell answers, can lower it. The desktop never sets it.
|
||||
/// </remarks>
|
||||
[ObservableProperty]
|
||||
private bool isEntryMenuOpen;
|
||||
|
||||
[RelayCommand]
|
||||
private void OpenEntryMenu() => IsEntryMenuOpen = true;
|
||||
|
||||
[RelayCommand]
|
||||
private void CloseEntryMenu() => IsEntryMenuOpen = false;
|
||||
|
||||
/// <summary>Lets go of everything chosen: the ticks and the selection both.</summary>
|
||||
/// <remarks>The ✕ on the phone's selection bar, which is how somebody says they did not mean it.</remarks>
|
||||
[RelayCommand]
|
||||
private void ClearRemoteBatch()
|
||||
{
|
||||
foreach (var row in RemoteEntries.Where(row => row.IsChecked))
|
||||
{
|
||||
row.IsChecked = false;
|
||||
}
|
||||
|
||||
SelectedRemoteEntry = null;
|
||||
IsEntryMenuOpen = false;
|
||||
RaiseBatchState();
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="CheckedRemoteLabel" />
|
||||
internal string CheckedLocalLabel => CheckedLocalCount switch
|
||||
{
|
||||
@@ -1511,6 +1558,8 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
OnPropertyChanged(nameof(HasCheckedLocal));
|
||||
OnPropertyChanged(nameof(CheckedRemoteLabel));
|
||||
OnPropertyChanged(nameof(CheckedLocalLabel));
|
||||
OnPropertyChanged(nameof(HasRemoteBatch));
|
||||
OnPropertyChanged(nameof(RemoteBatchLabel));
|
||||
OnPropertyChanged(nameof(CanDownload));
|
||||
OnPropertyChanged(nameof(CanUpload));
|
||||
RaiseItemActionState();
|
||||
@@ -4252,6 +4301,8 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
/// </remarks>
|
||||
partial void OnRemoteChanged(RemoteKind value)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsHostConnected));
|
||||
|
||||
// PERMS is the one item action that is not offered on both destinations; see
|
||||
// CanChangeRemotePermissions.
|
||||
OnPropertyChanged(nameof(CanChangeRemotePermissions));
|
||||
@@ -4287,6 +4338,8 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
/// </remarks>
|
||||
partial void OnIsConnectedChanged(bool value)
|
||||
{
|
||||
OnPropertyChanged(nameof(IsHostConnected));
|
||||
|
||||
if (value)
|
||||
{
|
||||
LostConnection = null;
|
||||
@@ -4314,6 +4367,8 @@ internal sealed partial class TransfersViewModel : ObservableObject, IAsyncDispo
|
||||
OnPropertyChanged(nameof(CanDownload));
|
||||
OnPropertyChanged(nameof(CanEditRemote));
|
||||
OnPropertyChanged(nameof(SelectedRemoteName));
|
||||
OnPropertyChanged(nameof(HasRemoteBatch));
|
||||
OnPropertyChanged(nameof(RemoteBatchLabel));
|
||||
|
||||
PendingRemoteDeletion = null;
|
||||
PendingRemoteMove = null;
|
||||
|
||||
Reference in new issue
Block a user