diff --git a/Ryujinx.Ava/Assets/Locales/en_US.json b/Ryujinx.Ava/Assets/Locales/en_US.json index fb8f800c0194..b2d6b43d7de7 100644 --- a/Ryujinx.Ava/Assets/Locales/en_US.json +++ b/Ryujinx.Ava/Assets/Locales/en_US.json @@ -429,6 +429,7 @@ "DlcManagerEnableAllButton": "Enable All", "DlcManagerDisableAllButton": "Disable All", "MenuBarOptionsChangeLanguage": "Change Language", + "MenuBarShowFileTypes": "Show File Types", "CommonSort": "Sort", "CommonShowNames": "Show Names", "CommonFavorite": "Favorite", diff --git a/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs b/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs index d5ff7854585f..da2115265ac5 100644 --- a/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs +++ b/Ryujinx.Ava/UI/ViewModels/MainWindowViewModel.cs @@ -1336,6 +1336,23 @@ public void ChangeLanguage(object languageCode) } } + public void ToggleFileType(string fileType) + { + _ = fileType switch + { + "NSP" => ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NSP, + "PFS0" => ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.PFS0, + "XCI" => ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.XCI, + "NCA" => ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NCA, + "NRO" => ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NRO, + "NSO" => ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value = !ConfigurationState.Instance.Ui.ShownFileTypes.NSO, + _ => throw new ArgumentOutOfRangeException(fileType), + }; + + ConfigurationState.Instance.ToFileFormat().SaveConfig(Program.ConfigurationPath); + LoadApplications(); + } + public async void ManageProfiles() { await NavigationDialogHost.Show(AccountManager, ContentManager, VirtualFileSystem, LibHacHorizonManager.RyujinxClient); diff --git a/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml b/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml index b1d768eadc68..d5b5efcdd684 100644 --- a/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml +++ b/Ryujinx.Ava/UI/Views/Main/MainMenuBarView.axaml @@ -78,6 +78,7 @@ + checkBoxes = new(); + + foreach (var item in Enum.GetValues(typeof (FileTypes))) + { + string fileName = Enum.GetName(typeof (FileTypes), item); + checkBoxes.Add(new CheckBox() + { + Content = $".{fileName}", + IsChecked = ((FileTypes)item).GetConfigValue(ConfigurationState.Instance.Ui.ShownFileTypes), + Command = MiniCommand.Create(() => ViewModel.ToggleFileType(fileName)) + }); + } + + return checkBoxes.ToArray(); + } + + private MenuItem[] GenerateLanguageMenuItems() + { List menuItems = new(); string localePath = "Ryujinx.Ava/Assets/Locales"; @@ -61,7 +87,7 @@ public MainMenuBarView() menuItems.Add(menuItem); } - ChangeLanguageMenuItem.Items = menuItems.ToArray(); + return menuItems.ToArray(); } protected override void OnAttachedToVisualTree(VisualTreeAttachmentEventArgs e) diff --git a/Ryujinx.Ui.Common/App/ApplicationLibrary.cs b/Ryujinx.Ui.Common/App/ApplicationLibrary.cs index 66cb7c73b62f..b7b57f1a2932 100644 --- a/Ryujinx.Ui.Common/App/ApplicationLibrary.cs +++ b/Ryujinx.Ui.Common/App/ApplicationLibrary.cs @@ -14,9 +14,11 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.HOS.SystemState; using Ryujinx.HLE.Loaders.Npdm; +using Ryujinx.Ui.Common.Configuration; using Ryujinx.Ui.Common.Configuration.System; using System; using System.Collections.Generic; +using System.Linq; using System.Globalization; using System.IO; using System.Reflection; @@ -109,7 +111,18 @@ public void LoadApplications(List appDirs, Language desiredTitleLanguage try { - foreach (string app in Directory.EnumerateFiles(appDir, "*", SearchOption.AllDirectories)) + IEnumerable files = Directory.EnumerateFiles(appDir, "*", SearchOption.AllDirectories).Where(file => + { + return + (Path.GetExtension(file).ToLower() is ".nsp" && ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value) || + (Path.GetExtension(file).ToLower() is ".pfs0" && ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value) || + (Path.GetExtension(file).ToLower() is ".xci" && ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value) || + (Path.GetExtension(file).ToLower() is ".nca" && ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value) || + (Path.GetExtension(file).ToLower() is ".nro" && ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value) || + (Path.GetExtension(file).ToLower() is ".nso" && ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value); + }); + + foreach (string app in files) { if (_cancellationToken.Token.IsCancellationRequested) { diff --git a/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs b/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs index 14c03957aa93..cb9adc86ca42 100644 --- a/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs +++ b/Ryujinx.Ui.Common/Configuration/ConfigurationFileFormat.cs @@ -14,7 +14,7 @@ public class ConfigurationFileFormat /// /// The current version of the file format /// - public const int CurrentVersion = 44; + public const int CurrentVersion = 45; /// /// Version of the configuration file format @@ -246,6 +246,11 @@ public class ConfigurationFileFormat /// public List GameDirs { get; set; } + /// + /// A list of file types to be hidden in the games List + /// + public ShownFileTypes ShownFileTypes { get; set; } + /// /// Language Code for the UI /// diff --git a/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs b/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs index 82a331c1618e..12cc1b8f8e2a 100644 --- a/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs +++ b/Ryujinx.Ui.Common/Configuration/ConfigurationState.cs @@ -60,6 +60,29 @@ public ColumnSortSettings() } } + /// + /// Used to toggle which file types are shown in the UI + /// + public class ShownFileTypeSettings + { + public ReactiveObject NSP { get; private set; } + public ReactiveObject PFS0 { get; private set; } + public ReactiveObject XCI { get; private set; } + public ReactiveObject NCA { get; private set; } + public ReactiveObject NRO { get; private set; } + public ReactiveObject NSO { get; private set; } + + public ShownFileTypeSettings() + { + NSP = new ReactiveObject(); + PFS0 = new ReactiveObject(); + XCI = new ReactiveObject(); + NCA = new ReactiveObject(); + NRO = new ReactiveObject(); + NSO = new ReactiveObject(); + } + } + /// /// Used to toggle columns in the GUI /// @@ -75,6 +98,11 @@ public ColumnSortSettings() /// public ReactiveObject> GameDirs { get; private set; } + /// + /// A list of file types to be hidden in the games List + /// + public ShownFileTypeSettings ShownFileTypes { get; private set; } + /// /// Language Code for the UI /// @@ -135,6 +163,7 @@ public UiSection() GuiColumns = new Columns(); ColumnSort = new ColumnSortSettings(); GameDirs = new ReactiveObject>(); + ShownFileTypes = new ShownFileTypeSettings(); EnableCustomTheme = new ReactiveObject(); CustomThemePath = new ReactiveObject(); BaseStyle = new ReactiveObject(); @@ -618,6 +647,15 @@ public ConfigurationFileFormat ToFileFormat() SortAscending = Ui.ColumnSort.SortAscending }, GameDirs = Ui.GameDirs, + ShownFileTypes = new ShownFileTypes + { + NSP = Ui.ShownFileTypes.NSP, + PFS0 = Ui.ShownFileTypes.PFS0, + XCI = Ui.ShownFileTypes.XCI, + NCA = Ui.ShownFileTypes.NCA, + NRO = Ui.ShownFileTypes.NRO, + NSO = Ui.ShownFileTypes.NSO, + }, LanguageCode = Ui.LanguageCode, EnableCustomTheme = Ui.EnableCustomTheme, CustomThemePath = Ui.CustomThemePath, @@ -702,7 +740,13 @@ public void LoadDefault() Ui.ColumnSort.SortColumnId.Value = 0; Ui.ColumnSort.SortAscending.Value = false; Ui.GameDirs.Value = new List(); - Ui.EnableCustomTheme.Value = false; + Ui.ShownFileTypes.NSP.Value = true; + Ui.ShownFileTypes.PFS0.Value = true; + Ui.ShownFileTypes.XCI.Value = true; + Ui.ShownFileTypes.NCA.Value = true; + Ui.ShownFileTypes.NRO.Value = true; + Ui.ShownFileTypes.NSO.Value = true; + Ui.EnableCustomTheme.Value = true; Ui.LanguageCode.Value = "en_US"; Ui.CustomThemePath.Value = ""; Ui.BaseStyle.Value = "Dark"; @@ -1238,7 +1282,7 @@ public ConfigurationLoadResult Load(ConfigurationFileFormat configurationFileFor if (configurationFileFormat.Version < 44) { - Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 42."); + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 44."); configurationFileFormat.AntiAliasing = AntiAliasing.None; configurationFileFormat.ScalingFilter = ScalingFilter.Bilinear; @@ -1247,6 +1291,23 @@ public ConfigurationLoadResult Load(ConfigurationFileFormat configurationFileFor configurationFileUpdated = true; } + if (configurationFileFormat.Version < 45) + { + Ryujinx.Common.Logging.Logger.Warning?.Print(LogClass.Application, $"Outdated configuration version {configurationFileFormat.Version}, migrating to version 45."); + + configurationFileFormat.ShownFileTypes = new ShownFileTypes + { + NSP = true, + PFS0 = true, + XCI = true, + NCA = true, + NRO = true, + NSO = true + }; + + configurationFileUpdated = true; + } + Logger.EnableFileLog.Value = configurationFileFormat.EnableFileLog; Graphics.ResScale.Value = configurationFileFormat.ResScale; Graphics.ResScaleCustom.Value = configurationFileFormat.ResScaleCustom; @@ -1305,6 +1366,12 @@ public ConfigurationLoadResult Load(ConfigurationFileFormat configurationFileFor Ui.ColumnSort.SortColumnId.Value = configurationFileFormat.ColumnSort.SortColumnId; Ui.ColumnSort.SortAscending.Value = configurationFileFormat.ColumnSort.SortAscending; Ui.GameDirs.Value = configurationFileFormat.GameDirs; + Ui.ShownFileTypes.NSP.Value = configurationFileFormat.ShownFileTypes.NSP; + Ui.ShownFileTypes.PFS0.Value = configurationFileFormat.ShownFileTypes.PFS0; + Ui.ShownFileTypes.XCI.Value = configurationFileFormat.ShownFileTypes.XCI; + Ui.ShownFileTypes.NCA.Value = configurationFileFormat.ShownFileTypes.NCA; + Ui.ShownFileTypes.NRO.Value = configurationFileFormat.ShownFileTypes.NRO; + Ui.ShownFileTypes.NSO.Value = configurationFileFormat.ShownFileTypes.NSO; Ui.EnableCustomTheme.Value = configurationFileFormat.EnableCustomTheme; Ui.LanguageCode.Value = configurationFileFormat.LanguageCode; Ui.CustomThemePath.Value = configurationFileFormat.CustomThemePath; diff --git a/Ryujinx.Ui.Common/Configuration/FileTypes.cs b/Ryujinx.Ui.Common/Configuration/FileTypes.cs new file mode 100644 index 000000000000..0b8b7384bc5f --- /dev/null +++ b/Ryujinx.Ui.Common/Configuration/FileTypes.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.Ui.Common +{ + public enum FileTypes + { + NSP, + PFS0, + XCI, + NCA, + NRO, + NSO + } +} diff --git a/Ryujinx.Ui.Common/Configuration/Ui/ShownFileTypes.cs b/Ryujinx.Ui.Common/Configuration/Ui/ShownFileTypes.cs new file mode 100644 index 000000000000..c0b76e85c0ac --- /dev/null +++ b/Ryujinx.Ui.Common/Configuration/Ui/ShownFileTypes.cs @@ -0,0 +1,12 @@ +namespace Ryujinx.Ui.Common.Configuration.Ui +{ + public struct ShownFileTypes + { + public bool NSP { get; set; } + public bool PFS0 { get; set; } + public bool XCI { get; set; } + public bool NCA { get; set; } + public bool NRO { get; set; } + public bool NSO { get; set; } + } +} diff --git a/Ryujinx.Ui.Common/Extensions/FileTypeExtensions.cs b/Ryujinx.Ui.Common/Extensions/FileTypeExtensions.cs new file mode 100644 index 000000000000..e2ac49504a1b --- /dev/null +++ b/Ryujinx.Ui.Common/Extensions/FileTypeExtensions.cs @@ -0,0 +1,25 @@ +using System; +using static Ryujinx.Ui.Common.Configuration.ConfigurationState.UiSection; + +namespace Ryujinx.Ui.Common +{ + public static class FileTypesExtensions + { + /// + /// Gets the current value for the correlating FileType name. + /// + /// The name of the parameter to get the value of. + /// The config instance to get the value from. + /// The current value of the setting. Value is if the file type is the be shown on the games list, otherwise. + public static bool GetConfigValue(this FileTypes type, ShownFileTypeSettings config) => type switch + { + FileTypes.NSP => config.NSP.Value, + FileTypes.PFS0 => config.PFS0.Value, + FileTypes.XCI => config.XCI.Value, + FileTypes.NCA => config.NCA.Value, + FileTypes.NRO => config.NRO.Value, + FileTypes.NSO => config.NSO.Value, + _ => throw new ArgumentOutOfRangeException(nameof(type), type, null) + }; + } +} diff --git a/Ryujinx/Ui/MainWindow.cs b/Ryujinx/Ui/MainWindow.cs index e0252016fff1..3e513dd28087 100644 --- a/Ryujinx/Ui/MainWindow.cs +++ b/Ryujinx/Ui/MainWindow.cs @@ -119,6 +119,12 @@ public class MainWindow : Window [GUI] CheckMenuItem _fileExtToggle; [GUI] CheckMenuItem _pathToggle; [GUI] CheckMenuItem _fileSizeToggle; + [GUI] CheckMenuItem _nspShown; + [GUI] CheckMenuItem _pfs0Shown; + [GUI] CheckMenuItem _xciShown; + [GUI] CheckMenuItem _ncaShown; + [GUI] CheckMenuItem _nroShown; + [GUI] CheckMenuItem _nsoShown; [GUI] Label _gpuBackend; [GUI] Label _dockedMode; [GUI] Label _aspectRatio; @@ -220,6 +226,20 @@ private MainWindow(Builder builder) : base(builder.GetRawOwnedObject("_mainWin") _pauseEmulation.Sensitive = false; _resumeEmulation.Sensitive = false; + _nspShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value; + _pfs0Shown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value; + _xciShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value; + _ncaShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value; + _nroShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value; + _nsoShown.Active = ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value; + + _nspShown.Toggled += NSP_Shown_Toggled; + _pfs0Shown.Toggled += PFS0_Shown_Toggled; + _xciShown.Toggled += XCI_Shown_Toggled; + _ncaShown.Toggled += NCA_Shown_Toggled; + _nroShown.Toggled += NRO_Shown_Toggled; + _nsoShown.Toggled += NSO_Shown_Toggled; + _fileTypesSubMenu.Visible = FileAssociationHelper.IsTypeAssociationSupported; if (ConfigurationState.Instance.Ui.GuiColumns.FavColumn) _favToggle.Active = true; @@ -1757,6 +1777,54 @@ private void Path_Toggled(object sender, EventArgs args) UpdateColumns(); } + private void NSP_Shown_Toggled(object sender, EventArgs args) + { + ConfigurationState.Instance.Ui.ShownFileTypes.NSP.Value = _nspShown.Active; + + SaveConfig(); + UpdateGameTable(); + } + + private void PFS0_Shown_Toggled(object sender, EventArgs args) + { + ConfigurationState.Instance.Ui.ShownFileTypes.PFS0.Value = _pfs0Shown.Active; + + SaveConfig(); + UpdateGameTable(); + } + + private void XCI_Shown_Toggled (object sender, EventArgs args) + { + ConfigurationState.Instance.Ui.ShownFileTypes.XCI.Value = _xciShown.Active; + + SaveConfig(); + UpdateGameTable(); + } + + private void NCA_Shown_Toggled (object sender, EventArgs args) + { + ConfigurationState.Instance.Ui.ShownFileTypes.NCA.Value = _ncaShown.Active; + + SaveConfig(); + UpdateGameTable(); + } + + private void NRO_Shown_Toggled (object sender, EventArgs args) + { + ConfigurationState.Instance.Ui.ShownFileTypes.NRO.Value = _nroShown.Active; + + SaveConfig(); + UpdateGameTable(); + } + + private void NSO_Shown_Toggled (object sender, EventArgs args) + { + ConfigurationState.Instance.Ui.ShownFileTypes.NSO.Value = _nsoShown.Active; + + SaveConfig(); + UpdateGameTable(); + } + private void RefreshList_Pressed(object sender, ButtonReleaseEventArgs args) { UpdateGameTable(); diff --git a/Ryujinx/Ui/MainWindow.glade b/Ryujinx/Ui/MainWindow.glade index 8ffbb97e53d1..58d5d9558ed8 100644 --- a/Ryujinx/Ui/MainWindow.glade +++ b/Ryujinx/Ui/MainWindow.glade @@ -262,6 +262,75 @@ + + + True + False + Select which file types to show + Show File Types + True + + + True + False + + + True + False + Shows .NSP files in the games list + .NSP + True + + + + + True + False + Shows .PFS0 files in the games list + .PFS0 + True + + + + + True + False + Shows .XCI files in the games list + .XCI + True + + + + + True + False + Shows .NCA files in the games list + .NCA + True + + + + + True + False + Shows .NRO files in the games list + .NRO + True + + + + + True + False + Shows .NSO files in the games list + .NSO + True + + + + + + True