using DodoSSH.Client.Session; namespace DodoSSH.Client.Shell.ViewModels; /// /// The shell's half of a link from Spelunk: holding it until there is a vault to act on it. /// internal sealed partial class MainWindowViewModel { /// /// Acts on a dodossh://spelunk/connect link now, or as soon as a vault is open. /// /// /// /// Called by the head, on the UI thread, for a link this launch was started with, a link a second launch /// passed down the doorbell, or one the platform delivered to the running application. The link has /// already been checked by ; what it may do is decided by /// , which never starts a sign-in by itself, and only /// connects through a Spelunk this device is already signed in to. /// /// /// A locked application keeps it rather than dropping it. Clicking a server in Spelunk and being /// asked for the passphrase is the ordinary first half of this; losing the click at the second half would /// make the button look broken. It is not kept across a restart. /// /// internal void OpenLink(SpelunkLink link) { ArgumentNullException.ThrowIfNull(link); pendingLink = link; if (State is ShellState.Unlocked && Vault is not null) { DeliverPendingLink(); return; } if (State is ShellState.Locked) { StatusMessage = $"Unlock to open {link.Name} from Spelunk."; } } /// Hands a waiting link to the open vault, on the Hosts screen where its answer appears. private void DeliverPendingLink() { if (pendingLink is not { } link || Vault is not { } vault) { return; } pendingLink = null; ShowScreen(ShellScreen.Hosts); // Not awaited: a connect reports its own progress and failures on the vault's status line and in its // tab, as a tap on the row does, and this is called from places that must not wait on a handshake. _ = vault.OpenSpelunkLinkAsync(link); } }