Public Access
Give the window its v5b chrome and each session surface its own shell
This commit is contained in:
1 parent
1b76c51fbb
commit
43c939b697
30 files changed
+4433
-1772
No files matched your search
@@ -35,40 +35,71 @@
|
||||
|
||||
<UserControl.Styles>
|
||||
<!--
|
||||
A directory is marked by colour rather than by an icon: this application ships no icon set, and the
|
||||
palette already reserves blue for "a directory, a distinct scope" — see App.axaml, where it is
|
||||
described as deliberately rare. This is the one place it is spent.
|
||||
── v5b ─────────────────────────────────────────────────────────────────────────────────────────────
|
||||
A directory used to be marked by colour alone — this application shipped no icon set when that rule
|
||||
was written. It ships one now: v5b embeds Material Icons as IconFont, already spent on the nav rail,
|
||||
the drawer and the session shell's own sidebar, and per SFTP.dc.html a file row draws a 14px glyph of
|
||||
its own — folder for a directory, and the closest classic Material Icons has to the design's own
|
||||
Material-Symbols-only "draft": insert_drive_file, a plain document rather than a page with a folded
|
||||
corner. Recorded as a deviation rather than silently swapped, because "draft" is simply not a glyph
|
||||
this font contains.
|
||||
|
||||
Two further colours come from the mode, and they are split across the two columns on purpose: NAME says
|
||||
what a row is, PERMS says what is notable about how it is set. So an executable is green in NAME —
|
||||
"live, yours, something that runs" — while a file anyone may write to is amber in PERMS, over the
|
||||
characters that actually say so. The two never compete for one TextBlock, which is what lets a
|
||||
world-writable executable show both facts instead of one winning an argument.
|
||||
So NAME's colour stopped being the directory's own mark — the glyph is now — and become what the
|
||||
design says instead: a folder is white and medium weight, a file is TextDim and regular. Blue is not
|
||||
spent here any more; Info keeps meaning "a distinct scope" everywhere else it already did, and this
|
||||
screen no longer borrows it.
|
||||
|
||||
Both are files only; see SftpEntry, which will not read a mode off a symbolic link or a directory.
|
||||
Rendering `-rwxrwxrwx` in two colours at once is not something this list can do, so amber over the whole
|
||||
string is the compromise: the eye lands on the column, and the string itself is the detail.
|
||||
A second colour still comes from the mode, and it still overrides the first rather than competing with
|
||||
it: an executable is Live green in NAME — "live, yours, something that runs" — regardless of whether
|
||||
the row beside it is asking for the folder colours or the file ones. PERMS keeps its own, separate
|
||||
amber for a mode anyone may write to, on the same reasoning as before: NAME says what a row is, PERMS
|
||||
says what is notable about how it is set, and the two never compete for one TextBlock.
|
||||
-->
|
||||
<Style Selector="TextBlock.entry">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.entry.dir">
|
||||
<Setter Property="Foreground" Value="{StaticResource Text}" />
|
||||
<Setter Property="FontWeight" Value="Medium" />
|
||||
</Style>
|
||||
<!--
|
||||
Two different hues, and after v2 that takes saying. These marks encode two independent facts in one
|
||||
column, so they have to be told apart at a glance — and they used to be, for free, because the accent
|
||||
was green and Info was blue. v2 made the accent blue too, which put #5B8CFF beside #7FB0FF: the same
|
||||
hue two steps apart, which is a shade rather than a distinction.
|
||||
|
||||
So an executable is Live green now. It is the one use of that colour that is not about a session, and
|
||||
it earns it on the same grounds — it is a fact about the file rather than something to press, and it
|
||||
is the colour this marker already was before the accent moved out from under it.
|
||||
Declared after .dir on purpose — Avalonia has no specificity, and an executable that is also somehow
|
||||
the target row would need this rule to win. It never is in practice; see SftpEntry, which reads the
|
||||
execute bit off a file's own mode and nothing else's.
|
||||
-->
|
||||
<Style Selector="TextBlock.entry.dir">
|
||||
<Setter Property="Foreground" Value="{StaticResource Info}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.entry.exec">
|
||||
<Setter Property="Foreground" Value="{StaticResource Live}" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
The glyph beside NAME. One quiet colour regardless of folder or file — the design's own renderVals
|
||||
gives both the same default iconFg — because the glyph itself already says which one a row is; the
|
||||
colour underneath it is furniture, on the same TextFaint-family step TextBlock.fieldglyph already uses
|
||||
for a mark meant to be skipped rather than read.
|
||||
-->
|
||||
<Style Selector="TextBlock.entryicon">
|
||||
<Setter Property="FontFamily" Value="{StaticResource IconFont}" />
|
||||
<Setter Property="FontSize" Value="14" />
|
||||
<Setter Property="Foreground" Value="{StaticResource TextGhost}" />
|
||||
<Setter Property="VerticalAlignment" Value="Center" />
|
||||
<Setter Property="HorizontalAlignment" Value="Center" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
SIZE and MODIFIED, both quieter than the design's own literal values ask for — rgb(93,95,116) and
|
||||
rgb(110,112,137) sit a step below every text colour this palette already names. Per
|
||||
design-notes/v5b-fidelity-notes.md's own instruction for values this close, the nearest existing steps
|
||||
are reused rather than two new keys added for a difference nobody would see: TextGhost for SIZE, which
|
||||
the design draws a shade darker than MODIFIED, and TextFaint — one step lighter — for MODIFIED, which
|
||||
keeps the two in the same order the design puts them in even though neither is the design's exact hex.
|
||||
-->
|
||||
<Style Selector="TextBlock.entrysize">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextGhost}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.entrydate">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
Faint by default, as this column has always been: a mode is there so its absence would be noticed. It
|
||||
steps up to amber only when it has something to say, which is the whole reason the default is quiet.
|
||||
@@ -84,6 +115,40 @@
|
||||
<Style Selector="TextBlock.perms.loose">
|
||||
<Setter Property="Foreground" Value="{StaticResource Warn}" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
── v5b: the TRANSFERS strip's own progress track ────────────────────────────────────────────────────
|
||||
5px, 3px radius, Chip's own fill under an AccentGradient indicator — the design's own slim bar. A real
|
||||
0% is what a queued transfer draws with this: the indicator's width is nothing, which reads exactly as
|
||||
the design's own queued sample row does (a bar the same colour as its own track). No indeterminate
|
||||
animation is drawn for it — a queued transfer really is at zero, so zero is the honest thing to show,
|
||||
not a state this screen has to invent furniture for.
|
||||
-->
|
||||
<Style Selector="ProgressBar.transferbar">
|
||||
<Setter Property="Height" Value="5" />
|
||||
<Setter Property="MinHeight" Value="5" />
|
||||
<Setter Property="CornerRadius" Value="3" />
|
||||
<Setter Property="Background" Value="{StaticResource Chip}" />
|
||||
<Setter Property="Foreground" Value="{StaticResource AccentGradient}" />
|
||||
</Style>
|
||||
|
||||
<!--
|
||||
The strip's own right-aligned status word. Quiet by default — a stopped transfer's "stopped" gets no
|
||||
rule of its own and falls through to this — and three states get their own colour: in motion, kept, and
|
||||
refused. See TransferRowViewModel.StatusWord for what word each state actually prints.
|
||||
-->
|
||||
<Style Selector="TextBlock.transferstatus">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextFaint}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.transferstatus.running">
|
||||
<Setter Property="Foreground" Value="{StaticResource TextDim}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.transferstatus.done">
|
||||
<Setter Property="Foreground" Value="{StaticResource Live}" />
|
||||
</Style>
|
||||
<Style Selector="TextBlock.transferstatus.failed">
|
||||
<Setter Property="Foreground" Value="{StaticResource Danger}" />
|
||||
</Style>
|
||||
</UserControl.Styles>
|
||||
|
||||
<Grid RowDefinitions="*,Auto">
|
||||
@@ -99,14 +164,34 @@
|
||||
-->
|
||||
<Grid Grid.Column="0" x:Name="LocalPane" RowDefinitions="Auto,Auto,Auto,*" DragDrop.AllowDrop="True">
|
||||
|
||||
<Border Grid.Row="0" Padding="12,7" BorderBrush="{StaticResource BorderSubtle}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<!--
|
||||
── v5b ─────────────────────────────────────────────────────────────────────────────────────────
|
||||
Per SFTP.dc.html: a 10px tracked-out label beside the current path in mono 13.5, and the pane's
|
||||
affordances restyled to quiet glyphs rather than dropped. "THIS MACHINE" becomes the design's own
|
||||
"LOCAL" — nothing in this file's own comments ever argued for that particular wording over the
|
||||
design's, unlike HOST/BUCKET across the arrow column, which keeps its own words for a reason
|
||||
recorded where it is drawn.
|
||||
|
||||
UP is arrow_upward here and arrow_downward on the host/bucket pane below, matching the design's own
|
||||
two glyphs exactly rather than picking one "up a directory" icon for both — both buttons do the same
|
||||
thing (go to the parent directory), and the pair reading differently is the design's own choice
|
||||
faithfully carried over rather than a functional difference invented to justify it.
|
||||
-->
|
||||
<Border Grid.Row="0" Padding="0,0,0,10" BorderThickness="0">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<TextBlock Grid.Column="0" Classes="label" Text="THIS MACHINE" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="6">
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="12" VerticalAlignment="Center">
|
||||
<TextBlock Classes="label" FontSize="10" Text="LOCAL" VerticalAlignment="Center" />
|
||||
<TextBlock Classes="mono" FontSize="13.5" FontWeight="Medium"
|
||||
Foreground="{StaticResource TextDim}" VerticalAlignment="Center"
|
||||
Text="{Binding LocalPath}" TextTrimming="CharacterEllipsis"
|
||||
ToolTip.Tip="{Binding LocalPath}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="4">
|
||||
<!--
|
||||
The drives, because the breadcrumb cannot reach them: above C:\ is a list rather than a
|
||||
directory. Without this the pane is stuck on whichever drive the user profile is on.
|
||||
directory. Without this the pane is stuck on whichever drive the user profile is on. Chips
|
||||
rather than the pane's own quiet icon buttons, because a drive is named rather than a single
|
||||
glyph — "C:" has no honest Material Icons equivalent.
|
||||
-->
|
||||
<ItemsControl ItemsSource="{Binding LocalRoots}" VerticalAlignment="Center">
|
||||
<ItemsControl.ItemsPanel>
|
||||
@@ -116,14 +201,20 @@
|
||||
</ItemsControl.ItemsPanel>
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:CrumbViewModel">
|
||||
<Button Classes="ghost" Content="{Binding Name}"
|
||||
<Button Classes="panechip" Content="{Binding Name}"
|
||||
Command="{Binding $parent[ItemsControl].((vm:TransfersViewModel)DataContext).GoLocalCommand}"
|
||||
CommandParameter="{Binding Path}" />
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
<Button Classes="ghost" Content="UP" Command="{Binding LocalUpCommand}" />
|
||||
<Button Classes="ghost" Content="REFRESH" Command="{Binding RefreshLocalCommand}" />
|
||||
<Button Classes="paneicon" Command="{Binding LocalUpCommand}"
|
||||
ToolTip.Tip="Up one directory">
|
||||
<TextBlock FontFamily="{StaticResource IconFont}" FontSize="16" Text="" />
|
||||
</Button>
|
||||
<Button Classes="paneicon" Command="{Binding RefreshLocalCommand}"
|
||||
ToolTip.Tip="Refresh">
|
||||
<TextBlock FontFamily="{StaticResource IconFont}" FontSize="16" Text="" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
@@ -150,25 +241,37 @@
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<Grid Grid.Row="2" ColumnDefinitions="2,*,84,110" Margin="0,2,12,4">
|
||||
<TextBlock Grid.Column="1" Classes="label" Text="NAME" FontSize="9.5" Margin="12,0,8,0" />
|
||||
<TextBlock Grid.Column="2" Classes="label" Text="SIZE" FontSize="9.5" />
|
||||
<TextBlock Grid.Column="3" Classes="label" Text="MODIFIED" FontSize="9.5" />
|
||||
<!--
|
||||
v5b: 20 for the glyph column rather than the design's bare icon with no gutter, because a Material
|
||||
glyph centred with no reserved width drifts as the font's own advance width varies between folder
|
||||
and insert_drive_file. 60/56 for SIZE/MODIFIED are narrower than the design's literal 80/78 — see
|
||||
the row template below for why the whole column set was chosen against 204 pixels rather than the
|
||||
design's own 1920-pixel canvas.
|
||||
-->
|
||||
<Grid Grid.Row="2" ColumnDefinitions="20,*,60,56" Margin="0,2,10,4">
|
||||
<TextBlock Grid.Column="1" Classes="label" Text="NAME" FontSize="9.5" Margin="8,0,8,0" />
|
||||
<TextBlock Grid.Column="2" Classes="label" Text="SIZE" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Column="3" Classes="label" Text="MODIFIED" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
|
||||
<ListBox Grid.Row="3" x:Name="LocalList" ItemsSource="{Binding LocalEntries}"
|
||||
<!--
|
||||
h38, radius 7, Track for hover and selected — see ListBox.filerows in App.axaml — and no rowmark:
|
||||
the design has nothing to distinguish "selected" from "hovered" beyond which one is currently true,
|
||||
and :selected alone already carries that once the pointer moves on.
|
||||
-->
|
||||
<ListBox Grid.Row="3" x:Name="LocalList" Classes="filerows" ItemsSource="{Binding LocalEntries}"
|
||||
SelectedItem="{Binding SelectedLocalEntry}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:LocalEntryRowViewModel">
|
||||
<Grid ColumnDefinitions="2,*,84,110" Margin="0,5,12,5">
|
||||
<Border Grid.Column="0" Classes="rowmark" />
|
||||
<Grid ColumnDefinitions="20,*,60,56" Height="38" Margin="14,0,10,0">
|
||||
<TextBlock Grid.Column="0" Classes="entryicon" Text="{Binding IconGlyph}" />
|
||||
<TextBlock Grid.Column="1" Classes="mono entry" Classes.dir="{Binding IsNavigable}"
|
||||
Text="{Binding Name}" FontSize="12"
|
||||
Margin="12,0,8,0" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="2" Classes="mono" Text="{Binding Size}" FontSize="10.5"
|
||||
Foreground="{StaticResource TextDim}" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Classes="mono" Text="{Binding Modified}" FontSize="10.5"
|
||||
Foreground="{StaticResource TextFaint}" VerticalAlignment="Center" />
|
||||
Text="{Binding Name}" FontSize="13.5"
|
||||
Margin="10,0,8,0" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="2" Classes="mono entrysize" Text="{Binding Size}" FontSize="12"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Classes="mono entrydate" Text="{Binding Modified}" FontSize="12"
|
||||
Margin="8,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
@@ -219,26 +322,41 @@
|
||||
<Grid Grid.Column="2" x:Name="RemotePane" RowDefinitions="Auto,Auto,Auto,Auto,Auto,*"
|
||||
DragDrop.AllowDrop="True">
|
||||
|
||||
<Border Grid.Row="0" Padding="12,7" BorderBrush="{StaticResource BorderSubtle}"
|
||||
BorderThickness="0,0,0,1">
|
||||
<!--
|
||||
── v5b ─────────────────────────────────────────────────────────────────────────────────────────
|
||||
HOST/BUCKET keep their own words rather than adopting the design's generic "REMOTE": the comment
|
||||
this replaced already carried a documented honesty reason — the pair is the difference between a
|
||||
directory tree and a flat namespace with inferred folders — and that reason still holds, so only
|
||||
the style moves to the design's 10px tracked label, not the wording.
|
||||
|
||||
UP is arrow_downward here, matching arrow_upward on the local pane above per the design's own two
|
||||
distinct glyphs; see that pane's own remark on why the pair differs without the actions differing.
|
||||
-->
|
||||
<Border Grid.Row="0" Padding="0,0,0,10" BorderThickness="0">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<!--
|
||||
Which kind of remote this pane is for, in the place the local pane names itself. It is the
|
||||
only thing left saying so on the screen itself — the bar that used to print SFTP or S3 across
|
||||
the top is gone — and the pair is worth keeping apart, because HOST and BUCKET is the
|
||||
difference between a directory tree and a flat namespace with inferred folders in it.
|
||||
-->
|
||||
<TextBlock Grid.Column="0" Classes="label" Text="HOST" VerticalAlignment="Center"
|
||||
IsVisible="{Binding ShowsHostPicker}" />
|
||||
<TextBlock Grid.Column="0" Classes="label" Text="BUCKET" VerticalAlignment="Center"
|
||||
IsVisible="{Binding ShowsBucketPicker}" />
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="6">
|
||||
<Button Classes="ghost" Content="UP" Command="{Binding RemoteUpCommand}"
|
||||
IsEnabled="{Binding IsConnected}" />
|
||||
<Button Classes="ghost" Content="REFRESH" Command="{Binding RefreshRemoteCommand}"
|
||||
IsEnabled="{Binding IsConnected}" />
|
||||
<Button Classes="danger" Content="DELETE" Command="{Binding DeleteRemoteCommand}"
|
||||
IsEnabled="{Binding CanDeleteRemote}" />
|
||||
<StackPanel Grid.Column="0" Orientation="Horizontal" Spacing="12" VerticalAlignment="Center">
|
||||
<TextBlock Classes="label" FontSize="10" Text="HOST" VerticalAlignment="Center"
|
||||
IsVisible="{Binding ShowsHostPicker}" />
|
||||
<TextBlock Classes="label" FontSize="10" Text="BUCKET" VerticalAlignment="Center"
|
||||
IsVisible="{Binding ShowsBucketPicker}" />
|
||||
<TextBlock Classes="mono" FontSize="13.5" FontWeight="Medium"
|
||||
Foreground="{StaticResource TextDim}" VerticalAlignment="Center"
|
||||
Text="{Binding RemotePath}" TextTrimming="CharacterEllipsis"
|
||||
ToolTip.Tip="{Binding RemotePath}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal" Spacing="4">
|
||||
<Button Classes="paneicon" Command="{Binding RemoteUpCommand}"
|
||||
IsEnabled="{Binding IsConnected}" ToolTip.Tip="Up one directory">
|
||||
<TextBlock FontFamily="{StaticResource IconFont}" FontSize="16" Text="" />
|
||||
</Button>
|
||||
<Button Classes="paneicon" Command="{Binding RefreshRemoteCommand}"
|
||||
IsEnabled="{Binding IsConnected}" ToolTip.Tip="Refresh">
|
||||
<TextBlock FontFamily="{StaticResource IconFont}" FontSize="16" Text="" />
|
||||
</Button>
|
||||
<Button Classes="paneicon danger" Command="{Binding DeleteRemoteCommand}"
|
||||
IsEnabled="{Binding CanDeleteRemote}" ToolTip.Tip="Delete on the host">
|
||||
<TextBlock FontFamily="{StaticResource IconFont}" FontSize="15" Text="" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</Border>
|
||||
@@ -246,27 +364,22 @@
|
||||
<!--
|
||||
◆ WHAT IS OPEN, AND WHAT CLOSES IT. Only while something is.
|
||||
|
||||
A row of its own rather than three more cells in the header above, and the reason is arithmetic
|
||||
rather than taste: this pane is 381 pixels wide at the window's minimum, UP, REFRESH and DELETE
|
||||
take most of that, and an account-at-host chip beside a DISCONNECT would have pushed one of them
|
||||
off the edge. The layout suite would have caught it — which is the point of stating the number
|
||||
here, so the next thing added to either row is measured against it rather than tried.
|
||||
v5b drops the account-at-host chip this row used to carry beside DISCONNECT: SessionHeader now
|
||||
prints the very same address above this whole screen — see MainWindowViewModel.SessionAddress,
|
||||
which already reads Transfers.ConnectedTo on the SFTP surface — and repeating it here stopped being
|
||||
information and started being the thing squeezing DISCONNECT off the edge. At the session shell's
|
||||
own narrower budget this pane is 204 pixels wide once QUICK ACCESS is showing beside it, where the
|
||||
170-pixel chip this row used to carry would have taken most of that on its own.
|
||||
|
||||
Two things and a gap, and the gap is the point: the status line was tried here and does not fit.
|
||||
What is left after a 170-pixel address and a DISCONNECT is about eighty pixels, which turns every
|
||||
sentence into its first word and an ellipsis. It is at the foot of the screen instead — see the
|
||||
queue's own strip, which has the width for one.
|
||||
The status line still is not here, for the reason the comment this replaced gave: there is no room
|
||||
for a sentence beside anything else this row holds. It is at the foot of the screen instead — see
|
||||
the queue's own strip.
|
||||
-->
|
||||
<Border Grid.Row="1" Padding="12,6" Background="{StaticResource Raised}"
|
||||
BorderBrush="{StaticResource BorderSubtle}" BorderThickness="0,0,0,1"
|
||||
IsVisible="{Binding IsConnected}">
|
||||
<Grid ColumnDefinitions="Auto,*,Auto">
|
||||
<Border Grid.Column="0" Classes="chip accent" MaxWidth="170">
|
||||
<TextBlock Text="{Binding ConnectedTo}" TextTrimming="CharacterEllipsis" />
|
||||
</Border>
|
||||
<Button Grid.Column="2" Classes="ghost" Content="DISCONNECT"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</Grid>
|
||||
<Button Classes="headerghost" HorizontalAlignment="Right" Content="DISCONNECT"
|
||||
Command="{Binding DisconnectCommand}" />
|
||||
</Border>
|
||||
|
||||
<!--
|
||||
@@ -277,6 +390,11 @@
|
||||
This is the strongest warning on any of these screens, and deliberately: everything else this
|
||||
application deletes is a tombstone against a copy the server still has, and a file on somebody's
|
||||
host is bytes with nothing behind them.
|
||||
|
||||
A WrapPanel for the two buttons rather than a horizontal StackPanel — v5b's own change, made once
|
||||
the session shell's sidebar could take this pane down to 204 pixels: "DELETE ON THE HOST" and
|
||||
CANCEL side by side want closer to 220, so at the narrow width they wrap onto their own line
|
||||
instead of one of them going off the edge, which the WrapPanel achieves for free.
|
||||
-->
|
||||
<Border Grid.Row="2" Padding="12,10" Background="{StaticResource DangerWash}"
|
||||
BorderBrush="{StaticResource DangerSoft}" BorderThickness="0,0,0,1"
|
||||
@@ -289,11 +407,12 @@
|
||||
Text="{Binding PendingRemoteDeletion.FullPath}" />
|
||||
<TextBlock Foreground="{StaticResource WarnText}" FontSize="12" TextWrapping="Wrap"
|
||||
Text="{Binding PendingRemoteDeletion.Consequence}" />
|
||||
<StackPanel Orientation="Horizontal" Spacing="8">
|
||||
<Button Classes="danger" Content="DELETE ON THE HOST"
|
||||
<WrapPanel>
|
||||
<Button Classes="danger" Content="DELETE ON THE HOST" Margin="0,0,8,4"
|
||||
Command="{Binding ConfirmDeleteRemoteCommand}" IsEnabled="{Binding !IsBusy}" />
|
||||
<Button Classes="ghost" Content="CANCEL" Command="{Binding CancelDeleteRemoteCommand}" />
|
||||
</StackPanel>
|
||||
<Button Classes="ghost" Content="CANCEL" Margin="0,0,0,4"
|
||||
Command="{Binding CancelDeleteRemoteCommand}" />
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
|
||||
@@ -324,37 +443,48 @@
|
||||
Making a directory sits here, beside the path it would be made in, rather than with the queue's
|
||||
controls. It exists because the queue refuses to overwrite: without somewhere else to put a file,
|
||||
"that name is already taken" is a dead end.
|
||||
|
||||
v5b narrows the box from 140 to 90: at the session shell's own 204-pixel width once QUICK ACCESS
|
||||
is showing, 140 plus MKDIR plus the spacing between them ran past the pane's own edge. Still wide
|
||||
enough for a real directory name to be typed and read back, which is what this box is for; a
|
||||
name that outgrows it scrolls inside the box the way every TextBox already does.
|
||||
-->
|
||||
<StackPanel Grid.Column="1" Orientation="Horizontal" Spacing="6"
|
||||
IsVisible="{Binding IsConnected}">
|
||||
<TextBox Width="140" Text="{Binding NewRemoteFolder}" PlaceholderText="new directory" />
|
||||
<TextBox Width="90" Text="{Binding NewRemoteFolder}" PlaceholderText="new directory" />
|
||||
<Button Classes="ghost" Content="MKDIR" Command="{Binding CreateRemoteFolderCommand}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
<Grid Grid.Row="4" ColumnDefinitions="2,*,84,110,92" Margin="0,2,12,4">
|
||||
<TextBlock Grid.Column="1" Classes="label" Text="NAME" FontSize="9.5" Margin="12,0,8,0" />
|
||||
<TextBlock Grid.Column="2" Classes="label" Text="SIZE" FontSize="9.5" />
|
||||
<TextBlock Grid.Column="3" Classes="label" Text="MODIFIED" FontSize="9.5" />
|
||||
<TextBlock Grid.Column="4" Classes="label" Text="PERMS" FontSize="9.5" />
|
||||
<!--
|
||||
v5b: PERMS keeps its own column — a real fact about a file on the host, dropped nowhere — but at
|
||||
48 pixels rather than the drawer's own wider habit, and SIZE/MODIFIED shrink to match the local
|
||||
pane's narrower numbers. See the local pane's own remark on why 204 rather than the design's 1920.
|
||||
-->
|
||||
<Grid Grid.Row="4" ColumnDefinitions="20,*,56,52,48" Margin="0,2,10,4">
|
||||
<TextBlock Grid.Column="1" Classes="label" Text="NAME" FontSize="9.5" Margin="8,0,8,0" />
|
||||
<TextBlock Grid.Column="2" Classes="label" Text="SIZE" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Column="3" Classes="label" Text="MODIFIED" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
<TextBlock Grid.Column="4" Classes="label" Text="PERMS" FontSize="9.5" HorizontalAlignment="Right" />
|
||||
</Grid>
|
||||
|
||||
<ListBox Grid.Row="5" x:Name="RemoteList" ItemsSource="{Binding RemoteEntries}"
|
||||
<ListBox Grid.Row="5" x:Name="RemoteList" Classes="filerows" ItemsSource="{Binding RemoteEntries}"
|
||||
SelectedItem="{Binding SelectedRemoteEntry}">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:RemoteEntryRowViewModel">
|
||||
<Grid ColumnDefinitions="2,*,84,110,92" Margin="0,5,12,5">
|
||||
<Border Grid.Column="0" Classes="rowmark" />
|
||||
<Grid ColumnDefinitions="20,*,56,52,48" Height="38" Margin="14,0,10,0">
|
||||
<TextBlock Grid.Column="0" Classes="entryicon" Text="{Binding IconGlyph}" />
|
||||
<TextBlock Grid.Column="1" Classes="mono entry" Classes.dir="{Binding IsNavigable}"
|
||||
Classes.exec="{Binding IsExecutable}"
|
||||
Text="{Binding Name}" FontSize="12"
|
||||
Margin="12,0,8,0" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="2" Classes="mono" Text="{Binding Size}" FontSize="10.5"
|
||||
Foreground="{StaticResource TextDim}" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Classes="mono" Text="{Binding Modified}" FontSize="10.5"
|
||||
Foreground="{StaticResource TextFaint}" VerticalAlignment="Center" />
|
||||
Text="{Binding Name}" FontSize="13.5"
|
||||
Margin="10,0,8,0" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Grid.Column="2" Classes="mono entrysize" Text="{Binding Size}" FontSize="12"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="3" Classes="mono entrydate" Text="{Binding Modified}" FontSize="12"
|
||||
Margin="8,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="4" Classes="mono perms" Classes.loose="{Binding IsWorldWritable}"
|
||||
Text="{Binding Permissions}" FontSize="10.5" VerticalAlignment="Center" />
|
||||
Text="{Binding Permissions}" FontSize="10" Margin="6,0,0,0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center" TextTrimming="CharacterEllipsis" />
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
@@ -392,10 +522,11 @@
|
||||
HorizontalAlignment="Center" VerticalAlignment="Center">
|
||||
|
||||
<!--
|
||||
The mark the hosts screen puts on a group, at the size an empty state can carry one. This
|
||||
application ships no icon set — see the note on colour at the top of this file — so a glyph in
|
||||
a rounded square is what an icon is here, and ▤ is already the one that means "a place things
|
||||
are kept".
|
||||
The mark the hosts screen puts on a group, at the size an empty state can carry one. Still a
|
||||
hand-picked glyph rather than one of the Material Icons codepoints the file rows now use — this
|
||||
invitation predates the app's own IconFont and is outside wave C's restyle, which touched the
|
||||
pane headers, the rows and the TRANSFERS strip and not this card — and ▤ already means "a place
|
||||
things are kept" without borrowing from a font built for a different visual language.
|
||||
-->
|
||||
<Border Width="44" Height="44" CornerRadius="12" HorizontalAlignment="Center"
|
||||
Background="{StaticResource Raised}" BorderBrush="{StaticResource Border}"
|
||||
@@ -545,94 +676,126 @@
|
||||
|
||||
</Grid>
|
||||
|
||||
<!-- ============ The queue ============ -->
|
||||
<Border Grid.Row="1" Background="{StaticResource Sidebar}" BorderBrush="{StaticResource Border}"
|
||||
BorderThickness="0,1,0,0" MaxHeight="196">
|
||||
<Grid RowDefinitions="Auto,*">
|
||||
<!--
|
||||
============ The TRANSFERS strip ============
|
||||
── v5b ─────────────────────────────────────────────────────────────────────────────────────────────
|
||||
DeepChrome and a top border, per SFTP.dc.html, in place of the plain Sidebar fill this used to carry —
|
||||
the same surface the session shell's own header and status bar are painted in, which is what fuses the
|
||||
strip into that frame rather than leaving it read as another pane. Two Borders share this row and
|
||||
exactly one is ever visible: the design's own header — TRANSFERS plus a count chip — with the queue
|
||||
underneath while there is one, and a single quiet line otherwise. That is the "collapse" wave C's own
|
||||
brief asks for: not zero height, because the honest sentence that used to live inside the full strip
|
||||
still has somewhere to be read, but far short of the full header-plus-rows shape.
|
||||
|
||||
<Border Grid.Row="0" Padding="12,7">
|
||||
<Grid ColumnDefinitions="Auto,Auto,*,Auto,Auto">
|
||||
<TextBlock Grid.Column="0" Classes="label" Text="TRANSFERS" VerticalAlignment="Center" />
|
||||
<TextBlock Grid.Column="1" Classes="mono" FontSize="10.5" Margin="10,0,0,0"
|
||||
The design's own aggregate throughput readout — "8.4 MB/s" beside an upward arrow — is not drawn.
|
||||
TransferRowViewModel.Progress computes a rate per transfer, off TransferSnapshot.BytesPerSecond, and
|
||||
nothing anywhere in this queue sums those into one number for the whole strip; inventing one here would
|
||||
be exactly the fabricated fact this project's honesty rule forbids. Recorded as a deviation rather than
|
||||
silently dropped.
|
||||
-->
|
||||
<Border Grid.Row="1" Background="{StaticResource DeepChrome}" BorderBrush="{StaticResource Border}"
|
||||
BorderThickness="0,1,0,0" MaxHeight="196" IsVisible="{Binding HasTransfers}">
|
||||
<Grid RowDefinitions="Auto,Auto,*,Auto" Margin="16,12">
|
||||
|
||||
<Grid Grid.Row="0" ColumnDefinitions="Auto,Auto,*">
|
||||
<TextBlock Grid.Column="0" Classes="label" FontSize="10" Text="TRANSFERS" VerticalAlignment="Center" />
|
||||
<!--
|
||||
h18, radius 5, Chip fill with no border — the design's own count chip, distinct from Border.chip's
|
||||
usual bordered-and-unfilled shape elsewhere in this application. ActiveTransfersLabel is
|
||||
"N active", off TransfersViewModel.ActiveTransfers: queued counts as active there for the reason
|
||||
its own remark gives, which matches what this chip is naming.
|
||||
-->
|
||||
<Border Grid.Column="1" Height="18" CornerRadius="5" Background="{StaticResource Chip}"
|
||||
Padding="8,0" Margin="10,0,0,0" VerticalAlignment="Center">
|
||||
<TextBlock Classes="mono" FontSize="10.5" FontWeight="Medium"
|
||||
Foreground="{StaticResource TextFaint}" VerticalAlignment="Center"
|
||||
Text="one at a time · nothing lands at its final name until it is complete" />
|
||||
Text="{Binding ActiveTransfersLabel}" />
|
||||
</Border>
|
||||
</Grid>
|
||||
|
||||
<!--
|
||||
◆ THE STATUS LINE, in the state where the remote pane has no room for one.
|
||||
<!--
|
||||
◆ THE STATUS LINE, in the state where the remote pane has no room for one — unchanged in meaning
|
||||
from the strip this replaced, only in paint. Right-aligned beside the queue's own "one at a time"
|
||||
policy sentence, which stays for the reason it always did: the queue refuses to overwrite, and
|
||||
nothing else on this screen says so.
|
||||
-->
|
||||
<Grid Grid.Row="1" ColumnDefinitions="*,Auto" Margin="0,8,0,10">
|
||||
<TextBlock Grid.Column="0" Classes="mono" FontSize="10.5" Foreground="{StaticResource TextGhost}"
|
||||
Text="one at a time · nothing lands at its final name until it is complete" />
|
||||
<TextBlock Grid.Column="1" Classes="hint" FontSize="11" Margin="16,0,0,0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis" TextWrapping="NoWrap"
|
||||
Text="{Binding Status}" IsVisible="{Binding IsConnected}" />
|
||||
</Grid>
|
||||
|
||||
It is here rather than beside DISCONNECT because this row spans the window and that one spans
|
||||
half of it: what the screen has to say about a session is a sentence, and a sentence needs the
|
||||
width. Only while something is open — the other half of the time it is inside the invitation
|
||||
in the remote pane, next to the button that provoked it, which is where a refusal has to be.
|
||||
<ScrollViewer Grid.Row="2">
|
||||
<ItemsControl ItemsSource="{Binding Transfers}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:TransferRowViewModel">
|
||||
<!--
|
||||
Per SFTP.dc.html: a 320-pixel ellipsized "source → destination" label, a slim progress track
|
||||
and a right-aligned status word — see TransferRowViewModel.Label/StatusWord. STOP, RETRY/
|
||||
RESUME and DISCARD are the app's own, kept per wave C's brief rather than dropped for having
|
||||
no equivalent in the design's static mock: icon-only now, restyled to the pane headers' own
|
||||
quiet-glyph idiom, with a tooltip carrying the word the button used to print.
|
||||
-->
|
||||
<Grid ColumnDefinitions="320,*,64,Auto" Margin="0,5" ColumnSpacing="14">
|
||||
<TextBlock Grid.Column="0" Classes="mono" FontSize="12"
|
||||
Foreground="{StaticResource TextDim}" VerticalAlignment="Center"
|
||||
Text="{Binding Label}" TextTrimming="CharacterEllipsis" />
|
||||
|
||||
Right-aligned in a free column, so it reads as this row's other end rather than as a third
|
||||
clause of the sentence to its left.
|
||||
-->
|
||||
<TextBlock Grid.Column="2" Classes="hint" FontSize="11.5" Margin="16,0,0,0"
|
||||
HorizontalAlignment="Right" VerticalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis" TextWrapping="NoWrap"
|
||||
Text="{Binding Status}" IsVisible="{Binding IsConnected}" />
|
||||
</Grid>
|
||||
</Border>
|
||||
<ProgressBar Grid.Column="1" Classes="transferbar" Minimum="0" Maximum="100"
|
||||
Value="{Binding Percent}" VerticalAlignment="Center"
|
||||
ToolTip.Tip="{Binding Progress}" />
|
||||
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<StackPanel>
|
||||
<TextBlock Classes="hint" FontSize="11.5" Margin="12,4,12,14"
|
||||
IsVisible="{Binding !HasTransfers}"
|
||||
Text="Nothing queued. Choose a file in either pane and press the arrow pointing the way you want it to go." />
|
||||
<TextBlock Grid.Column="2" Classes="mono transferstatus"
|
||||
Classes.running="{Binding IsInProgress}" Classes.done="{Binding IsDone}"
|
||||
Classes.failed="{Binding HasFailed}" FontSize="12" FontWeight="Medium"
|
||||
Text="{Binding StatusWord}" TextAlignment="Right" VerticalAlignment="Center" />
|
||||
|
||||
<ItemsControl ItemsSource="{Binding Transfers}">
|
||||
<ItemsControl.ItemTemplate>
|
||||
<DataTemplate x:DataType="vm:TransferRowViewModel">
|
||||
<Grid ColumnDefinitions="16,150,*,190,Auto" Margin="12,4">
|
||||
<TextBlock Grid.Column="0" Classes="mono" Text="{Binding Arrow}" FontSize="12"
|
||||
Foreground="{StaticResource Accent}" VerticalAlignment="Center" />
|
||||
<StackPanel Grid.Column="1" Margin="0,0,8,0">
|
||||
<TextBlock Classes="mono" Text="{Binding Name}" FontSize="11.5"
|
||||
Foreground="{StaticResource Text}" TextTrimming="CharacterEllipsis" />
|
||||
<TextBlock Classes="mono" Text="{Binding Path}" FontSize="10"
|
||||
Foreground="{StaticResource TextFaint}"
|
||||
TextTrimming="CharacterEllipsis" />
|
||||
</StackPanel>
|
||||
|
||||
<ProgressBar Grid.Column="2" Height="4" Minimum="0" Maximum="100"
|
||||
Value="{Binding Percent}" VerticalAlignment="Center"
|
||||
Foreground="{StaticResource Accent}"
|
||||
Background="{StaticResource Raised}" />
|
||||
|
||||
<TextBlock Grid.Column="3" Classes="mono" Text="{Binding Progress}" FontSize="10.5"
|
||||
Margin="10,0" VerticalAlignment="Center"
|
||||
TextTrimming="CharacterEllipsis"
|
||||
Foreground="{StaticResource TextDim}" />
|
||||
|
||||
<StackPanel Grid.Column="4" Orientation="Horizontal" Spacing="6">
|
||||
<Border Classes="chip">
|
||||
<TextBlock Text="{Binding StateLabel}" />
|
||||
</Border>
|
||||
<Button Classes="ghost" Content="STOP" IsVisible="{Binding IsRunning}"
|
||||
Command="{Binding $parent[ItemsControl].((vm:TransfersViewModel)DataContext).CancelTransferCommand}"
|
||||
CommandParameter="{Binding}" />
|
||||
<Button Classes="ghost" Content="{Binding RetryLabel}" IsVisible="{Binding CanRetry}"
|
||||
Command="{Binding $parent[ItemsControl].((vm:TransfersViewModel)DataContext).RetryTransferCommand}"
|
||||
CommandParameter="{Binding}" />
|
||||
<Button Classes="danger" Content="DISCARD" IsVisible="{Binding IsFinished}"
|
||||
Command="{Binding $parent[ItemsControl].((vm:TransfersViewModel)DataContext).DiscardTransferCommand}"
|
||||
CommandParameter="{Binding}" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
|
||||
<Button Classes="ghost" Content="CLEAR FINISHED" Margin="12,6,12,12"
|
||||
HorizontalAlignment="Left" Command="{Binding ClearCompletedCommand}"
|
||||
IsVisible="{Binding HasTransfers}" />
|
||||
</StackPanel>
|
||||
<StackPanel Grid.Column="3" Orientation="Horizontal" Spacing="4">
|
||||
<Button Classes="paneicon" Width="22" Height="22" IsVisible="{Binding IsRunning}"
|
||||
ToolTip.Tip="Stop this transfer"
|
||||
Command="{Binding $parent[ItemsControl].((vm:TransfersViewModel)DataContext).CancelTransferCommand}"
|
||||
CommandParameter="{Binding}">
|
||||
<TextBlock FontFamily="{StaticResource IconFont}" FontSize="13" Text="" />
|
||||
</Button>
|
||||
<Button Classes="paneicon" Width="22" Height="22" IsVisible="{Binding CanRetry}"
|
||||
ToolTip.Tip="{Binding RetryLabel}"
|
||||
Command="{Binding $parent[ItemsControl].((vm:TransfersViewModel)DataContext).RetryTransferCommand}"
|
||||
CommandParameter="{Binding}">
|
||||
<TextBlock FontFamily="{StaticResource IconFont}" FontSize="13" Text="" />
|
||||
</Button>
|
||||
<Button Classes="paneicon danger" Width="22" Height="22" IsVisible="{Binding IsFinished}"
|
||||
ToolTip.Tip="Discard this row"
|
||||
Command="{Binding $parent[ItemsControl].((vm:TransfersViewModel)DataContext).DiscardTransferCommand}"
|
||||
CommandParameter="{Binding}">
|
||||
<TextBlock FontFamily="{StaticResource IconFont}" FontSize="13" Text="" />
|
||||
</Button>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</DataTemplate>
|
||||
</ItemsControl.ItemTemplate>
|
||||
</ItemsControl>
|
||||
</ScrollViewer>
|
||||
|
||||
<Button Grid.Row="3" Classes="ghost" Content="CLEAR FINISHED" Margin="0,10,0,0"
|
||||
HorizontalAlignment="Left" Command="{Binding ClearCompletedCommand}" />
|
||||
|
||||
</Grid>
|
||||
</Border>
|
||||
|
||||
<!--
|
||||
The collapsed shape: no header, no count chip, no rows — just the honest sentence the full strip
|
||||
carried before anything was ever queued, kept per wave C's own brief rather than dropped along with the
|
||||
rest of the strip's furniture.
|
||||
-->
|
||||
<Border Grid.Row="1" Background="{StaticResource DeepChrome}" BorderBrush="{StaticResource Border}"
|
||||
BorderThickness="0,1,0,0" Padding="16,12" IsVisible="{Binding !HasTransfers}">
|
||||
<TextBlock Classes="hint" FontSize="11.5" Foreground="{StaticResource TextFaint}"
|
||||
Text="Nothing queued. Choose a file in either pane and press the arrow pointing the way you want it to go." />
|
||||
</Border>
|
||||
|
||||
<!--
|
||||
First contact and a changed key, over the whole screen. The same two refusals a terminal makes, and
|
||||
they arrive here on their own because this is a separate connection — a host trusted for a shell is
|
||||
|
||||
Reference in new issue
Block a user