From 6dbcdfea47e60aadefd59a75e43549793481f853 Mon Sep 17 00:00:00 2001 From: TSRBerry <20988865+TSRBerry@users.noreply.github.com> Date: Sun, 16 Apr 2023 09:09:02 +0200 Subject: [PATCH] Ava: Fix nca extraction window never closing & minor cleanup (#4569) * ava: Remove unused doWhileDeferred parameters * ava: Minimally improve swkbd dialog It's currently impossible to get the dialog to redirect focus to the InputBox. * ava: Fix nca extraction dialog never closing Also contains some minor cleanup --- Ryujinx.Ava/Common/ApplicationHelper.cs | 29 +++++----- Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml | 3 +- .../UI/Applet/SwkbdAppletDialog.axaml.cs | 45 +++------------ Ryujinx.Ava/UI/Controls/InputDialog.axaml | 32 ----------- Ryujinx.Ava/UI/Controls/InputDialog.axaml.cs | 57 ------------------- .../UI/Controls/UpdateWaitWindow.axaml.cs | 11 ++++ Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs | 32 +---------- .../UI/ViewModels/MainWindowViewModel.cs | 2 +- .../Windows/ContentDialogOverlayWindow.axaml | 18 +++--- 9 files changed, 45 insertions(+), 184 deletions(-) delete mode 100644 Ryujinx.Ava/UI/Controls/InputDialog.axaml delete mode 100644 Ryujinx.Ava/UI/Controls/InputDialog.axaml.cs diff --git a/Ryujinx.Ava/Common/ApplicationHelper.cs b/Ryujinx.Ava/Common/ApplicationHelper.cs index 161ef859..8c36a636 100644 --- a/Ryujinx.Ava/Common/ApplicationHelper.cs +++ b/Ryujinx.Ava/Common/ApplicationHelper.cs @@ -13,6 +13,7 @@ using LibHac.Tools.Fs; using LibHac.Tools.FsSystem; using LibHac.Tools.FsSystem.NcaUtils; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.UI.Controls; using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Windows; using Ryujinx.Common.Logging; @@ -152,25 +153,17 @@ namespace Ryujinx.Ava.Common string destination = await folderDialog.ShowAsync(_owner); var cancellationToken = new CancellationTokenSource(); + UpdateWaitWindow waitingDialog = new( + LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle], + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogNcaExtractionMessage, ncaSectionType, Path.GetFileName(titleFilePath)), + cancellationToken); + if (!string.IsNullOrWhiteSpace(destination)) { Thread extractorThread = new(() => { - Dispatcher.UIThread.Post(async () => - { - UserResult result = await ContentDialogHelper.CreateConfirmationDialog( - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogNcaExtractionMessage, ncaSectionType, Path.GetFileName(titleFilePath)), - "", - "", - LocaleManager.Instance[LocaleKeys.InputDialogCancel], - LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle]); + Dispatcher.UIThread.Post(waitingDialog.Show); - if (result == UserResult.Cancel) - { - cancellationToken.Cancel(); - } - }); - using FileStream file = new(titleFilePath, FileMode.Open, FileAccess.Read); Nca mainNca = null; @@ -222,6 +215,8 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.InvokeAsync(async () => { + waitingDialog.Close(); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionMainNcaNotFoundErrorMessage]); }); @@ -263,11 +258,15 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.InvokeAsync(async () => { + waitingDialog.Close(); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.DialogNcaExtractionCheckLogErrorMessage]); }); } else if (resultCode.Value.IsSuccess()) { + Dispatcher.UIThread.Post(waitingDialog.Close); + NotificationHelper.Show( LocaleManager.Instance[LocaleKeys.DialogNcaExtractionTitle], $"{titleName}\n\n{LocaleManager.Instance[LocaleKeys.DialogNcaExtractionSuccessMessage]}", @@ -284,6 +283,8 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.InvokeAsync(async () => { + waitingDialog.Close(); + await ContentDialogHelper.CreateErrorDialog(ex.Message); }); } diff --git a/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml b/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml index 43ccf9e7..65504569 100644 --- a/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml +++ b/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml @@ -48,6 +48,7 @@ Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Center" + Focusable="True" KeyUp="Message_KeyUp" Text="{Binding Message}" TextInput="Message_TextInput" @@ -61,4 +62,4 @@ HorizontalAlignment="Stretch" TextWrapping="Wrap" /> - \ No newline at end of file + diff --git a/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs b/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs index fb689ec2..cb69e96b 100644 --- a/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs +++ b/Ryujinx.Ava/UI/Applet/SwkbdAppletDialog.axaml.cs @@ -45,6 +45,13 @@ namespace Ryujinx.Ava.UI.Controls InitializeComponent(); } + protected override void OnGotFocus(GotFocusEventArgs e) + { + // FIXME: This does not work. Might be a bug in Avalonia with DialogHost + // Currently focus will be redirected to the overlay window instead. + Input.Focus(); + } + public string Message { get; set; } = ""; public string MainText { get; set; } = ""; public string SecondaryText { get; set; } = ""; @@ -59,24 +66,6 @@ namespace Ryujinx.Ava.UI.Controls string input = string.Empty; - var overlay = new ContentDialogOverlayWindow() - { - Height = window.Bounds.Height, - Width = window.Bounds.Width, - Position = window.PointToScreen(new Point()) - }; - - window.PositionChanged += OverlayOnPositionChanged; - - void OverlayOnPositionChanged(object sender, PixelPointEventArgs e) - { - overlay.Position = window.PointToScreen(new Point()); - } - - contentDialog = overlay.ContentDialog; - - bool opened = false; - content.SetInputLengthValidation(args.StringLengthMin, args.StringLengthMax); content._host = contentDialog; @@ -97,25 +86,7 @@ namespace Ryujinx.Ava.UI.Controls }; contentDialog.Closed += handler; - overlay.Opened += OverlayOnActivated; - - async void OverlayOnActivated(object sender, EventArgs e) - { - if (opened) - { - return; - } - - opened = true; - - overlay.Position = window.PointToScreen(new Point()); - - await contentDialog.ShowAsync(overlay); - contentDialog.Closed -= handler; - overlay.Close(); - }; - - await overlay.ShowDialog(window); + await ContentDialogHelper.ShowAsync(contentDialog); return (result, input); } diff --git a/Ryujinx.Ava/UI/Controls/InputDialog.axaml b/Ryujinx.Ava/UI/Controls/InputDialog.axaml deleted file mode 100644 index ed1ceda3..00000000 --- a/Ryujinx.Ava/UI/Controls/InputDialog.axaml +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - - - - - \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Controls/InputDialog.axaml.cs b/Ryujinx.Ava/UI/Controls/InputDialog.axaml.cs deleted file mode 100644 index 8dba5e2b..00000000 --- a/Ryujinx.Ava/UI/Controls/InputDialog.axaml.cs +++ /dev/null @@ -1,57 +0,0 @@ -using Avalonia.Controls; -using FluentAvalonia.UI.Controls; -using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.Helpers; -using Ryujinx.Ava.UI.Models; -using System.Threading.Tasks; - -namespace Ryujinx.Ava.UI.Controls -{ - public partial class InputDialog : UserControl - { - public string Message { get; set; } - public string Input { get; set; } - public string SubMessage { get; set; } - - public uint MaxLength { get; } - - public InputDialog(string message, string input = "", string subMessage = "", uint maxLength = int.MaxValue) - { - Message = message; - Input = input; - SubMessage = subMessage; - MaxLength = maxLength; - - DataContext = this; - } - - public InputDialog() - { - InitializeComponent(); - } - - public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, string message, - string input = "", string subMessage = "", uint maxLength = int.MaxValue) - { - UserResult result = UserResult.Cancel; - - InputDialog content = new InputDialog(message, input, subMessage, maxLength); - ContentDialog contentDialog = new ContentDialog - { - Title = title, - PrimaryButtonText = LocaleManager.Instance[LocaleKeys.InputDialogOk], - SecondaryButtonText = "", - CloseButtonText = LocaleManager.Instance[LocaleKeys.InputDialogCancel], - Content = content, - PrimaryButtonCommand = MiniCommand.Create(() => - { - result = UserResult.Ok; - input = content.Input; - }) - }; - await contentDialog.ShowAsync(); - - return (result, input); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs b/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs index 9db7b5d4..80a437e3 100644 --- a/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs +++ b/Ryujinx.Ava/UI/Controls/UpdateWaitWindow.axaml.cs @@ -1,15 +1,26 @@ using Avalonia.Controls; using Ryujinx.Ava.UI.Windows; +using System.Threading; namespace Ryujinx.Ava.UI.Controls { public partial class UpdateWaitWindow : StyleableWindow { + public UpdateWaitWindow(string primaryText, string secondaryText, CancellationTokenSource cancellationToken) : this(primaryText, secondaryText) + { + SystemDecorations = SystemDecorations.Full; + ShowInTaskbar = true; + + Closing += (_, _) => cancellationToken.Cancel(); + } + public UpdateWaitWindow(string primaryText, string secondaryText) : this() { PrimaryText.Text = primaryText; SecondaryText.Text = secondaryText; WindowStartupLocation = WindowStartupLocation.CenterOwner; + SystemDecorations = SystemDecorations.BorderOnly; + ShowInTaskbar = false; } public UpdateWaitWindow() diff --git a/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs b/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs index 8f0c670e..cb474506 100644 --- a/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs +++ b/Ryujinx.Ava/UI/Helpers/ContentDialogHelper.cs @@ -27,7 +27,6 @@ namespace Ryujinx.Ava.UI.Helpers string closeButton, UserResult primaryButtonResult = UserResult.Ok, ManualResetEvent deferResetEvent = null, - Func doWhileDeferred = null, TypedEventHandler deferCloseAction = null) { UserResult result = UserResult.None; @@ -78,12 +77,11 @@ namespace Ryujinx.Ava.UI.Helpers int iconSymbol, UserResult primaryButtonResult = UserResult.Ok, ManualResetEvent deferResetEvent = null, - Func doWhileDeferred = null, TypedEventHandler deferCloseAction = null) { Grid content = CreateTextDialogContent(primaryText, secondaryText, iconSymbol); - return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, doWhileDeferred, deferCloseAction); + return await ShowContentDialog(title, content, primaryButton, secondaryButton, closeButton, primaryButtonResult, deferResetEvent, deferCloseAction); } public async static Task ShowDeferredContentDialog( @@ -111,7 +109,6 @@ namespace Ryujinx.Ava.UI.Helpers iconSymbol, primaryButton == LocaleManager.Instance[LocaleKeys.InputDialogYes] ? UserResult.Yes : UserResult.Ok, deferResetEvent, - doWhileDeferred, DeferClose); async void DeferClose(ContentDialog sender, ContentDialogButtonClickEventArgs args) @@ -236,11 +233,6 @@ namespace Ryujinx.Ava.UI.Helpers primaryButtonResult); } - internal static UpdateWaitWindow CreateWaitingDialog(string mainText, string secondaryText) - { - return new(mainText, secondaryText); - } - internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText) { await ShowTextDialog( @@ -319,28 +311,6 @@ namespace Ryujinx.Ava.UI.Helpers LocaleManager.Instance[LocaleKeys.DialogExitSubMessage]); } - internal static async Task CreateInputDialog( - string title, - string mainText, - string subText, - uint maxLength = int.MaxValue, - string input = "") - { - var result = await InputDialog.ShowInputDialog( - title, - mainText, - input, - subText, - maxLength); - - if (result.Result == UserResult.Ok) - { - return result.Input; - } - - return string.Empty; - } - public static async Task ShowAsync(ContentDialog contentDialog) { ContentDialogResult result; diff --git a/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs index da211526..14d7a0fe 100644 --- a/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs +++ b/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs @@ -972,7 +972,7 @@ namespace Ryujinx.Ava.UI.ViewModels LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); - UpdateWaitWindow waitingDialog = ContentDialogHelper.CreateWaitingDialog(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallWaitMessage]); + UpdateWaitWindow waitingDialog = new(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallWaitMessage]); if (result == UserResult.Yes) { diff --git a/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml b/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml index 6cdcae2b..8b52bade 100644 --- a/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml +++ b/Ryujinx.Ava/UI/Windows/ContentDialogOverlayWindow.axaml @@ -1,4 +1,4 @@ - + Focusable="False"> - - - +