diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 1981148de..cea0a88c5 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -64,55 +64,101 @@ namespace Ryujinx.Ava.UI.ViewModels public partial class MainWindowViewModel : BaseModel { private const int HotKeyPressDelayMs = 500; + private delegate int LoadContentFromFolderDelegate(List dirs, out int numRemoved); - [ObservableProperty] private ObservableCollectionExtended _applications; - [ObservableProperty] private string _aspectRatioStatusText; - [ObservableProperty] private string _loadHeading; - [ObservableProperty] private string _cacheLoadStatus; - [ObservableProperty] private string _dockedStatusText; - [ObservableProperty] private string _fifoStatusText; - [ObservableProperty] private string _gameStatusText; - [ObservableProperty] private string _volumeStatusText; - [ObservableProperty] private string _gpuNameText; - [ObservableProperty] private string _backendText; - [ObservableProperty] private string _shaderCountText; - [ObservableProperty] private bool _showShaderCompilationHint; - [ObservableProperty] private bool _isFullScreen; - [ObservableProperty] private int _progressMaximum; - [ObservableProperty] private int _progressValue; - [ObservableProperty] private bool _showMenuAndStatusBar = true; - [ObservableProperty] private bool _showStatusSeparator; - [ObservableProperty] private Brush _progressBarForegroundColor; - [ObservableProperty] private Brush _progressBarBackgroundColor; - [ObservableProperty] private Brush _vSyncModeColor; -#nullable enable - [ObservableProperty] private byte[]? _selectedIcon; -#nullable disable - [ObservableProperty] private int _statusBarProgressMaximum; - [ObservableProperty] private int _statusBarProgressValue; - [ObservableProperty] private string _statusBarProgressStatusText; - [ObservableProperty] private bool _statusBarProgressStatusVisible; - [ObservableProperty] private bool _isPaused; - [ObservableProperty] private bool _isLoadingIndeterminate = true; - [ObservableProperty] private bool _showAll; - [ObservableProperty] private string _lastScannedAmiiboId; + [ObservableProperty] public partial ObservableCollectionExtended Applications { get; set; } + + [ObservableProperty] public partial string AspectRatioStatusText { get; set; } + + [ObservableProperty] public partial string LoadHeading { get; set; } + + [ObservableProperty] public partial string CacheLoadStatus { get; set; } + + [ObservableProperty] public partial string DockedStatusText { get; set; } + + [ObservableProperty] public partial string FifoStatusText { get; set; } + + [ObservableProperty] public partial string GameStatusText { get; set; } + + [ObservableProperty] public partial string VolumeStatusText { get; set; } + + [ObservableProperty] public partial string GpuNameText { get; set; } + + [ObservableProperty] public partial string BackendText { get; set; } + + [ObservableProperty] public partial string ShaderCountText { get; set; } + + [ObservableProperty] public partial bool ShowShaderCompilationHint { get; set; } + + [ObservableProperty] public partial bool IsFullScreen { get; set; } + + [ObservableProperty] public partial int ProgressMaximum { get; set; } + + [ObservableProperty] public partial int ProgressValue { get; set; } + + [ObservableProperty] public partial bool ShowMenuAndStatusBar { get; set; } = true; + + [ObservableProperty] public partial bool ShowStatusSeparator { get; set; } + + [ObservableProperty] public partial Brush ProgressBarForegroundColor { get; set; } + + [ObservableProperty] public partial Brush ProgressBarBackgroundColor { get; set; } + +#pragma warning disable MVVMTK0042 // Must stay a normal observable field declaration since this is used as an out parameter target [ObservableProperty] private ReadOnlyObservableCollection _appsObservableList; - [ObservableProperty] private long _lastFullscreenToggle = Environment.TickCount64; - [ObservableProperty] private bool _showContent = true; - [ObservableProperty] private float _volumeBeforeMute; - [ObservableProperty] private bool _areMimeTypesRegistered = FileAssociationHelper.AreMimeTypesRegistered; - [ObservableProperty] private Cursor _cursor; - [ObservableProperty] private string _title; - [ObservableProperty] private WindowState _windowState; - [ObservableProperty] private double _windowWidth; - [ObservableProperty] private double _windowHeight; - [ObservableProperty] private bool _isActive; - [ObservableProperty] private bool _isSubMenuOpen; - [ObservableProperty] private ApplicationContextMenu _listAppContextMenu; - [ObservableProperty] private ApplicationContextMenu _gridAppContextMenu; - [ObservableProperty] private bool _isRyuLdnEnabled; - [ObservableProperty] private bool _updateAvailable; +#pragma warning restore MVVMTK0042 + + [ObservableProperty] public partial Brush VSyncModeColor { get; set; } +#nullable enable + [ObservableProperty] public partial byte[]? SelectedIcon { get; set; } +#nullable disable + [ObservableProperty] public partial int StatusBarProgressMaximum { get; set; } + + [ObservableProperty] public partial int StatusBarProgressValue { get; set; } + + [ObservableProperty] public partial string StatusBarProgressStatusText { get; set; } + + [ObservableProperty] public partial bool StatusBarProgressStatusVisible { get; set; } + + [ObservableProperty] public partial bool IsPaused { get; set; } + + [ObservableProperty] public partial bool IsLoadingIndeterminate { get; set; } = true; + + [ObservableProperty] public partial bool ShowAll { get; set; } + + [ObservableProperty] public partial string LastScannedAmiiboId { get; set; } + + [ObservableProperty] + public partial long LastFullscreenToggle { get; set; } = Environment.TickCount64; + [ObservableProperty] public partial bool ShowContent { get; set; } = true; + + [ObservableProperty] public partial float VolumeBeforeMute { get; set; } + + [ObservableProperty] + public partial bool AreMimeTypesRegistered { get; set; } = FileAssociationHelper.AreMimeTypesRegistered; + + [ObservableProperty] public partial Cursor Cursor { get; set; } + + [ObservableProperty] public partial string Title { get; set; } + + [ObservableProperty] public partial WindowState WindowState { get; set; } + + [ObservableProperty] public partial double WindowWidth { get; set; } + + [ObservableProperty] public partial double WindowHeight { get; set; } + + [ObservableProperty] public partial bool IsActive { get; set; } + + [ObservableProperty] public partial bool IsSubMenuOpen { get; set; } + + [ObservableProperty] public partial ApplicationContextMenu ListAppContextMenu { get; set; } + + [ObservableProperty] public partial ApplicationContextMenu GridAppContextMenu { get; set; } + + [ObservableProperty] public partial bool IsRyuLdnEnabled { get; set; } + + [ObservableProperty] public partial bool UpdateAvailable { get; set; } public static AsyncRelayCommand UpdateCommand { get; } = Commands.Create(async () => { @@ -120,27 +166,17 @@ namespace Ryujinx.Ava.UI.ViewModels await Updater.BeginUpdateAsync(true); }); - private bool _showTotalTimePlayed; - private bool _showLoadProgress; private bool _isGameRunning; - private bool _isAmiiboRequested; - private bool _isAmiiboBinRequested; private string _searchText; private Timer _searchTimer; - private string _vSyncModeText; private string _showUiKey = "F4"; private string _pauseKey = "F5"; private string _screenshotKey = "F8"; private float _volume; - private bool _isAppletMenuActive; - private bool _statusBarVisible; - private bool _canUpdate = true; private ApplicationData _currentApplicationData; private readonly AutoResetEvent _rendererWaitEvent; private int _customVSyncInterval; private int _customVSyncIntervalPercentageProxy; - private ApplicationData _listSelectedApplication; - private ApplicationData _gridSelectedApplication; // Key is Title ID /// @@ -266,20 +302,20 @@ namespace Ryujinx.Ava.UI.ViewModels public bool CanUpdate { - get => _canUpdate && EnableNonGameRunningControls && Updater.CanUpdate(); + get => field && EnableNonGameRunningControls && Updater.CanUpdate(); set { - _canUpdate = value; + field = value; OnPropertyChanged(); } - } + } = true; public bool StatusBarVisible { - get => _statusBarVisible && EnableNonGameRunningControls; + get => field && EnableNonGameRunningControls; set { - _statusBarVisible = value; + field = value; OnPropertyChanged(); } @@ -311,20 +347,21 @@ namespace Ryujinx.Ava.UI.ViewModels public bool IsAmiiboRequested { - get => _isAmiiboRequested && _isGameRunning; + get => field && _isGameRunning; set { - _isAmiiboRequested = value; + field = value; OnPropertyChanged(); } } + public bool IsAmiiboBinRequested { - get => _isAmiiboBinRequested && _isGameRunning; + get => field && _isGameRunning; set { - _isAmiiboBinRequested = value; + field = value; OnPropertyChanged(); } @@ -334,10 +371,10 @@ namespace Ryujinx.Ava.UI.ViewModels public bool ShowLoadProgress { - get => _showLoadProgress; + get; set { - _showLoadProgress = value; + field = value; OnPropertyChanged(); OnPropertyChanged(nameof(ShowFirmwareStatus)); @@ -359,24 +396,24 @@ namespace Ryujinx.Ava.UI.ViewModels public bool ShowTotalTimePlayed { - get => _showTotalTimePlayed && EnableNonGameRunningControls; + get => field && EnableNonGameRunningControls; set { - _showTotalTimePlayed = value; + field = value; OnPropertyChanged(); } } public ApplicationData ListSelectedApplication { - get => _listSelectedApplication; + get; set { - _listSelectedApplication = value; + field = value; - if (_listSelectedApplication != null && ListAppContextMenu == null) + if (field != null && ListAppContextMenu == null) ListAppContextMenu = new ApplicationContextMenu(); - else if (_listSelectedApplication == null && ListAppContextMenu != null) + else if (field == null && ListAppContextMenu != null) ListAppContextMenu = null!; OnPropertyChanged(); @@ -385,14 +422,14 @@ namespace Ryujinx.Ava.UI.ViewModels public ApplicationData GridSelectedApplication { - get => _gridSelectedApplication; + get; set { - _gridSelectedApplication = value; + field = value; - if (_gridSelectedApplication != null && GridAppContextMenu == null) + if (field != null && GridAppContextMenu == null) GridAppContextMenu = new ApplicationContextMenu(); - else if (_gridSelectedApplication == null && GridAppContextMenu != null) + else if (field == null && GridAppContextMenu != null) GridAppContextMenu = null!; OnPropertyChanged(); @@ -421,13 +458,18 @@ namespace Ryujinx.Ava.UI.ViewModels public bool HasDlc => ApplicationLibrary.HasDlcs(SelectedApplication.Id); - public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0; + public bool OpenUserSaveDirectoryEnabled => SelectedApplication.HasControlHolder && + SelectedApplication.ControlHolder.Value.UserAccountSaveDataSize > 0; - public bool OpenDeviceSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0; + public bool OpenDeviceSaveDirectoryEnabled => SelectedApplication.HasControlHolder && + SelectedApplication.ControlHolder.Value.DeviceSaveDataSize > 0; - public bool TrimXCIEnabled => XCIFileTrimmer.CanTrim(SelectedApplication.Path, new XCITrimmerLog.MainWindow(this)); + public bool TrimXCIEnabled => + XCIFileTrimmer.CanTrim(SelectedApplication.Path, new XCITrimmerLog.MainWindow(this)); - public bool OpenBcatSaveDirectoryEnabled => SelectedApplication.HasControlHolder && SelectedApplication.ControlHolder.Value.BcatDeliveryCacheStorageSize > 0; + public bool OpenBcatSaveDirectoryEnabled => SelectedApplication.HasControlHolder && + SelectedApplication.ControlHolder.Value + .BcatDeliveryCacheStorageSize > 0; public bool ShowCustomVSyncIntervalPicker => _isGameRunning && AppHost.Device.VSyncMode == VSyncMode.Custom; @@ -465,7 +507,6 @@ namespace Ryujinx.Ava.UI.ViewModels } set { - } } @@ -491,10 +532,10 @@ namespace Ryujinx.Ava.UI.ViewModels public string VSyncModeText { - get => _vSyncModeText; + get; set { - _vSyncModeText = value; + field = value; OnPropertyChanged(); OnPropertyChanged(nameof(ShowCustomVSyncIntervalPicker)); @@ -523,10 +564,10 @@ namespace Ryujinx.Ava.UI.ViewModels public bool IsAppletMenuActive { - get => _isAppletMenuActive && EnableNonGameRunningControls; + get => field && EnableNonGameRunningControls; set { - _isAppletMenuActive = value; + field = value; OnPropertyChanged(); } @@ -798,7 +839,8 @@ namespace Ryujinx.Ava.UI.ViewModels #region PrivateMethods - private static SortExpressionComparer CreateComparer(bool ascending, Func selector) => + private static SortExpressionComparer CreateComparer(bool ascending, + Func selector) => ascending ? SortExpressionComparer.Ascending(selector) : SortExpressionComparer.Descending(selector); @@ -807,15 +849,15 @@ namespace Ryujinx.Ava.UI.ViewModels => SortMode switch { #pragma warning disable IDE0055 // Disable formatting - ApplicationSort.Title => CreateComparer(IsAscending, app => app.Name), - ApplicationSort.Developer => CreateComparer(IsAscending, app => app.Developer), - ApplicationSort.LastPlayed => new LastPlayedSortComparer(IsAscending), + ApplicationSort.Title => CreateComparer(IsAscending, app => app.Name), + ApplicationSort.Developer => CreateComparer(IsAscending, app => app.Developer), + ApplicationSort.LastPlayed => new LastPlayedSortComparer(IsAscending), ApplicationSort.TotalTimePlayed => new TimePlayedSortComparer(IsAscending), - ApplicationSort.FileType => CreateComparer(IsAscending, app => app.FileExtension), - ApplicationSort.FileSize => CreateComparer(IsAscending, app => app.FileSize), - ApplicationSort.Path => CreateComparer(IsAscending, app => app.Path), - ApplicationSort.Favorite => CreateComparer(IsAscending, app => new AppListFavoriteComparable(app)), - ApplicationSort.TitleId => CreateComparer(IsAscending, app => app.Id), + ApplicationSort.FileType => CreateComparer(IsAscending, app => app.FileExtension), + ApplicationSort.FileSize => CreateComparer(IsAscending, app => app.FileSize), + ApplicationSort.Path => CreateComparer(IsAscending, app => app.Path), + ApplicationSort.Favorite => CreateComparer(IsAscending, app => new AppListFavoriteComparable(app)), + ApplicationSort.TitleId => CreateComparer(IsAscending, app => app.Id), _ => null, #pragma warning restore IDE0055 }; @@ -847,7 +889,8 @@ namespace Ryujinx.Ava.UI.ViewModels CompareInfo compareInfo = CultureInfo.CurrentCulture.CompareInfo; - return compareInfo.IndexOf(app.Name, _searchText, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) >= 0; + return compareInfo.IndexOf(app.Name, _searchText, + CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) >= 0; } return false; @@ -861,21 +904,27 @@ namespace Ryujinx.Ava.UI.ViewModels if (firmwareVersion == null) { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareNotFoundErrorMessage, filename)); + await ContentDialogHelper.CreateErrorDialog( + LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogFirmwareInstallerFirmwareNotFoundErrorMessage, filename)); return; } - string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallTitle, firmwareVersion.VersionString); - string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallMessage, firmwareVersion.VersionString); + string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogFirmwareInstallerFirmwareInstallTitle, firmwareVersion.VersionString); + string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogFirmwareInstallerFirmwareInstallMessage, firmwareVersion.VersionString); SystemVersion currentVersion = ContentManager.GetCurrentFirmwareVersion(); if (currentVersion != null) { - dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallSubMessage, currentVersion.VersionString); + dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogFirmwareInstallerFirmwareInstallSubMessage, currentVersion.VersionString); } - dialogMessage += LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallConfirmMessage]; + dialogMessage += + LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallConfirmMessage]; UserResult result = await ContentDialogHelper.CreateConfirmationDialog( dialogTitle, @@ -884,7 +933,8 @@ namespace Ryujinx.Ava.UI.ViewModels LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); - UpdateWaitWindow waitingDialog = new(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallWaitMessage]); + UpdateWaitWindow waitingDialog = new(dialogTitle, + LocaleManager.Instance[LocaleKeys.DialogFirmwareInstallerFirmwareInstallWaitMessage]); if (result == UserResult.Yes) { @@ -905,7 +955,9 @@ namespace Ryujinx.Ava.UI.ViewModels { waitingDialog.Close(); - string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage, firmwareVersion.VersionString); + string message = LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogFirmwareInstallerFirmwareInstallSuccessMessage, + firmwareVersion.VersionString); await ContentDialogHelper.CreateInfoDialog( dialogTitle, @@ -918,7 +970,8 @@ namespace Ryujinx.Ava.UI.ViewModels // Purge Applet Cache. - DirectoryInfo miiEditorCacheFolder = new(Path.Combine(AppDataManager.GamesDirPath, "0100000000001009", "cache")); + DirectoryInfo miiEditorCacheFolder = new(Path.Combine(AppDataManager.GamesDirPath, + "0100000000001009", "cache")); if (miiEditorCacheFolder.Exists) { @@ -939,10 +992,7 @@ namespace Ryujinx.Ava.UI.ViewModels { RefreshFirmwareStatus(); } - }) - { - Name = "GUI.FirmwareInstallerThread", - }; + }) { Name = "GUI.FirmwareInstallerThread", }; thread.Start(); } @@ -967,17 +1017,22 @@ namespace Ryujinx.Ava.UI.ViewModels try { string systemDirectory = AppDataManager.KeysDirPath; - if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && Directory.Exists(AppDataManager.KeysDirPathUser)) + if (AppDataManager.Mode == AppDataManager.LaunchMode.UserProfile && + Directory.Exists(AppDataManager.KeysDirPathUser)) { systemDirectory = AppDataManager.KeysDirPathUser; } - string dialogTitle = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallTitle); - string dialogMessage = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallMessage); - + string dialogTitle = + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallTitle); + string dialogMessage = + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallMessage); + if (ContentManager.AreKeysAlredyPresent(systemDirectory)) { - dialogMessage += LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSubMessage); + dialogMessage += + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys + .DialogKeysInstallerKeysInstallSubMessage); } dialogMessage += LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallConfirmMessage]; @@ -989,7 +1044,8 @@ namespace Ryujinx.Ava.UI.ViewModels LocaleManager.Instance[LocaleKeys.InputDialogNo], LocaleManager.Instance[LocaleKeys.RyujinxConfirm]); - UpdateWaitWindow waitingDialog = new(dialogTitle, LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallWaitMessage]); + UpdateWaitWindow waitingDialog = new(dialogTitle, + LocaleManager.Instance[LocaleKeys.DialogKeysInstallerKeysInstallWaitMessage]); if (result == UserResult.Yes) { @@ -1010,7 +1066,9 @@ namespace Ryujinx.Ava.UI.ViewModels { waitingDialog.Close(); - string message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysInstallSuccessMessage); + string message = + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys + .DialogKeysInstallerKeysInstallSuccessMessage); await ContentDialogHelper.CreateInfoDialog( dialogTitle, @@ -1031,7 +1089,8 @@ namespace Ryujinx.Ava.UI.ViewModels string message = ex.Message; if (ex is FormatException) { - message = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename); + message = LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.DialogKeysInstallerKeysNotFoundErrorMessage, filename); } await ContentDialogHelper.CreateErrorDialog(message); @@ -1041,10 +1100,7 @@ namespace Ryujinx.Ava.UI.ViewModels { VirtualFileSystem.ReloadKeySet(); } - }) - { - Name = "GUI.KeysInstallerThread", - }; + }) { Name = "GUI.KeysInstallerThread", }; thread.Start(); } @@ -1063,6 +1119,7 @@ namespace Ryujinx.Ava.UI.ViewModels await ContentDialogHelper.CreateErrorDialog(ex.Message); } } + private void ProgressHandler(T state, int current, int total) where T : Enum { Dispatcher.UIThread.Post(() => @@ -1082,7 +1139,8 @@ namespace Ryujinx.Ava.UI.ViewModels IsLoadingIndeterminate = false; break; case LoadState.Loaded: - LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, _currentApplicationData.Name); + LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, + _currentApplicationData.Name); IsLoadingIndeterminate = true; CacheLoadStatus = string.Empty; break; @@ -1103,7 +1161,8 @@ namespace Ryujinx.Ava.UI.ViewModels IsLoadingIndeterminate = false; break; case ShaderCacheLoadingState.Loaded: - LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, _currentApplicationData.Name); + LoadHeading = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.LoadingHeading, + _currentApplicationData.Name); IsLoadingIndeterminate = true; CacheLoadStatus = string.Empty; break; @@ -1203,12 +1262,12 @@ namespace Ryujinx.Ava.UI.ViewModels _rendererWaitEvent.Set(); } - private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle) + private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, + LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle) { - Optional> result = await StorageProvider.OpenMultiFolderPickerAsync(new FolderPickerOpenOptions - { - Title = LocaleManager.Instance[dirSelectDialogTitle] - }); + Optional> result = + await StorageProvider.OpenMultiFolderPickerAsync( + new FolderPickerOpenOptions { Title = LocaleManager.Instance[dirSelectDialogTitle] }); if (result.TryGet(out IReadOnlyList foldersToLoad)) { @@ -1223,7 +1282,8 @@ namespace Ryujinx.Ava.UI.ViewModels await Dispatcher.UIThread.InvokeAsync(async () => { await ContentDialogHelper.ShowTextDialog( - LocaleManager.Instance[numAdded > 0 || numRemoved > 0 ? LocaleKeys.RyujinxConfirm : LocaleKeys.RyujinxInfo], + LocaleManager.Instance[ + numAdded > 0 || numRemoved > 0 ? LocaleKeys.RyujinxConfirm : LocaleKeys.RyujinxInfo], msg, string.Empty, string.Empty, @@ -1252,17 +1312,21 @@ namespace Ryujinx.Ava.UI.ViewModels public void LoadConfigurableHotKeys() { - if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUI, out Avalonia.Input.Key showUiKey)) + if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.ShowUI, + out Avalonia.Input.Key showUiKey)) { ShowUiKey = new KeyGesture(showUiKey); } - if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, out Avalonia.Input.Key screenshotKey)) + if (AvaloniaKeyboardMappingHelper.TryGetAvaKey( + (Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Screenshot, + out Avalonia.Input.Key screenshotKey)) { ScreenshotKey = new KeyGesture(screenshotKey); } - if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, out Avalonia.Input.Key pauseKey)) + if (AvaloniaKeyboardMappingHelper.TryGetAvaKey((Key)ConfigurationState.Instance.Hid.Hotkeys.Value.Pause, + out Avalonia.Input.Key pauseKey)) { PauseKey = new KeyGesture(pauseKey); } @@ -1282,7 +1346,8 @@ namespace Ryujinx.Ava.UI.ViewModels public void SetGridMode() => Glyph = Glyph.Grid; - public void SetAspectRatio(AspectRatio aspectRatio) => ConfigurationState.Instance.Graphics.AspectRatio.Value = aspectRatio; + public void SetAspectRatio(AspectRatio aspectRatio) => + ConfigurationState.Instance.Graphics.AspectRatio.Value = aspectRatio; public async Task InstallFirmwareFromFile() { @@ -1374,7 +1439,8 @@ namespace Ryujinx.Ava.UI.ViewModels } catch (Exception ex) { - Logger.Error?.Print(LogClass.Application, $"Failed to create directory at path {screenshotsDir}. Error : {ex.GetType().Name}", "Screenshot"); + Logger.Error?.Print(LogClass.Application, + $"Failed to create directory at path {screenshotsDir}. Error : {ex.GetType().Name}", "Screenshot"); return; } @@ -1447,7 +1513,8 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task ManageProfiles() { - await NavigationDialogHost.Show(AccountManager, ContentManager, VirtualFileSystem, LibHacHorizonManager.RyujinxClient); + await NavigationDialogHost.Show(AccountManager, ContentManager, VirtualFileSystem, + LibHacHorizonManager.RyujinxClient); } public void SimulateWakeUpMessage() @@ -1524,7 +1591,8 @@ namespace Ryujinx.Ava.UI.ViewModels } else { - await ContentDialogHelper.CreateErrorDialog(LocaleManager.Instance[LocaleKeys.MenuBarFileOpenFromFileError]); + await ContentDialogHelper.CreateErrorDialog( + LocaleManager.Instance[LocaleKeys.MenuBarFileOpenFromFileError]); } } } @@ -1549,17 +1617,17 @@ namespace Ryujinx.Ava.UI.ViewModels public async Task OpenFolder() { - Optional result = await StorageProvider.OpenSingleFolderPickerAsync(new FolderPickerOpenOptions - { - Title = LocaleManager.Instance[LocaleKeys.LoadUnpackedGameFromFolderDialogTitle] - }); + Optional result = await StorageProvider.OpenSingleFolderPickerAsync( + new FolderPickerOpenOptions + { + Title = LocaleManager.Instance[LocaleKeys.LoadUnpackedGameFromFolderDialogTitle] + }); if (result.TryGet(out IStorageFolder value)) { ApplicationData applicationData = new() { - Name = Path.GetFileNameWithoutExtension(value.Path.LocalPath), - Path = value.Path.LocalPath, + Name = Path.GetFileNameWithoutExtension(value.Path.LocalPath), Path = value.Path.LocalPath, }; await LoadApplication(applicationData); @@ -1569,29 +1637,34 @@ namespace Ryujinx.Ava.UI.ViewModels public static bool InitializeUserConfig(ApplicationData application) { // Code where conditions will be met before loading the user configuration (Global Config) - string backendThreadingInit = Program.BackendThreadingArg ?? ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString(); + string backendThreadingInit = Program.BackendThreadingArg ?? + ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString(); // If a configuration is found in the "/games/xxxxxxxxxxxxxx" folder, the program will load the user setting. string idGame = application.IdBaseString; - if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), out ConfigurationFileFormat configurationFileFormat)) + if (ConfigurationFileFormat.TryLoad(Program.GetDirGameUserConfig(idGame), + out ConfigurationFileFormat configurationFileFormat)) { // Loads the user configuration, having previously changed the global configuration to the user configuration - ConfigurationState.Instance.Load(configurationFileFormat, Program.GetDirGameUserConfig(idGame, true), idGame); + ConfigurationState.Instance.Load(configurationFileFormat, Program.GetDirGameUserConfig(idGame, true), + idGame); - if (ConfigurationFileFormat.TryLoad(Program.GlobalConfigurationPath, out ConfigurationFileFormat configurationFileFormatExtra)) + if (ConfigurationFileFormat.TryLoad(Program.GlobalConfigurationPath, + out ConfigurationFileFormat configurationFileFormatExtra)) { //This is where the global configuration will be stored. //This allows you to change the global configuration settings during the game (for example, the global input setting) - ConfigurationState.InstanceExtra.Load(configurationFileFormatExtra, Program.GlobalConfigurationPath); + ConfigurationState.InstanceExtra.Load(configurationFileFormatExtra, + Program.GlobalConfigurationPath); } } // Code where conditions will be executed after loading user configuration if (ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() != backendThreadingInit) { - Rebooter.RebootAppWithGame(application.Path, + Rebooter.RebootAppWithGame(application.Path, [ - "--bt", + "--bt", ConfigurationState.Instance.Graphics.BackendThreading.Value.ToString() ]); @@ -1601,7 +1674,8 @@ namespace Ryujinx.Ava.UI.ViewModels return false; } - public async Task LoadApplication(ApplicationData application, bool startFullscreen = false, BlitStruct? customNacpData = null) + public async Task LoadApplication(ApplicationData application, bool startFullscreen = false, + BlitStruct? customNacpData = null) { if (InitializeUserConfig(application)) return; @@ -1624,7 +1698,8 @@ namespace Ryujinx.Ava.UI.ViewModels Logger.RestartTime(); - SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, ConfigurationState.Instance.System.Language, application.Id); + SelectedIcon ??= ApplicationLibrary.GetApplicationIcon(application.Path, + ConfigurationState.Instance.System.Language, application.Id); PrepareLoadScreen(); @@ -1662,7 +1737,6 @@ namespace Ryujinx.Ava.UI.ViewModels Thread gameThread = new(InitializeGame) { Name = "GUI.WindowThread" }; gameThread.Start(); - } public void SwitchToRenderer(bool startFullscreen) => @@ -1694,7 +1768,8 @@ namespace Ryujinx.Ava.UI.ViewModels if (version != null) { - LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarSystemVersion, version.VersionString); + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarSystemVersion, + version.VersionString); hasApplet = version.Major > 3; } @@ -1747,7 +1822,7 @@ namespace Ryujinx.Ava.UI.ViewModels if (AppHost.Device.System.SearchingForAmiibo(out int deviceId) && IsGameRunning) { string titleId = AppHost.Device.Processes.ActiveApplication.ProgramIdText.ToUpper(); - AmiiboWindow window = new(ShowAll, LastScannedAmiiboId, titleId); + AmiiboWindow window = new(ShowAll, LastScannedAmiiboId ?? string.Empty, titleId); await StyleableAppWindow.ShowAsync(window); @@ -1760,22 +1835,24 @@ namespace Ryujinx.Ava.UI.ViewModels } } } + public async Task OpenBinFile() { if (AppHost.Device.System.SearchingForAmiibo(out _) && IsGameRunning) { - Optional result = await StorageProvider.OpenSingleFilePickerAsync(new FilePickerOpenOptions - { - Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], - FileTypeFilter = new List + Optional result = await StorageProvider.OpenSingleFilePickerAsync( + new FilePickerOpenOptions { - new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) + Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], + FileTypeFilter = new List { - Patterns = ["*.bin"], + new(LocaleManager.Instance[LocaleKeys.AllSupportedFormats]) + { + Patterns = ["*.bin"], + } } - } - }); - + }); + if (result.HasValue) { AppHost.Device.System.ScanAmiiboFromBin(result.Value.Path.LocalPath); @@ -1826,9 +1903,11 @@ namespace Ryujinx.Ava.UI.ViewModels if (ConfigurationState.Instance.Logger.EnableTrace.Value) { string mainMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckLoggingEnabledMessage]; - string secondaryMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckLoggingEnabledConfirmMessage]; + string secondaryMessage = + LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckLoggingEnabledConfirmMessage]; - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog(mainMessage, secondaryMessage); + UserResult result = + await ContentDialogHelper.CreateLocalizedConfirmationDialog(mainMessage, secondaryMessage); if (result == UserResult.Yes) { @@ -1841,9 +1920,11 @@ namespace Ryujinx.Ava.UI.ViewModels if (!string.IsNullOrWhiteSpace(ConfigurationState.Instance.Graphics.ShadersDumpPath.Value)) { string mainMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckShaderDumpEnabledMessage]; - string secondaryMessage = LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckShaderDumpEnabledConfirmMessage]; + string secondaryMessage = + LocaleManager.Instance[LocaleKeys.DialogPerformanceCheckShaderDumpEnabledConfirmMessage]; - UserResult result = await ContentDialogHelper.CreateLocalizedConfirmationDialog(mainMessage, secondaryMessage); + UserResult result = + await ContentDialogHelper.CreateLocalizedConfirmationDialog(mainMessage, secondaryMessage); if (result == UserResult.Yes) { @@ -1890,7 +1971,8 @@ namespace Ryujinx.Ava.UI.ViewModels double savings = (double)trimmer.DiskSpaceSavingsB / 1024.0 / 1024.0; double currentFileSize = (double)trimmer.FileSizeB / 1024.0 / 1024.0; double cartDataSize = (double)trimmer.DataSizeB / 1024.0 / 1024.0; - string secondaryText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.TrimXCIFileDialogSecondaryText, currentFileSize, cartDataSize, savings); + string secondaryText = LocaleManager.Instance.UpdateAndGetDynamicValue( + LocaleKeys.TrimXCIFileDialogSecondaryText, currentFileSize, cartDataSize, savings); UserResult result = await ContentDialogHelper.CreateConfirmationDialog( LocaleManager.Instance[LocaleKeys.TrimXCIFileDialogPrimaryText], @@ -1906,7 +1988,9 @@ namespace Ryujinx.Ava.UI.ViewModels { Dispatcher.UIThread.Post(() => { - StatusBarProgressStatusText = LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarXCIFileTrimming, Path.GetFileName(filename)); + StatusBarProgressStatusText = + LocaleManager.Instance.UpdateAndGetDynamicValue(LocaleKeys.StatusBarXCIFileTrimming, + Path.GetFileName(filename)); StatusBarProgressStatusVisible = true; StatusBarProgressMaximum = 1; StatusBarProgressValue = 0; @@ -1931,11 +2015,7 @@ namespace Ryujinx.Ava.UI.ViewModels StatusBarVisible = false; }); } - }) - { - Name = "GUI.XCIFileTrimmerThread", - IsBackground = true, - }; + }) { Name = "GUI.XCIFileTrimmerThread", IsBackground = true, }; XCIFileTrimThread.Start(); } } @@ -1997,7 +2077,8 @@ namespace Ryujinx.Ava.UI.ViewModels public static RelayCommand OpenUserSaveDirectory { get; } = Commands.CreateConditional(vm => vm?.SelectedApplication != null, viewModel => - OpenSaveDirectory(viewModel, SaveDataType.Account, viewModel.AccountManager.LastOpenedUser.UserId.ToLibHac()) + OpenSaveDirectory(viewModel, SaveDataType.Account, + viewModel.AccountManager.LastOpenedUser.UserId.ToLibHac()) ); public static RelayCommand OpenDeviceSaveDirectory { get; } = @@ -2053,7 +2134,8 @@ namespace Ryujinx.Ava.UI.ViewModels viewModel => { string modsBasePath = ModLoader.GetModsBasePath(); - string titleModsPath = ModLoader.GetApplicationDir(modsBasePath, viewModel.SelectedApplication.IdString); + string titleModsPath = + ModLoader.GetApplicationDir(modsBasePath, viewModel.SelectedApplication.IdString); OpenHelper.OpenFolder(titleModsPath); }); @@ -2063,7 +2145,8 @@ namespace Ryujinx.Ava.UI.ViewModels viewModel => { string sdModsBasePath = ModLoader.GetSdModsBasePath(); - string titleModsPath = ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.IdString); + string titleModsPath = + ModLoader.GetApplicationDir(sdModsBasePath, viewModel.SelectedApplication.IdString); OpenHelper.OpenFolder(titleModsPath); }); diff --git a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs index 7d42c004c..c2ba634f1 100644 --- a/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/SettingsViewModel.cs @@ -46,47 +46,49 @@ namespace Ryujinx.Ava.UI.ViewModels private readonly Dictionary _networkInterfaces; - private float _customResolutionScale; private int _resolutionScale; - private int _graphicsBackendMultithreadingIndex; - private float _volume; - [ObservableProperty] private bool _isVulkanAvailable = true; - [ObservableProperty] private bool _gameListNeedsRefresh; + [ObservableProperty] + public partial bool IsVulkanAvailable { get; set; } = true; + + [ObservableProperty] + public partial bool GameListNeedsRefresh { get; set; } + private readonly List _gpuIds = []; - private bool _useInputGlobalConfig; - private int _graphicsBackendIndex; private int _scalingFilter; - private int _scalingFilterLevel; private int _customVSyncInterval; - private bool _enableCustomVSyncInterval; private int _customVSyncIntervalPercentageProxy; private VSyncMode _vSyncMode; - private long _turboModeMultiplier; public event Action CloseWindow; public event Action SaveSettingsEvent; public event Action LocalGlobalInputSwitchEvent; - private int _networkInterfaceIndex; - private int _multiplayerModeIndex; - private string _ldnPassphrase; - [ObservableProperty] private string _ldnServer; - - private bool _enableGDBStub; - private ushort _gdbStubPort; - private bool _debuggerSuspendOnStart; - public SettingsHacksViewModel DirtyHacks { get; } - private readonly bool _isGameRunning; - private readonly Bitmap _gameIcon; - private readonly string _gameTitle; - private readonly string _gamePath; - private readonly string _gameId; - public bool IsGameRunning => _isGameRunning; - public Bitmap GameIcon => _gameIcon; - public string GamePath => _gamePath; - public string GameTitle => _gameTitle; - public string GameId => _gameId; + public bool IsGameRunning + { + get; + } + + public Bitmap GameIcon + { + get; + } + + public string GamePath + { + get; + } + + public string GameTitle + { + get; + } + + public string GameId + { + get; + } + public bool IsGameTitleNotNull => !string.IsNullOrEmpty(GameTitle); public double PanelOpacity => IsGameTitleNotNull ? 0.5 : 1; @@ -104,17 +106,18 @@ namespace Ryujinx.Ava.UI.ViewModels public int GraphicsBackendMultithreadingIndex { - get => _graphicsBackendMultithreadingIndex; + get; set { - _graphicsBackendMultithreadingIndex = value; + field = value; - if (_graphicsBackendMultithreadingIndex != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value) + if (field != (int)ConfigurationState.Instance.Graphics.BackendThreading.Value) { Dispatcher.UIThread.InvokeAsync(() => - ContentDialogHelper.CreateInfoDialog(LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage], - string.Empty, - string.Empty, + ContentDialogHelper.CreateInfoDialog( + LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningMessage], + string.Empty, + string.Empty, LocaleManager.Instance[LocaleKeys.InputDialogOk], LocaleManager.Instance[LocaleKeys.DialogSettingsBackendThreadingWarningTitle]) ); @@ -126,10 +129,10 @@ namespace Ryujinx.Ava.UI.ViewModels public float CustomResolutionScale { - get => _customResolutionScale; + get; set { - _customResolutionScale = MathF.Round(value, 1); + field = MathF.Round(value, 1); OnPropertyChanged(); } @@ -152,12 +155,12 @@ namespace Ryujinx.Ava.UI.ViewModels public int FocusLostActionType { get; set; } public bool UseGlobalInputConfig - { - get => _useInputGlobalConfig; + { + get; set { - _useInputGlobalConfig = value; - LocalGlobalInputSwitchEvent?.Invoke(_useInputGlobalConfig); + field = value; + LocalGlobalInputSwitchEvent?.Invoke(field); OnPropertyChanged(nameof(InputPanelOpacity)); OnPropertyChanged(); } @@ -196,10 +199,10 @@ namespace Ryujinx.Ava.UI.ViewModels public bool EnableCustomVSyncInterval { - get => _enableCustomVSyncInterval; + get; set { - _enableCustomVSyncInterval = value; + field = value; if (_vSyncMode == VSyncMode.Custom && !value) { VSyncMode = VSyncMode.Switch; @@ -233,12 +236,12 @@ namespace Ryujinx.Ava.UI.ViewModels public long TurboMultiplier { - get => _turboModeMultiplier; + get; set { - if (_turboModeMultiplier != value) + if (field != value) { - _turboModeMultiplier = value; + field = value; OnPropertyChanged(); OnPropertyChanged((nameof(TurboMultiplierPercentageText))); @@ -285,10 +288,10 @@ namespace Ryujinx.Ava.UI.ViewModels public string LdnPassphrase { - get => _ldnPassphrase; + get; set { - _ldnPassphrase = value; + field = value; IsInvalidLdnPassphraseVisible = !ValidateLdnPassphrase(value); OnPropertyChanged(); @@ -304,29 +307,33 @@ namespace Ryujinx.Ava.UI.ViewModels public int AspectRatio { get; set; } public int AntiAliasingEffect { get; set; } public string ScalingFilterLevelText => ScalingFilterLevel.ToString("0"); + public int ScalingFilterLevel { - get => _scalingFilterLevel; + get; set { - _scalingFilterLevel = value; + field = value; OnPropertyChanged(); OnPropertyChanged(nameof(ScalingFilterLevelText)); } } + public int OpenglDebugLevel { get; set; } public int MemoryMode { get; set; } public int BaseStyleIndex { get; set; } + public int GraphicsBackendIndex { - get => _graphicsBackendIndex; + get; set { - _graphicsBackendIndex = value; + field = value; OnPropertyChanged(); OnPropertyChanged(nameof(IsVulkanSelected)); } } + public int ScalingFilter { get => _scalingFilter; @@ -342,12 +349,12 @@ namespace Ryujinx.Ava.UI.ViewModels public float Volume { - get => _volume; + get; set { - _volume = value; + field = value; - ConfigurationState.Instance.System.AudioVolume.Value = _volume / 100; + ConfigurationState.Instance.System.AudioVolume.Value = field / 100; OnPropertyChanged(); } @@ -373,19 +380,19 @@ namespace Ryujinx.Ava.UI.ViewModels public int NetworkInterfaceIndex { - get => _networkInterfaceIndex; + get; set { - _networkInterfaceIndex = value != -1 ? value : 0; + field = value != -1 ? value : 0; } } public int MultiplayerModeIndex { - get => _multiplayerModeIndex; + get; set { - _multiplayerModeIndex = value; + field = value; } } @@ -393,31 +400,31 @@ namespace Ryujinx.Ava.UI.ViewModels public bool EnableGdbStub { - get => _enableGDBStub; + get; set { - _enableGDBStub = value; - ConfigurationState.Instance.Debug.EnableGdbStub.Value = _enableGDBStub; + field = value; + ConfigurationState.Instance.Debug.EnableGdbStub.Value = field; } } public ushort GDBStubPort { - get => _gdbStubPort; + get; set { - _gdbStubPort = value; - ConfigurationState.Instance.Debug.GdbStubPort.Value = _gdbStubPort; + field = value; + ConfigurationState.Instance.Debug.GdbStubPort.Value = field; } } public bool DebuggerSuspendOnStart { - get => _debuggerSuspendOnStart; + get; set { - _debuggerSuspendOnStart = value; - ConfigurationState.Instance.Debug.DebuggerSuspendOnStart.Value = _debuggerSuspendOnStart; + field = value; + ConfigurationState.Instance.Debug.DebuggerSuspendOnStart.Value = field; } } @@ -450,13 +457,13 @@ namespace Ryujinx.Ava.UI.ViewModels if (gameIconData != null && gameIconData.Length > 0) { using var ms = new MemoryStream(gameIconData); - _gameIcon = new Bitmap(ms); + GameIcon = new Bitmap(ms); } - _isGameRunning = gameRunning; - _gamePath = gamePath; - _gameTitle = gameName; - _gameId = gameId; + IsGameRunning = gameRunning; + GamePath = gamePath; + GameTitle = gameName; + GameId = gameId; if (customConfig) // During the game. If there is no user config, then load the global config window { @@ -718,7 +725,6 @@ namespace Ryujinx.Ava.UI.ViewModels MultiplayerModeIndex = (int)config.Multiplayer.Mode.Value; DisableP2P = config.Multiplayer.DisableP2p; LdnPassphrase = config.Multiplayer.LdnPassphrase; - LdnServer = config.Multiplayer.LdnServer; // Debug EnableGdbStub = config.Debug.EnableGdbStub.Value; @@ -845,7 +851,6 @@ namespace Ryujinx.Ava.UI.ViewModels config.Multiplayer.Mode.Value = (MultiplayerMode)MultiplayerModeIndex; config.Multiplayer.DisableP2p.Value = DisableP2P; config.Multiplayer.LdnPassphrase.Value = LdnPassphrase; - config.Multiplayer.LdnServer.Value = LdnServer; // Debug config.Debug.EnableGdbStub.Value = EnableGdbStub;