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:
2026-07-31 21:03:22 +02:00
199 changed files with 31294 additions and 775 deletions
+57 -1
View File
@@ -271,13 +271,32 @@
runs horizontally and a left bar on a row of tabs reads as a divider between them.
-->
<Style Selector="Button.tab">
<Setter Property="Padding" Value="12,0" />
<!-- Less on the right than the left: the close box lives inside the tab and brings its own margin. -->
<Setter Property="Padding" Value="12,0,7,0" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
<Setter Property="FontSize" Value="10.5" />
<Setter Property="FontWeight" Value="Medium" />
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
</Style>
<!--
The button that opens a connection. A tab in every respect but the marks a tab carries: no active
state, because it is never the thing showing, and no right border, because it is not separating
itself from anything.
-->
<Style Selector="Button.tab.plus">
<Setter Property="Padding" Value="0" />
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
</Style>
<Style Selector="Button.tab.plus /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="BorderThickness" Value="0,2,0,0" />
<Setter Property="BorderBrush" Value="Transparent" />
</Style>
<Style Selector="Button.tab.plus:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{StaticResource Text}" />
<Setter Property="Background" Value="{StaticResource Raised}" />
</Style>
<Style Selector="Button.tab /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
<Setter Property="BorderBrush" Value="{StaticResource BorderSubtle}" />
@@ -290,6 +309,34 @@
<Setter Property="BorderThickness" Value="0,2,0,0" />
</Style>
<!--
A pair of buttons standing in for a two-way choice, inside a pane rather than down a rail. Not the
.cat style, which stretches to fill a 176-pixel rail row and would be wrong at this width — and which
the category rail's own test counts, so borrowing it would have made this a fourth category.
-->
<Style Selector="Button.choice">
<Setter Property="Padding" Value="10,5" />
<Setter Property="FontFamily" Value="{StaticResource MonoFont}" />
<Setter Property="FontSize" Value="9.5" />
<Setter Property="LetterSpacing" Value="0.5" />
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
</Style>
<Style Selector="Button.choice /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="CornerRadius" Value="4" />
<Setter Property="Background" Value="{StaticResource Raised}" />
<Setter Property="BorderBrush" Value="{StaticResource Border}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
</Style>
<Style Selector="Button.choice:pointerover /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{StaticResource Text}" />
</Style>
<Style Selector="Button.choice.active /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Background" Value="{StaticResource AccentWash}" />
<Setter Property="BorderBrush" Value="{StaticResource Accent}" />
<Setter Property="Foreground" Value="{StaticResource Text}" />
</Style>
<!-- The close box on a tab, and the window controls. Square, quiet, and red only where it means it. -->
<Style Selector="Button.close /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
@@ -299,6 +346,15 @@
<Setter Property="Foreground" Value="{StaticResource Danger}" />
</Style>
<!--
The one inside a tab, as opposed to the ones in the titlebar. Rounded and small, because a square
full-height red panel inside a tab reads as a divider between two tabs rather than as part of one —
which is what it looked like while it was a sibling of the tab instead of a child.
-->
<Style Selector="Button.close.inline /template/ ContentPresenter#PART_ContentPresenter">
<Setter Property="CornerRadius" Value="3" />
</Style>
<!--
Text input. Fluent draws a filled box with a thick focus underline; this design draws a hairline field
that changes border colour, and the two do not sit together in one row.