Public Access
Rebuilds the client's shell from an imported design: a titlebar and nav rail it draws itself, real multi-session tabs over the one WebView, a Ctrl+K host search, and a vault screen that merges keys, passwords and pinned host keys into one table. Hosts left the vault column for their own screen beside the terminal, which is what the design asks for and turned out to be the better split anyway. Two screens the design shows have nothing behind them yet — file transfer and teams — and say so plainly rather than rendering invented data; every other gap between the design and this build is recorded in docs/design-import-gaps.md.
91 lines
3.6 KiB
C#
91 lines
3.6 KiB
C#
using Avalonia;
|
|
using Avalonia.Controls;
|
|
|
|
namespace DodoSSH.Client.App.Views;
|
|
|
|
/// <summary>
|
|
/// The screen behind a nav-rail entry whose feature does not exist yet.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// <para>
|
|
/// Styled properties set from XAML rather than a view model, because there is no state here — a screen
|
|
/// saying what is absent has nothing to observe, and a view model per absent feature would be two classes
|
|
/// whose only job is to hold four strings.
|
|
/// </para>
|
|
/// <para>
|
|
/// <see cref="Missing"/> takes the list rather than the markup listing it inline, so the two instances of
|
|
/// this control differ only in their content and the layout is written once.
|
|
/// </para>
|
|
/// </remarks>
|
|
internal sealed partial class NotBuiltScreen : UserControl
|
|
{
|
|
/// <summary>What the feature is called, in the design's own words.</summary>
|
|
public static readonly StyledProperty<string> TitleProperty =
|
|
AvaloniaProperty.Register<NotBuiltScreen, string>(nameof(Title), string.Empty);
|
|
|
|
/// <summary>Which milestone it belongs to, so the chip is a fact and not an apology.</summary>
|
|
public static readonly StyledProperty<string> MilestoneProperty =
|
|
AvaloniaProperty.Register<NotBuiltScreen, string>(nameof(Milestone), string.Empty);
|
|
|
|
/// <summary>One paragraph on what the design shows and why none of it is here.</summary>
|
|
public static readonly StyledProperty<string> SummaryProperty =
|
|
AvaloniaProperty.Register<NotBuiltScreen, string>(nameof(Summary), string.Empty);
|
|
|
|
/// <summary>The specific pieces, each naming the layer it would land in.</summary>
|
|
public static readonly StyledProperty<IEnumerable<string>?> MissingProperty =
|
|
AvaloniaProperty.Register<NotBuiltScreen, IEnumerable<string>?>(nameof(Missing));
|
|
|
|
/// <summary>What somebody wanting this today should do instead.</summary>
|
|
public static readonly StyledProperty<string> InsteadProperty =
|
|
AvaloniaProperty.Register<NotBuiltScreen, string>(nameof(Instead), string.Empty);
|
|
|
|
public NotBuiltScreen()
|
|
{
|
|
InitializeComponent();
|
|
|
|
// Bound in code rather than in the markup, because the markup's own DataContext is the shell and
|
|
// these five are properties of this control. Self-bindings in XAML would need a relative source on
|
|
// every one of them, which is five chances to point one at the wrong object.
|
|
TitleText.Bind(TextBlock.TextProperty, this.GetObservable(TitleProperty));
|
|
MilestoneText.Bind(TextBlock.TextProperty, this.GetObservable(MilestoneProperty));
|
|
SummaryText.Bind(TextBlock.TextProperty, this.GetObservable(SummaryProperty));
|
|
InsteadText.Bind(TextBlock.TextProperty, this.GetObservable(InsteadProperty));
|
|
MissingList.Bind(ItemsControl.ItemsSourceProperty, this.GetObservable(MissingProperty));
|
|
}
|
|
|
|
/// <inheritdoc cref="TitleProperty" />
|
|
public string Title
|
|
{
|
|
get => GetValue(TitleProperty);
|
|
set => SetValue(TitleProperty, value);
|
|
}
|
|
|
|
/// <inheritdoc cref="MilestoneProperty" />
|
|
public string Milestone
|
|
{
|
|
get => GetValue(MilestoneProperty);
|
|
set => SetValue(MilestoneProperty, value);
|
|
}
|
|
|
|
/// <inheritdoc cref="SummaryProperty" />
|
|
public string Summary
|
|
{
|
|
get => GetValue(SummaryProperty);
|
|
set => SetValue(SummaryProperty, value);
|
|
}
|
|
|
|
/// <inheritdoc cref="MissingProperty" />
|
|
public IEnumerable<string>? Missing
|
|
{
|
|
get => GetValue(MissingProperty);
|
|
set => SetValue(MissingProperty, value);
|
|
}
|
|
|
|
/// <inheritdoc cref="InsteadProperty" />
|
|
public string Instead
|
|
{
|
|
get => GetValue(InsteadProperty);
|
|
set => SetValue(InsteadProperty, value);
|
|
}
|
|
}
|