Public Access
Desktop: let a lock pressed during an unlock win, instead of the unlock finishing behind it
This commit is contained in:
1 parent
37e9d74938
commit
079a273d46
3 files changed
+99
-6
No files matched your search
@@ -2963,13 +2963,24 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
/// </remarks>
|
||||
private async Task AdoptAsync(VaultSession session, CancellationToken cancellationToken)
|
||||
{
|
||||
// ◆ Which lock this unlock started under. Every await below is a moment the user can press Lock, and
|
||||
// LockAsync can only close what has been handed over by then — so an unlock still attaching its
|
||||
// stores used to finish after the lock and open the vault behind the lock screen.
|
||||
var generation = locks;
|
||||
|
||||
await AttachStoresAsync(session, cancellationToken).ConfigureAwait(true);
|
||||
|
||||
// Before the vault view model, because that is what reads it — and read at all rather than defaulted
|
||||
// to "everything shown", because a vault somebody set aside last week should still be set aside.
|
||||
visibility = await VaultVisibility.LoadAsync(session, cancellationToken).ConfigureAwait(true);
|
||||
|
||||
Vault = new VaultViewModel(
|
||||
if (generation != locks)
|
||||
{
|
||||
await AbandonAsync(session).ConfigureAwait(true);
|
||||
return;
|
||||
}
|
||||
|
||||
var opened = Vault = new VaultViewModel(
|
||||
session,
|
||||
workspace,
|
||||
knownHosts,
|
||||
@@ -2993,9 +3004,30 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
// are both !CanRegisterDevice, and only the second has anything to withdraw.
|
||||
CanForgetDevice = session.Profile.DeviceWrappedPrivateKey is not null;
|
||||
|
||||
await Vault.LoadAsync(cancellationToken).ConfigureAwait(true);
|
||||
await OpenAsync(opened, generation, cancellationToken).ConfigureAwait(true);
|
||||
}
|
||||
|
||||
AfterTheFirstLoad(Vault);
|
||||
/// <summary>Loads the vault just handed over, and starts it syncing — unless a lock has closed it since.</summary>
|
||||
/// <remarks>
|
||||
/// From here the vault belongs to the shell, so a lock closes it itself: there is nothing to undo, only
|
||||
/// nothing more to do to a vault that is gone. Before these checks, a lock pressed while the first load
|
||||
/// ran left this to carry on into a disposed session and a vault the shell no longer held.
|
||||
/// </remarks>
|
||||
private async Task OpenAsync(VaultViewModel opened, int generation, CancellationToken cancellationToken)
|
||||
{
|
||||
if (generation != locks)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
await opened.LoadAsync(cancellationToken).ConfigureAwait(true);
|
||||
|
||||
if (generation != locks)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AfterTheFirstLoad(opened);
|
||||
|
||||
// After the first load, so the list is on screen before anything talks to a server. The loop is
|
||||
// started from the UI thread deliberately: every pass resumes here, which is what keeps the
|
||||
@@ -3010,7 +3042,21 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
// and unlocking must never wait on one. Everything the unlock screen promises about working
|
||||
// offline stops being true the moment the passphrase leads to a socket. So the vault opens, and
|
||||
// the titlebar says OFFLINE until the round trip this starts has an answer.
|
||||
Vault.StartAutoSync();
|
||||
opened.StartAutoSync();
|
||||
}
|
||||
|
||||
/// <summary>Puts away an unlock that a lock overtook before the vault was handed over.</summary>
|
||||
/// <remarks>
|
||||
/// Everything <see cref="LockAsync"/> would have closed had it been here to close: the stores attached to
|
||||
/// this session, the switches read from it, and the session itself, whose keys nothing else now holds.
|
||||
/// </remarks>
|
||||
private async Task AbandonAsync(VaultSession session)
|
||||
{
|
||||
knownHosts.Close();
|
||||
connectionLog.Close();
|
||||
visibility = null;
|
||||
|
||||
await session.DisposeAsync().ConfigureAwait(true);
|
||||
}
|
||||
|
||||
/// <summary>Everything an unlock does that needs the vault's lists to have been read.</summary>
|
||||
@@ -3272,6 +3318,10 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
[RelayCommand]
|
||||
private async Task LockAsync()
|
||||
{
|
||||
// Counted first, so an unlock still on its way in sees it at its next step and stands down rather than
|
||||
// opening the vault after this has run. See AdoptAsync.
|
||||
locks++;
|
||||
|
||||
// First, and before the session it read from goes: a synchronisation pass may be in flight, and it
|
||||
// ends by refreshing this store. Detaching now makes that refresh a no-op instead of a set of pins
|
||||
// reappearing behind a lock screen.
|
||||
@@ -3319,6 +3369,9 @@ internal sealed partial class MainWindowViewModel : ObservableObject, IAsyncDisp
|
||||
[ObservableProperty]
|
||||
private bool isConfirmingSignOut;
|
||||
|
||||
/// <summary>How many times this shell has been locked, for an unlock to notice it was overtaken.</summary>
|
||||
private int locks;
|
||||
|
||||
/// <summary>
|
||||
/// What signing out costs, on this machine, right now.
|
||||
/// </summary>
|
||||
|
||||
Reference in new issue
Block a user