From 746711da9d0c2a8e3bcc2119f70c4d4f620873db Mon Sep 17 00:00:00 2001 From: Jaap-Jan de Wit | DodoTech Date: Wed, 5 Aug 2026 08:43:33 +0200 Subject: [PATCH] Let a tap on the phone's host list mean connect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Choosing a machine raised the connect bar over the bottom of the list: a password box, CONNECT, EDIT, MOVE and DELETE. Five controls in the way of the one thing a tap on a machine's name obviously means. So the gestures split. A tap connects. A long press raises the bar, with all five. The pencil in the phone's header — its only persistent chrome — edits whichever host is chosen, which is the one of the five common enough to be worth a control that is always in the same place. The flag doing it is the desktop's own IsHostPaneOpen rather than a second one. That head made exactly this move when a selection stopped opening its drawer, and the question both are asking is "has somebody asked about this host" — answering it twice is how two heads come to disagree about what a selection means. One tap cannot finish: a host that authenticates with a typed password has nowhere on a list to be given one. That tap raises the bar with the box in it and says so, and a second tap with the box filled in connects. The branch is in the view model rather than in the head, because "can this machine be reached without asking for anything" is the same question the bar's own password box answers, and a copy of it in a view would be a second reading of a binding chain that has one. Two mechanics worth knowing. Avalonia raises Tapped on release whatever the press lasted, so a long press would open the bar and then connect — one touch firing both gestures — which is why HostsScreen tracks the hold and swallows the tap it precedes. And Holding only fires once IsHoldingEnabled is set, so that and the handler are attached together rather than one in markup and one in code. ConnectToRecent now opens the pane rather than selecting the row. On the phone it has to: a selection alone raises nothing now, so going back to a recent machine would land on a screen with nothing to press. --- README.md | 11 +- docs/manual-checks.md | 56 ++++++++-- .../Views/HostsScreen.axaml | 36 ++++++- .../Views/HostsScreen.axaml.cs | 101 +++++++++++++++++- .../Views/PhoneShell.axaml | 28 ++++- .../ViewModels/MainWindowViewModel.cs | 16 ++- .../ViewModels/VaultViewModel.cs | 99 ++++++++++++++++- .../ShellFlowTests.cs | 91 +++++++++++++++- 8 files changed, 412 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 7c78662..715f08c 100644 --- a/README.md +++ b/README.md @@ -489,7 +489,16 @@ transfer starts, the download runs into the cache, and the finished bytes are co chose. That order has one visible cost, and the screen says it rather than leaving it to be discovered: the picker creates the file when you dismiss it, so a download that then fails leaves an empty one there. The alternative is a picker that appears minutes later over whatever you moved on to — and often while the app -is in the background, where Android will not show one at all. Hosts and groups are made, corrected and taken +is in the background, where Android will not show one at all. + +**On the phone's host list a tap connects.** It used to choose the machine and raise a bar over the bottom of +the list — a password box, CONNECT, EDIT, MOVE and DELETE — which put five controls in the way of the one +thing tapping a machine's name obviously means. So the gestures split: a tap connects, a **long press** raises +that bar, and the **pencil in the header** edits whichever host is chosen. The one tap that cannot finish is a +host that authenticates with a password you type, because there is nowhere on a list to type it — that tap +raises the bar with the box in it and says so, and tapping the row again once it is filled in connects. + +Hosts and groups are made, corrected and taken away here now, from a floating + on the Hosts screen and a menu on each group's heading, and both editors are cards in the list's own row rather than dialogs, so the form never covers the thing it is about. Every question a deletion asks is the desktop's, counted the same way and drawn in the place the buttons that diff --git a/docs/manual-checks.md b/docs/manual-checks.md index a679e99..4a006c1 100644 --- a/docs/manual-checks.md +++ b/docs/manual-checks.md @@ -863,8 +863,8 @@ Run on a 360dp-wide device or emulator, unlocked, on HOSTS. Look at the bottom right of the host list with no host selected. -**Pass:** a filled accent circle, 56×56, clear of the bottom edge and of the last row's text. Then select a -host so the connect bar rises. +**Pass:** a filled accent circle, 56×56, clear of the bottom edge and of the last row's text. Then press +and hold a host so the connect bar rises. **Pass:** the + has moved up with the bar and is not over the CONNECT button. @@ -1004,7 +1004,7 @@ intended answer, not a failure. ### 8.13 DELETE under a host is not beside EDIT -Select a host so the connect bar rises. +Press and hold a host so the connect bar rises. **Pass:** CONNECT, then EDIT and MOVE side by side, then DELETE full width in the danger colour on a row of its own beneath them. On a host with nowhere to move to, MOVE is absent and the row is EDIT alone. @@ -1017,6 +1017,46 @@ puts them back with the host still there. **Failure means:** a bar that kept its buttons under the question is one where DELETE can be pressed twice, the second press landing on whatever the list rebuilt underneath. + +### 8.14 A tap connects, and a long press is what raises the bar · **the one worth the most care** + +On a host bound to a key or a stored credential — one that needs nothing typed — tap the row once. + +**Pass:** it connects, and the terminal takes the screen. **Nothing rises over the list on the way past** — +no password box, no CONNECT, no EDIT/MOVE/DELETE. Come back to HOSTS: still nothing. + +Now press and hold the same row. + +**Pass:** the bar comes up, naming that host, with all of it. Press and hold a different row: the bar +follows to that one rather than staying on the first. + +Now tap a host that authenticates with a **typed password**. + +**Pass:** it does not dial. The bar rises with the password box in it and the status line says the host asks +for a password. Type it and press CONNECT — or tap the row a second time, which is the same thing — and it +connects. + +**Failure means:** a tap that raises the bar is the old behaviour, where choosing a machine put five +controls over the bottom of the list in the way of the one thing a tap on its name means. A tap that dials +a password host with an empty box is worse: the connection fails somewhere the user cannot see why. A long +press that connects means `held` in `HostsScreen.axaml.cs` is not suppressing the `Tapped` that follows a +hold, so one touch fires both gestures. + +### 8.15 The pencil in the header edits the chosen host + +With a host chosen — by a tap that connected, or by a long press — look at the header beside LOCK. + +**Pass:** a pencil. It opens that host's editor. With nothing chosen there is no pencil at all rather than a +greyed one, and while an editor is open it is gone. + +Navigate to Settings and back. + +**Pass:** the pencil is absent on every screen but HOSTS, including Settings and the keychain. + +**Failure means:** a pencil visible over another screen is the `IsHostsShowing` wrapper gone — see +`PhoneShell.axaml`, which nests the two conditions because Avalonia's bindings have no "and". A pencil that +stays while the host editor is up is `CanEditSelectedHost` no longer reading `AnEditorIsOpen`. + --- ## Phase 9 — Tag chips and the picker @@ -1216,12 +1256,14 @@ seriousness here, since this password is typed rather than stored and so is type With at least one keychain host and one machine connected to by hand in the log, open Connections with nothing running. -**Pass:** tapping the keychain one lands on HOSTS with that host selected and its connect bar up. Tapping -the hand-typed one puts its address back in the box on this screen and leaves the password box **empty**. -Neither one dials anything on its own. +**Pass:** tapping the keychain one lands on HOSTS with that host selected **and its connect bar up**. +Tapping the hand-typed one puts its address back in the box on this screen and leaves the password box +**empty**. Neither one dials anything on its own. **Failure means:** if the hand-typed one navigates to HOSTS, the log entry is carrying a host id it should -not have. If the password came back, something is storing it — it never was. +not have. If the password came back, something is storing it — it never was. And if the keychain one arrives +with the host selected but **no bar**, `ConnectToRecent` is setting the selection rather than opening the +pane: since 8.14 a selection alone raises nothing, so that is a screen with nothing to press. ### 11.9 Settings holds the keychain, and back walks out of it diff --git a/src/DodoSSH.Client.Android/Views/HostsScreen.axaml b/src/DodoSSH.Client.Android/Views/HostsScreen.axaml index ad837cd..9113c64 100644 --- a/src/DodoSSH.Client.Android/Views/HostsScreen.axaml +++ b/src/DodoSSH.Client.Android/Views/HostsScreen.axaml @@ -31,6 +31,23 @@ Both editors are cards in the list's own row, swapped for the list rather than stacked over it, which is what SnippetsScreen does and for the reason written there: a form on top of the list hides what it is about. There is no dialog and no editor screen anywhere on this head. + + ── ◆ v4: A TAP CONNECTS, AND THE BAR IS WHAT A LONG PRESS IS FOR. ─────────────────────────────────────── + Choosing a row used to raise the connect bar over the bottom of the list — a password box, CONNECT, EDIT, + MOVE and DELETE, five controls in the way of the one thing a tap on a machine's name means. So the + gestures split, and each one now does what it looks like it does: + + · a tap connects, and the bar never appears; + · a long press asks about the host: the bar comes up, with all five; + · the pencil in the phone's header edits whatever is chosen, which is the one action common enough to + be worth a control that is always in the same place. + + The one case a tap cannot finish is a host that authenticates with a typed password, since there is + nowhere to type it. That tap raises the bar with the box in it and says so — see + VaultViewModel.ConnectToRowAsync, which is where the branch lives and why it is not in this head. + + It is the same move the desktop grid made when a selection stopped opening its drawer, and it reuses that + head's flag rather than inventing a second one; see VaultViewModel.IsHostPaneOpen. --> - + @@ -548,8 +576,10 @@ + +