diff --git a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs index 65cf7a9e6..ccd707058 100644 --- a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs +++ b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs @@ -41,6 +41,7 @@ namespace Ryujinx.UI.App.Common private readonly byte[] _ncaIcon; private readonly byte[] _nroIcon; private readonly byte[] _nsoIcon; + private readonly byte[] _folderIcon; private readonly VirtualFileSystem _virtualFileSystem; private Language _desiredTitleLanguage; @@ -58,6 +59,7 @@ namespace Ryujinx.UI.App.Common _ncaIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NCA.png"); _nroIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NRO.png"); _nsoIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_NSO.png"); + _folderIcon = GetResourceBytes("Ryujinx.UI.Common.Resources.Icon_Folder.png"); } private static byte[] GetResourceBytes(string resourceName) @@ -113,7 +115,31 @@ namespace Ryujinx.UI.App.Common try { - IEnumerable files = Directory.EnumerateFiles(appDir, "*", SearchOption.AllDirectories).Where(file => + IEnumerable folders = Directory.EnumerateDirectories(appDir, "*", SearchOption.TopDirectoryOnly); + foreach (string folder in folders) + { + if (_cancellationToken.Token.IsCancellationRequested) + { + return; + } + + var fileInfo = new FileInfo(folder); + + var fullPath = fileInfo.ResolveLinkTarget(true)?.FullName ?? fileInfo.FullName; + ApplicationData folderData = new() + { + TitleName = fileInfo.Name, + FileExtension = "Folder", + Path = fullPath, + Icon = _folderIcon, + }; + OnApplicationAdded(new ApplicationAddedEventArgs + { + AppData = folderData, + }); + } + + IEnumerable files = Directory.EnumerateFiles(appDir, "*", SearchOption.TopDirectoryOnly).Where(file => { return (Path.GetExtension(file).ToLower() is ".nsp" && ConfigurationState.Instance.UI.ShownFileTypes.NSP.Value) || @@ -163,7 +189,26 @@ namespace Ryujinx.UI.App.Common return; } - long fileSize = new FileInfo(applicationPath).Length; + var fileInfo = new FileInfo(applicationPath); + + if ((fileInfo.Attributes & FileAttributes.Directory) == FileAttributes.Directory) + { + Console.WriteLine($"Found directory 2: {fileInfo.Name}"); + ApplicationData folder = new() + { + TitleName = fileInfo.Name, + FileExtension = "Folder", + Developer = "null", + Path = applicationPath, + Icon = _nsoIcon, + }; + OnApplicationAdded(new ApplicationAddedEventArgs + { + AppData = folder, + }); + } + + long fileSize = fileInfo.Length; string titleName = "Unknown"; string titleId = "0000000000000000"; string developer = "Unknown"; diff --git a/src/Ryujinx.UI.Common/Resources/Icon_Folder.png b/src/Ryujinx.UI.Common/Resources/Icon_Folder.png new file mode 100644 index 000000000..dba7ff44d Binary files /dev/null and b/src/Ryujinx.UI.Common/Resources/Icon_Folder.png differ diff --git a/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj b/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj index 387e998b0..eb84aad61 100644 --- a/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj +++ b/src/Ryujinx.UI.Common/Ryujinx.UI.Common.csproj @@ -15,6 +15,7 @@ + @@ -33,6 +34,7 @@ + diff --git a/src/Ryujinx/UI/Helpers/Glyph.cs b/src/Ryujinx/UI/Helpers/Glyph.cs index f257dc02c..d44f0875a 100644 --- a/src/Ryujinx/UI/Helpers/Glyph.cs +++ b/src/Ryujinx/UI/Helpers/Glyph.cs @@ -4,6 +4,7 @@ namespace Ryujinx.Ava.UI.Helpers { List, Grid, + Back, Chip, } } diff --git a/src/Ryujinx/UI/Helpers/GlyphValueConverter.cs b/src/Ryujinx/UI/Helpers/GlyphValueConverter.cs index 7da23648e..9731123e9 100644 --- a/src/Ryujinx/UI/Helpers/GlyphValueConverter.cs +++ b/src/Ryujinx/UI/Helpers/GlyphValueConverter.cs @@ -13,6 +13,7 @@ namespace Ryujinx.Ava.UI.Helpers { { Glyph.List, char.ConvertFromUtf32((int)Symbol.List) }, { Glyph.Grid, char.ConvertFromUtf32((int)Symbol.ViewAll) }, + { Glyph.Back, char.ConvertFromUtf32((int)Symbol.Back) }, { Glyph.Chip, char.ConvertFromUtf32(59748) }, }; diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index 17bd69b14..c5de76f5a 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -51,6 +51,7 @@ namespace Ryujinx.Ava.UI.ViewModels private const int HotKeyPressDelayMs = 500; private ObservableCollection _applications; + private Queue _pathHistory; private string _aspectStatusText; private string _loadHeading; @@ -120,6 +121,7 @@ namespace Ryujinx.Ava.UI.ViewModels .Bind(out _appsObservableList).AsObservableList(); _rendererWaitEvent = new AutoResetEvent(false); + _pathHistory = new Queue(); if (Program.PreviewerDetached) { @@ -1281,6 +1283,34 @@ namespace Ryujinx.Ava.UI.ViewModels ShowConsole = !ShowConsole; } + public void OpenFolder(string path) + { + _pathHistory.Enqueue(path); + Applications.Clear(); + List SearchPaths = new List(); + SearchPaths.Add(path); + ApplicationLibrary.LoadApplications(SearchPaths, ConfigurationState.Instance.System.Language); + } + + public void NavigateBack() + { + if (_pathHistory.Count != 0) + { + string path = _pathHistory.Dequeue(); + Applications.Clear(); + if (_pathHistory.Count == 0) + { + ApplicationLibrary.LoadApplications(ConfigurationState.Instance.UI.GameDirs, ConfigurationState.Instance.System.Language); + } + else + { + List SearchPaths = new List(); + SearchPaths.Add(path); + ApplicationLibrary.LoadApplications(SearchPaths, ConfigurationState.Instance.System.Language); + } + } + } + public void SetListMode() { Glyph = Glyph.List; diff --git a/src/Ryujinx/UI/Views/Main/MainViewControls.axaml b/src/Ryujinx/UI/Views/Main/MainViewControls.axaml index cc21b5c60..b49aaacc2 100644 --- a/src/Ryujinx/UI/Views/Main/MainViewControls.axaml +++ b/src/Ryujinx/UI/Views/Main/MainViewControls.axaml @@ -18,6 +18,19 @@ Margin="0,0,0,5" Height="35" HorizontalAlignment="Stretch"> +