diff --git a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs index f26014821..99e4dc078 100644 --- a/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs +++ b/src/Ryujinx.UI.Common/App/ApplicationLibrary.cs @@ -497,7 +497,6 @@ namespace Ryujinx.UI.App.Common : IntegrityCheckLevel.None; using IFileSystem pfs = PartitionFileSystemUtils.OpenApplicationFileSystem(filePath, _virtualFileSystem); - // Dictionary updates = pfs.GetContentData(ContentMetaType.AddOnContent, _virtualFileSystem, checkLevel); foreach (DirectoryEntryEx fileEntry in pfs.EnumerateEntries("/", "*.nca")) { @@ -517,11 +516,7 @@ namespace Ryujinx.UI.App.Common } } - if (titleUpdates.Count == 0) - { - return false; - } - return true; + return titleUpdates.Count != 0; } } } diff --git a/src/Ryujinx.UI.Common/Models/DownloadableContentModel.cs b/src/Ryujinx.UI.Common/Models/DownloadableContentModel.cs new file mode 100644 index 000000000..6668fb212 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/DownloadableContentModel.cs @@ -0,0 +1,23 @@ +namespace Ryujinx.UI.Common.Models +{ + public class DownloadableContentModel + { + public ulong TitleId { get; } + public string ContainerPath { get; } + public string FullPath { get; } + public bool Enabled { get; } + public bool IsBundled { get; } + + public string FileName => System.IO.Path.GetFileName(ContainerPath); + public string TitleIdStr => TitleId.ToString("X16"); + + public DownloadableContentModel(ulong titleId, string containerPath, string fullPath, bool enabled) + { + TitleId = titleId; + ContainerPath = containerPath; + FullPath = fullPath; + Enabled = enabled; + IsBundled = System.IO.Path.GetExtension(containerPath)?.ToLower() == ".xci"; + } + } +} diff --git a/src/Ryujinx.UI.Common/Models/TitleUpdateModel.cs b/src/Ryujinx.UI.Common/Models/TitleUpdateModel.cs new file mode 100644 index 000000000..259a623f6 --- /dev/null +++ b/src/Ryujinx.UI.Common/Models/TitleUpdateModel.cs @@ -0,0 +1,22 @@ +namespace Ryujinx.UI.Common.Models +{ + public class TitleUpdateModel + { + public ulong TitleId { get; } + public ulong Version { get; } + public string DisplayVersion { get; } + public string Path { get; } + public bool IsBundled { get; } + + public string TitleIdStr => TitleId.ToString("X16"); + + public TitleUpdateModel(ulong titleId, ulong version, string displayVersion, string path) + { + TitleId = titleId; + Version = version; + DisplayVersion = displayVersion; + Path = path; + IsBundled = System.IO.Path.GetExtension(path)?.ToLower() == ".xci"; + } + } +} diff --git a/src/Ryujinx/UI/Helpers/DownloadableContentLabelConverter.cs b/src/Ryujinx/UI/Helpers/DownloadableContentLabelConverter.cs new file mode 100644 index 000000000..0ef63e490 --- /dev/null +++ b/src/Ryujinx/UI/Helpers/DownloadableContentLabelConverter.cs @@ -0,0 +1,42 @@ +using Avalonia; +using Avalonia.Data; +using Avalonia.Data.Converters; +using Ryujinx.Ava.Common.Locale; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace Ryujinx.Ava.UI.Helpers +{ + internal class DownloadableContentLabelConverter : IMultiValueConverter + { + public static DownloadableContentLabelConverter Instance = new(); + + public object Convert(IList values, Type targetType, object parameter, CultureInfo culture) + { + if (values.Any(it => it is UnsetValueType)) + { + return BindingOperations.DoNothing; + } + + if (values.Count != 2 || !targetType.IsAssignableFrom(typeof(string))) + { + return null; + } + + if (values is not [string label, bool isBundled]) + { + return null; + } + + return isBundled ? $"{LocaleManager.Instance[LocaleKeys.TitleBundledDlcLabel]} {label}" : label; + } + + public object[] ConvertBack(object[] values, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + + } +} diff --git a/src/Ryujinx/UI/Helpers/TitleUpdateLabelConverter.cs b/src/Ryujinx/UI/Helpers/TitleUpdateLabelConverter.cs new file mode 100644 index 000000000..f454d7620 --- /dev/null +++ b/src/Ryujinx/UI/Helpers/TitleUpdateLabelConverter.cs @@ -0,0 +1,42 @@ +using Avalonia; +using Avalonia.Data; +using Avalonia.Data.Converters; +using Ryujinx.Ava.Common.Locale; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace Ryujinx.Ava.UI.Helpers +{ + internal class TitleUpdateLabelConverter : IMultiValueConverter + { + public static TitleUpdateLabelConverter Instance = new(); + + public object Convert(IList values, Type targetType, object parameter, CultureInfo culture) + { + if (values.Any(it => it is UnsetValueType)) + { + return BindingOperations.DoNothing; + } + + if (values.Count != 2 || !targetType.IsAssignableFrom(typeof(string))) + { + return null; + } + + if (values is not [string label, bool isBundled]) + { + return null; + } + + var key = isBundled ? LocaleKeys.TitleBundledUpdateVersionLabel : LocaleKeys.TitleUpdateVersionLabel; + return LocaleManager.Instance.UpdateAndGetDynamicValue(key, label); + } + + public object[] ConvertBack(object[] values, Type[] targetTypes, object parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } + } +} diff --git a/src/Ryujinx/UI/Models/DownloadableContentModel.cs b/src/Ryujinx/UI/Models/DownloadableContentModel.cs deleted file mode 100644 index 1409d9713..000000000 --- a/src/Ryujinx/UI/Models/DownloadableContentModel.cs +++ /dev/null @@ -1,39 +0,0 @@ -using Ryujinx.Ava.Common.Locale; -using Ryujinx.Ava.UI.ViewModels; -using System.IO; - -namespace Ryujinx.Ava.UI.Models -{ - public class DownloadableContentModel : BaseModel - { - private bool _enabled; - - public bool Enabled - { - get => _enabled; - set - { - _enabled = value; - - OnPropertyChanged(); - } - } - - public string TitleId { get; } - public string ContainerPath { get; } - public string FullPath { get; } - - public string FileName => Path.GetFileName(ContainerPath); - - public string Label => - Path.GetExtension(FileName)?.ToLower() == ".xci" ? $"{LocaleManager.Instance[LocaleKeys.TitleBundledDlcLabel]} {FileName}" : FileName; - - public DownloadableContentModel(string titleId, string containerPath, string fullPath, bool enabled) - { - TitleId = titleId; - ContainerPath = containerPath; - FullPath = fullPath; - Enabled = enabled; - } - } -} diff --git a/src/Ryujinx/UI/Models/TitleUpdateModel.cs b/src/Ryujinx/UI/Models/TitleUpdateModel.cs deleted file mode 100644 index 46f6f46d8..000000000 --- a/src/Ryujinx/UI/Models/TitleUpdateModel.cs +++ /dev/null @@ -1,21 +0,0 @@ -using Ryujinx.Ava.Common.Locale; - -namespace Ryujinx.Ava.UI.Models -{ - public class TitleUpdateModel - { - public uint Version { get; } - public string Path { get; } - public string Label { get; } - - public TitleUpdateModel(uint version, string displayVersion, string path) - { - Version = version; - Label = LocaleManager.Instance.UpdateAndGetDynamicValue( - System.IO.Path.GetExtension(path)?.ToLower() == ".xci" ? LocaleKeys.TitleBundledUpdateVersionLabel : LocaleKeys.TitleUpdateVersionLabel, - displayVersion - ); - Path = path; - } - } -} diff --git a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs index c919a7ad1..defe99dde 100644 --- a/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/DownloadableContentManagerViewModel.cs @@ -19,6 +19,7 @@ using Ryujinx.HLE.FileSystem; using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Utilities; using Ryujinx.UI.App.Common; +using Ryujinx.UI.Common.Models; using System; using System.Collections.Generic; using System.IO; @@ -142,7 +143,7 @@ namespace Ryujinx.Ava.UI.ViewModels Nca nca = TryOpenNca(ncaFile.Get.AsStorage(), downloadableContentContainer.ContainerPath); if (nca != null) { - var content = new DownloadableContentModel(nca.Header.TitleId.ToString("X16"), + var content = new DownloadableContentModel(nca.Header.TitleId, downloadableContentContainer.ContainerPath, downloadableContentNca.FullPath, downloadableContentNca.Enabled); @@ -183,7 +184,7 @@ namespace Ryujinx.Ava.UI.ViewModels { if (arg is DownloadableContentModel content) { - return string.IsNullOrWhiteSpace(_search) || content.FileName.ToLower().Contains(_search.ToLower()) || content.TitleId.ToLower().Contains(_search.ToLower()); + return string.IsNullOrWhiteSpace(_search) || content.FileName.ToLower().Contains(_search.ToLower()) || content.TitleIdStr.ToLower().Contains(_search.ToLower()); } return false; @@ -261,7 +262,7 @@ namespace Ryujinx.Ava.UI.ViewModels continue; } - var content = new DownloadableContentModel(nca.Header.TitleId.ToString("X16"), path, fileEntry.FullPath, true); + var content = new DownloadableContentModel(nca.Header.TitleId, path, fileEntry.FullPath, true); DownloadableContents.Add(content); Dispatcher.UIThread.InvokeAsync(() => SelectedDownloadableContents.Add(content)); @@ -327,7 +328,7 @@ namespace Ryujinx.Ava.UI.ViewModels container.DownloadableContentNcaList.Add(new DownloadableContentNca { Enabled = downloadableContent.Enabled, - TitleId = Convert.ToUInt64(downloadableContent.TitleId, 16), + TitleId = downloadableContent.TitleId, FullPath = downloadableContent.FullPath, }); } diff --git a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs index e9b39dfe1..3f6cc46b7 100644 --- a/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/TitleUpdateViewModel.cs @@ -20,6 +20,7 @@ using Ryujinx.HLE.Loaders.Processes.Extensions; using Ryujinx.HLE.Utilities; using Ryujinx.UI.App.Common; using Ryujinx.UI.Common.Configuration; +using Ryujinx.UI.Common.Models; using System; using System.Collections.Generic; using System.IO; @@ -190,7 +191,7 @@ namespace Ryujinx.Ava.UI.ViewModels nacpFile.Get.Read(out _, 0, SpanHelpers.AsByteSpan(ref controlData), ReadOption.None).ThrowIfFailure(); var displayVersion = controlData.DisplayVersionString.ToString(); - var update = new TitleUpdateModel(content.Version.Version, displayVersion, path); + var update = new TitleUpdateModel(content.ApplicationId, content.Version.Version, displayVersion, path); TitleUpdates.Add(update); diff --git a/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml b/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml index 98aac09ce..a94e78630 100644 --- a/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml +++ b/src/Ryujinx/UI/Windows/DownloadableContentManagerWindow.axaml @@ -6,13 +6,17 @@ xmlns:locale="clr-namespace:Ryujinx.Ava.Common.Locale" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:viewModels="clr-namespace:Ryujinx.Ava.UI.ViewModels" - xmlns:models="clr-namespace:Ryujinx.Ava.UI.Models" + xmlns:models="clr-namespace:Ryujinx.UI.Common.Models;assembly=Ryujinx.UI.Common" xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" + xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" Width="500" Height="380" mc:Ignorable="d" x:DataType="viewModels:DownloadableContentManagerViewModel" Focusable="True"> + + + @@ -96,8 +100,14 @@ VerticalAlignment="Center" MaxLines="2" TextWrapping="Wrap" - TextTrimming="CharacterEllipsis" - Text="{Binding Label}" /> + TextTrimming="CharacterEllipsis"> + + + + + + + + + + @@ -38,8 +42,14 @@ + TextWrapping="Wrap"> + + + + + + +