Public Access
Merge branch 'main' into the Android head
Main grew the screens the host-management plan called for — hosts, pins, snippets, logs, import, teams — plus the ObjectStore and Import projects behind two of them, and moved WindowsDeviceKeyStore into the desktop head's Platform folder. Five of those view models landed in a directory this branch had already moved, so they join the rest in DodoSSH.Client.Shell: git spotted the rename and put them there, and the namespaces followed. Shell picks up ObjectStore and Import as a result, which the Android head then gets transitively and will use neither of at first — scoped storage means there is no ~/.ssh/config to import, and file transfer is out of its first scope. Desktop suites green at 155 and 64.
This commit is contained in:
@@ -1,11 +1,14 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Controls.ApplicationLifetimes;
|
||||
using Avalonia.Input.Platform;
|
||||
using Avalonia.Markup.Xaml;
|
||||
using DodoSSH.Client.Shell.Terminal;
|
||||
using DodoSSH.Client.Shell.ViewModels;
|
||||
using DodoSSH.Client.App.Platform;
|
||||
using DodoSSH.Client.App.Views;
|
||||
using DodoSSH.Client.Auth;
|
||||
using DodoSSH.Client.Session;
|
||||
using DodoSSH.Client.Shell.Terminal;
|
||||
using DodoSSH.Client.Shell.ViewModels;
|
||||
using DodoSSH.Client.Ssh;
|
||||
using DodoSSH.Client.Storage;
|
||||
using DodoSSH.Client.Terminal;
|
||||
@@ -47,6 +50,28 @@ internal sealed partial class DodoSshApp : Application
|
||||
/// nowhere honest to release them.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <summary>
|
||||
/// Puts one line of text on the system clipboard.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The clipboard is reached through the window, and at composition time there is no window yet — hence
|
||||
/// a closure that looks it up on each call rather than a reference captured now. A machine with no
|
||||
/// clipboard falls through silently here; the view model is the one that decides what to say, and it
|
||||
/// distinguishes "no clipboard on this machine" from "copied" because they are different answers.
|
||||
/// <para>
|
||||
/// A delegate rather than handing the view model an <c>IClipboard</c>, so that nothing in the view
|
||||
/// models needs a visual and every test that drives them stays window-free.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
private static Func<string, Task> ClipboardWriter(IClassicDesktopStyleApplicationLifetime desktop) =>
|
||||
async text =>
|
||||
{
|
||||
if (TopLevel.GetTopLevel(desktop.MainWindow) is { Clipboard: { } clipboard })
|
||||
{
|
||||
await clipboard.SetTextAsync(text).ConfigureAwait(false);
|
||||
}
|
||||
};
|
||||
|
||||
private static void Compose(IClassicDesktopStyleApplicationLifetime desktop)
|
||||
{
|
||||
var paths = ClientPaths.Default;
|
||||
@@ -74,7 +99,7 @@ internal sealed partial class DodoSshApp : Application
|
||||
// Chosen once, here, because it is a property of the machine and not of any session. A computer with
|
||||
// a usable TPM gets the store that keeps a device key behind a Windows consent prompt; anything else
|
||||
// gets one that reports itself unavailable, so unlock keeps asking for the passphrase. See ADR 0007.
|
||||
var deviceKeys = DeviceKeyStores.ForThisMachine(paths);
|
||||
var deviceKeys = DesktopDeviceKeyStores.ForThisMachine(paths);
|
||||
|
||||
var viewModel = new MainWindowViewModel(
|
||||
paths,
|
||||
@@ -93,7 +118,9 @@ internal sealed partial class DodoSshApp : Application
|
||||
// makes a launch after the first one arrive online rather than merely enrolled.
|
||||
resume: async (url, refreshToken, cancellationToken) => await ServerConnection
|
||||
.ResumeAsync(url, refreshToken, TimeProvider.System, cancellationToken)
|
||||
.ConfigureAwait(false));
|
||||
.ConfigureAwait(false),
|
||||
|
||||
copyToClipboard: ClipboardWriter(desktop));
|
||||
|
||||
desktop.MainWindow = new MainWindow { DataContext = viewModel };
|
||||
|
||||
|
||||
Reference in New Issue
Block a user