diff --git a/src/Ryujinx/Assets/locales.json b/src/Ryujinx/Assets/locales.json index 9f9053ae0..8ec664c81 100644 --- a/src/Ryujinx/Assets/locales.json +++ b/src/Ryujinx/Assets/locales.json @@ -1524,6 +1524,156 @@ }, { "ID": "GameListHeaderDeveloper", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Developed by {0}", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "GameListHeaderVersion", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "Έκδοση: {0}", + "en_US": "Version: {0}", + "es_ES": "Versión: {0}", + "fr_FR": "", + "he_IL": "", + "it_IT": "Versione: {0}", + "ja_JP": "バージョン: {0}", + "ko_KR": "버전: {0}", + "no_NO": "Versjon: {0}", + "pl_PL": "Wersja: {0}", + "pt_BR": "Versão: {0}", + "ru_RU": "Версия: {0}", + "sv_SE": "", + "th_TH": "เวอร์ชั่น: {0}", + "tr_TR": "Sürüm: {0}", + "uk_UA": "Версія: {0}", + "zh_CN": "版本: {0}", + "zh_TW": "版本: {0}" + } + }, + { + "ID": "GameListHeaderTimePlayed", + "Translations": { + "ar_SA": "", + "de_DE": "Spielzeit: {0}", + "el_GR": "Χρόνος: {0}", + "en_US": "Play Time: {0}", + "es_ES": "Tiempo jugado: {0}", + "fr_FR": "Temps de jeu: {0}", + "he_IL": "", + "it_IT": "Tempo di gioco: {0}", + "ja_JP": "プレイ時間: {0}", + "ko_KR": "플레이 타임: {0}", + "no_NO": "Spilletid: {0}", + "pl_PL": "Czas w grze: {0}", + "pt_BR": "Tempo de jogo: {0}", + "ru_RU": "Время в игре: {0}", + "sv_SE": "Speltid: {0}", + "th_TH": "เล่นไปแล้ว: {0}", + "tr_TR": "Oynama Süresi: {0}", + "uk_UA": "Зіграно часу: {0}", + "zh_CN": "游玩时长: {0}", + "zh_TW": "遊玩時數: {0}" + } + }, + { + "ID": "GameListHeaderLastPlayed", + "Translations": { + "ar_SA": "", + "de_DE": "Zuletzt gespielt: {0}", + "el_GR": "Παίχτηκε: {0}", + "en_US": "Last Played: {0}", + "es_ES": "Jugado por última vez: {0}", + "fr_FR": "Dernière partie jouée: {0}", + "he_IL": "", + "it_IT": "Ultima partita: {0}", + "ja_JP": "最終プレイ日時: {0}", + "ko_KR": "마지막 플레이: {0}", + "no_NO": "Sist Spilt: {0}", + "pl_PL": "Ostatnio grane: {0}", + "pt_BR": "Último jogo: {0}", + "ru_RU": "Последний запуск: {0}", + "sv_SE": "Senast spelad: {0}", + "th_TH": "เล่นล่าสุด: {0}", + "tr_TR": "Son Oynama Tarihi: {0}", + "uk_UA": "Востаннє зіграно: {0}", + "zh_CN": "最近游玩: {0}", + "zh_TW": "最近遊玩: {0}" + } + }, + { + "ID": "GameListHeaderFileExtension", + "Translations": { + "ar_SA": "", + "de_DE": "Dateiformat: {0}", + "el_GR": "Κατάληξη: {0}", + "en_US": "Extension: {0}", + "es_ES": "Extensión: {0}", + "fr_FR": "Extension du Fichier: {0}", + "he_IL": "", + "it_IT": "Estensione: {0}", + "ja_JP": "ファイル拡張子: {0}", + "ko_KR": "파일 확장자: {0}", + "no_NO": "Fil Eks.: {0}", + "pl_PL": "Rozszerzenie pliku: {0}", + "pt_BR": "Extensão: {0}", + "ru_RU": "Расширение файла: {0}", + "sv_SE": "Filänd: {0}", + "th_TH": "นามสกุลไฟล์: {0}", + "tr_TR": "Dosya Uzantısı: {0}", + "uk_UA": "Розширення файлу: {0}", + "zh_CN": "扩展名: {0}", + "zh_TW": "副檔名: {0}" + } + }, + { + "ID": "GameListHeaderFileSize", + "Translations": { + "ar_SA": "", + "de_DE": "Dateigröße: {0}", + "el_GR": "Μέγεθος Αρχείου: {0}", + "en_US": "File Size: {0}", + "es_ES": "Tamaño del archivo: {0}", + "fr_FR": "Taille du Fichier: {0}", + "he_IL": "", + "it_IT": "Dimensione file: {0}", + "ja_JP": "ファイルサイズ: {0}", + "ko_KR": "파일 크기: {0}", + "no_NO": "Fil Størrelse: {0}", + "pl_PL": "Rozmiar pliku: {0}", + "pt_BR": "Tamanho: {0}", + "ru_RU": "Размер файла: {0}", + "sv_SE": "Filstorlek: {0}", + "th_TH": "ขนาดไฟล์: {0}", + "tr_TR": "Dosya Boyutu: {0}", + "uk_UA": "Розмір файлу: {0}", + "zh_CN": "大小: {0}", + "zh_TW": "檔案大小: {0}" + } + }, + { + "ID": "GameListSortDeveloper", "Translations": { "ar_SA": "المطور", "de_DE": "Entwickler", @@ -1548,32 +1698,7 @@ } }, { - "ID": "GameListHeaderVersion", - "Translations": { - "ar_SA": "الإصدار", - "de_DE": "", - "el_GR": "Έκδοση", - "en_US": "Version", - "es_ES": "Versión", - "fr_FR": "", - "he_IL": "גרסה", - "it_IT": "Versione", - "ja_JP": "バージョン", - "ko_KR": "버전", - "no_NO": "Versjon", - "pl_PL": "Wersja", - "pt_BR": "Versão", - "ru_RU": "Версия", - "sv_SE": "", - "th_TH": "เวอร์ชั่น", - "tr_TR": "Sürüm", - "uk_UA": "Версія", - "zh_CN": "版本", - "zh_TW": "版本" - } - }, - { - "ID": "GameListHeaderTimePlayed", + "ID": "GameListSortTimePlayed", "Translations": { "ar_SA": "وقت اللعب", "de_DE": "Spielzeit", @@ -1598,7 +1723,7 @@ } }, { - "ID": "GameListHeaderLastPlayed", + "ID": "GameListSortLastPlayed", "Translations": { "ar_SA": "آخر مرة لُعبت", "de_DE": "Zuletzt gespielt", @@ -1623,7 +1748,7 @@ } }, { - "ID": "GameListHeaderFileExtension", + "ID": "GameListSortFileExtension", "Translations": { "ar_SA": "صيغة الملف", "de_DE": "Dateiformat", @@ -1648,7 +1773,7 @@ } }, { - "ID": "GameListHeaderFileSize", + "ID": "GameListSortFileSize", "Translations": { "ar_SA": "حجم الملف", "de_DE": "Dateigröße", @@ -1673,7 +1798,7 @@ } }, { - "ID": "GameListHeaderPath", + "ID": "GameListSortPath", "Translations": { "ar_SA": "المسار", "de_DE": "Pfad", @@ -1697,6 +1822,106 @@ "zh_TW": "路徑" } }, + { + "ID": "GameListHeaderCompatibilityStatus", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Compatibility:", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "GameListHeaderTitleId", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Title ID:", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "GameListHeaderHostedGames", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Hosted Games: {0}", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, + { + "ID": "GameListHeaderPlayerCount", + "Translations": { + "ar_SA": "", + "de_DE": "", + "el_GR": "", + "en_US": "Online Players: {0}", + "es_ES": "", + "fr_FR": "", + "he_IL": "", + "it_IT": "", + "ja_JP": "", + "ko_KR": "", + "no_NO": "", + "pl_PL": "", + "pt_BR": "", + "ru_RU": "", + "sv_SE": "", + "th_TH": "", + "tr_TR": "", + "uk_UA": "", + "zh_CN": "", + "zh_TW": "" + } + }, { "ID": "GameListContextMenuOpenUserSaveDirectory", "Translations": { @@ -2578,7 +2803,7 @@ "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Show Game Stats", + "en_US": "Show Game Info", "es_ES": "", "fr_FR": "", "he_IL": "", @@ -2603,7 +2828,7 @@ "ar_SA": "", "de_DE": "", "el_GR": "", - "en_US": "Show the other various information about the currently selected game that is missing from the Grid view layout.", + "en_US": "Show stats & details about the currently selected game.", "es_ES": "", "fr_FR": "", "he_IL": "", diff --git a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml index acade1df9..3e47a1910 100644 --- a/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml +++ b/src/Ryujinx/UI/Controls/ApplicationContextMenu.axaml @@ -26,7 +26,6 @@ Icon="{ext:Icon mdi-gamepad}" ToolTip.Tip="{ext:Locale GameListContextMenuShowCompatEntryToolTip}"/> - - - - - - - - - - - - - - - - + x:DataType="viewModels:ApplicationDataViewModel"> + + + + + + + + + + + + + + + + + + + + + + + + + + - - + diff --git a/src/Ryujinx/UI/Controls/ApplicationDataView.axaml.cs b/src/Ryujinx/UI/Controls/ApplicationDataView.axaml.cs index 0bd22a243..e85e1188e 100644 --- a/src/Ryujinx/UI/Controls/ApplicationDataView.axaml.cs +++ b/src/Ryujinx/UI/Controls/ApplicationDataView.axaml.cs @@ -23,10 +23,12 @@ namespace Ryujinx.Ava.UI.Controls { ContentDialog contentDialog = new() { + Title = appData.Name, PrimaryButtonText = string.Empty, SecondaryButtonText = string.Empty, CloseButtonText = LocaleManager.Instance[LocaleKeys.SettingsButtonClose], - Content = new ApplicationDataView { DataContext = appData } + MinWidth = 256, + Content = new ApplicationDataView { DataContext = new ApplicationDataViewModel(appData) } }; Style closeButton = new(x => x.Name("CloseButton")); diff --git a/src/Ryujinx/UI/Controls/ApplicationListView.axaml b/src/Ryujinx/UI/Controls/ApplicationListView.axaml index 151bf5b32..ab4b38621 100644 --- a/src/Ryujinx/UI/Controls/ApplicationListView.axaml +++ b/src/Ryujinx/UI/Controls/ApplicationListView.axaml @@ -140,7 +140,8 @@ TextWrapping="Wrap" /> diff --git a/src/Ryujinx/UI/Helpers/Converters/MultiplayerInfoConverter.cs b/src/Ryujinx/UI/Helpers/Converters/MultiplayerInfoConverter.cs index 47d0b94d0..7694e8883 100644 --- a/src/Ryujinx/UI/Helpers/Converters/MultiplayerInfoConverter.cs +++ b/src/Ryujinx/UI/Helpers/Converters/MultiplayerInfoConverter.cs @@ -1,27 +1,31 @@ using Avalonia.Data.Converters; using Avalonia.Markup.Xaml; +using Gommon; +using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Utilities.AppLibrary; using System; using System.Globalization; +using System.Text; namespace Ryujinx.Ava.UI.Helpers { internal class MultiplayerInfoConverter : MarkupExtension, IValueConverter { - private static readonly MultiplayerInfoConverter _instance = new(); + public static readonly MultiplayerInfoConverter Instance = new(); public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { - if (value is ApplicationData applicationData) - { - if (applicationData.PlayerCount != 0 && applicationData.GameCount != 0) - { - return $"Hosted Games: {applicationData.GameCount}\nOnline Players: {applicationData.PlayerCount}"; - } - } - - return ""; + if (value is not ApplicationData { HasLdnGames: true } applicationData) + return ""; + return new StringBuilder() + .AppendLine( + LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames] + .Format(applicationData.GameCount)) + .Append( + LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount] + .Format(applicationData.PlayerCount)) + .ToString(); } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) @@ -31,7 +35,7 @@ namespace Ryujinx.Ava.UI.Helpers public override object ProvideValue(IServiceProvider serviceProvider) { - return _instance; + return Instance; } } } diff --git a/src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs b/src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs new file mode 100644 index 000000000..9e0a3554a --- /dev/null +++ b/src/Ryujinx/UI/ViewModels/ApplicationDataViewModel.cs @@ -0,0 +1,26 @@ +using Gommon; +using Ryujinx.Ava.Common.Locale; +using Ryujinx.Ava.Utilities.AppLibrary; + +namespace Ryujinx.Ava.UI.ViewModels +{ + public class ApplicationDataViewModel : BaseModel + { + public ApplicationData AppData { get; } + + public ApplicationDataViewModel(ApplicationData appData) => AppData = appData; + + public string FormattedVersion => LocaleManager.Instance[LocaleKeys.GameListHeaderVersion].Format(AppData.Version); + public string FormattedDeveloper => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper].Format(AppData.Developer); + + public string FormattedFileExtension => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension].Format(AppData.FileExtension); + public string FormattedLastPlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderLastPlayed].Format(AppData.LastPlayedString); + public string FormattedPlayTime => LocaleManager.Instance[LocaleKeys.GameListHeaderTimePlayed].Format(AppData.TimePlayedString); + public string FormattedFileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize].Format(AppData.FileSizeString); + + public string FormattedLdnInfo => + $"{LocaleManager.Instance[LocaleKeys.GameListHeaderHostedGames].Format(AppData.GameCount)}" + + $"\n" + + $"{LocaleManager.Instance[LocaleKeys.GameListHeaderPlayerCount].Format(AppData.PlayerCount)}"; + } +} diff --git a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs index d7a09a0e3..499eedc8d 100644 --- a/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs +++ b/src/Ryujinx/UI/ViewModels/MainWindowViewModel.cs @@ -633,15 +633,15 @@ namespace Ryujinx.Ava.UI.ViewModels { return SortMode switch { - ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication], - ApplicationSort.Developer => LocaleManager.Instance[LocaleKeys.GameListHeaderDeveloper], - ApplicationSort.LastPlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderLastPlayed], - ApplicationSort.TotalTimePlayed => LocaleManager.Instance[LocaleKeys.GameListHeaderTimePlayed], - ApplicationSort.FileType => LocaleManager.Instance[LocaleKeys.GameListHeaderFileExtension], - ApplicationSort.FileSize => LocaleManager.Instance[LocaleKeys.GameListHeaderFileSize], - ApplicationSort.Path => LocaleManager.Instance[LocaleKeys.GameListHeaderPath], ApplicationSort.Favorite => LocaleManager.Instance[LocaleKeys.CommonFavorite], ApplicationSort.TitleId => LocaleManager.Instance[LocaleKeys.DlcManagerTableHeadingTitleIdLabel], + ApplicationSort.Title => LocaleManager.Instance[LocaleKeys.GameListHeaderApplication], + ApplicationSort.Developer => LocaleManager.Instance[LocaleKeys.GameListSortDeveloper], + ApplicationSort.LastPlayed => LocaleManager.Instance[LocaleKeys.GameListSortLastPlayed], + ApplicationSort.TotalTimePlayed => LocaleManager.Instance[LocaleKeys.GameListSortTimePlayed], + ApplicationSort.FileType => LocaleManager.Instance[LocaleKeys.GameListSortFileExtension], + ApplicationSort.FileSize => LocaleManager.Instance[LocaleKeys.GameListSortFileSize], + ApplicationSort.Path => LocaleManager.Instance[LocaleKeys.GameListSortPath], _ => string.Empty, }; } diff --git a/src/Ryujinx/UI/Views/Main/MainViewControls.axaml b/src/Ryujinx/UI/Views/Main/MainViewControls.axaml index cdc66a138..db557b417 100644 --- a/src/Ryujinx/UI/Views/Main/MainViewControls.axaml +++ b/src/Ryujinx/UI/Views/Main/MainViewControls.axaml @@ -113,37 +113,37 @@ Tag="TitleId" /> diff --git a/src/Ryujinx/Utilities/AppLibrary/ApplicationData.cs b/src/Ryujinx/Utilities/AppLibrary/ApplicationData.cs index aef54819e..48e30e663 100644 --- a/src/Ryujinx/Utilities/AppLibrary/ApplicationData.cs +++ b/src/Ryujinx/Utilities/AppLibrary/ApplicationData.cs @@ -49,6 +49,9 @@ namespace Ryujinx.Ava.Utilities.AppLibrary public int PlayerCount { get; set; } public int GameCount { get; set; } + + public bool HasLdnGames => PlayerCount != 0 && GameCount != 0; + public TimeSpan TimePlayed { get; set; } public DateTime? LastPlayed { get; set; } public string FileExtension { get; set; }