Public Access
Give the phone the rest of its screens, and a way in
All seven screens of the design, plus the two it does not draw because it starts at an enrolled phone: naming a server, and choosing a passphrase. The five states docs/android-port.md worried about losing at 360dp are all here and none of them softened. The changed-key refusal is a full-screen panel rather than a bottom sheet, because a sheet is swipe-to-dismiss by convention and that screen must have no way forward. The recovery code raises FLAG_SECURE for its own state and lowers it afterwards, so the sentence about screenshots is true rather than decorative. The delete confirmations keep their counts and replace the row in place. Signing in works, and the seam it needed is worth more than the implementation: IAuthorizationCallback now sits between OidcClient and the loopback listener, so the two heads differ in where the response arrives and in nothing else. PKCE, the state check, discovery, the token exchange and the key binding stay one implementation — a second OIDC client would be a second place for a security bug to live. The phone registers a private-use scheme with the system rather than binding a loopback port, which on a shared device any other app can do first. The accessory key row needed TerminalWorkspace.SendInputAsync: ordinary typing goes from the renderer straight down the socket, and there was no way in for the keys a software keyboard does not have. Ctrl latches, because one thumb cannot chord, and the latch is drawn — a modifier that is on and does not look on is how somebody sends ^L to a database prompt believing they typed an l. 597 client tests green, including two new ones for the input path and one for the terminal surface command. Nothing has run on a device.
This commit is contained in:
@@ -1,10 +1,82 @@
|
||||
using global::Android.Views;
|
||||
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Markup.Xaml;
|
||||
|
||||
using DodoSSH.Client.Android.Platform;
|
||||
using DodoSSH.Client.Shell.ViewModels;
|
||||
|
||||
namespace DodoSSH.Client.Android.Views;
|
||||
|
||||
/// <summary>The phone's single view. The desktop head's MainWindow, without the window.</summary>
|
||||
internal sealed partial class PhoneShell : UserControl
|
||||
{
|
||||
public PhoneShell() => AvaloniaXamlLoader.Load(this);
|
||||
private MainWindowViewModel? shell;
|
||||
|
||||
public PhoneShell()
|
||||
{
|
||||
AvaloniaXamlLoader.Load(this);
|
||||
|
||||
DataContextChanged += (_, _) =>
|
||||
{
|
||||
if (shell is not null)
|
||||
{
|
||||
shell.PropertyChanged -= OnShellChanged;
|
||||
}
|
||||
|
||||
shell = DataContext as MainWindowViewModel;
|
||||
|
||||
if (shell is not null)
|
||||
{
|
||||
shell.PropertyChanged += OnShellChanged;
|
||||
ApplyScreenshotPolicy(shell.State);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void OnShellChanged(object? sender, System.ComponentModel.PropertyChangedEventArgs e)
|
||||
{
|
||||
if (shell is not null && e.PropertyName is nameof(MainWindowViewModel.State))
|
||||
{
|
||||
ApplyScreenshotPolicy(shell.State);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Blocks screenshots and screen recording while the recovery code is on screen.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// The recovery screen says screenshots are blocked, and this is what makes that true rather than a
|
||||
/// claim. <c>FLAG_SECURE</c> is a window flag — no control can set it — so it lives here, on the one
|
||||
/// object that has the activity.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// <b>It is worth being clear about what this buys.</b> It stops the obvious accident — a screenshot
|
||||
/// of the only copy of an unrecoverable code landing in a cloud photo library — and it excludes the
|
||||
/// screen from the recent-apps thumbnail, which is the part users never think about. It stops nothing
|
||||
/// determined: a second phone photographs the screen perfectly well. The code is meant to be written
|
||||
/// down, and this only pushes people away from the one place it must not be written down to.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Lowered again afterwards rather than left on. Leaving it set would make the terminal unscreenshotable
|
||||
/// too, and a screenshot of a shell is a thing people legitimately want.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
private static void ApplyScreenshotPolicy(ShellState state)
|
||||
{
|
||||
if (PhoneEnvironment.CurrentActivity?.Window is not { } window)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (state is ShellState.ShowingRecoveryCode)
|
||||
{
|
||||
window.SetFlags(WindowManagerFlags.Secure, WindowManagerFlags.Secure);
|
||||
}
|
||||
else
|
||||
{
|
||||
window.ClearFlags(WindowManagerFlags.Secure);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user