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,9 +1,56 @@
|
||||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using DodoSSH.Client.Shell.ViewModels;
|
||||
|
||||
namespace DodoSSH.Client.App.Views;
|
||||
|
||||
/// <summary>The tab strip above the terminal.</summary>
|
||||
/// <summary>The tab strip, above every screen.</summary>
|
||||
internal sealed partial class TerminalTabs : UserControl
|
||||
{
|
||||
public TerminalTabs() => InitializeComponent();
|
||||
|
||||
/// <summary>
|
||||
/// Closes a tab on a middle click.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// Wired on the tab's own template root, which is the whole answer to "and not on the strip itself".
|
||||
/// A middle press on the background, on the sentence, or on the button that opens a connection reaches
|
||||
/// no handler at all, because there is none there to reach. Nothing has to test what was clicked.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b><c>PointerUpdateKind</c>, not <c>IsMiddleButtonPressed</c>.</b> The latter reports button
|
||||
/// <em>state</em>: it is equally true for a left press made while the middle button happens to be held,
|
||||
/// and for every press during a middle drag. The question here is which button caused this press, and
|
||||
/// that is the one thing only <c>PointerUpdateKind</c> answers.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// On press rather than on release, which is what every browser and every terminal does. Matching a
|
||||
/// release to its press would need capture tracking, to buy the ability to change your mind about a
|
||||
/// middle click — a gesture nobody makes by accident and nobody aborts.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
private void OnTabPointerPressed(object? sender, PointerPressedEventArgs e)
|
||||
{
|
||||
if (sender is not Visual { DataContext: TerminalTabViewModel tab }
|
||||
|| DataContext is not MainWindowViewModel shell)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.GetCurrentPoint((Visual)sender).Properties.PointerUpdateKind
|
||||
is not PointerUpdateKind.MiddleButtonPressed)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Handled, so the strip's ScrollViewer does not also take this as the start of a pan.
|
||||
e.Handled = true;
|
||||
|
||||
// Fire-and-forget, as the host sidebar's double-tap connect is: CloseTabCommand is asynchronous —
|
||||
// it waits for the workspace to tear the session down — and an event handler has nowhere to await
|
||||
// it. Its failures are the workspace's to report, not this strip's.
|
||||
shell.CloseTabCommand.Execute(tab);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user