diff options
46 files changed, 967 insertions, 952 deletions
diff --git a/Ryujinx.Ava/App.axaml.cs b/Ryujinx.Ava/App.axaml.cs index ef295a61..180c74b4 100644 --- a/Ryujinx.Ava/App.axaml.cs +++ b/Ryujinx.Ava/App.axaml.cs @@ -55,7 +55,6 @@ namespace Ryujinx.Ava if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { var result = await ContentDialogHelper.CreateConfirmationDialog( - (desktop.MainWindow as MainWindow).SettingsWindow, LocaleManager.Instance["DialogThemeRestartMessage"], LocaleManager.Instance["DialogThemeRestartSubMessage"], LocaleManager.Instance["InputDialogYes"], diff --git a/Ryujinx.Ava/AppHost.cs b/Ryujinx.Ava/AppHost.cs index 55693ed3..c6f2265c 100644 --- a/Ryujinx.Ava/AppHost.cs +++ b/Ryujinx.Ava/AppHost.cs @@ -417,10 +417,12 @@ namespace Ryujinx.Ava { if (userError == UserError.NoFirmware) { - string message = string.Format(LocaleManager.Instance["DialogFirmwareInstallEmbeddedMessage"], firmwareVersion.VersionString); + string message = string.Format(LocaleManager.Instance["DialogFirmwareInstallEmbeddedMessage"], + firmwareVersion.VersionString); - UserResult result = await ContentDialogHelper.CreateConfirmationDialog(_parent, - LocaleManager.Instance["DialogFirmwareNoFirmwareInstalledMessage"], message, LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], ""); + UserResult result = await ContentDialogHelper.CreateConfirmationDialog( + LocaleManager.Instance["DialogFirmwareNoFirmwareInstalledMessage"], message, + LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], ""); if (result != UserResult.Yes) { @@ -450,12 +452,12 @@ namespace Ryujinx.Ava string message = string.Format(LocaleManager.Instance["DialogFirmwareInstallEmbeddedSuccessMessage"], firmwareVersion.VersionString); - await ContentDialogHelper.CreateInfoDialog(_parent, - string.Format(LocaleManager.Instance["DialogFirmwareInstalledMessage"], firmwareVersion.VersionString), - message, - LocaleManager.Instance["InputDialogOk"], - "", - LocaleManager.Instance["RyujinxInfo"]); + await ContentDialogHelper.CreateInfoDialog( + string.Format(LocaleManager.Instance["DialogFirmwareInstalledMessage"], firmwareVersion.VersionString), + message, + LocaleManager.Instance["InputDialogOk"], + "", + LocaleManager.Instance["RyujinxInfo"]); } } else @@ -879,7 +881,7 @@ namespace Ryujinx.Ava } _dialogShown = true; - shouldExit = await ContentDialogHelper.CreateStopEmulationDialog(_parent); + shouldExit = await ContentDialogHelper.CreateStopEmulationDialog(); _dialogShown = false; } @@ -896,7 +898,7 @@ namespace Ryujinx.Ava { Dispatcher.UIThread.Post(() => { - _parent.Cursor = _isMouseInRenderer ? InvisibleCursor : Cursor.Default; + _parent.Cursor = _isMouseInRenderer ? InvisibleCursor : Cursor.Default; }); } else diff --git a/Ryujinx.Ava/Assets/Locales/en_US.json b/Ryujinx.Ava/Assets/Locales/en_US.json index 2aaf52e0..dd18dd9e 100644 --- a/Ryujinx.Ava/Assets/Locales/en_US.json +++ b/Ryujinx.Ava/Assets/Locales/en_US.json @@ -256,8 +256,8 @@ "UserProfilesSaveProfileName": "Save Profile Name", "UserProfilesChangeProfileImage": "Change Profile Image", "UserProfilesAvailableUserProfiles": "Available User Profiles:", - "UserProfilesAddNewProfile": "Add New Profile", - "UserProfilesDeleteSelectedProfile": "Delete Selected Profile", + "UserProfilesAddNewProfile": "Create Profile", + "UserProfilesDeleteSelectedProfile": "Delete Selected", "UserProfilesClose": "Close", "ProfileImageSelectionTitle": "Profile Image Selection", "ProfileImageSelectionHeader": "Choose a profile Image", @@ -568,5 +568,12 @@ "UpdateWindowTitle": "Manage Game Updates", "CheatWindowHeading": "Cheats Available for {0} [{1}]", "DlcWindowHeading": "DLC Available for {0} [{1}]", + "UserProfilesEditProfile": "Edit Selected", + "Cancel": "Cancel", + "Save": "Save", + "Discard": "Discard", + "UserProfilesSetProfileImage": "Set Profile Image", + "UserProfileEmptyNameError": "Name is required", + "UserProfileNoImageError": "Profile image must be set", "GameUpdateWindowHeading": "Updates Available for {0} [{1}]" } diff --git a/Ryujinx.Ava/Common/ApplicationHelper.cs b/Ryujinx.Ava/Common/ApplicationHelper.cs index d83ca2c1..6cbe9d16 100644 --- a/Ryujinx.Ava/Common/ApplicationHelper.cs +++ b/Ryujinx.Ava/Common/ApplicationHelper.cs @@ -81,7 +81,6 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.Post(async () => { await ContentDialogHelper.CreateErrorDialog( - _owner, string.Format(LocaleManager.Instance["DialogMessageCreateSaveErrorMessage"], result.ToStringWithName())); }); @@ -101,8 +100,7 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(_owner, - string.Format(LocaleManager.Instance["DialogMessageFindSaveErrorMessage"], result.ToStringWithName())); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogMessageFindSaveErrorMessage"], result.ToStringWithName())); }); return false; @@ -161,7 +159,6 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.Post(async () => { UserResult result = await ContentDialogHelper.CreateConfirmationDialog( - _owner, string.Format(LocaleManager.Instance["DialogNcaExtractionMessage"], ncaSectionType, Path.GetFileName(titleFilePath)), "", "", @@ -232,7 +229,7 @@ namespace Ryujinx.Ava.Common "Extraction failure. The main NCA was not present in the selected file"); Dispatcher.UIThread.InvokeAsync(async () => { - await ContentDialogHelper.CreateErrorDialog(_owner, LocaleManager.Instance["DialogNcaExtractionMainNcaNotFoundErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogNcaExtractionMainNcaNotFoundErrorMessage"]); }); return; } @@ -273,7 +270,7 @@ namespace Ryujinx.Ava.Common $"LibHac returned error code: {resultCode.Value.ErrorCode}"); Dispatcher.UIThread.InvokeAsync(async () => { - await ContentDialogHelper.CreateErrorDialog(_owner, LocaleManager.Instance["DialogNcaExtractionCheckLogErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogNcaExtractionCheckLogErrorMessage"]); }); } else if (resultCode.Value.IsSuccess()) @@ -281,7 +278,6 @@ namespace Ryujinx.Ava.Common Dispatcher.UIThread.InvokeAsync(async () => { await ContentDialogHelper.CreateInfoDialog( - _owner, LocaleManager.Instance["DialogNcaExtractionSuccessMessage"], "", LocaleManager.Instance["InputDialogOk"], @@ -298,7 +294,7 @@ namespace Ryujinx.Ava.Common { Dispatcher.UIThread.InvokeAsync(async () => { - await ContentDialogHelper.CreateErrorDialog(_owner, ex.Message); + await ContentDialogHelper.CreateErrorDialog(ex.Message); }); } } diff --git a/Ryujinx.Ava/Modules/Updater/Updater.cs b/Ryujinx.Ava/Modules/Updater/Updater.cs index 362435c8..bbcf6679 100644 --- a/Ryujinx.Ava/Modules/Updater/Updater.cs +++ b/Ryujinx.Ava/Modules/Updater/Updater.cs @@ -76,7 +76,7 @@ namespace Ryujinx.Modules Logger.Error?.Print(LogClass.Application, "Failed to convert the current Ryujinx version!"); Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateWarningDialog(mainWindow, LocaleManager.Instance["DialogUpdaterConvertFailedMessage"], LocaleManager.Instance["DialogUpdaterCancelUpdateMessage"]); + await ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance["DialogUpdaterConvertFailedMessage"], LocaleManager.Instance["DialogUpdaterCancelUpdateMessage"]); }); return; @@ -111,7 +111,7 @@ namespace Ryujinx.Modules { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateUpdaterInfoDialog(mainWindow, LocaleManager.Instance["DialogUpdaterAlreadyOnLatestVersionMessage"], ""); + await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance["DialogUpdaterAlreadyOnLatestVersionMessage"], ""); }); } @@ -129,7 +129,7 @@ namespace Ryujinx.Modules { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateUpdaterInfoDialog(mainWindow, LocaleManager.Instance["DialogUpdaterAlreadyOnLatestVersionMessage"], ""); + await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance["DialogUpdaterAlreadyOnLatestVersionMessage"], ""); }); } @@ -142,7 +142,7 @@ namespace Ryujinx.Modules Logger.Error?.Print(LogClass.Application, exception.Message); Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(mainWindow, LocaleManager.Instance["DialogUpdaterFailedToGetVersionMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogUpdaterFailedToGetVersionMessage"]); }); return; @@ -157,7 +157,7 @@ namespace Ryujinx.Modules Logger.Error?.Print(LogClass.Application, "Failed to convert the received Ryujinx version from Github!"); Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateWarningDialog(mainWindow, LocaleManager.Instance["DialogUpdaterConvertFailedGithubMessage"], LocaleManager.Instance["DialogUpdaterCancelUpdateMessage"]); + await ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance["DialogUpdaterConvertFailedGithubMessage"], LocaleManager.Instance["DialogUpdaterCancelUpdateMessage"]); }); return; @@ -169,7 +169,7 @@ namespace Ryujinx.Modules { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateUpdaterInfoDialog(mainWindow, LocaleManager.Instance["DialogUpdaterAlreadyOnLatestVersionMessage"], ""); + await ContentDialogHelper.CreateUpdaterInfoDialog(LocaleManager.Instance["DialogUpdaterAlreadyOnLatestVersionMessage"], ""); }); } @@ -550,7 +550,7 @@ namespace Ryujinx.Modules { if (showWarnings) { - ContentDialogHelper.CreateWarningDialog(parent, LocaleManager.Instance["DialogUpdaterArchNotSupportedMessage"], + ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance["DialogUpdaterArchNotSupportedMessage"], LocaleManager.Instance["DialogUpdaterArchNotSupportedSubMessage"]); } @@ -561,7 +561,7 @@ namespace Ryujinx.Modules { if (showWarnings) { - ContentDialogHelper.CreateWarningDialog(parent, LocaleManager.Instance["DialogUpdaterNoInternetMessage"], + ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance["DialogUpdaterNoInternetMessage"], LocaleManager.Instance["DialogUpdaterNoInternetSubMessage"]); } @@ -572,7 +572,7 @@ namespace Ryujinx.Modules { if (showWarnings) { - ContentDialogHelper.CreateWarningDialog(parent, LocaleManager.Instance["DialogUpdaterDirtyBuildMessage"], + ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance["DialogUpdaterDirtyBuildMessage"], LocaleManager.Instance["DialogUpdaterDirtyBuildSubMessage"]); } @@ -585,13 +585,11 @@ namespace Ryujinx.Modules { if (ReleaseInformations.IsFlatHubBuild()) { - ContentDialogHelper.CreateWarningDialog(parent, - LocaleManager.Instance["UpdaterDisabledWarningTitle"], LocaleManager.Instance["DialogUpdaterFlatpakNotSupportedMessage"]); + ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance["UpdaterDisabledWarningTitle"], LocaleManager.Instance["DialogUpdaterFlatpakNotSupportedMessage"]); } else { - ContentDialogHelper.CreateWarningDialog(parent, - LocaleManager.Instance["UpdaterDisabledWarningTitle"], LocaleManager.Instance["DialogUpdaterDirtyBuildSubMessage"]); + ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance["UpdaterDisabledWarningTitle"], LocaleManager.Instance["DialogUpdaterDirtyBuildSubMessage"]); } } diff --git a/Ryujinx.Ava/Ryujinx.Ava.csproj b/Ryujinx.Ava/Ryujinx.Ava.csproj index 2f0f342d..67e159f6 100644 --- a/Ryujinx.Ava/Ryujinx.Ava.csproj +++ b/Ryujinx.Ava/Ryujinx.Ava.csproj @@ -26,6 +26,7 @@ <PackageReference Include="jp2masa.Avalonia.Flexbox" Version="0.2.0" /> <PackageReference Include="DynamicData" Version="7.9.4" /> <PackageReference Include="FluentAvaloniaUI" Version="1.4.1" /> + <PackageReference Include="XamlNameReferenceGenerator" Version="1.3.4" /> <PackageReference Include="Ryujinx.Audio.OpenAL.Dependencies" Version="1.21.0.1" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" /> <PackageReference Include="Ryujinx.Graphics.Nvdec.Dependencies" Version="5.0.1-build10" Condition="'$(RuntimeIdentifier)' != 'linux-x64' AND '$(RuntimeIdentifier)' != 'osx-x64'" /> diff --git a/Ryujinx.Ava/Ui/Applet/AvaHostUiHandler.cs b/Ryujinx.Ava/Ui/Applet/AvaHostUiHandler.cs index f129cd71..133bcc03 100644 --- a/Ryujinx.Ava/Ui/Applet/AvaHostUiHandler.cs +++ b/Ryujinx.Ava/Ui/Applet/AvaHostUiHandler.cs @@ -92,7 +92,7 @@ namespace Ryujinx.Ava.Ui.Applet } catch (Exception ex) { - await ContentDialogHelper.CreateErrorDialog(_parent, string.Format(LocaleManager.Instance["DialogMessageDialogErrorExceptionMessage"], ex)); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogMessageDialogErrorExceptionMessage"], ex)); dialogCloseEvent.Set(); } @@ -126,7 +126,7 @@ namespace Ryujinx.Ava.Ui.Applet catch (Exception ex) { error = true; - await ContentDialogHelper.CreateErrorDialog(_parent, string.Format(LocaleManager.Instance["DialogSoftwareKeyboardErrorExceptionMessage"], ex)); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogSoftwareKeyboardErrorExceptionMessage"], ex)); } finally { @@ -181,7 +181,7 @@ namespace Ryujinx.Ava.Ui.Applet catch (Exception ex) { dialogCloseEvent.Set(); - await ContentDialogHelper.CreateErrorDialog(_parent, string.Format(LocaleManager.Instance["DialogErrorAppletErrorExceptionMessage"], ex)); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogErrorAppletErrorExceptionMessage"], ex)); } }); diff --git a/Ryujinx.Ava/Ui/Applet/ErrorAppletWindow.axaml.cs b/Ryujinx.Ava/Ui/Applet/ErrorAppletWindow.axaml.cs index 12fb8b0f..b4acd155 100644 --- a/Ryujinx.Ava/Ui/Applet/ErrorAppletWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Applet/ErrorAppletWindow.axaml.cs @@ -9,7 +9,7 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.Ui.Applet { - internal class ErrorAppletWindow : StyleableWindow + internal partial class ErrorAppletWindow : StyleableWindow { private readonly Window _owner; private object _buttonResponse; @@ -50,8 +50,6 @@ namespace Ryujinx.Ava.Ui.Applet public string Message { get; set; } - public StackPanel ButtonStack { get; set; } - private void AddButton(string label, object tag) { Dispatcher.UIThread.InvokeAsync(() => @@ -79,11 +77,5 @@ namespace Ryujinx.Ava.Ui.Applet return _buttonResponse; } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - ButtonStack = this.FindControl<StackPanel>("ButtonStack"); - } } }
\ 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 2d56c0b5..d7bb4b74 100644 --- a/Ryujinx.Ava/Ui/Applet/SwkbdAppletDialog.axaml.cs +++ b/Ryujinx.Ava/Ui/Applet/SwkbdAppletDialog.axaml.cs @@ -13,7 +13,7 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.Ui.Controls { - internal class SwkbdAppletDialog : UserControl + internal partial class SwkbdAppletDialog : UserControl { private Predicate<int> _checkLength; private int _inputMax; @@ -30,6 +30,10 @@ namespace Ryujinx.Ava.Ui.Controls _placeholder = placeholder; InitializeComponent(); + Input.Watermark = _placeholder; + + Input.AddHandler(TextInputEvent, Message_TextInput, RoutingStrategies.Tunnel, true); + SetInputLengthValidation(0, int.MaxValue); // Disable by default. } @@ -43,23 +47,9 @@ namespace Ryujinx.Ava.Ui.Controls public string MainText { get; set; } = ""; public string SecondaryText { get; set; } = ""; - public TextBlock Error { get; private set; } - public TextBox Input { get; set; } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - Error = this.FindControl<TextBlock>("Error"); - Input = this.FindControl<TextBox>("Input"); - - Input.Watermark = _placeholder; - - Input.AddHandler(TextInputEvent, Message_TextInput, RoutingStrategies.Tunnel, true); - } - public static async Task<(UserResult Result, string Input)> ShowInputDialog(StyleableWindow window, string title, SoftwareKeyboardUiArgs args) { - ContentDialog contentDialog = window.ContentDialog; + ContentDialog contentDialog = new ContentDialog(); UserResult result = UserResult.Cancel; diff --git a/Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs b/Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs index cdc5de93..15ecaa77 100644 --- a/Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs +++ b/Ryujinx.Ava/Ui/Controls/ContentDialogHelper.cs @@ -16,7 +16,6 @@ namespace Ryujinx.Ava.Ui.Controls private static bool _isChoiceDialogOpen; private async static Task<UserResult> ShowContentDialog( - StyleableWindow window, string title, string primaryText, string secondaryText, @@ -28,35 +27,32 @@ namespace Ryujinx.Ava.Ui.Controls { UserResult result = UserResult.None; - ContentDialog contentDialog = window.ContentDialog; + ContentDialog contentDialog = new ContentDialog(); await ShowDialog(); async Task ShowDialog() { - if (contentDialog != null) - { - contentDialog.Title = title; - contentDialog.PrimaryButtonText = primaryButton; - contentDialog.SecondaryButtonText = secondaryButton; - contentDialog.CloseButtonText = closeButton; - contentDialog.Content = CreateDialogTextContent(primaryText, secondaryText, iconSymbol); + contentDialog.Title = title; + contentDialog.PrimaryButtonText = primaryButton; + contentDialog.SecondaryButtonText = secondaryButton; + contentDialog.CloseButtonText = closeButton; + contentDialog.Content = CreateDialogTextContent(primaryText, secondaryText, iconSymbol); - contentDialog.PrimaryButtonCommand = MiniCommand.Create(() => - { - result = primaryButtonResult; - }); - contentDialog.SecondaryButtonCommand = MiniCommand.Create(() => - { - result = UserResult.No; - }); - contentDialog.CloseButtonCommand = MiniCommand.Create(() => - { - result = UserResult.Cancel; - }); + contentDialog.PrimaryButtonCommand = MiniCommand.Create(() => + { + result = primaryButtonResult; + }); + contentDialog.SecondaryButtonCommand = MiniCommand.Create(() => + { + result = UserResult.No; + }); + contentDialog.CloseButtonCommand = MiniCommand.Create(() => + { + result = UserResult.Cancel; + }); - await contentDialog.ShowAsync(ContentDialogPlacement.Popup); - }; + await contentDialog.ShowAsync(ContentDialogPlacement.Popup); } return result; @@ -78,35 +74,30 @@ namespace Ryujinx.Ava.Ui.Controls UserResult result = UserResult.None; - ContentDialog contentDialog = window.ContentDialog; - - Window overlay = window; - - if (contentDialog != null) + ContentDialog contentDialog = new ContentDialog { - contentDialog.PrimaryButtonClick += DeferClose; - contentDialog.Title = title; - contentDialog.PrimaryButtonText = primaryButton; - contentDialog.SecondaryButtonText = secondaryButton; - contentDialog.CloseButtonText = closeButton; - contentDialog.Content = CreateDialogTextContent(primaryText, secondaryText, iconSymbol); - - contentDialog.PrimaryButtonCommand = MiniCommand.Create(() => + Title = title, + PrimaryButtonText = primaryButton, + SecondaryButtonText = secondaryButton, + CloseButtonText = closeButton, + Content = CreateDialogTextContent(primaryText, secondaryText, iconSymbol), + PrimaryButtonCommand = MiniCommand.Create(() => { result = primaryButton == LocaleManager.Instance["InputDialogYes"] ? UserResult.Yes : UserResult.Ok; - }); - contentDialog.SecondaryButtonCommand = MiniCommand.Create(() => - { - contentDialog.PrimaryButtonClick -= DeferClose; - result = UserResult.No; - }); - contentDialog.CloseButtonCommand = MiniCommand.Create(() => - { - contentDialog.PrimaryButtonClick -= DeferClose; - result = UserResult.Cancel; - }); - await contentDialog.ShowAsync(ContentDialogPlacement.Popup); + }), }; + contentDialog.SecondaryButtonCommand = MiniCommand.Create(() => + { + contentDialog.PrimaryButtonClick -= DeferClose; + result = UserResult.No; + }); + contentDialog.CloseButtonCommand = MiniCommand.Create(() => + { + contentDialog.PrimaryButtonClick -= DeferClose; + result = UserResult.Cancel; + }); + contentDialog.PrimaryButtonClick += DeferClose; + await contentDialog.ShowAsync(ContentDialogPlacement.Popup); return result; @@ -141,7 +132,7 @@ namespace Ryujinx.Ava.Ui.Controls if (doWhileDeferred != null) { - await doWhileDeferred(overlay); + await doWhileDeferred(window); deferResetEvent.Set(); } @@ -191,7 +182,6 @@ namespace Ryujinx.Ava.Ui.Controls } public static async Task<UserResult> CreateInfoDialog( - StyleableWindow window, string primary, string secondaryText, string acceptButton, @@ -199,7 +189,6 @@ namespace Ryujinx.Ava.Ui.Controls string title) { return await ShowContentDialog( - window, title, primary, secondaryText, @@ -210,7 +199,6 @@ namespace Ryujinx.Ava.Ui.Controls } internal static async Task<UserResult> CreateConfirmationDialog( - StyleableWindow window, string primaryText, string secondaryText, string acceptButtonText, @@ -219,7 +207,6 @@ namespace Ryujinx.Ava.Ui.Controls UserResult primaryButtonResult = UserResult.Yes) { return await ShowContentDialog( - window, string.IsNullOrWhiteSpace(title) ? LocaleManager.Instance["DialogConfirmationTitle"] : title, primaryText, secondaryText, @@ -235,10 +222,9 @@ namespace Ryujinx.Ava.Ui.Controls return new(mainText, secondaryText); } - internal static async Task CreateUpdaterInfoDialog(StyleableWindow window, string primary, string secondaryText) + internal static async Task CreateUpdaterInfoDialog(string primary, string secondaryText) { await ShowContentDialog( - window, LocaleManager.Instance["DialogUpdaterTitle"], primary, secondaryText, @@ -248,24 +234,9 @@ namespace Ryujinx.Ava.Ui.Controls (int)Symbol.Important); } - internal static async Task ShowNotAvailableMessage(StyleableWindow window) - { - // Temporary placeholder for features to be added - await ShowContentDialog( - window, - "Feature Not Available", - "The selected feature is not available in this version.", - "", - "", - "", - LocaleManager.Instance["InputDialogOk"], - (int)Symbol.Important); - } - - internal static async Task CreateWarningDialog(StyleableWindow window, string primary, string secondaryText) + internal static async Task CreateWarningDialog(string primary, string secondaryText) { await ShowContentDialog( - window, LocaleManager.Instance["DialogWarningTitle"], primary, secondaryText, @@ -275,12 +246,11 @@ namespace Ryujinx.Ava.Ui.Controls (int)Symbol.Important); } - internal static async Task CreateErrorDialog(StyleableWindow owner, string errorMessage, string secondaryErrorMessage = "") + internal static async Task CreateErrorDialog(string errorMessage, string secondaryErrorMessage = "") { Logger.Error?.Print(LogClass.Application, errorMessage); await ShowContentDialog( - owner, LocaleManager.Instance["DialogErrorTitle"], LocaleManager.Instance["DialogErrorMessage"], errorMessage, @@ -290,7 +260,7 @@ namespace Ryujinx.Ava.Ui.Controls (int)Symbol.Dismiss); } - internal static async Task<bool> CreateChoiceDialog(StyleableWindow window, string title, string primary, string secondaryText) + internal static async Task<bool> CreateChoiceDialog(string title, string primary, string secondaryText) { if (_isChoiceDialogOpen) { @@ -301,7 +271,6 @@ namespace Ryujinx.Ava.Ui.Controls UserResult response = await ShowContentDialog( - window, title, primary, secondaryText, @@ -316,19 +285,17 @@ namespace Ryujinx.Ava.Ui.Controls return response == UserResult.Yes; } - internal static async Task<bool> CreateExitDialog(StyleableWindow owner) + internal static async Task<bool> CreateExitDialog() { return await CreateChoiceDialog( - owner, LocaleManager.Instance["DialogExitTitle"], LocaleManager.Instance["DialogExitMessage"], LocaleManager.Instance["DialogExitSubMessage"]); } - internal static async Task<bool> CreateStopEmulationDialog(StyleableWindow owner) + internal static async Task<bool> CreateStopEmulationDialog() { return await CreateChoiceDialog( - owner, LocaleManager.Instance["DialogStopEmulationTitle"], LocaleManager.Instance["DialogStopEmulationMessage"], LocaleManager.Instance["DialogExitSubMessage"]); @@ -338,12 +305,10 @@ namespace Ryujinx.Ava.Ui.Controls string title, string mainText, string subText, - StyleableWindow owner, uint maxLength = int.MaxValue, string input = "") { var result = await InputDialog.ShowInputDialog( - owner, title, mainText, input, diff --git a/Ryujinx.Ava/Ui/Controls/InputDialog.axaml.cs b/Ryujinx.Ava/Ui/Controls/InputDialog.axaml.cs index b9bbb66d..e4b37dec 100644 --- a/Ryujinx.Ava/Ui/Controls/InputDialog.axaml.cs +++ b/Ryujinx.Ava/Ui/Controls/InputDialog.axaml.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.Ui.Controls { - public class InputDialog : UserControl + public partial class InputDialog : UserControl { public string Message { get; set; } public string Input { get; set; } @@ -24,8 +24,6 @@ namespace Ryujinx.Ava.Ui.Controls MaxLength = maxLength; DataContext = this; - - InitializeComponent(); } public InputDialog() @@ -33,33 +31,26 @@ namespace Ryujinx.Ava.Ui.Controls InitializeComponent(); } - private void InitializeComponent() + public static async Task<(UserResult Result, string Input)> ShowInputDialog(string title, string message, + string input = "", string subMessage = "", uint maxLength = int.MaxValue) { - AvaloniaXamlLoader.Load(this); - } - - public static async Task<(UserResult Result, string Input)> ShowInputDialog(StyleableWindow window, string title, string message, string input = "", string subMessage = "", uint maxLength = int.MaxValue) - { - ContentDialog contentDialog = window.ContentDialog; - UserResult result = UserResult.Cancel; - InputDialog content = new InputDialog(message, input = "", subMessage = "", maxLength); - - if (contentDialog != null) + InputDialog content = new InputDialog(message, input, subMessage, maxLength); + ContentDialog contentDialog = new ContentDialog { - contentDialog.Title = title; - contentDialog.PrimaryButtonText = LocaleManager.Instance["InputDialogOk"]; - contentDialog.SecondaryButtonText = ""; - contentDialog.CloseButtonText = LocaleManager.Instance["InputDialogCancel"]; - contentDialog.Content = content; - contentDialog.PrimaryButtonCommand = MiniCommand.Create(() => + Title = title, + PrimaryButtonText = LocaleManager.Instance["InputDialogOk"], + SecondaryButtonText = "", + CloseButtonText = LocaleManager.Instance["InputDialogCancel"], + Content = content, + PrimaryButtonCommand = MiniCommand.Create(() => { result = UserResult.Ok; input = content.Input; - }); - await contentDialog.ShowAsync(); - } + }) + }; + await contentDialog.ShowAsync(); return (result, input); } diff --git a/Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml b/Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml new file mode 100644 index 00000000..b0ab5d30 --- /dev/null +++ b/Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml @@ -0,0 +1,10 @@ +<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:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" + mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" + x:Class="Ryujinx.Ava.Ui.Controls.NavigationDialogHost"> + <ui:Frame HorizontalAlignment="Stretch" VerticalAlignment="Stretch" + x:Name="ContentFrame" /> +</UserControl>
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml.cs b/Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml.cs new file mode 100644 index 00000000..9ba631ad --- /dev/null +++ b/Ryujinx.Ava/Ui/Controls/NavigationDialogHost.axaml.cs @@ -0,0 +1,85 @@ +using Avalonia; +using Avalonia.Controls; +using FluentAvalonia.UI.Controls; +using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Ui.ViewModels; +using Ryujinx.HLE.FileSystem; +using Ryujinx.HLE.HOS.Services.Account.Acc; +using System; +using System.Threading.Tasks; + +namespace Ryujinx.Ava.Ui.Controls +{ + public partial class NavigationDialogHost : UserControl + { + public AccountManager AccountManager { get; } + public ContentManager ContentManager { get; } + public UserProfileViewModel ViewModel { get; set; } + + public NavigationDialogHost() + { + InitializeComponent(); + } + + public NavigationDialogHost(AccountManager accountManager, ContentManager contentManager, + VirtualFileSystem virtualFileSystem) + { + AccountManager = accountManager; + ContentManager = contentManager; + ViewModel = new UserProfileViewModel(this); + + + if (contentManager.GetCurrentFirmwareVersion() != null) + { + Task.Run(() => + { + AvatarProfileViewModel.PreloadAvatars(contentManager, virtualFileSystem); + }); + } + InitializeComponent(); + } + + public void GoBack(object parameter = null) + { + if (ContentFrame.BackStack.Count > 0) + { + ContentFrame.GoBack(); + } + + ViewModel.LoadProfiles(); + } + + public void Navigate(Type sourcePageType, object parameter) + { + ContentFrame.Navigate(sourcePageType, parameter); + } + + public static async Task Show(AccountManager ownerAccountManager, ContentManager ownerContentManager, VirtualFileSystem ownerVirtualFileSystem) + { + var content = new NavigationDialogHost(ownerAccountManager, ownerContentManager, ownerVirtualFileSystem); + ContentDialog contentDialog = new ContentDialog + { + Title = LocaleManager.Instance["UserProfileWindowTitle"], + PrimaryButtonText = "", + SecondaryButtonText = "", + CloseButtonText = LocaleManager.Instance["UserProfilesClose"], + Content = content, + Padding = new Thickness(0) + }; + + contentDialog.Closed += (sender, args) => + { + content.ViewModel.Dispose(); + }; + + await contentDialog.ShowAsync(); + } + + protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) + { + base.OnAttachedToVisualTree(e); + + Navigate(typeof(UserSelector), this); + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml b/Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml index c6f43f43..750edf8b 100644 --- a/Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml +++ b/Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml @@ -1,14 +1,10 @@ -<Window xmlns="https://github.com/avaloniaui" +<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" mc:Ignorable="d" xmlns:Locale="clr-namespace:Ryujinx.Ava.Common.Locale" - x:Class="Ryujinx.Ava.Ui.Controls.ProfileImageSelectionDialog" - SizeToContent="WidthAndHeight" - WindowStartupLocation="CenterOwner" - Title="{Locale:Locale ProfileImageSelectionTitle}" - CanResize="false"> + x:Class="Ryujinx.Ava.Ui.Controls.ProfileImageSelectionDialog"> <Grid HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="5,10,5, 5"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> @@ -32,4 +28,4 @@ </Button> </StackPanel> </Grid> -</Window>
\ No newline at end of file +</UserControl>
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml.cs b/Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml.cs index 728b8906..5d361af9 100644 --- a/Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml.cs +++ b/Ryujinx.Ava/Ui/Controls/ProfileImageSelectionDialog.axaml.cs @@ -1,8 +1,10 @@ -using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; +using Avalonia.VisualTree; +using FluentAvalonia.UI.Controls; +using FluentAvalonia.UI.Navigation; using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.Ui.Windows; using Ryujinx.HLE.FileSystem; using SixLabors.ImageSharp; @@ -12,36 +14,40 @@ using Image = SixLabors.ImageSharp.Image; namespace Ryujinx.Ava.Ui.Controls { - public class ProfileImageSelectionDialog : StyleableWindow + public partial class ProfileImageSelectionDialog : UserControl { - private readonly ContentManager _contentManager; + private ContentManager _contentManager; + private NavigationDialogHost _parent; + private TempProfile _profile; public bool FirmwareFound => _contentManager.GetCurrentFirmwareVersion() != null; - public byte[] BufferImageProfile { get; set; } - - public ProfileImageSelectionDialog(ContentManager contentManager) - { - _contentManager = contentManager; - DataContext = this; - InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif - } - public ProfileImageSelectionDialog() { - DataContext = this; InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif + AddHandler(Frame.NavigatedToEvent, (s, e) => + { + NavigatedTo(e); + }, RoutingStrategies.Direct); } - private void InitializeComponent() + private void NavigatedTo(NavigationEventArgs arg) { - AvaloniaXamlLoader.Load(this); + if (Program.PreviewerDetached) + { + switch (arg.NavigationMode) + { + case NavigationMode.New: + (_parent, _profile) = ((NavigationDialogHost, TempProfile))arg.Parameter; + _contentManager = _parent.ContentManager; + break; + case NavigationMode.Back: + _parent.GoBack(); + break; + } + + DataContext = this; + } } private async void Import_OnClick(object sender, RoutedEventArgs e) @@ -58,7 +64,7 @@ namespace Ryujinx.Ava.Ui.Controls dialog.AllowMultiple = false; - string[] image = await dialog.ShowAsync(this); + string[] image = await dialog.ShowAsync(((TopLevel)_parent.GetVisualRoot()) as Window); if (image != null) { @@ -66,28 +72,22 @@ namespace Ryujinx.Ava.Ui.Controls { string imageFile = image[0]; - ProcessProfileImage(File.ReadAllBytes(imageFile)); + _profile.Image = ProcessProfileImage(File.ReadAllBytes(imageFile)); } - Close(); + _parent.GoBack(); } } - private async void SelectFirmwareImage_OnClick(object sender, RoutedEventArgs e) + private void SelectFirmwareImage_OnClick(object sender, RoutedEventArgs e) { if (FirmwareFound) { - AvatarWindow window = new(_contentManager); - - await window.ShowDialog(this); - - BufferImageProfile = window.SelectedImage; - - Close(); + _parent.Navigate(typeof(AvatarWindow), (_parent, _profile)); } } - private void ProcessProfileImage(byte[] buffer) + private static byte[] ProcessProfileImage(byte[] buffer) { using (Image image = Image.Load(buffer)) { @@ -97,7 +97,7 @@ namespace Ryujinx.Ava.Ui.Controls { image.SaveAsJpeg(streamJpg); - BufferImageProfile = streamJpg.ToArray(); + return streamJpg.ToArray(); } } } diff --git a/Ryujinx.Ava/Ui/Controls/UpdateWaitWindow.axaml.cs b/Ryujinx.Ava/Ui/Controls/UpdateWaitWindow.axaml.cs index e4108ba4..eff15c7b 100644 --- a/Ryujinx.Ava/Ui/Controls/UpdateWaitWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Controls/UpdateWaitWindow.axaml.cs @@ -5,7 +5,7 @@ using Ryujinx.Ava.Ui.Windows; namespace Ryujinx.Ava.Ui.Controls { - public class UpdateWaitWindow : StyleableWindow + public partial class UpdateWaitWindow : StyleableWindow { public UpdateWaitWindow(string primaryText, string secondaryText) : this() { @@ -21,15 +21,5 @@ namespace Ryujinx.Ava.Ui.Controls this.AttachDevTools(); #endif } - - public TextBlock PrimaryText { get; private set; } - public TextBlock SecondaryText { get; private set; } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - PrimaryText = this.FindControl<TextBlock>("PrimaryText"); - SecondaryText = this.FindControl<TextBlock>("SecondaryText"); - } } }
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/UserEditor.axaml b/Ryujinx.Ava/Ui/Controls/UserEditor.axaml new file mode 100644 index 00000000..fed5f8cb --- /dev/null +++ b/Ryujinx.Ava/Ui/Controls/UserEditor.axaml @@ -0,0 +1,55 @@ +<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" + mc:Ignorable="d" + Padding="0" + Margin="0" + xmlns:Locale="clr-namespace:Ryujinx.Ava.Common.Locale" + xmlns:viewModels="clr-namespace:Ryujinx.Ava.Ui.ViewModels" + xmlns:models="clr-namespace:Ryujinx.Ava.Ui.Models" + xmlns:controls="clr-namespace:Ryujinx.Ava.Ui.Controls" + xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" + x:Class="Ryujinx.Ava.Ui.Controls.UserEditor"> + <UserControl.Resources> + <controls:BitmapArrayValueConverter x:Key="ByteImage" /> + </UserControl.Resources> + <Grid Margin="0"> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto"/> + <ColumnDefinition/> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="*"/> + <RowDefinition Height="Auto"/> + </Grid.RowDefinitions> + <StackPanel Orientation="Vertical" VerticalAlignment="Stretch" HorizontalAlignment="Left"> + <Image + Margin="0" + HorizontalAlignment="Stretch" + VerticalAlignment="Top" + Height="96" Width="96" + Name="ProfileImage" + Source="{Binding Image, Converter={StaticResource ByteImage}}" /> + <Button Margin="5" Content="{Locale:Locale UserProfilesChangeProfileImage}" + Name="ChangePictureButton" + Click="ChangePictureButton_Click" + HorizontalAlignment="Stretch"/> + <Button Margin="5" Content="{Locale:Locale UserProfilesSetProfileImage}" + Name="AddPictureButton" + Click="ChangePictureButton_Click" + HorizontalAlignment="Stretch"/> + </StackPanel> + <StackPanel Grid.Row="0" Orientation="Vertical" HorizontalAlignment="Stretch" Grid.Column="1" Spacing="10" + Margin="5, 10"> + <TextBox Name="NameBox" Width="300" Text="{Binding Name}" MaxLength="{Binding MaxProfileNameLength}" + HorizontalAlignment="Stretch" /> + <TextBlock Text="{Binding UserId}" Name="IdLabel" /> + </StackPanel> + <StackPanel Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Orientation="Horizontal" Spacing="10" HorizontalAlignment="Right"> + <Button Content="{Locale:Locale Save}" Name="SaveButton" Click="SaveButton_Click"/> + <Button HorizontalAlignment="Right" Content="{Locale:Locale Discard}" + Name="CloseButton" Click="CloseButton_Click"/> + </StackPanel> + </Grid> +</UserControl> diff --git a/Ryujinx.Ava/Ui/Controls/UserEditor.axaml.cs b/Ryujinx.Ava/Ui/Controls/UserEditor.axaml.cs new file mode 100644 index 00000000..1bc1b325 --- /dev/null +++ b/Ryujinx.Ava/Ui/Controls/UserEditor.axaml.cs @@ -0,0 +1,123 @@ +using Avalonia.Controls; +using Avalonia.Data; +using Avalonia.Interactivity; +using FluentAvalonia.UI.Controls; +using FluentAvalonia.UI.Navigation; +using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Ui.Models; +using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile; + +namespace Ryujinx.Ava.Ui.Controls +{ + public partial class UserEditor : UserControl + { + private NavigationDialogHost _parent; + private UserProfile _profile; + private bool _isNewUser; + + public TempProfile TempProfile { get; set; } + public uint MaxProfileNameLength => 0x20; + + public UserEditor() + { + InitializeComponent(); + AddHandler(Frame.NavigatedToEvent, (s, e) => + { + NavigatedTo(e); + }, RoutingStrategies.Direct); + } + + private void NavigatedTo(NavigationEventArgs arg) + { + if (Program.PreviewerDetached) + { + switch (arg.NavigationMode) + { + case NavigationMode.New: + var args = ((NavigationDialogHost parent, UserProfile profile, bool isNewUser))arg.Parameter; + _isNewUser = args.isNewUser; + if (!_isNewUser) + { + _profile = args.profile; + TempProfile = new TempProfile(_profile); + } + else + { + TempProfile = new TempProfile(); + } + + _parent = args.parent; + break; + } + + DataContext = TempProfile; + + AddPictureButton.IsVisible = _isNewUser; + IdLabel.IsVisible = !_isNewUser; + ChangePictureButton.IsVisible = !_isNewUser; + } + } + + private void CloseButton_Click(object sender, RoutedEventArgs e) + { + _parent?.GoBack(); + } + + private void SaveButton_Click(object sender, RoutedEventArgs e) + { + DataValidationErrors.ClearErrors(NameBox); + bool isInvalid = false; + + if (string.IsNullOrWhiteSpace(TempProfile.Name)) + { + DataValidationErrors.SetError(NameBox, new DataValidationException(LocaleManager.Instance["UserProfileEmptyNameError"])); + + isInvalid = true; + } + + if (TempProfile.Image == null) + { + ContentDialogHelper.CreateWarningDialog(LocaleManager.Instance["UserProfileNoImageError"], ""); + + isInvalid = true; + } + + if(isInvalid) + { + return; + } + + if (_profile != null) + { + _profile.Name = TempProfile.Name; + _profile.Image = TempProfile.Image; + _profile.UpdateState(); + _parent.AccountManager.SetUserName(_profile.UserId, _profile.Name); + _parent.AccountManager.SetUserImage(_profile.UserId, _profile.Image); + } + else if (_isNewUser) + { + _parent.AccountManager.AddUser(TempProfile.Name, TempProfile.Image); + } + else + { + return; + } + + _parent?.GoBack(); + } + + public void SelectProfileImage() + { + _parent.Navigate(typeof(ProfileImageSelectionDialog), (_parent, TempProfile)); + } + + private void ChangePictureButton_Click(object sender, RoutedEventArgs e) + { + if (_profile != null || _isNewUser) + { + SelectProfileImage(); + } + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/UserErrorDialog.cs b/Ryujinx.Ava/Ui/Controls/UserErrorDialog.cs index 1f8f68e3..0b2d2c11 100644 --- a/Ryujinx.Ava/Ui/Controls/UserErrorDialog.cs +++ b/Ryujinx.Ava/Ui/Controls/UserErrorDialog.cs @@ -75,7 +75,7 @@ namespace Ryujinx.Ava.Ui.Controls string setupButtonLabel = isInSetupGuide ? LocaleManager.Instance["OpenSetupGuideMessage"] : ""; - var result = await ContentDialogHelper.CreateInfoDialog(owner, + var result = await ContentDialogHelper.CreateInfoDialog( string.Format(LocaleManager.Instance["DialogUserErrorDialogMessage"], errorCode, GetErrorTitle(error)), GetErrorDescription(error) + (isInSetupGuide ? LocaleManager.Instance["DialogUserErrorDialogInfoMessage"] diff --git a/Ryujinx.Ava/Ui/Controls/UserSelector.axaml b/Ryujinx.Ava/Ui/Controls/UserSelector.axaml new file mode 100644 index 00000000..3bca7d7d --- /dev/null +++ b/Ryujinx.Ava/Ui/Controls/UserSelector.axaml @@ -0,0 +1,90 @@ +<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:flex="clr-namespace:Avalonia.Flexbox;assembly=Avalonia.Flexbox" + xmlns:Locale="clr-namespace:Ryujinx.Ava.Common.Locale" + xmlns:viewModels="clr-namespace:Ryujinx.Ava.Ui.ViewModels" + xmlns:controls="clr-namespace:Ryujinx.Ava.Ui.Controls" + xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" + mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" + x:Class="Ryujinx.Ava.Ui.Controls.UserSelector"> + <UserControl.Resources> + <controls:BitmapArrayValueConverter x:Key="ByteImage" /> + </UserControl.Resources> + <Design.DataContext> + <viewModels:UserProfileViewModel /> + </Design.DataContext> + <Grid HorizontalAlignment="Stretch" + VerticalAlignment="Stretch"> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <ListBox HorizontalAlignment="Stretch" VerticalAlignment="Center" Margin="5" Items="{Binding Profiles}" + DoubleTapped="ProfilesList_DoubleTapped" + SelectionChanged="SelectingItemsControl_SelectionChanged"> + <ListBox.ItemsPanel> + <ItemsPanelTemplate> + <flex:FlexPanel + HorizontalAlignment="Stretch" + VerticalAlignment="Stretch" + AlignContent="FlexStart" + JustifyContent="Center" /> + </ItemsPanelTemplate> + </ListBox.ItemsPanel> + <ListBox.ItemTemplate> + <DataTemplate> + <Grid> + <Border + Margin="2" + HorizontalAlignment="Stretch" + VerticalAlignment="Stretch" + ClipToBounds="True" + CornerRadius="5"> + <Grid Margin="0"> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Image + Grid.Row="0" + Margin="0" + HorizontalAlignment="Stretch" + VerticalAlignment="Top" + Height="96" Width="96" + Source="{Binding Image, Converter={StaticResource ByteImage}}" /> + <StackPanel + Grid.Row="1" + Height="30" + Margin="5" + HorizontalAlignment="Stretch" + VerticalAlignment="Stretch"> + <TextBlock + HorizontalAlignment="Stretch" + Text="{Binding Name}" + TextAlignment="Center" + TextWrapping="Wrap" /> + </StackPanel> + </Grid> + </Border> + <Border HorizontalAlignment="Left" VerticalAlignment="Top" + IsVisible="{Binding IsOpened}" + Background="LimeGreen" + Width="10" + Height="10" + Margin="5" + CornerRadius="5" /> + </Grid> + </DataTemplate> + </ListBox.ItemTemplate> + </ListBox> + <StackPanel Grid.Row="1" Orientation="Horizontal" Margin="10,0" Spacing="10" HorizontalAlignment="Center"> + <Button Content="{Locale:Locale UserProfilesAddNewProfile}" Command="{Binding AddUser}" /> + <Button IsEnabled="{Binding IsSelectedProfiledEditable}" + Content="{Locale:Locale UserProfilesEditProfile}" Command="{Binding EditUser}" /> + <Button IsEnabled="{Binding IsSelectedProfileDeletable}" + Content="{Locale:Locale UserProfilesDeleteSelectedProfile}" Command="{Binding DeleteUser}" /> + </StackPanel> + </Grid> +</UserControl>
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Controls/UserSelector.axaml.cs b/Ryujinx.Ava/Ui/Controls/UserSelector.axaml.cs new file mode 100644 index 00000000..027351ee --- /dev/null +++ b/Ryujinx.Ava/Ui/Controls/UserSelector.axaml.cs @@ -0,0 +1,79 @@ +using Avalonia.Controls; +using Avalonia.Interactivity; +using FluentAvalonia.UI.Controls; +using FluentAvalonia.UI.Navigation; +using Ryujinx.Ava.Ui.ViewModels; +using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile; + +namespace Ryujinx.Ava.Ui.Controls +{ + public partial class UserSelector : UserControl + { + private NavigationDialogHost _parent; + public UserProfileViewModel ViewModel { get; set; } + + public UserSelector() + { + InitializeComponent(); + + if (Program.PreviewerDetached) + { + AddHandler(Frame.NavigatedToEvent, (s, e) => + { + NavigatedTo(e); + }, Avalonia.Interactivity.RoutingStrategies.Direct); + } + } + + private void NavigatedTo(NavigationEventArgs arg) + { + if (Program.PreviewerDetached) + { + switch (arg.NavigationMode) + { + case NavigationMode.New: + _parent = (NavigationDialogHost)arg.Parameter; + ViewModel = _parent.ViewModel; + break; + } + + DataContext = ViewModel; + } + } + + private void ProfilesList_DoubleTapped(object sender, RoutedEventArgs e) + { + if (sender is ListBox listBox) + { + int selectedIndex = listBox.SelectedIndex; + + if (selectedIndex >= 0 && selectedIndex < ViewModel.Profiles.Count) + { + ViewModel.SelectedProfile = ViewModel.Profiles[selectedIndex]; + + _parent?.AccountManager?.OpenUser(ViewModel.SelectedProfile.UserId); + + ViewModel.LoadProfiles(); + + foreach (UserProfile profile in ViewModel.Profiles) + { + profile.UpdateState(); + } + } + } + } + + private void SelectingItemsControl_SelectionChanged(object sender, SelectionChangedEventArgs e) + { + if (sender is ListBox listBox) + { + int selectedIndex = listBox.SelectedIndex; + + if (selectedIndex >= 0 && selectedIndex < ViewModel.Profiles.Count) + { + ViewModel.HighlightedProfile = ViewModel.Profiles[selectedIndex]; + } + } + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Models/TempProfile.cs b/Ryujinx.Ava/Ui/Models/TempProfile.cs new file mode 100644 index 00000000..e943687a --- /dev/null +++ b/Ryujinx.Ava/Ui/Models/TempProfile.cs @@ -0,0 +1,55 @@ +using Ryujinx.Ava.Ui.ViewModels; +using Ryujinx.HLE.HOS.Services.Account.Acc; +using System; + +namespace Ryujinx.Ava.Ui.Models +{ + public class TempProfile : BaseModel + { + private readonly UserProfile _profile; + private byte[] _image = null; + private string _name = String.Empty; + private UserId _userId; + + public byte[] Image + { + get => _image; + set + { + _image = value; + OnPropertyChanged(); + } + } + + public UserId UserId + { + get => _userId; + set + { + _userId = value; + OnPropertyChanged(); + } + } + + public string Name + { + get => _name; + set + { + _name = value; + OnPropertyChanged(); + } + } + + public TempProfile(UserProfile profile) + { + _profile = profile; + + Image = profile.Image; + Name = profile.Name; + UserId = profile.UserId; + } + + public TempProfile(){} + } +}
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/ViewModels/AmiiboWindowViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/AmiiboWindowViewModel.cs index 9f411ba2..7015df44 100644 --- a/Ryujinx.Ava/Ui/ViewModels/AmiiboWindowViewModel.cs +++ b/Ryujinx.Ava/Ui/ViewModels/AmiiboWindowViewModel.cs @@ -390,7 +390,7 @@ namespace Ryujinx.Ava.Ui.ViewModels return amiiboJsonString; } - await ContentDialogHelper.CreateInfoDialog(_owner, LocaleManager.Instance["DialogAmiiboApiTitle"], + await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance["DialogAmiiboApiTitle"], LocaleManager.Instance["DialogAmiiboApiFailFetchMessage"], LocaleManager.Instance["InputDialogOk"], "", @@ -440,7 +440,7 @@ namespace Ryujinx.Ava.Ui.ViewModels private async void ShowInfoDialog() { - await ContentDialogHelper.CreateInfoDialog(_owner, LocaleManager.Instance["DialogAmiiboApiTitle"], + await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance["DialogAmiiboApiTitle"], LocaleManager.Instance["DialogAmiiboApiConnectErrorMessage"], LocaleManager.Instance["InputDialogOk"], "", diff --git a/Ryujinx.Ava/Ui/ViewModels/ControllerSettingsViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/ControllerSettingsViewModel.cs index c570aa8d..a3abdd3b 100644 --- a/Ryujinx.Ava/Ui/ViewModels/ControllerSettingsViewModel.cs +++ b/Ryujinx.Ava/Ui/ViewModels/ControllerSettingsViewModel.cs @@ -327,12 +327,12 @@ namespace Ryujinx.Ava.Ui.ViewModels public async void ShowMotionConfig() { - await MotionSettingsWindow.Show(this, _owner.GetVisualRoot() as StyleableWindow); + await MotionSettingsWindow.Show(this); } public async void ShowRumbleConfig() { - await RumbleSettingsWindow.Show(this, _owner.GetVisualRoot() as StyleableWindow); + await RumbleSettingsWindow.Show(this); } private void LoadInputDriver() @@ -701,8 +701,8 @@ namespace Ryujinx.Ava.Ui.ViewModels catch (InvalidOperationException) { Logger.Error?.Print(LogClass.Configuration, $"Profile {ProfileName} is incompatible with the current input configuration system."); - await ContentDialogHelper.CreateErrorDialog(_owner.GetVisualRoot() as StyleableWindow, - String.Format(LocaleManager.Instance["DialogProfileInvalidProfileErrorMessage"], ProfileName)); + + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogProfileInvalidProfileErrorMessage"], ProfileName)); return; } @@ -736,7 +736,7 @@ namespace Ryujinx.Ava.Ui.ViewModels if (ProfileName == LocaleManager.Instance["ControllerSettingsProfileDefault"]) { - await ContentDialogHelper.CreateErrorDialog(_owner.GetVisualRoot() as StyleableWindow, LocaleManager.Instance["DialogProfileDefaultProfileOverwriteErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogProfileDefaultProfileOverwriteErrorMessage"]); return; } @@ -769,7 +769,7 @@ namespace Ryujinx.Ava.Ui.ViewModels } else { - await ContentDialogHelper.CreateErrorDialog(_owner.GetVisualRoot() as StyleableWindow, LocaleManager.Instance["DialogProfileInvalidProfileNameErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogProfileInvalidProfileNameErrorMessage"]); } } } @@ -782,7 +782,6 @@ namespace Ryujinx.Ava.Ui.ViewModels } UserResult result = await ContentDialogHelper.CreateConfirmationDialog( - _owner.GetVisualRoot() as StyleableWindow, LocaleManager.Instance["DialogProfileDeleteProfileTitle"], LocaleManager.Instance["DialogProfileDeleteProfileMessage"], LocaleManager.Instance["InputDialogYes"], diff --git a/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs index 9c027773..7e6452f9 100644 --- a/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs +++ b/Ryujinx.Ava/Ui/ViewModels/MainWindowViewModel.cs @@ -708,7 +708,7 @@ namespace Ryujinx.Ava.Ui.ViewModels { return; } - + if (_owner.AppHost.Device.System.SearchingForAmiibo(out int deviceId)) { string titleId = _owner.AppHost.Device.Application.TitleIdText.ToUpper(); @@ -975,9 +975,7 @@ namespace Ryujinx.Ava.Ui.ViewModels public async void ManageProfiles() { - UserProfileWindow window = new(_owner.AccountManager, _owner.ContentManager, _owner.VirtualFileSystem); - - await window.ShowDialog(_owner); + await NavigationDialogHost.Show(_owner.AccountManager, _owner.ContentManager, _owner.VirtualFileSystem); } public async void OpenAboutWindow() @@ -1054,8 +1052,7 @@ namespace Ryujinx.Ava.Ui.ViewModels { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(_owner, - LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]); }); return; @@ -1138,7 +1135,7 @@ namespace Ryujinx.Ava.Ui.ViewModels DirectoryInfo backupDir = new(Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "cpu", "1")); // FIXME: Found a way to reproduce the bold effect on the title name (fork?). - UserResult result = await ContentDialogHelper.CreateConfirmationDialog(_owner, LocaleManager.Instance["DialogWarning"], + UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance["DialogWarning"], string.Format(LocaleManager.Instance["DialogPPTCDeletionMessage"], selection.TitleName), LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], LocaleManager.Instance["RyujinxConfirm"]); List<FileInfo> cacheFiles = new(); @@ -1163,7 +1160,7 @@ namespace Ryujinx.Ava.Ui.ViewModels } catch (Exception e) { - await ContentDialogHelper.CreateErrorDialog(_owner, string.Format(LocaleManager.Instance["DialogPPTCDeletionErrorMessage"], file.Name, e)); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogPPTCDeletionErrorMessage"], file.Name, e)); } } } @@ -1201,7 +1198,7 @@ namespace Ryujinx.Ava.Ui.ViewModels DirectoryInfo shaderCacheDir = new(Path.Combine(AppDataManager.GamesDirPath, selection.TitleId, "cache", "shader")); // FIXME: Found a way to reproduce the bold effect on the title name (fork?). - UserResult result = await ContentDialogHelper.CreateConfirmationDialog(_owner, LocaleManager.Instance["DialogWarning"], + UserResult result = await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance["DialogWarning"], string.Format(LocaleManager.Instance["DialogShaderDeletionMessage"], selection.TitleName), LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], LocaleManager.Instance["RyujinxConfirm"]); List<DirectoryInfo> oldCacheDirectories = new List<DirectoryInfo>(); @@ -1224,7 +1221,7 @@ namespace Ryujinx.Ava.Ui.ViewModels } catch (Exception e) { - await ContentDialogHelper.CreateErrorDialog(_owner, string.Format(LocaleManager.Instance["DialogPPTCDeletionErrorMessage"], directory.Name, e)); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogPPTCDeletionErrorMessage"], directory.Name, e)); } } } @@ -1237,7 +1234,7 @@ namespace Ryujinx.Ava.Ui.ViewModels } catch (Exception e) { - await ContentDialogHelper.CreateErrorDialog(_owner, string.Format(LocaleManager.Instance["ShaderCachePurgeError"], file.Name, e)); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["ShaderCachePurgeError"], file.Name, e)); } } } @@ -1316,12 +1313,11 @@ namespace Ryujinx.Ava.Ui.ViewModels Task.Run(() => { if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, - out ulong titleIdNumber)) + out ulong titleIdNumber)) { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(_owner, - LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]); }); return; @@ -1342,12 +1338,11 @@ namespace Ryujinx.Ava.Ui.ViewModels Task.Run(() => { if (!ulong.TryParse(selection.TitleId, NumberStyles.HexNumber, CultureInfo.InvariantCulture, - out ulong titleIdNumber)) + out ulong titleIdNumber)) { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(_owner, - LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogRyujinxErrorMessage"], LocaleManager.Instance["DialogInvalidTitleIdErrorMessage"]); }); return; @@ -1406,7 +1401,7 @@ namespace Ryujinx.Ava.Ui.ViewModels if (firmwareVersion == null) { - await ContentDialogHelper.CreateErrorDialog(_owner, string.Format(LocaleManager.Instance["DialogFirmwareInstallerFirmwareNotFoundErrorMessage"], filename)); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogFirmwareInstallerFirmwareNotFoundErrorMessage"], filename)); return; } @@ -1426,7 +1421,6 @@ namespace Ryujinx.Ava.Ui.ViewModels dialogMessage += LocaleManager.Instance["DialogFirmwareInstallerFirmwareInstallConfirmMessage"]; UserResult result = await ContentDialogHelper.CreateConfirmationDialog( - _owner, dialogTitle, dialogMessage, LocaleManager.Instance["InputDialogYes"], @@ -1456,7 +1450,7 @@ namespace Ryujinx.Ava.Ui.ViewModels string message = string.Format(LocaleManager.Instance["DialogFirmwareInstallerFirmwareInstallSuccessMessage"], firmwareVersion.VersionString); - await ContentDialogHelper.CreateInfoDialog(_owner, dialogTitle, message, LocaleManager.Instance["InputDialogOk"], "", LocaleManager.Instance["RyujinxInfo"]); + await ContentDialogHelper.CreateInfoDialog(dialogTitle, message, LocaleManager.Instance["InputDialogOk"], "", LocaleManager.Instance["RyujinxInfo"]); Logger.Info?.Print(LogClass.Application, message); // Purge Applet Cache. @@ -1475,7 +1469,7 @@ namespace Ryujinx.Ava.Ui.ViewModels { waitingDialog.Close(); - await ContentDialogHelper.CreateErrorDialog(_owner, ex.Message); + await ContentDialogHelper.CreateErrorDialog(ex.Message); }); } finally @@ -1496,7 +1490,7 @@ namespace Ryujinx.Ava.Ui.ViewModels } catch (Exception ex) { - await ContentDialogHelper.CreateErrorDialog(_owner, ex.Message); + await ContentDialogHelper.CreateErrorDialog(ex.Message); } } diff --git a/Ryujinx.Ava/Ui/ViewModels/SettingsViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/SettingsViewModel.cs index ef7a53e6..7b175f08 100644 --- a/Ryujinx.Ava/Ui/ViewModels/SettingsViewModel.cs +++ b/Ryujinx.Ava/Ui/ViewModels/SettingsViewModel.cs @@ -63,8 +63,7 @@ namespace Ryujinx.Ava.Ui.ViewModels { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateInfoDialog(_owner, - LocaleManager.Instance["DialogSettingsBackendThreadingWarningMessage"], + await ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance["DialogSettingsBackendThreadingWarningMessage"], "", "", LocaleManager.Instance["InputDialogOk"], diff --git a/Ryujinx.Ava/Ui/ViewModels/UserProfileViewModel.cs b/Ryujinx.Ava/Ui/ViewModels/UserProfileViewModel.cs index 66fa7e34..f7a50077 100644 --- a/Ryujinx.Ava/Ui/ViewModels/UserProfileViewModel.cs +++ b/Ryujinx.Ava/Ui/ViewModels/UserProfileViewModel.cs @@ -1,31 +1,27 @@ using Avalonia.Threading; using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Ui.Controls; -using Ryujinx.Ava.Ui.Windows; using Ryujinx.HLE.HOS.Services.Account.Acc; using System; using System.Collections.ObjectModel; using System.Linq; -using System.Threading.Tasks; using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile; namespace Ryujinx.Ava.Ui.ViewModels { public class UserProfileViewModel : BaseModel, IDisposable { - private const uint MaxProfileNameLength = 0x20; - - private readonly UserProfileWindow _owner; + private readonly NavigationDialogHost _owner; private UserProfile _selectedProfile; - private string _tempUserName; + private UserProfile _highlightedProfile; public UserProfileViewModel() { Profiles = new ObservableCollection<UserProfile>(); } - public UserProfileViewModel(UserProfileWindow owner) : this() + public UserProfileViewModel(NavigationDialogHost owner) : this() { _owner = owner; @@ -42,12 +38,29 @@ namespace Ryujinx.Ava.Ui.ViewModels _selectedProfile = value; OnPropertyChanged(nameof(SelectedProfile)); - OnPropertyChanged(nameof(IsSelectedProfileDeletable)); + OnPropertyChanged(nameof(IsHighlightedProfileDeletable)); + OnPropertyChanged(nameof(IsHighlightedProfileEditable)); } } - public bool IsSelectedProfileDeletable => - _selectedProfile != null && _selectedProfile.UserId != AccountManager.DefaultUserId; + public bool IsHighlightedProfileEditable => + _highlightedProfile != null; + + public bool IsHighlightedProfileDeletable => + _highlightedProfile != null && _highlightedProfile.UserId != AccountManager.DefaultUserId; + + public UserProfile HighlightedProfile + { + get => _highlightedProfile; + set + { + _highlightedProfile = value; + + OnPropertyChanged(nameof(HighlightedProfile)); + OnPropertyChanged(nameof(IsHighlightedProfileDeletable)); + OnPropertyChanged(nameof(IsHighlightedProfileEditable)); + } + } public void Dispose() { @@ -78,64 +91,24 @@ namespace Ryujinx.Ava.Ui.ViewModels } } - public async void ChooseProfileImage() + public void AddUser() { - await SelectProfileImage(); + UserProfile userProfile = null; + _owner.Navigate(typeof(UserEditor), (this._owner, userProfile, true)); } - public async Task SelectProfileImage(bool isNewUser = false) + public void EditUser() { - ProfileImageSelectionDialog selectionDialog = new(_owner.ContentManager); - - await selectionDialog.ShowDialog(_owner); - - if (selectionDialog.BufferImageProfile != null) - { - if (isNewUser) - { - if (!string.IsNullOrWhiteSpace(_tempUserName)) - { - _owner.AccountManager.AddUser(_tempUserName, selectionDialog.BufferImageProfile); - } - } - else if (SelectedProfile != null) - { - _owner.AccountManager.SetUserImage(SelectedProfile.UserId, selectionDialog.BufferImageProfile); - SelectedProfile.Image = selectionDialog.BufferImageProfile; - - SelectedProfile = null; - } - - LoadProfiles(); - } - } - - public async void AddUser() - { - var dlgTitle = LocaleManager.Instance["InputDialogAddNewProfileTitle"]; - var dlgMainText = LocaleManager.Instance["InputDialogAddNewProfileHeader"]; - var dlgSubText = string.Format(LocaleManager.Instance["InputDialogAddNewProfileSubtext"], - MaxProfileNameLength); - - _tempUserName = - await ContentDialogHelper.CreateInputDialog(dlgTitle, dlgMainText, dlgSubText, _owner, - MaxProfileNameLength); - - if (!string.IsNullOrWhiteSpace(_tempUserName)) - { - await SelectProfileImage(true); - } - - _tempUserName = String.Empty; + _owner.Navigate(typeof(UserEditor), (this._owner, _highlightedProfile ?? SelectedProfile, false)); } public async void DeleteUser() { - if (_selectedProfile != null) + if (_highlightedProfile != null) { var lastUserId = _owner.AccountManager.LastOpenedUser.UserId; - if (_selectedProfile.UserId == lastUserId) + if (_highlightedProfile.UserId == lastUserId) { // If we are deleting the currently open profile, then we must open something else before deleting. var profile = Profiles.FirstOrDefault(x => x.UserId != lastUserId); @@ -144,8 +117,7 @@ namespace Ryujinx.Ava.Ui.ViewModels { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(_owner, - LocaleManager.Instance["DialogUserProfileDeletionWarningMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogUserProfileDeletionWarningMessage"]); }); return; @@ -155,13 +127,12 @@ namespace Ryujinx.Ava.Ui.ViewModels } var result = - await ContentDialogHelper.CreateConfirmationDialog(_owner, - LocaleManager.Instance["DialogUserProfileDeletionConfirmMessage"], "", + await ContentDialogHelper.CreateConfirmationDialog(LocaleManager.Instance["DialogUserProfileDeletionConfirmMessage"], "", LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], ""); if (result == UserResult.Yes) { - _owner.AccountManager.DeleteUser(_selectedProfile.UserId); + _owner.AccountManager.DeleteUser(_highlightedProfile.UserId); } } diff --git a/Ryujinx.Ava/Ui/Windows/AboutWindow.axaml b/Ryujinx.Ava/Ui/Windows/AboutWindow.axaml index aeaac5da..505b8004 100644 --- a/Ryujinx.Ava/Ui/Windows/AboutWindow.axaml +++ b/Ryujinx.Ava/Ui/Windows/AboutWindow.axaml @@ -17,43 +17,43 @@ SizeToContent="Width" WindowStartupLocation="CenterOwner" mc:Ignorable="d"> - <Grid + <Grid Margin="15" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition Height="*" /> - </Grid.RowDefinitions> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition Width="*" /> - </Grid.ColumnDefinitions> - <Grid + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="*" /> + </Grid.RowDefinitions> + <Grid.ColumnDefinitions> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="Auto" /> + <ColumnDefinition Width="*" /> + </Grid.ColumnDefinitions> + <Grid Grid.Row="1" Grid.Column="0" Margin="20" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> - <Grid.RowDefinitions> - <RowDefinition Height="*" /> - <RowDefinition Height="*" /> - <RowDefinition /> - <RowDefinition /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Grid Grid.Row="0"> - <Grid.ColumnDefinitions> - <ColumnDefinition /> - <ColumnDefinition /> - </Grid.ColumnDefinitions> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Image + <Grid.RowDefinitions> + <RowDefinition Height="*" /> + <RowDefinition Height="*" /> + <RowDefinition /> + <RowDefinition /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Grid Grid.Row="0"> + <Grid.ColumnDefinitions> + <ColumnDefinition /> + <ColumnDefinition /> + </Grid.ColumnDefinitions> + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Image Grid.Row="0" Grid.RowSpan="3" Grid.Column="0" @@ -61,21 +61,21 @@ MinWidth="50" Margin="5,10,20,10" Source="resm:Ryujinx.Ui.Common.Resources.Logo_Ryujinx.png?assembly=Ryujinx.Ui.Common" /> - <TextBlock + <TextBlock Grid.Row="0" Grid.Column="1" Margin="0,20,0,0" FontSize="35" Text="Ryujinx" TextAlignment="Center" /> - <TextBlock + <TextBlock Grid.Row="1" Grid.Column="1" Margin="0,0,0,0" FontSize="16" Text="(REE-YOU-JINX)" TextAlignment="Center" /> - <Button + <Button Grid.Row="2" Grid.Column="1" Margin="0" @@ -83,27 +83,27 @@ Background="Transparent" Click="Button_OnClick" Tag="https://www.ryujinx.org/"> - <TextBlock + <TextBlock Text="www.ryujinx.org" TextAlignment="Center" TextDecorations="Underline" ToolTip.Tip="{locale:Locale AboutUrlTooltipMessage}" /> - </Button> - </Grid> - <TextBlock + </Button> + </Grid> + <TextBlock Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Version}" TextAlignment="Center" /> - <TextBlock + <TextBlock Grid.Row="2" Margin="20" HorizontalAlignment="Center" MaxLines="2" Text="{locale:Locale AboutDisclaimerMessage}" TextAlignment="Center" /> - <TextBlock + <TextBlock Name="AmiiboLabel" Grid.Row="3" Margin="20" @@ -112,94 +112,94 @@ PointerPressed="AmiiboLabel_OnPointerPressed" Text="{locale:Locale AboutAmiiboDisclaimerMessage}" TextAlignment="Center" /> - <StackPanel + <StackPanel Grid.Row="4" HorizontalAlignment="Center" Orientation="Horizontal" Spacing="10"> - <StackPanel Orientation="Vertical" ToolTip.Tip="{locale:Locale AboutPatreonUrlTooltipMessage}"> - <Button + <StackPanel Orientation="Vertical" ToolTip.Tip="{locale:Locale AboutPatreonUrlTooltipMessage}"> + <Button Height="65" Background="Transparent" Click="Button_OnClick" Tag="https://www.patreon.com/ryujinx"> - <Grid> - <Grid.RowDefinitions> - <RowDefinition /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Image Source="resm:Ryujinx.Ui.Common.Resources.Logo_Patreon.png?assembly=Ryujinx.Ui.Common" /> - <TextBlock + <Grid> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Image Source="resm:Ryujinx.Ui.Common.Resources.Logo_Patreon.png?assembly=Ryujinx.Ui.Common" /> + <TextBlock Grid.Row="1" Margin="0,5,0,0" HorizontalAlignment="Center" Text="Patreon" /> - </Grid> - </Button> - </StackPanel> - <StackPanel Orientation="Vertical" ToolTip.Tip="{locale:Locale AboutGithubUrlTooltipMessage}"> - <Button + </Grid> + </Button> + </StackPanel> + <StackPanel Orientation="Vertical" ToolTip.Tip="{locale:Locale AboutGithubUrlTooltipMessage}"> + <Button Height="65" Background="Transparent" Click="Button_OnClick" Tag="https://github.com/Ryujinx/Ryujinx"> - <Grid> - <Grid.RowDefinitions> - <RowDefinition /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Image Source="resm:Ryujinx.Ui.Common.Resources.Logo_GitHub.png?assembly=Ryujinx.Ui.Common" /> - <TextBlock + <Grid> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Image Source="resm:Ryujinx.Ui.Common.Resources.Logo_GitHub.png?assembly=Ryujinx.Ui.Common" /> + <TextBlock Grid.Row="1" Margin="0,5,0,0" HorizontalAlignment="Center" Text="GitHub" /> - </Grid> - </Button> - </StackPanel> - <StackPanel Orientation="Vertical" ToolTip.Tip="{locale:Locale AboutDiscordUrlTooltipMessage}"> - <Button + </Grid> + </Button> + </StackPanel> + <StackPanel Orientation="Vertical" ToolTip.Tip="{locale:Locale AboutDiscordUrlTooltipMessage}"> + <Button Height="65" Background="Transparent" Click="Button_OnClick" Tag="https://discordapp.com/invite/N2FmfVc"> - <Grid> - <Grid.RowDefinitions> - <RowDefinition /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Image Source="resm:Ryujinx.Ui.Common.Resources.Logo_Discord.png?assembly=Ryujinx.Ui.Common" /> - <TextBlock + <Grid> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Image Source="resm:Ryujinx.Ui.Common.Resources.Logo_Discord.png?assembly=Ryujinx.Ui.Common" /> + <TextBlock Grid.Row="1" Margin="0,5,0,0" HorizontalAlignment="Center" Text="Discord" /> - </Grid> - </Button> - </StackPanel> - <StackPanel Orientation="Vertical" ToolTip.Tip="{locale:Locale AboutTwitterUrlTooltipMessage}"> - <Button + </Grid> + </Button> + </StackPanel> + <StackPanel Orientation="Vertical" ToolTip.Tip="{locale:Locale AboutTwitterUrlTooltipMessage}"> + <Button Height="65" Background="Transparent" Click="Button_OnClick" Tag="https://twitter.com/RyujinxEmu"> - <Grid> - <Grid.RowDefinitions> - <RowDefinition /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Image Source="resm:Ryujinx.Ui.Common.Resources.Logo_Twitter.png?assembly=Ryujinx.Ui.Common" /> - <TextBlock + <Grid> + <Grid.RowDefinitions> + <RowDefinition /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <Image Source="resm:Ryujinx.Ui.Common.Resources.Logo_Twitter.png?assembly=Ryujinx.Ui.Common" /> + <TextBlock Grid.Row="1" Margin="0,5,0,0" HorizontalAlignment="Center" Text="Twitter" /> - </Grid> - </Button> - </StackPanel> - </StackPanel> - </Grid> - <Border + </Grid> + </Button> + </StackPanel> + </StackPanel> + </Grid> + <Border Grid.Row="1" Grid.Column="1" Width="2" @@ -207,62 +207,62 @@ VerticalAlignment="Stretch" BorderBrush="White" BorderThickness="1,0,0,0"> - <Separator Width="0" /> - </Border> - <Grid + <Separator Width="0" /> + </Border> + <Grid Grid.Row="1" Grid.Column="2" Margin="20" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <TextBlock + <Grid.RowDefinitions> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + <RowDefinition Height="Auto" /> + </Grid.RowDefinitions> + <TextBlock FontWeight="Bold" Text="{locale:Locale AboutRyujinxAboutTitle}" TextDecorations="Underline" /> - <TextBlock + <TextBlock Grid.Row="1" Margin="20,5,5,5" LineHeight="20" Text="{locale:Locale AboutRyujinxAboutContent}" /> - <TextBlock + <TextBlock Grid.Row="2" Margin="0,10,0,0" FontWeight="Bold" Text="{locale:Locale AboutRyujinxMaintainersTitle}" TextDecorations="Underline" /> - <TextBlock + <TextBlock Grid.Row="3" Margin="20,5,5,5" LineHeight="20" Text="{Binding Developers}" /> - <Button + <Button Grid.Row="4" HorizontalAlignment="Right" Background="Transparent" Click="Button_OnClick" Tag="https://github.com/Ryujinx/Ryujinx/graphs/contributors?type=a"> - <TextBlock + <TextBlock Text="{locale:Locale AboutRyujinxContributorsButtonHeader}" TextAlignment="Right" TextDecorations="Underline" ToolTip.Tip="{locale:Locale AboutRyujinxMaintainersContentTooltipMessage}" /> - </Button> - <TextBlock + </Button> + <TextBlock Grid.Row="5" Margin="0,0,0,0" FontWeight="Bold" Text="{locale:Locale AboutRyujinxSupprtersTitle}" TextDecorations="Underline" /> - <Border + <Border Grid.Row="6" Width="460" Height="200" @@ -271,12 +271,12 @@ VerticalAlignment="Stretch" BorderBrush="White" BorderThickness="1"> - <TextBlock + <TextBlock Name="SupportersTextBlock" VerticalAlignment="Top" Text="{Binding Supporters}" TextWrapping="Wrap" /> - </Border> - </Grid> - </Grid> + </Border> + </Grid> + </Grid> </window:StyleableWindow> diff --git a/Ryujinx.Ava/Ui/Windows/AboutWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/AboutWindow.axaml.cs index 3f93ccb7..75e9901b 100644 --- a/Ryujinx.Ava/Ui/Windows/AboutWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/AboutWindow.axaml.cs @@ -13,7 +13,7 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.Ui.Windows { - public class AboutWindow : StyleableWindow + public partial class AboutWindow : StyleableWindow { public AboutWindow() { @@ -39,15 +39,6 @@ namespace Ryujinx.Ava.Ui.Windows public string Developers => string.Format(LocaleManager.Instance["AboutPageDeveloperListMore"], "gdkchan, Ac_K, Thog, rip in peri peri, LDj3SNuD, emmaus, Thealexbarney, Xpl0itR, GoffyDude, »jD«"); - public TextBlock SupportersTextBlock { get; set; } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - - SupportersTextBlock = this.FindControl<TextBlock>("SupportersTextBlock"); - } - private void Button_OnClick(object sender, RoutedEventArgs e) { if (sender is Button button) diff --git a/Ryujinx.Ava/Ui/Windows/AmiiboWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/AmiiboWindow.axaml.cs index bd0935a9..5ed84571 100644 --- a/Ryujinx.Ava/Ui/Windows/AmiiboWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/AmiiboWindow.axaml.cs @@ -7,7 +7,7 @@ using Ryujinx.Ava.Ui.ViewModels; namespace Ryujinx.Ava.Ui.Windows { - public class AmiiboWindow : StyleableWindow + public partial class AmiiboWindow : StyleableWindow { public AmiiboWindow(bool showAll, string lastScannedAmiiboId, string titleId) { @@ -44,11 +44,6 @@ namespace Ryujinx.Ava.Ui.Windows public Amiibo.AmiiboApi ScannedAmiibo { get; set; } public AmiiboWindowViewModel ViewModel { get; set; } - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - private void ScanButton_Click(object sender, RoutedEventArgs e) { if (ViewModel.AmiiboSelectedIndex > -1) diff --git a/Ryujinx.Ava/Ui/Windows/AvatarWindow.axaml b/Ryujinx.Ava/Ui/Windows/AvatarWindow.axaml index 6c7576bc..0be65130 100644 --- a/Ryujinx.Ava/Ui/Windows/AvatarWindow.axaml +++ b/Ryujinx.Ava/Ui/Windows/AvatarWindow.axaml @@ -1,36 +1,35 @@ -<Window xmlns="https://github.com/avaloniaui" +<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:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="350" x:Class="Ryujinx.Ava.Ui.Windows.AvatarWindow" - CanResize="False" + Margin="0" + Padding="0" xmlns:Locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:viewModels="clr-namespace:Ryujinx.Ava.Ui.ViewModels" xmlns:controls="clr-namespace:Ryujinx.Ava.Ui.Controls" - WindowStartupLocation="CenterOwner" x:CompileBindings="True" - x:DataType="viewModels:AvatarProfileViewModel" - SizeToContent="WidthAndHeight"> + x:DataType="viewModels:AvatarProfileViewModel"> <Design.DataContext> <viewModels:AvatarProfileViewModel /> </Design.DataContext> - <Window.Resources> - <controls:BitmapArrayValueConverter x:Key="ByteImage" /> - </Window.Resources> - <Grid Margin="5" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> + <UserControl.Resources> + <controls:BitmapArrayValueConverter x:Key="ByteImage" /> + </UserControl.Resources> + <Grid Margin="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="*" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> - <ListBox Grid.Row="1" BorderThickness="0" SelectedIndex="{Binding SelectedIndex}" Width="600" Height="500" + <ListBox Grid.Row="1" BorderThickness="0" SelectedIndex="{Binding SelectedIndex}" Height="400" Items="{Binding Images}" HorizontalAlignment="Stretch" VerticalAlignment="Center"> <ListBox.ItemsPanel> <ItemsPanelTemplate> - <WrapPanel Orientation="Horizontal" MaxWidth="600" Margin="0" HorizontalAlignment="Center" /> + <WrapPanel Orientation="Horizontal" MaxWidth="700" Margin="0" HorizontalAlignment="Center" /> </ItemsPanelTemplate> </ListBox.ItemsPanel> <ListBox.ItemTemplate> @@ -45,9 +44,9 @@ <StackPanel Grid.Row="3" Orientation="Horizontal" Spacing="10" Margin="10" HorizontalAlignment="Center"> <Button Content="{Locale:Locale AvatarChoose}" Width="200" Name="ChooseButton" Click="ChooseButton_OnClick" /> <ui:ColorPickerButton Color="{Binding BackgroundColor, Mode=TwoWay}" Name="ColorButton" /> - <Button HorizontalAlignment="Right" Content="{Locale:Locale AvatarClose}" Click="CloseButton_OnClick" + <Button HorizontalAlignment="Right" Content="{Locale:Locale Discard}" Click="CloseButton_OnClick" Name="CloseButton" Width="200" /> </StackPanel> </Grid> -</Window>
\ No newline at end of file +</UserControl>
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Windows/AvatarWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/AvatarWindow.axaml.cs index 25e89846..2189f47d 100644 --- a/Ryujinx.Ava/Ui/Windows/AvatarWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/AvatarWindow.axaml.cs @@ -1,70 +1,76 @@ -using Avalonia; +using Avalonia.Controls; using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; -using Ryujinx.Ava.Common.Locale; +using FluentAvalonia.UI.Controls; +using FluentAvalonia.UI.Navigation; +using Ryujinx.Ava.Ui.Controls; +using Ryujinx.Ava.Ui.Models; using Ryujinx.Ava.Ui.ViewModels; using Ryujinx.HLE.FileSystem; -using System; namespace Ryujinx.Ava.Ui.Windows { - public class AvatarWindow : StyleableWindow + public partial class AvatarWindow : UserControl { + private NavigationDialogHost _parent; + private TempProfile _profile; + public AvatarWindow(ContentManager contentManager) { ContentManager = contentManager; - ViewModel = new AvatarProfileViewModel(() => ViewModel.ReloadImages()); DataContext = ViewModel; InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif - Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance["AvatarWindowTitle"]; } public AvatarWindow() { InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif + + AddHandler(Frame.NavigatedToEvent, (s, e) => + { + NavigatedTo(e); + }, RoutingStrategies.Direct); + } + + private void NavigatedTo(NavigationEventArgs arg) + { if (Program.PreviewerDetached) { - Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance["AvatarWindowTitle"]; + if (arg.NavigationMode == NavigationMode.New) + { + (_parent, _profile) = ((NavigationDialogHost, TempProfile))arg.Parameter; + ContentManager = _parent.ContentManager; + if (Program.PreviewerDetached) + { + ViewModel = new AvatarProfileViewModel(() => ViewModel.ReloadImages()); + } + + DataContext = ViewModel; + } } } - public ContentManager ContentManager { get; } - - public byte[] SelectedImage { get; set; } + public ContentManager ContentManager { get; private set; } internal AvatarProfileViewModel ViewModel { get; set; } - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - - protected override void OnClosed(EventArgs e) + private void CloseButton_OnClick(object sender, RoutedEventArgs e) { ViewModel.Dispose(); - base.OnClosed(e); - } - private void CloseButton_OnClick(object sender, RoutedEventArgs e) - { - Close(); + _parent.GoBack(); } private void ChooseButton_OnClick(object sender, RoutedEventArgs e) { if (ViewModel.SelectedIndex > -1) { - SelectedImage = ViewModel.SelectedImage; + _profile.Image = ViewModel.SelectedImage; + + ViewModel.Dispose(); - Close(); + _parent.GoBack(); } } } diff --git a/Ryujinx.Ava/Ui/Windows/CheatWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/CheatWindow.axaml.cs index 33abeb8d..e3cccdd3 100644 --- a/Ryujinx.Ava/Ui/Windows/CheatWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/CheatWindow.axaml.cs @@ -12,7 +12,7 @@ using System.Linq; namespace Ryujinx.Ava.Ui.Windows { - public class CheatWindow : StyleableWindow + public partial class CheatWindow : StyleableWindow { private readonly string _enabledCheatsPath; public bool NoCheatsFound { get; } @@ -102,11 +102,6 @@ namespace Ryujinx.Ava.Ui.Windows this.AttachDevTools(); } - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - } - public void Save() { if (NoCheatsFound) diff --git a/Ryujinx.Ava/Ui/Windows/ControllerSettingsWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/ControllerSettingsWindow.axaml.cs index 03213599..45262bcd 100644 --- a/Ryujinx.Ava/Ui/Windows/ControllerSettingsWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/ControllerSettingsWindow.axaml.cs @@ -24,11 +24,10 @@ using Key = Ryujinx.Input.Key; namespace Ryujinx.Ava.Ui.Windows { - public class ControllerSettingsWindow : UserControl + public partial class ControllerSettingsWindow : UserControl { private bool _dialogOpen; - public Grid SettingButtons { get; set; } private ButtonKeyAssigner _currentAssigner; internal ControllerSettingsViewModel ViewModel { get; set; } @@ -48,13 +47,6 @@ namespace Ryujinx.Ava.Ui.Windows } } - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - - SettingButtons = this.FindControl<Grid>("SettingButtons"); - } - protected override void OnPointerReleased(PointerReleasedEventArgs e) { base.OnPointerReleased(e); @@ -165,7 +157,6 @@ namespace Ryujinx.Ava.Ui.Windows _dialogOpen = true; var result = await ContentDialogHelper.CreateConfirmationDialog( - this.GetVisualRoot() as StyleableWindow, LocaleManager.Instance["DialogControllerSettingsModifiedConfirmMessage"], LocaleManager.Instance["DialogControllerSettingsModifiedConfirmSubMessage"], LocaleManager.Instance["InputDialogYes"], diff --git a/Ryujinx.Ava/Ui/Windows/DlcManagerWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/DlcManagerWindow.axaml.cs index 7450c64f..09b221e3 100644 --- a/Ryujinx.Ava/Ui/Windows/DlcManagerWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/DlcManagerWindow.axaml.cs @@ -1,7 +1,6 @@ using Avalonia; using Avalonia.Collections; using Avalonia.Controls; -using Avalonia.Markup.Xaml; using Avalonia.Threading; using LibHac.Common; using LibHac.Fs; @@ -27,7 +26,7 @@ using Path = System.IO.Path; namespace Ryujinx.Ava.Ui.Windows { - public class DlcManagerWindow : StyleableWindow + public partial class DlcManagerWindow : StyleableWindow { private readonly List<DlcContainer> _dlcContainerList; private readonly string _dlcJsonPath; @@ -35,7 +34,6 @@ namespace Ryujinx.Ava.Ui.Windows public VirtualFileSystem VirtualFileSystem { get; } public AvaloniaList<DlcModel> Dlcs { get; set; } - public Grid DlcGrid { get; private set; } public ulong TitleId { get; } public string TitleName { get; } @@ -47,7 +45,7 @@ namespace Ryujinx.Ava.Ui.Windows InitializeComponent(); AttachDebugDevTools(); - + Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance["DlcWindowTitle"]; } @@ -72,7 +70,7 @@ namespace Ryujinx.Ava.Ui.Windows InitializeComponent(); AttachDebugDevTools(); - + Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance["DlcWindowTitle"]; LoadDlcs(); @@ -84,15 +82,6 @@ namespace Ryujinx.Ava.Ui.Windows this.AttachDevTools(); } - private void InitializeComponent() - { - Dlcs = new AvaloniaList<DlcModel>(); - - AvaloniaXamlLoader.Load(this); - - DlcGrid = this.FindControl<Grid>("DlcGrid"); - } - private void LoadDlcs() { foreach (DlcContainer dlcContainer in _dlcContainerList) @@ -129,8 +118,7 @@ namespace Ryujinx.Ava.Ui.Windows { Dispatcher.UIThread.InvokeAsync(async () => { - await ContentDialogHelper.CreateErrorDialog(this, - string.Format(LocaleManager.Instance[ + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance[ "DialogDlcLoadNcaErrorMessage"], ex.Message, containerPath)); }); } @@ -180,7 +168,7 @@ namespace Ryujinx.Ava.Ui.Windows if (!containsDlc) { - await ContentDialogHelper.CreateErrorDialog(this, LocaleManager.Instance["DialogDlcNoDlcErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogDlcNoDlcErrorMessage"]); } } } @@ -189,7 +177,7 @@ namespace Ryujinx.Ava.Ui.Windows { if (removeSelectedOnly) { - Dlcs.RemoveAll(Dlcs.Where(x => x.IsEnabled).ToList()); + Dlcs.RemoveAll(Dlcs.Where(x => x.IsEnabled).ToList()); } else { diff --git a/Ryujinx.Ava/Ui/Windows/MainWindow.axaml b/Ryujinx.Ava/Ui/Windows/MainWindow.axaml index f79b4f79..f02cd001 100644 --- a/Ryujinx.Ava/Ui/Windows/MainWindow.axaml +++ b/Ryujinx.Ava/Ui/Windows/MainWindow.axaml @@ -38,18 +38,6 @@ <RowDefinition Height="*" /> </Grid.RowDefinitions> <controls:OffscreenTextBox Name="HiddenTextBox" Grid.Row="0" /> - <ContentControl - Grid.Row="1" - Focusable="False" - IsVisible="False" - KeyboardNavigation.IsTabStop="False"> - <ui:ContentDialog - Name="ContentDialog" - IsPrimaryButtonEnabled="True" - IsSecondaryButtonEnabled="True" - IsVisible="True" - KeyboardNavigation.IsTabStop="False" /> - </ContentControl> <StackPanel Grid.Row="0" IsVisible="False"> <controls:HotKeyControl Name="FullscreenHotKey" Command="{ReflectionBinding ToggleFullscreen}" /> <controls:HotKeyControl Name="FullscreenHotKey2" Command="{ReflectionBinding ToggleFullscreen}" /> diff --git a/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs index 2b5c10e2..d55dd413 100644 --- a/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/MainWindow.axaml.cs @@ -36,7 +36,7 @@ using InputManager = Ryujinx.Input.HLE.InputManager; using ProgressBar = Avalonia.Controls.ProgressBar; namespace Ryujinx.Ava.Ui.Windows { - public class MainWindow : StyleableWindow + public partial class MainWindow : StyleableWindow { private bool _canUpdate; private bool _isClosing; @@ -62,22 +62,6 @@ namespace Ryujinx.Ava.Ui.Windows public InputManager InputManager { get; private set; } internal RendererControl GlRenderer { get; private set; } - public ContentControl ContentFrame { get; private set; } - public TextBlock LoadStatus { get; private set; } - public TextBlock FirmwareStatus { get; private set; } - public TextBox SearchBox { get; private set; } - public ProgressBar LoadProgressBar { get; private set; } - public Menu Menu { get; private set; } - public MenuItem UpdateMenuItem { get; private set; } - public MenuItem ActionsMenuItem { get; private set; } - public GameGridView GameGrid { get; private set; } - public GameListView GameList { get; private set; } - public OffscreenTextBox HiddenTextBox { get; private set; } - public HotKeyControl FullscreenHotKey { get; private set; } - public HotKeyControl FullscreenHotKey2 { get; private set; } - public HotKeyControl DockToggleHotKey { get; private set; } - public HotKeyControl ExitHotKey { get; private set; } - public ToggleSplitButton VolumeStatus { get; set; } internal MainWindowViewModel ViewModel { get; private set; } public SettingsWindow SettingsWindow { get; set; } @@ -102,6 +86,7 @@ namespace Ryujinx.Ava.Ui.Windows DataContext = ViewModel; InitializeComponent(); + Load(); AttachDebugDevTools(); UiHandler = new AvaHostUiHandler(this); @@ -192,7 +177,9 @@ namespace Ryujinx.Ava.Ui.Windows string mainMessage = LocaleManager.Instance["DialogPerformanceCheckLoggingEnabledMessage"]; string secondaryMessage = LocaleManager.Instance["DialogPerformanceCheckLoggingEnabledConfirmMessage"]; - UserResult result = await ContentDialogHelper.CreateConfirmationDialog(this, mainMessage, secondaryMessage, LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], LocaleManager.Instance["RyujinxConfirm"]); + UserResult result = await ContentDialogHelper.CreateConfirmationDialog(mainMessage, secondaryMessage, + LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], + LocaleManager.Instance["RyujinxConfirm"]); if (result != UserResult.Yes) { @@ -205,9 +192,12 @@ namespace Ryujinx.Ava.Ui.Windows if (!string.IsNullOrWhiteSpace(ConfigurationState.Instance.Graphics.ShadersDumpPath.Value)) { string mainMessage = LocaleManager.Instance["DialogPerformanceCheckShaderDumpEnabledMessage"]; - string secondaryMessage = LocaleManager.Instance["DialogPerformanceCheckShaderDumpEnabledConfirmMessage"]; + string secondaryMessage = + LocaleManager.Instance["DialogPerformanceCheckShaderDumpEnabledConfirmMessage"]; - UserResult result = await ContentDialogHelper.CreateConfirmationDialog(this, mainMessage, secondaryMessage, LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], LocaleManager.Instance["RyujinxConfirm"]); + UserResult result = await ContentDialogHelper.CreateConfirmationDialog(mainMessage, secondaryMessage, + LocaleManager.Instance["InputDialogYes"], LocaleManager.Instance["InputDialogNo"], + LocaleManager.Instance["RyujinxConfirm"]); if (result != UserResult.Yes) { @@ -231,7 +221,7 @@ namespace Ryujinx.Ava.Ui.Windows { if (AppHost != null) { - await ContentDialogHelper.CreateInfoDialog(this, + await ContentDialogHelper.CreateInfoDialog( LocaleManager.Instance["DialogLoadAppGameAlreadyLoadedMessage"], LocaleManager.Instance["DialogLoadAppGameAlreadyLoadedSubMessage"], LocaleManager.Instance["InputDialogOk"], @@ -254,7 +244,7 @@ namespace Ryujinx.Ava.Ui.Windows PrepareLoadScreen(); - _mainViewContent = ContentFrame.Content as Control; + _mainViewContent = Content.Content as Control; GlRenderer = new RendererControl(3, 3, ConfigurationState.Instance.Logger.GraphicsDebugLevel); AppHost = new AppHost(GlRenderer, InputManager, path, VirtualFileSystem, ContentManager, AccountManager, _userChannelPersistence, this); @@ -321,7 +311,7 @@ namespace Ryujinx.Ava.Ui.Windows Dispatcher.UIThread.InvokeAsync(() => { - ContentFrame.Content = GlRenderer; + Content.Content = GlRenderer; if (startFullscreen && WindowState != WindowState.FullScreen) { @@ -365,9 +355,9 @@ namespace Ryujinx.Ava.Ui.Windows Dispatcher.UIThread.InvokeAsync(() => { - if (ContentFrame.Content != _mainViewContent) + if (Content.Content != _mainViewContent) { - ContentFrame.Content = _mainViewContent; + Content.Content = _mainViewContent; } ViewModel.ShowMenuAndStatusBar = true; @@ -501,27 +491,8 @@ namespace Ryujinx.Ava.Ui.Windows ViewModel.IsAppletMenuActive = hasApplet; } - private void InitializeComponent() + private void Load() { - AvaloniaXamlLoader.Load(this); - - ContentFrame = this.FindControl<ContentControl>("Content"); - GameList = this.FindControl<GameListView>("GameList"); - LoadStatus = this.FindControl<TextBlock>("LoadStatus"); - FirmwareStatus = this.FindControl<TextBlock>("FirmwareStatus"); - LoadProgressBar = this.FindControl<ProgressBar>("LoadProgressBar"); - SearchBox = this.FindControl<TextBox>("SearchBox"); - Menu = this.FindControl<Menu>("Menu"); - UpdateMenuItem = this.FindControl<MenuItem>("UpdateMenuItem"); - GameGrid = this.FindControl<GameGridView>("GameGrid"); - HiddenTextBox = this.FindControl<OffscreenTextBox>("HiddenTextBox"); - FullscreenHotKey = this.FindControl<HotKeyControl>("FullscreenHotKey"); - FullscreenHotKey2 = this.FindControl<HotKeyControl>("FullscreenHotKey2"); - DockToggleHotKey = this.FindControl<HotKeyControl>("DockToggleHotKey"); - ExitHotKey = this.FindControl<HotKeyControl>("ExitHotKey"); - VolumeStatus = this.FindControl<ToggleSplitButton>("VolumeStatus"); - ActionsMenuItem = this.FindControl<MenuItem>("ActionsMenuItem"); - VolumeStatus.Click += VolumeStatus_CheckedChanged; GameGrid.ApplicationOpened += Application_Opened; @@ -710,7 +681,7 @@ namespace Ryujinx.Ava.Ui.Windows { Dispatcher.UIThread.InvokeAsync(async () => { - _isClosing = await ContentDialogHelper.CreateExitDialog(this); + _isClosing = await ContentDialogHelper.CreateExitDialog(); if (_isClosing) { diff --git a/Ryujinx.Ava/Ui/Windows/MotionSettingsWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/MotionSettingsWindow.axaml.cs index ce513b4b..ec919530 100644 --- a/Ryujinx.Ava/Ui/Windows/MotionSettingsWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/MotionSettingsWindow.axaml.cs @@ -9,13 +9,14 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.Ui.Windows { - public class MotionSettingsWindow : UserControl + public partial class MotionSettingsWindow : UserControl { private readonly InputConfiguration<GamepadInputId, StickInputId> _viewmodel; public MotionSettingsWindow() { InitializeComponent(); + DataContext = _viewmodel; } public MotionSettingsWindow(ControllerSettingsViewModel viewmodel) @@ -36,46 +37,36 @@ namespace Ryujinx.Ava.Ui.Windows }; InitializeComponent(); - } - - private void InitializeComponent() - { DataContext = _viewmodel; - - AvaloniaXamlLoader.Load(this); } - public static async Task Show(ControllerSettingsViewModel viewmodel, StyleableWindow window) + public static async Task Show(ControllerSettingsViewModel viewmodel) { - ContentDialog contentDialog = window.ContentDialog; - - string name = string.Empty; - MotionSettingsWindow content = new MotionSettingsWindow(viewmodel); - if (contentDialog != null) + ContentDialog contentDialog = new ContentDialog { - contentDialog.Title = LocaleManager.Instance["ControllerMotionTitle"]; - contentDialog.PrimaryButtonText = LocaleManager.Instance["ControllerSettingsSave"]; - contentDialog.SecondaryButtonText = ""; - contentDialog.CloseButtonText = LocaleManager.Instance["ControllerSettingsClose"]; - contentDialog.Content = content; - contentDialog.PrimaryButtonClick += (sender, args) => - { - var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>; - config.Slot = content._viewmodel.Slot; - config.EnableMotion = content._viewmodel.EnableMotion; - config.Sensitivity = content._viewmodel.Sensitivity; - config.GyroDeadzone = content._viewmodel.GyroDeadzone; - config.AltSlot = content._viewmodel.AltSlot; - config.DsuServerHost = content._viewmodel.DsuServerHost; - config.DsuServerPort = content._viewmodel.DsuServerPort; - config.EnableCemuHookMotion = content._viewmodel.EnableCemuHookMotion; - config.MirrorInput = content._viewmodel.MirrorInput; - }; + Title = LocaleManager.Instance["ControllerMotionTitle"], + PrimaryButtonText = LocaleManager.Instance["ControllerSettingsSave"], + SecondaryButtonText = "", + CloseButtonText = LocaleManager.Instance["ControllerSettingsClose"], + Content = content + }; + contentDialog.PrimaryButtonClick += (sender, args) => + { + var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>; + config.Slot = content._viewmodel.Slot; + config.EnableMotion = content._viewmodel.EnableMotion; + config.Sensitivity = content._viewmodel.Sensitivity; + config.GyroDeadzone = content._viewmodel.GyroDeadzone; + config.AltSlot = content._viewmodel.AltSlot; + config.DsuServerHost = content._viewmodel.DsuServerHost; + config.DsuServerPort = content._viewmodel.DsuServerPort; + config.EnableCemuHookMotion = content._viewmodel.EnableCemuHookMotion; + config.MirrorInput = content._viewmodel.MirrorInput; + }; - await contentDialog.ShowAsync(); - } + await contentDialog.ShowAsync(); } } }
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Windows/RumbleSettingsWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/RumbleSettingsWindow.axaml.cs index 6c25423b..bc8b04e4 100644 --- a/Ryujinx.Ava/Ui/Windows/RumbleSettingsWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/RumbleSettingsWindow.axaml.cs @@ -9,13 +9,14 @@ using System.Threading.Tasks; namespace Ryujinx.Ava.Ui.Windows { - public class RumbleSettingsWindow : UserControl + public partial class RumbleSettingsWindow : UserControl { private readonly InputConfiguration<GamepadInputId, StickInputId> _viewmodel; public RumbleSettingsWindow() { InitializeComponent(); + DataContext = _viewmodel; } public RumbleSettingsWindow(ControllerSettingsViewModel viewmodel) @@ -24,44 +25,34 @@ namespace Ryujinx.Ava.Ui.Windows _viewmodel = new InputConfiguration<GamepadInputId, StickInputId>() { - StrongRumble = config.StrongRumble, - WeakRumble = config.WeakRumble + StrongRumble = config.StrongRumble, WeakRumble = config.WeakRumble }; InitializeComponent(); - } - - private void InitializeComponent() - { DataContext = _viewmodel; - - AvaloniaXamlLoader.Load(this); } - public static async Task Show(ControllerSettingsViewModel viewmodel, StyleableWindow window) + public static async Task Show(ControllerSettingsViewModel viewmodel) { - ContentDialog contentDialog = window.ContentDialog; - - string name = string.Empty; - RumbleSettingsWindow content = new RumbleSettingsWindow(viewmodel); - if (contentDialog != null) + ContentDialog contentDialog = new ContentDialog { - contentDialog.Title = LocaleManager.Instance["ControllerRumbleTitle"]; - contentDialog.PrimaryButtonText = LocaleManager.Instance["ControllerSettingsSave"]; - contentDialog.SecondaryButtonText = ""; - contentDialog.CloseButtonText = LocaleManager.Instance["ControllerSettingsClose"]; - contentDialog.Content = content; - contentDialog.PrimaryButtonClick += (sender, args) => - { - var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>; - config.StrongRumble = content._viewmodel.StrongRumble; - config.WeakRumble = content._viewmodel.WeakRumble; - }; - - await contentDialog.ShowAsync(); - } + Title = LocaleManager.Instance["ControllerRumbleTitle"], + PrimaryButtonText = LocaleManager.Instance["ControllerSettingsSave"], + SecondaryButtonText = "", + CloseButtonText = LocaleManager.Instance["ControllerSettingsClose"], + Content = content, + }; + + contentDialog.PrimaryButtonClick += (sender, args) => + { + var config = viewmodel.Configuration as InputConfiguration<GamepadInputId, StickInputId>; + config.StrongRumble = content._viewmodel.StrongRumble; + config.WeakRumble = content._viewmodel.WeakRumble; + }; + + await contentDialog.ShowAsync(); } } }
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml b/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml index fe04302f..493d6798 100644 --- a/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml +++ b/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml @@ -31,16 +31,11 @@ <RowDefinition /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> - <ContentControl + <ContentPresenter + x:Name="ContentPresenter" Grid.Row="1" - Focusable="False" IsVisible="False" - KeyboardNavigation.IsTabStop="False"> - <ui:ContentDialog Name="ContentDialog" - IsPrimaryButtonEnabled="True" - IsSecondaryButtonEnabled="True" - IsVisible="False" /> - </ContentControl> + KeyboardNavigation.IsTabStop="False"/> <Grid Name="Pages" IsVisible="False" Grid.Row="2"> <ScrollViewer Name="UiPage" Margin="0,0,10,0" diff --git a/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml.cs index 654281fe..371d6b64 100644 --- a/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/SettingsWindow.axaml.cs @@ -1,5 +1,6 @@ using Avalonia; using Avalonia.Controls; +using Avalonia.Controls.Presenters; using Avalonia.Controls.Primitives; using Avalonia.Data; using Avalonia.Data.Converters; @@ -28,24 +29,8 @@ using TimeZone = Ryujinx.Ava.Ui.Models.TimeZone; namespace Ryujinx.Ava.Ui.Windows { - public class SettingsWindow : StyleableWindow + public partial class SettingsWindow : StyleableWindow { - private ListBox _gameList; - private TextBox _pathBox; - private AutoCompleteBox _timeZoneBox; - private ControllerSettingsWindow _controllerSettings; - - // Pages - private Control _uiPage; - private Control _inputPage; - private Control _hotkeysPage; - private Control _systemPage; - private Control _cpuPage; - private Control _graphicsPage; - private Control _audioPage; - private Control _networkPage; - private Control _loggingPage; - private NavigationView _navPanel; private ButtonKeyAssigner _currentAssigner; internal SettingsViewModel ViewModel { get; set; } @@ -58,6 +43,7 @@ namespace Ryujinx.Ava.Ui.Windows DataContext = ViewModel; InitializeComponent(); + Load(); AttachDebugDevTools(); FuncMultiValueConverter<string, string> converter = new(parts => string.Format("{0} {1} {2}", parts.ToArray())); @@ -66,7 +52,7 @@ namespace Ryujinx.Ava.Ui.Windows tzMultiBinding.Bindings.Add(new Binding("Location")); tzMultiBinding.Bindings.Add(new Binding("Abbreviation")); - _timeZoneBox.ValueMemberBinding = tzMultiBinding; + TimeZoneBox.ValueMemberBinding = tzMultiBinding; } public SettingsWindow() @@ -75,6 +61,7 @@ namespace Ryujinx.Ava.Ui.Windows DataContext = ViewModel; InitializeComponent(); + Load(); AttachDebugDevTools(); } @@ -84,31 +71,11 @@ namespace Ryujinx.Ava.Ui.Windows this.AttachDevTools(); } - private void InitializeComponent() + private void Load() { - AvaloniaXamlLoader.Load(this); - - _pathBox = this.FindControl<TextBox>("PathBox"); - _gameList = this.FindControl<ListBox>("GameList"); - _timeZoneBox = this.FindControl<AutoCompleteBox>("TimeZoneBox"); - _controllerSettings = this.FindControl<ControllerSettingsWindow>("ControllerSettings"); - - _uiPage = this.FindControl<Control>("UiPage"); - _inputPage = this.FindControl<Control>("InputPage"); - _hotkeysPage = this.FindControl<Control>("HotkeysPage"); - _systemPage = this.FindControl<Control>("SystemPage"); - _cpuPage = this.FindControl<Control>("CpuPage"); - _graphicsPage = this.FindControl<Control>("GraphicsPage"); - _audioPage = this.FindControl<Control>("AudioPage"); - _networkPage = this.FindControl<Control>("NetworkPage"); - _loggingPage = this.FindControl<Control>("LoggingPage"); - - var pageGrid = this.FindControl<Grid>("Pages"); - pageGrid.Children.Clear(); - - _navPanel = this.FindControl<NavigationView>("NavPanel"); - _navPanel.SelectionChanged += NavPanelOnSelectionChanged; - _navPanel.SelectedItem = _navPanel.MenuItems.ElementAt(0); + Pages.Children.Clear(); + NavPanel.SelectionChanged += NavPanelOnSelectionChanged; + NavPanel.SelectedItem = NavPanel.MenuItems.ElementAt(0); } private void Button_Checked(object sender, RoutedEventArgs e) @@ -174,31 +141,31 @@ namespace Ryujinx.Ava.Ui.Windows switch (navitem.Tag.ToString()) { case "UiPage": - _navPanel.Content = _uiPage; + NavPanel.Content = UiPage; break; case "InputPage": - _navPanel.Content = _inputPage; + NavPanel.Content = InputPage; break; case "HotkeysPage": - _navPanel.Content = _hotkeysPage; + NavPanel.Content = HotkeysPage; break; case "SystemPage": - _navPanel.Content = _systemPage; + NavPanel.Content = SystemPage; break; case "CpuPage": - _navPanel.Content = _cpuPage; + NavPanel.Content = CpuPage; break; case "GraphicsPage": - _navPanel.Content = _graphicsPage; + NavPanel.Content = GraphicsPage; break; case "AudioPage": - _navPanel.Content = _audioPage; + NavPanel.Content = AudioPage; break; case "NetworkPage": - _navPanel.Content = _networkPage; + NavPanel.Content = NetworkPage; break; case "LoggingPage": - _navPanel.Content = _loggingPage; + NavPanel.Content = LoggingPage; break; } } @@ -206,7 +173,7 @@ namespace Ryujinx.Ava.Ui.Windows private async void AddButton_OnClick(object sender, RoutedEventArgs e) { - string path = _pathBox.Text; + string path = PathBox.Text; if (!string.IsNullOrWhiteSpace(path) && Directory.Exists(path) && !ViewModel.GameDirectories.Contains(path)) { @@ -225,7 +192,7 @@ namespace Ryujinx.Ava.Ui.Windows private void RemoveButton_OnClick(object sender, RoutedEventArgs e) { - List<string> selected = new(_gameList.SelectedItems.Cast<string>()); + List<string> selected = new(GameList.SelectedItems.Cast<string>()); foreach (string path in selected) { @@ -279,7 +246,7 @@ namespace Ryujinx.Ava.Ui.Windows { ViewModel.SaveSettings(); - _controllerSettings?.SaveCurrentProfile(); + ControllerSettings?.SaveCurrentProfile(); if (Owner is MainWindow window) { @@ -289,7 +256,7 @@ namespace Ryujinx.Ava.Ui.Windows protected override void OnClosed(EventArgs e) { - _controllerSettings.Dispose(); + ControllerSettings.Dispose(); _currentAssigner?.Cancel(); _currentAssigner = null; base.OnClosed(e); diff --git a/Ryujinx.Ava/Ui/Windows/StyleableWindow.cs b/Ryujinx.Ava/Ui/Windows/StyleableWindow.cs index e268cac1..f427adc3 100644 --- a/Ryujinx.Ava/Ui/Windows/StyleableWindow.cs +++ b/Ryujinx.Ava/Ui/Windows/StyleableWindow.cs @@ -11,7 +11,6 @@ namespace Ryujinx.Ava.Ui.Windows { public class StyleableWindow : Window { - public ContentDialog ContentDialog { get; private set; } public IBitmap IconImage { get; set; } public StyleableWindow() @@ -26,15 +25,9 @@ namespace Ryujinx.Ava.Ui.Windows IconImage = new Bitmap(stream); } - public void LoadDialog() - { - ContentDialog = this.FindControl<ContentDialog>("ContentDialog"); - } - protected override void OnOpened(EventArgs e) { base.OnOpened(e); - ContentDialog = this.FindControl<ContentDialog>("ContentDialog"); } protected override void OnApplyTemplate(TemplateAppliedEventArgs e) diff --git a/Ryujinx.Ava/Ui/Windows/TitleUpdateWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/TitleUpdateWindow.axaml.cs index e465dc6e..4e26ee73 100644 --- a/Ryujinx.Ava/Ui/Windows/TitleUpdateWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/TitleUpdateWindow.axaml.cs @@ -28,14 +28,14 @@ using Avalonia.Threading; namespace Ryujinx.Ava.Ui.Windows { - public class TitleUpdateWindow : StyleableWindow + public partial class TitleUpdateWindow : StyleableWindow { private readonly string _updateJsonPath; private TitleUpdateMetadata _titleUpdateWindowData; public VirtualFileSystem VirtualFileSystem { get; } - internal AvaloniaList<TitleUpdateModel> TitleUpdates { get; set; } + internal AvaloniaList<TitleUpdateModel> TitleUpdates { get; set; } = new AvaloniaList<TitleUpdateModel>(); public string TitleId { get; } public string TitleName { get; } @@ -84,13 +84,6 @@ namespace Ryujinx.Ava.Ui.Windows this.AttachDevTools(); } - private void InitializeComponent() - { - TitleUpdates = new AvaloniaList<TitleUpdateModel>(); - - AvaloniaXamlLoader.Load(this); - } - private void LoadUpdates() { TitleUpdates.Add(new TitleUpdateModel(default, string.Empty, true)); @@ -154,8 +147,7 @@ namespace Ryujinx.Ava.Ui.Windows { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(this, - LocaleManager.Instance["DialogUpdateAddUpdateErrorMessage"]); + await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance["DialogUpdateAddUpdateErrorMessage"]); }); } } @@ -163,8 +155,7 @@ namespace Ryujinx.Ava.Ui.Windows { Dispatcher.UIThread.Post(async () => { - await ContentDialogHelper.CreateErrorDialog(this, - string.Format(LocaleManager.Instance["DialogDlcLoadNcaErrorMessage"], ex.Message, path)); + await ContentDialogHelper.CreateErrorDialog(string.Format(LocaleManager.Instance["DialogDlcLoadNcaErrorMessage"], ex.Message, path)); }); } } diff --git a/Ryujinx.Ava/Ui/Windows/UpdaterWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/UpdaterWindow.axaml.cs index ed217fe3..ff947477 100644 --- a/Ryujinx.Ava/Ui/Windows/UpdaterWindow.axaml.cs +++ b/Ryujinx.Ava/Ui/Windows/UpdaterWindow.axaml.cs @@ -11,7 +11,7 @@ using System.Runtime.InteropServices; namespace Ryujinx.Ava.Ui.Windows { - public class UpdaterWindow : StyleableWindow + public partial class UpdaterWindow : StyleableWindow { private readonly string _buildUrl; private readonly MainWindow _mainWindow; @@ -36,21 +36,6 @@ namespace Ryujinx.Ava.Ui.Windows _buildUrl = buildUrl; } - public TextBlock MainText { get; set; } - public TextBlock SecondaryText { get; set; } - public ProgressBar ProgressBar { get; set; } - public StackPanel ButtonBox { get; set; } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - - MainText = this.FindControl<TextBlock>("MainText"); - SecondaryText = this.FindControl<TextBlock>("SecondaryText"); - ProgressBar = this.FindControl<ProgressBar>("ProgressBar"); - ButtonBox = this.FindControl<StackPanel>("ButtonBox"); - } - [DllImport("libc", SetLastError = true)] private static extern int chmod(string path, uint mode); diff --git a/Ryujinx.Ava/Ui/Windows/UserProfileWindow.axaml b/Ryujinx.Ava/Ui/Windows/UserProfileWindow.axaml deleted file mode 100644 index 4b004206..00000000 --- a/Ryujinx.Ava/Ui/Windows/UserProfileWindow.axaml +++ /dev/null @@ -1,107 +0,0 @@ -<window:StyleableWindow xmlns="https://github.com/avaloniaui" - xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" - xmlns:d="http://schemas.microsoft.com/expression/blend/2008" - xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" - xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="350" - x:Class="Ryujinx.Ava.Ui.Windows.UserProfileWindow" - xmlns:Locale="clr-namespace:Ryujinx.Ava.Common.Locale" - xmlns:viewModels="clr-namespace:Ryujinx.Ava.Ui.ViewModels" - xmlns:controls="clr-namespace:Ryujinx.Ava.Ui.Controls" - xmlns:window="clr-namespace:Ryujinx.Ava.Ui.Windows" - CanResize="False" - Width="850" MinHeight="550" Height="550" - WindowStartupLocation="CenterOwner" - SizeToContent="Manual" - MinWidth="600"> - <Design.DataContext> - <viewModels:UserProfileViewModel /> - </Design.DataContext> - <Window.Resources> - <controls:BitmapArrayValueConverter x:Key="ByteImage" /> - </Window.Resources> - <Grid Margin="15" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition Height="Auto" /> - <RowDefinition /> - <RowDefinition Height="Auto" /> - </Grid.RowDefinitions> - <Grid Grid.Row="1"> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition /> - </Grid.RowDefinitions> - <ContentControl - Focusable="False" - IsVisible="False" - KeyboardNavigation.IsTabStop="False"> - <ui:ContentDialog Name="ContentDialog" - IsPrimaryButtonEnabled="True" - IsSecondaryButtonEnabled="True" - IsVisible="False" /> - </ContentControl> - <TextBlock Text="{Locale:Locale UserProfilesSelectedUserProfile}" /> - <Grid Grid.Row="1" Margin="10"> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition /> - <ColumnDefinition Width="Auto" /> - </Grid.ColumnDefinitions> - <Image Height="96" Width="96" - Source="{Binding SelectedProfile.Image, Converter={StaticResource ByteImage}}" /> - <StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Grid.Column="1" Spacing="10" - Margin="5, 10"> - <TextBox Name="NameBox" Text="{Binding SelectedProfile.Name, Mode=OneWay}" - HorizontalAlignment="Stretch" /> - <TextBlock Text="{Binding SelectedProfile.UserId}" /> - </StackPanel> - <StackPanel Orientation="Vertical" HorizontalAlignment="Stretch" Grid.Column="2" Spacing="10" - Margin="5"> - <Button Content="{Locale:Locale UserProfilesSaveProfileName}" Name="SetNameButton" - Click="SetNameButton_OnClick" /> - <Button Name="SelectProfileImage" Command="{Binding ChooseProfileImage}" - Content="{Locale:Locale UserProfilesChangeProfileImage}" /> - </StackPanel> - </Grid> - </Grid> - <Grid Grid.Row="2"> - <Grid.RowDefinitions> - <RowDefinition Height="Auto" /> - <RowDefinition /> - </Grid.RowDefinitions> - <TextBlock Text="{Locale:Locale UserProfilesAvailableUserProfiles}" /> - <ListBox Grid.Row="1" Margin="10" Name="ProfilesList" DoubleTapped="ProfilesList_DoubleTapped" - Items="{Binding Profiles}"> - <ListBox.ItemTemplate> - <DataTemplate> - <Grid HorizontalAlignment="Stretch"> - <Grid.ColumnDefinitions> - <ColumnDefinition Width="Auto" /> - <ColumnDefinition /> - </Grid.ColumnDefinitions> - <Grid Grid.Column="0" Background="{DynamicResource ThemeAccentColorBrush}" - Grid.ColumnSpan="2" - HorizontalAlignment="Stretch" VerticalAlignment="Stretch" MinHeight="5" MinWidth="5" - IsVisible="{Binding IsOpened}" /> - <Image Grid.Column="0" Height="96" Width="96" - Source="{Binding Image, Converter={StaticResource ByteImage}}" /> - <StackPanel Margin="10" Orientation="Vertical" HorizontalAlignment="Stretch" - VerticalAlignment="Center" Grid.Column="1"> - <TextBlock Text="{Binding Name}" /> - <TextBlock Text="{Binding UserId}" /> - </StackPanel> - </Grid> - </DataTemplate> - </ListBox.ItemTemplate> - </ListBox> - </Grid> - <StackPanel Grid.Row="3" Orientation="Horizontal" Margin="10,0" Spacing="10" HorizontalAlignment="Stretch"> - <Button Content="{Locale:Locale UserProfilesAddNewProfile}" Command="{Binding AddUser}" /> - <Button IsEnabled="{Binding IsSelectedProfileDeletable}" - Content="{Locale:Locale UserProfilesDeleteSelectedProfile}" Command="{Binding DeleteUser}" /> - <Button HorizontalAlignment="Right" Content="{Locale:Locale UserProfilesClose}" Click="CloseButton_OnClick" - Name="CloseButton" /> - </StackPanel> - </Grid> -</window:StyleableWindow>
\ No newline at end of file diff --git a/Ryujinx.Ava/Ui/Windows/UserProfileWindow.axaml.cs b/Ryujinx.Ava/Ui/Windows/UserProfileWindow.axaml.cs deleted file mode 100644 index e78e0384..00000000 --- a/Ryujinx.Ava/Ui/Windows/UserProfileWindow.axaml.cs +++ /dev/null @@ -1,102 +0,0 @@ -using Avalonia; -using Avalonia.Controls; -using Avalonia.Interactivity; -using Avalonia.Markup.Xaml; -using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.Ui.ViewModels; -using Ryujinx.HLE.FileSystem; -using Ryujinx.HLE.HOS.Services.Account.Acc; -using System.Threading.Tasks; -using UserProfile = Ryujinx.Ava.Ui.Models.UserProfile; - -namespace Ryujinx.Ava.Ui.Windows -{ - public class UserProfileWindow : StyleableWindow - { - private TextBox _nameBox; - - public UserProfileWindow(AccountManager accountManager, ContentManager contentManager, - VirtualFileSystem virtualFileSystem) - { - AccountManager = accountManager; - ContentManager = contentManager; - ViewModel = new UserProfileViewModel(this); - - DataContext = ViewModel; - - InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif - if (contentManager.GetCurrentFirmwareVersion() != null) - { - Task.Run(() => - { - AvatarProfileViewModel.PreloadAvatars(contentManager, virtualFileSystem); - }); - } - - Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance["UserProfileWindowTitle"]; - } - - public UserProfileWindow() - { - ViewModel = new UserProfileViewModel(); - - DataContext = ViewModel; - - InitializeComponent(); -#if DEBUG - this.AttachDevTools(); -#endif - Title = $"Ryujinx {Program.Version} - " + LocaleManager.Instance["UserProfileWindowTitle"]; - } - - public AccountManager AccountManager { get; } - public ContentManager ContentManager { get; } - - public UserProfileViewModel ViewModel { get; set; } - - private void InitializeComponent() - { - AvaloniaXamlLoader.Load(this); - _nameBox = this.FindControl<TextBox>("NameBox"); - } - - private void ProfilesList_DoubleTapped(object sender, RoutedEventArgs e) - { - if (sender is ListBox listBox) - { - int selectedIndex = listBox.SelectedIndex; - - if (selectedIndex >= 0 && selectedIndex < ViewModel.Profiles.Count) - { - ViewModel.SelectedProfile = ViewModel.Profiles[selectedIndex]; - - AccountManager.OpenUser(ViewModel.SelectedProfile.UserId); - - ViewModel.LoadProfiles(); - - foreach (UserProfile profile in ViewModel.Profiles) - { - profile.UpdateState(); - } - } - } - } - - private void CloseButton_OnClick(object sender, RoutedEventArgs e) - { - Close(); - } - - private void SetNameButton_OnClick(object sender, RoutedEventArgs e) - { - if (!string.IsNullOrWhiteSpace(_nameBox.Text)) - { - ViewModel.SelectedProfile.Name = _nameBox.Text; - AccountManager.SetUserName(ViewModel.SelectedProfile.UserId, _nameBox.Text); - } - } - } -}
\ No newline at end of file |