add a setup finished screen

added the ability to hide the help button (basically just for the finish screen, because it has a bigger discord button in the same place)
holding shift while opening the setup wizard now opens it in passive mode, aka it will install only what you need. this is mostly for testing and likely will be nuked before this code as a whole is made part of the official emulator, but it might not
This commit is contained in:
GreemDev
2025-11-29 02:17:23 -06:00
parent 804a4e0bcb
commit e12a77d4a3
11 changed files with 247 additions and 23 deletions

View File

@@ -0,0 +1,40 @@
<UserControl xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:markup="clr-namespace:Ryujinx.Ava.Common.Markup"
xmlns:pages="clr-namespace:Ryujinx.Ava.UI.SetupWizard.Pages"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:DataType="pages:SetupFinishedPageContext"
x:Class="Ryujinx.Ava.UI.SetupWizard.Pages.SetupFinishedPage">
<Grid
ColumnDefinitions="*"
RowDefinitions="*,Auto"
VerticalAlignment="Stretch"
HorizontalAlignment="Stretch">
<Border
Margin="15"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
CornerRadius="5"
Background="{DynamicResource AppListBackgroundColor}">
<TextBlock Margin="15" Text="{markup:Locale SetupWizardFinalPageDescription}" TextAlignment="Center" TextWrapping="Wrap" />
</Border>
<Button Grid.Row="1"
VerticalAlignment="Bottom"
HorizontalAlignment="Center"
MinWidth="45"
MinHeight="32"
Padding="8"
Background="Transparent"
Click="Button_OnClick"
CornerRadius="5"
Tag="https://discord.gg/PEuzjrFXUA"
ToolTip.Tip="{markup:Locale AboutDiscordUrlTooltipMessage}">
<StackPanel Orientation="Horizontal" Spacing="5">
<Image Source="{Binding OwningWizard.DiscordLogo}" />
<TextBlock Text="Discord"/>
</StackPanel>
</Button>
</Grid>
</UserControl>

View File

@@ -0,0 +1,22 @@
using Avalonia.Controls;
using Avalonia.Interactivity;
using Ryujinx.Ava.UI.Controls;
using Ryujinx.Common.Helper;
namespace Ryujinx.Ava.UI.SetupWizard.Pages
{
public partial class SetupFinishedPage : RyujinxControl<SetupFinishedPageContext>
{
public SetupFinishedPage()
{
InitializeComponent();
}
private void Button_OnClick(object sender, RoutedEventArgs e)
{
if (sender is Button { Tag: string url })
OpenHelper.OpenUrl(url);
}
}
}

View File

@@ -0,0 +1,13 @@
using Gommon;
using Ryujinx.Ava.Common.Locale;
namespace Ryujinx.Ava.UI.SetupWizard.Pages
{
public class SetupFinishedPageContext() : SetupWizardPageContext(LocaleKeys.SetupWizardFinalPageTitle)
{
public override LocaleKeys ActionContent => LocaleKeys.SetupWizardFinalPageAction;
// informative step; this implementation is not called.
public override Result CompleteStep() => Result.Success;
}
}

View File

@@ -35,8 +35,9 @@ namespace Ryujinx.Ava.UI.SetupWizard
}
Retry:
bool result = await NextPage<SetupFirmwarePage, SetupFirmwarePageContext>(out SetupFirmwarePageContext fwContext)
.Show();
bool result =
await NextPage<SetupFirmwarePage, SetupFirmwarePageContext>(out SetupFirmwarePageContext fwContext)
.Show();
if (!result)
return false;
@@ -49,5 +50,10 @@ namespace Ryujinx.Ava.UI.SetupWizard
return true;
}
private ValueTask<bool> Finish()
=> NextPage<SetupFinishedPage, SetupFinishedPageContext>(out _)
.WithHelpButtonVisible(false)
.Show();
}
}

View File

@@ -43,7 +43,8 @@ namespace Ryujinx.Ava.UI.SetupWizard
where TContext : SetupWizardPageContext, new()
=> NextPage()
.WithContent<TControl, TContext>(out boundContext)
.WithTitle(boundContext.Title);
.WithTitle(boundContext.Title)
.WithActionContent(boundContext.ActionContent);
public void SignalConfigModified()
{
@@ -82,6 +83,9 @@ namespace Ryujinx.Ava.UI.SetupWizard
if (!await SetupFirmware())
goto Keys;
if (!await Finish())
goto Firmware;
Return:
if (_configWasModified)
ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.GlobalConfigurationPath);

View File

@@ -68,7 +68,7 @@ namespace Ryujinx.Ava.UI.SetupWizard
where TControl : RyujinxControl<TContext>, new()
where TContext : SetupWizardPageContext, new()
{
boundContext = new() { NotificationManager = ownerWizard.NotificationManager };
boundContext = new() { OwningWizard = ownerWizard };
if (boundContext.CreateHelpContent() is { } content)
WithHelpContent(content);
@@ -84,5 +84,11 @@ namespace Ryujinx.Ava.UI.SetupWizard
ActionContent = content;
return this;
}
public SetupWizardPage WithHelpButtonVisible(bool visible)
{
ShowHelpButton = visible;
return this;
}
}
}

View File

@@ -28,6 +28,8 @@ namespace Ryujinx.Ava.UI.SetupWizard
[ObservableProperty] public partial bool HasHelpContent { get; set; }
[ObservableProperty] public partial bool ShowHelpButton { get; set; } = true;
[ObservableProperty]
public partial object? ActionContent { get; set; } = LocaleManager.Instance[LocaleKeys.SetupWizardActionNext];

View File

@@ -3,23 +3,33 @@ using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels;
namespace Ryujinx.Ava.UI.SetupWizard
{
public abstract class SetupWizardPageContext(LocaleKeys title) : BaseModel
{
public RyujinxSetupWizard OwningWizard
{
get;
init
{
field = value;
NotificationManager = field.NotificationManager;
}
}
public RyujinxNotificationManager NotificationManager { get; private init; }
public LocaleKeys Title => title;
public RyujinxNotificationManager NotificationManager { get; init; }
public virtual LocaleKeys ActionContent => LocaleKeys.SetupWizardActionNext;
// ReSharper disable once UnusedMemberInSuper.Global
// it's used implicitly as we use this type as a where guard for generics for WithContent<TControl, TContext>,
// it also ensures all context types implement completion
public abstract Result CompleteStep();
#nullable enable
public virtual object? CreateHelpContent()
#nullable disable
{
return null;
}
public virtual object? CreateHelpContent() => null;
}
}

View File

@@ -70,8 +70,7 @@
</ScrollViewer>
<Grid ColumnDefinitions="Auto,Auto,*" Grid.Row="1">
<ToggleButton Name="InfoToggle"
Padding="6">
<ToggleButton Name="InfoToggle" Padding="6" IsVisible="{Binding ShowHelpButton}">
<fa:Icon Value="fa-solid fa-circle-info" />
</ToggleButton>