mirror of
https://git.ryujinx.app/ryubing/ryujinx.git
synced 2025-12-11 16:36:58 +00:00
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:
parent
3bec37e756
commit
9dcb71e120
11 changed files with 247 additions and 23 deletions
|
|
@ -25216,6 +25216,81 @@
|
|||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFinalPageTitle",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Setup Complete",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFinalPageDescription",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Your installation of Ryubing (aka Ryujinx) has been completed.\n\nIf you require assistance, feel free to join our Discord server and ask for help,\nafter verifying your possession of a modded Nintendo Switch.",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"ID": "SetupWizardFinalPageAction",
|
||||
"Translations": {
|
||||
"ar_SA": "",
|
||||
"de_DE": "",
|
||||
"el_GR": "",
|
||||
"en_US": "Finish",
|
||||
"es_ES": "",
|
||||
"fr_FR": "",
|
||||
"he_IL": "",
|
||||
"it_IT": "",
|
||||
"ja_JP": "",
|
||||
"ko_KR": "",
|
||||
"no_NO": "",
|
||||
"pl_PL": "",
|
||||
"pt_BR": "",
|
||||
"ru_RU": "",
|
||||
"sv_SE": "",
|
||||
"th_TH": "",
|
||||
"tr_TR": "",
|
||||
"uk_UA": "",
|
||||
"zh_CN": "",
|
||||
"zh_TW": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
using Avalonia;
|
||||
using Avalonia.Controls;
|
||||
using Avalonia.Input;
|
||||
using Avalonia.Layout;
|
||||
using Avalonia.Threading;
|
||||
using Gommon;
|
||||
|
|
@ -31,6 +32,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
{
|
||||
public MainWindow Window { get; private set; }
|
||||
|
||||
|
||||
public MainMenuBarView()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
|
@ -51,7 +53,9 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
AboutWindowMenuItem.Command = Commands.Create(AboutView.Show);
|
||||
CompatibilityListMenuItem.Command = Commands.Create(() => CompatibilityListWindow.Show());
|
||||
LdnGameListMenuItem.Command = Commands.Create(() => LdnGamesListWindow.Show());
|
||||
SetupWizardMenuItem.Command = Commands.Create(() => RyujinxSetupWizardWindow.ShowAsync(overwriteMode: true));
|
||||
SetupWizardMenuItem.Command = Commands.Create(() =>
|
||||
RyujinxSetupWizardWindow.ShowAsync(overwriteMode: !PollShiftPressed())
|
||||
);
|
||||
|
||||
UpdateMenuItem.Command = MainWindowViewModel.UpdateCommand;
|
||||
|
||||
|
|
@ -64,9 +68,42 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
WindowSize1440PMenuItem.Command =
|
||||
WindowSize2160PMenuItem.Command = Commands.Create<string>(ChangeWindowSize);
|
||||
|
||||
KeyDown += OnKeyDown;
|
||||
KeyUp += OnKeyUp;
|
||||
|
||||
LocaleManager.Instance.LocaleChanged += OnLocaleChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// KeyUp is not reliably invoked (or invoked at all, seemingly) when a window showing up causes the main menu bar to view,
|
||||
/// as shift is technically raised when that control is no longer the foreground control.
|
||||
///
|
||||
/// This stores <see cref="IsShiftPressed"/> to a temp variable, sets <see cref="IsShiftPressed"/> to false (if it is true), then returns the temp variable.
|
||||
/// </summary>
|
||||
private bool PollShiftPressed()
|
||||
{
|
||||
bool temp = IsShiftPressed;
|
||||
if (temp)
|
||||
IsShiftPressed = false;
|
||||
return temp;
|
||||
}
|
||||
|
||||
private bool IsShiftPressed { get; set; }
|
||||
|
||||
private void OnKeyDown(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key is Key.LeftShift or Key.RightShift && !IsShiftPressed)
|
||||
//down is called even for keys that have been held for a while, aka key repeats.
|
||||
//the check for shift being pressed prevents setting the variable every time the down event is received, if shift is already known to be pressed.
|
||||
IsShiftPressed = true;
|
||||
}
|
||||
|
||||
private void OnKeyUp(object sender, KeyEventArgs e)
|
||||
{
|
||||
if (e.Key is Key.LeftShift or Key.RightShift)
|
||||
IsShiftPressed = false;
|
||||
}
|
||||
|
||||
private void OnLocaleChanged()
|
||||
{
|
||||
ChangeLanguageMenuItem.ItemsSource = GenerateLanguageMenuItems();
|
||||
|
|
@ -147,11 +184,13 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
}
|
||||
else
|
||||
{
|
||||
bool customConfigExists = File.Exists(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString));
|
||||
bool customConfigExists =
|
||||
File.Exists(Program.GetDirGameUserConfig(ViewModel.SelectedApplication.IdString));
|
||||
|
||||
if (!ViewModel.IsGameRunning || !customConfigExists)
|
||||
{
|
||||
await Window.SettingsWindow.ShowDialog(Window); // The game is not running, or if the user configuration does not exist
|
||||
await Window.SettingsWindow
|
||||
.ShowDialog(Window); // The game is not running, or if the user configuration does not exist
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -175,7 +214,8 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
if (!MiiApplet.CanStart(out ApplicationData appData, out BlitStruct<ApplicationControlProperty> nacpData))
|
||||
return;
|
||||
|
||||
await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
|
||||
await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen,
|
||||
nacpData);
|
||||
}
|
||||
|
||||
public async Task OpenCheatManagerForCurrentApp()
|
||||
|
|
@ -183,7 +223,8 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
if (!ViewModel.IsGameRunning)
|
||||
return;
|
||||
|
||||
string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
|
||||
string name = ViewModel.AppHost.Device.Processes.ActiveApplication.ApplicationControlProperties
|
||||
.Title[(int)ViewModel.AppHost.Device.System.State.DesiredTitleLanguage].NameString.ToString();
|
||||
|
||||
await StyleableAppWindow.ShowAsync(
|
||||
new CheatWindow(
|
||||
|
|
@ -212,18 +253,24 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
{
|
||||
ViewModel.AreMimeTypesRegistered = FileAssociationHelper.Install();
|
||||
if (ViewModel.AreMimeTypesRegistered)
|
||||
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
|
||||
await ContentDialogHelper.CreateInfoDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesSuccessMessage], string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
|
||||
else
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesErrorMessage]);
|
||||
await ContentDialogHelper.CreateErrorDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogInstallFileTypesErrorMessage]);
|
||||
}
|
||||
|
||||
private async Task UninstallFileTypes()
|
||||
{
|
||||
ViewModel.AreMimeTypesRegistered = !FileAssociationHelper.Uninstall();
|
||||
if (!ViewModel.AreMimeTypesRegistered)
|
||||
await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage], string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
|
||||
await ContentDialogHelper.CreateInfoDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesSuccessMessage], string.Empty,
|
||||
LocaleManager.Instance[LocaleKeys.InputDialogOk], string.Empty, string.Empty);
|
||||
else
|
||||
await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesErrorMessage]);
|
||||
await ContentDialogHelper.CreateErrorDialog(
|
||||
LocaleManager.Instance[LocaleKeys.DialogUninstallFileTypesErrorMessage]);
|
||||
}
|
||||
|
||||
private void ChangeWindowSize(string resolution)
|
||||
|
|
@ -235,7 +282,7 @@ namespace Ryujinx.Ava.UI.Views.Main
|
|||
|
||||
// Correctly size window when 'TitleBar' is enabled (Nov. 14, 2024)
|
||||
double barsHeight = ((Window.StatusBarHeight + Window.MenuBarHeight) +
|
||||
(ConfigurationState.Instance.ShowOldUI ? (int)Window.TitleBar.Height : 0));
|
||||
(ConfigurationState.Instance.ShowOldUI ? (int)Window.TitleBar.Height : 0));
|
||||
|
||||
double windowWidthScaled = (resolutionWidth * Program.WindowScaleFactor);
|
||||
double windowHeightScaled = ((resolutionHeight + barsHeight) * Program.WindowScaleFactor);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue