Files
DodoSSH/src/DodoSSH.Client.Android/Views/RecoveryCodeScreen.axaml
T

91 lines
5.0 KiB
XML

<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:DodoSSH.Client.Shell.ViewModels"
x:Class="DodoSSH.Client.Android.Views.RecoveryCodeScreen"
x:DataType="vm:MainWindowViewModel"
Background="{StaticResource Canvas}">
<!--
Design 07 — RECOVERY CODE, and the ◆ the plan worries about most after the changed-key refusal.
Three properties make this screen what it is, and all three are structural rather than cosmetic:
there is no back and no skip — this control draws no navigation at all, and the shell state it belongs
to has no other exit; CONTINUE is disabled until the checkbox is ticked, bound to
RecoveryCodeWrittenDown rather than to anything this view keeps; and the code is selectable so it can be
copied into a password manager, which is what people actually do with it and what refusing would only
push into a screenshot.
The design says screenshots are blocked here. That is FLAG_SECURE on the activity, which is a window
flag rather than anything a control can set — see PhoneShell's code-behind, which raises it for exactly
this state and lowers it afterwards.
-->
<ScrollViewer>
<StackPanel Margin="24,40,24,32" Spacing="0">
<TextBlock Classes="label" Text="ENROLLMENT · STEP 3 OF 3" Foreground="{StaticResource TextFaint}" />
<TextBlock Classes="title" Text="YOUR RECOVERY CODE" FontSize="17" Margin="0,10,0,0" />
<TextBlock Classes="body" Margin="0,10,0,0"
Text="This is the only moment this code exists. It is not stored on the server — by design, there is no reset. Losing it together with your passphrase makes the vault unrecoverable." />
<!--
SelectableTextBox rather than a grid of chunks. The design draws eight two-word cells, which is a
good way to read a code and a bad way to copy one: a user who cannot select it will photograph the
screen, and that is a worse home for it than their clipboard.
-->
<!--
◆ CornerRadius 12, not 6. Its padding, 14,13, is Border.card's own — this box was already drawn to a
card's proportions, in every dimension but the corner — so under v2's ladder 6 was an outlier this
file never explained. It is worse than unexplained now: v5's ladder gives 6 to a chip, and a
full-width box holding the one secret this whole screen exists to show is not a chip wearing a
card's padding by coincidence. 12 is what a card-shaped box gets on this ladder, and this one always
was one.
-->
<Border Margin="0,20,0,0" Background="{StaticResource Field}" BorderBrush="{StaticResource BorderMid}"
BorderThickness="1" CornerRadius="12" Padding="14,13">
<SelectableTextBlock Text="{Binding RecoveryCode}"
FontFamily="{StaticResource MonoFont}" FontSize="14"
Foreground="{StaticResource Accent}"
LetterSpacing="1.5" LineHeight="26" TextWrapping="Wrap" />
</Border>
<!--
◆ COPY, and on this head it is the difference between selectable and reachable. The comment above
says a user who cannot get the code out of the box photographs the screen; selecting a monospaced,
letter-spaced string with a thumb is the version of "can" that people give up on halfway, and this
screen blocks screenshots — so without a button the honest options were retyping it or losing it.
Full width and above the tick rather than beside the code, because it is a step in the sequence
this screen walks somebody through: read it, take it, confirm you have it. A small icon in the
corner of the box would be the same control drawn as an afterthought.
What it puts on the clipboard is the one secret this application deliberately offers there — see
MainWindowViewModel.CopyRecoveryCode, which sets out why that is right here and wrong for a private
key, and what the status line has to say afterwards.
-->
<Button Classes="secondary" Content="COPY CODE" Margin="0,10,0,0" Height="44"
Command="{Binding CopyRecoveryCodeCommand}" />
<TextBlock Classes="detail" Margin="0,8,0,0" TextWrapping="Wrap"
Text="{Binding StatusMessage}" />
<CheckBox IsChecked="{Binding RecoveryCodeWrittenDown}" Margin="0,20,0,0" MinHeight="44">
<TextBlock Classes="body" Foreground="{StaticResource Text}"
Text="I have written this code down. I understand it will never be shown again." />
</CheckBox>
<Button Classes="primary" Content="CONTINUE" Margin="0,16,0,0"
Command="{Binding ConfirmRecoveryCodeCommand}"
IsEnabled="{Binding RecoveryCodeWrittenDown}" />
<TextBlock Classes="detail" Margin="0,10,0,0" TextAlignment="Center" TextWrapping="Wrap"
Text="no skip · no back · screenshots are blocked on this screen" />
</StackPanel>
</ScrollViewer>
</UserControl>