Desktop: show the right vault's people, leave settings on lock, say when an import fell short, and stop host names being cut to four letters
ci / build and test (push) Successful in 3m26s
ci / android head (push) Successful in 3m50s
ci / desktop nightly (push) Failing after 37s
ci / api image (push) Successful in 17s

- Choosing a vault while the screen was busy went through a gate that did nothing, so the members
  panel kept showing the previous vault's people under the new name. The read now starts regardless;
  the selection generation discards answers for an earlier choice.
- Locking or signing out from Settings left the window in settings mode under the lock card, with no
  title bar to drag, minimise or close, and unlock returned to Settings. Leaving the unlocked state
  leaves Settings and closes the members panel; Escape closes that panel before leaving Settings.
- Both importers reported success when the keychain was busy and skipped the batch, or failed partway.
  ImportOutcome now carries refused hosts and why a batch stopped, and the screens say so.
- Host cards: the sync badge took 70 of 214 pixels from the name ("bastion" drew as "bast…", two k8s
  workers both as "k8s…"); it now sits on the address line. Tag chips wrap and trim inside the card.
  Keychain names trim inside their column instead of printing over TYPE, and the Security page's
  caption wraps inside its card.
This commit is contained in:
jaap-jan committed 2026-10-02 13:16:55 +02:00
1 parent 0e8fe4fc80
commit a4b81da597
11 files changed
+314 -68

No files matched your search

@@ -1639,11 +1639,32 @@ internal sealed partial class VaultsViewModel(
}
// Fire-and-forget on purpose, and the only place in this class that is: selection changes come
// from a list box, which has no cancellation token and no way to await. Wrapped here rather than
// inside the read, because the read is also awaited from inside a reload that already holds the
// busy gate — and a second RunAsync there would find the gate held by its own caller and skip the
// members list entirely.
_ = RunAsync(() => LoadSelectedAsync(CancellationToken.None));
// from a list box, which has no cancellation token and no way to await.
//
// ◆ Not through RunAsync. Its busy gate returns at once while anything else runs — the first load,
// a share, a reload — so a vault chosen in that moment never had its people read, and the panel
// went on showing the previous vault's under the new one's name, with SHARE and REVOKE acting on
// that mixture. The read does not need the gate: LoadSelectedAsync bumps the selection generation,
// and every answer for an earlier selection is discarded by it.
_ = LoadSelectionAsync();
}
/// <summary>Reads the newly selected vault's people, turning a failure into a sentence.</summary>
private async Task LoadSelectionAsync()
{
try
{
await LoadSelectedAsync(CancellationToken.None).ConfigureAwait(true);
}
catch (DodoSshApiException exception)
{
Status = exception.Message;
}
catch (Exception exception) when (exception is not OutOfMemoryException
and not OperationCanceledException)
{
Status = exception.Message;
}
}
partial void OnPendingActionChanged(VaultActionRequest? value)