Compare commits

...

6 Commits

12 changed files with 569 additions and 158 deletions

View File

@@ -1524,6 +1524,156 @@
}, },
{ {
"ID": "GameListHeaderDeveloper", "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": { "Translations": {
"ar_SA": "المطور", "ar_SA": "المطور",
"de_DE": "Entwickler", "de_DE": "Entwickler",
@@ -1548,32 +1698,7 @@
} }
}, },
{ {
"ID": "GameListHeaderVersion", "ID": "GameListSortTimePlayed",
"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",
"Translations": { "Translations": {
"ar_SA": "وقت اللعب", "ar_SA": "وقت اللعب",
"de_DE": "Spielzeit", "de_DE": "Spielzeit",
@@ -1598,7 +1723,7 @@
} }
}, },
{ {
"ID": "GameListHeaderLastPlayed", "ID": "GameListSortLastPlayed",
"Translations": { "Translations": {
"ar_SA": "آخر مرة لُعبت", "ar_SA": "آخر مرة لُعبت",
"de_DE": "Zuletzt gespielt", "de_DE": "Zuletzt gespielt",
@@ -1623,7 +1748,7 @@
} }
}, },
{ {
"ID": "GameListHeaderFileExtension", "ID": "GameListSortFileExtension",
"Translations": { "Translations": {
"ar_SA": "صيغة الملف", "ar_SA": "صيغة الملف",
"de_DE": "Dateiformat", "de_DE": "Dateiformat",
@@ -1648,7 +1773,7 @@
} }
}, },
{ {
"ID": "GameListHeaderFileSize", "ID": "GameListSortFileSize",
"Translations": { "Translations": {
"ar_SA": "حجم الملف", "ar_SA": "حجم الملف",
"de_DE": "Dateigröße", "de_DE": "Dateigröße",
@@ -1673,7 +1798,7 @@
} }
}, },
{ {
"ID": "GameListHeaderPath", "ID": "GameListSortPath",
"Translations": { "Translations": {
"ar_SA": "المسار", "ar_SA": "المسار",
"de_DE": "Pfad", "de_DE": "Pfad",
@@ -1697,6 +1822,106 @@
"zh_TW": "路徑" "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", "ID": "GameListContextMenuOpenUserSaveDirectory",
"Translations": { "Translations": {
@@ -2578,7 +2803,7 @@
"ar_SA": "", "ar_SA": "",
"de_DE": "", "de_DE": "",
"el_GR": "", "el_GR": "",
"en_US": "Show Game Stats", "en_US": "Show Game Info",
"es_ES": "", "es_ES": "",
"fr_FR": "", "fr_FR": "",
"he_IL": "", "he_IL": "",
@@ -2603,7 +2828,7 @@
"ar_SA": "", "ar_SA": "",
"de_DE": "", "de_DE": "",
"el_GR": "", "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": "", "es_ES": "",
"fr_FR": "", "fr_FR": "",
"he_IL": "", "he_IL": "",
@@ -23272,6 +23497,131 @@
"zh_TW": "無法啟動" "zh_TW": "無法啟動"
} }
}, },
{
"ID": "CompatibilityListPlayableTooltip",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Boots and plays without any crashes or GPU bugs of any kind, and at a speed fast enough to reasonably enjoy on an average PC.",
"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": "CompatibilityListIngameTooltip",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Boots and goes in-game but suffers from one or more of the following: crashes, deadlocks, GPU bugs, distractingly bad audio, or is simply too slow. Game still might able to be played all the way through, but not as the game is intended to play.",
"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": "CompatibilityListMenusTooltip",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Boots and goes past the title screen but does not make it into main gameplay.",
"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": "CompatibilityListBootsTooltip",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Boots but does not make it past the title screen.",
"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": "CompatibilityListNothingTooltip",
"Translations": {
"ar_SA": "",
"de_DE": "",
"el_GR": "",
"en_US": "Does not boot or shows no signs of activity.",
"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": "ExtractAocListHeader", "ID": "ExtractAocListHeader",
"Translations": { "Translations": {

View File

@@ -26,7 +26,6 @@
Icon="{ext:Icon mdi-gamepad}" Icon="{ext:Icon mdi-gamepad}"
ToolTip.Tip="{ext:Locale GameListContextMenuShowCompatEntryToolTip}"/> ToolTip.Tip="{ext:Locale GameListContextMenuShowCompatEntryToolTip}"/>
<MenuItem <MenuItem
IsVisible="{Binding IsGrid}"
Click="OpenApplicationData_Click" Click="OpenApplicationData_Click"
Header="{ext:Locale GameListContextMenuShowGameData}" Header="{ext:Locale GameListContextMenuShowGameData}"
Icon="{ext:Icon mdi-chart-line}" Icon="{ext:Icon mdi-chart-line}"

View File

@@ -2,115 +2,113 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers" xmlns:helpers="clr-namespace:Ryujinx.Ava.UI.Helpers"
xmlns:ui="clr-namespace:FluentAvalonia.UI.Controls;assembly=FluentAvalonia" xmlns:ext="using:Ryujinx.Ava.Common.Markup"
xmlns:appLibrary="using:Ryujinx.Ava.Utilities.AppLibrary" xmlns:viewModels="using:Ryujinx.Ava.UI.ViewModels"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450"
x:Class="Ryujinx.Ava.UI.Controls.ApplicationDataView" x:Class="Ryujinx.Ava.UI.Controls.ApplicationDataView"
x:DataType="appLibrary:ApplicationData"> x:DataType="viewModels:ApplicationDataViewModel">
<StackPanel Orientation="Vertical"> <StackPanel Orientation="Horizontal">
<Grid <Image Margin="0"
RowDefinitions="Auto, Auto, Auto, Auto" MaxWidth="256"
ColumnDefinitions="*"> MinWidth="256"
<TextBlock Grid.Row="0" Source="{Binding AppData.Icon, Converter={x:Static helpers:BitmapArrayValueConverter.Instance}}" />
HorizontalAlignment="Center" <Border Margin="5, 0" Width="1" Height="256" BorderBrush="Gray" Background="Gray" />
Padding="0, -2, 0, 5" <StackPanel Orientation="Vertical">
Classes="h1" <Grid
Text="{Binding Name}" /> RowDefinitions="Auto,Auto,Auto"
<TextBlock Grid.Row="1" ColumnDefinitions="*">
HorizontalAlignment="Center" <StackPanel Grid.Row="0">
Text="{Binding Version}" <TextBlock HorizontalAlignment="Left"
TextAlignment="Start" Text="{Binding FormattedVersion}"
TextWrapping="Wrap" /> TextAlignment="Start"
<TextBlock Grid.Row="2" TextWrapping="Wrap" />
HorizontalAlignment="Center" <TextBlock HorizontalAlignment="Left"
Text="{Binding Developer}" Text="{Binding FormattedDeveloper}"
TextAlignment="Start" TextAlignment="Start"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<StackPanel Grid.ColumnSpan="2" Grid.Row="3" <TextBlock HorizontalAlignment="Stretch"
HorizontalAlignment="Center" Text="{Binding FormattedFileExtension}"
Orientation="Horizontal" Margin="0 10, 0, 0" TextAlignment="Start"
Spacing="5"> TextWrapping="Wrap" />
<Button <TextBlock HorizontalAlignment="Stretch"
Click="PlayabilityStatus_OnClick" Text="{Binding FormattedFileSize}"
HorizontalContentAlignment="Left" TextAlignment="Start"
VerticalAlignment="Center" TextWrapping="Wrap" />
IsVisible="{Binding HasPlayabilityInfo}" </StackPanel>
Background="{DynamicResource AppListBackgroundColor}" <Separator Grid.Row="1" Margin="0, 10, 0, 10" Height="1" BorderBrush="Gray" Background="Gray" />
Padding="0"> <StackPanel Grid.Row="2"
<TextBlock HorizontalAlignment="Left"
Margin="1.5" Orientation="Vertical"
Tag="{Binding IdString}" Spacing="5">
Text="{Binding LocalizedStatus}" <StackPanel Orientation="Horizontal" IsVisible="{Binding AppData.HasPlayabilityInfo}">
Foreground="{Binding PlayabilityStatus, Converter={x:Static helpers:PlayabilityStatusConverter.Shared}}" <TextBlock Padding="0, 0, 5, 0" Text="{ext:Locale GameListHeaderCompatibilityStatus}" />
TextAlignment="Start" <Button
TextWrapping="Wrap" /> Click="PlayabilityStatus_OnClick"
<Button.Styles> HorizontalContentAlignment="Left"
<Style Selector="Button"> VerticalAlignment="Center"
<Setter Property="MinWidth" Background="{DynamicResource AppListBackgroundColor}"
Value="0" /> Padding="0">
<!-- avoids very wide buttons from the overall project avalonia style --> <TextBlock
</Style> Margin="1.5"
</Button.Styles> Tag="{Binding AppData.IdString}"
</Button> Text="{Binding AppData.LocalizedStatus}"
<Button Foreground="{Binding AppData.PlayabilityStatus, Converter={x:Static helpers:PlayabilityStatusConverter.Shared}}"
Click="IdString_OnClick" ToolTip.Tip="{Binding AppData.LocalizedStatusTooltip}"
HorizontalContentAlignment="Left" TextAlignment="Start"
VerticalAlignment="Center" TextWrapping="Wrap" />
Background="{DynamicResource AppListBackgroundColor}" <Button.Styles>
Padding="0"> <Style Selector="Button">
<TextBlock <Setter Property="MinWidth"
Margin="1.5" Value="0" />
HorizontalAlignment="Stretch" <!-- avoids very wide buttons from the overall project avalonia style -->
Text="{Binding IdString}" </Style>
TextAlignment="Start" </Button.Styles>
TextWrapping="Wrap" /> </Button>
</Button> </StackPanel>
</StackPanel> <StackPanel Orientation="Horizontal">
</Grid> <TextBlock Padding="0, 0, 5, 0" Text="{ext:Locale GameListHeaderTitleId}" />
<Separator Margin="0, 10, 0, 10" /> <Button
<Grid ColumnDefinitions="Auto,*,Auto"> Click="IdString_OnClick"
<StackPanel Grid.Column="0" HorizontalContentAlignment="Left"
Margin="10,0,0,0" VerticalAlignment="Center"
HorizontalAlignment="Left" Background="{DynamicResource AppListBackgroundColor}"
VerticalAlignment="Top" Padding="0">
Orientation="Vertical" <TextBlock
Spacing="5"> Margin="1.5"
<TextBlock HorizontalAlignment="Stretch"
HorizontalAlignment="Stretch" Text="{Binding AppData.IdString}"
Text="{Binding FileExtension}" TextAlignment="Start"
TextAlignment="Start" TextWrapping="Wrap" />
TextWrapping="Wrap" /> </Button>
<TextBlock </StackPanel>
HorizontalAlignment="Stretch" </StackPanel>
Text="{Binding Converter={helpers:MultiplayerInfoConverter}}" </Grid>
TextAlignment="Start" <Separator Margin="0, 10, 0, 10" Height="1" BorderBrush="Gray" Background="Gray" />
TextWrapping="Wrap" /> <TextBlock
</StackPanel> HorizontalAlignment="Stretch"
IsVisible="{Binding AppData.HasLdnGames}"
Text="{Binding FormattedLdnInfo}"
TextAlignment="Start"
TextWrapping="Wrap" />
<Separator IsVisible="{Binding AppData.HasLdnGames}" Margin="0, 10, 0, 10" Height="1" BorderBrush="Gray" Background="Gray" />
<StackPanel <StackPanel
Grid.Column="2" HorizontalAlignment="Left"
Margin="0,0,10,0"
HorizontalAlignment="Right"
VerticalAlignment="Top" VerticalAlignment="Top"
Orientation="Vertical" Orientation="Vertical"
Spacing="5"> Spacing="5">
<TextBlock <TextBlock
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding LastPlayedString}" Text="{Binding FormattedLastPlayed}"
TextAlignment="End" TextAlignment="Start"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<TextBlock <TextBlock
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding TimePlayedString}" Text="{Binding FormattedPlayTime}"
IsVisible="{Binding HasPlayedPreviously}" IsVisible="{Binding AppData.HasPlayedPreviously}"
TextAlignment="End" TextAlignment="Start"
TextWrapping="Wrap" />
<TextBlock
HorizontalAlignment="Stretch"
Text="{Binding FileSizeString}"
TextAlignment="End"
TextWrapping="Wrap" /> TextWrapping="Wrap" />
</StackPanel> </StackPanel>
</Grid> </StackPanel>
</StackPanel> </StackPanel>
</UserControl> </UserControl>

View File

@@ -23,10 +23,12 @@ namespace Ryujinx.Ava.UI.Controls
{ {
ContentDialog contentDialog = new() ContentDialog contentDialog = new()
{ {
Title = appData.Name,
PrimaryButtonText = string.Empty, PrimaryButtonText = string.Empty,
SecondaryButtonText = string.Empty, SecondaryButtonText = string.Empty,
CloseButtonText = LocaleManager.Instance[LocaleKeys.SettingsButtonClose], 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")); Style closeButton = new(x => x.Name("CloseButton"));

View File

@@ -93,7 +93,8 @@
IsVisible="{Binding HasPlayabilityInfo}" IsVisible="{Binding HasPlayabilityInfo}"
Background="{DynamicResource AppListBackgroundColor}" Background="{DynamicResource AppListBackgroundColor}"
Margin="-1, 0, 0, 0" Margin="-1, 0, 0, 0"
Padding="0" > Padding="0"
ToolTip.Tip="{Binding LocalizedStatusTooltip}">
<TextBlock <TextBlock
Margin="1.5" Margin="1.5"
Tag="{Binding IdString}" Tag="{Binding IdString}"
@@ -140,7 +141,8 @@
TextWrapping="Wrap" /> TextWrapping="Wrap" />
<TextBlock <TextBlock
HorizontalAlignment="Stretch" HorizontalAlignment="Stretch"
Text="{Binding Converter={helpers:MultiplayerInfoConverter}}" IsVisible="{Binding HasLdnGames}"
Text="{Binding Converter={x:Static helpers:MultiplayerInfoConverter.Instance}}"
TextAlignment="Start" TextAlignment="Start"
TextWrapping="Wrap"/> TextWrapping="Wrap"/>
</StackPanel> </StackPanel>

View File

@@ -1,27 +1,31 @@
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Avalonia.Markup.Xaml; using Avalonia.Markup.Xaml;
using Gommon;
using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.Utilities.AppLibrary; using Ryujinx.Ava.Utilities.AppLibrary;
using System; using System;
using System.Globalization; using System.Globalization;
using System.Text;
namespace Ryujinx.Ava.UI.Helpers namespace Ryujinx.Ava.UI.Helpers
{ {
internal class MultiplayerInfoConverter : MarkupExtension, IValueConverter 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) public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{ {
if (value is ApplicationData applicationData) if (value is not ApplicationData { HasLdnGames: true } applicationData)
{ return "";
if (applicationData.PlayerCount != 0 && applicationData.GameCount != 0)
{
return $"Hosted Games: {applicationData.GameCount}\nOnline Players: {applicationData.PlayerCount}";
}
}
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) 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) public override object ProvideValue(IServiceProvider serviceProvider)
{ {
return _instance; return Instance;
} }
} }
} }

View File

@@ -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)}";
}
}

View File

@@ -633,15 +633,15 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
return SortMode switch 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.Favorite => LocaleManager.Instance[LocaleKeys.CommonFavorite],
ApplicationSort.TitleId => LocaleManager.Instance[LocaleKeys.DlcManagerTableHeadingTitleIdLabel], 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, _ => string.Empty,
}; };
} }

View File

@@ -113,37 +113,37 @@
Tag="TitleId" /> Tag="TitleId" />
<RadioButton <RadioButton
Checked="Sort_Checked" Checked="Sort_Checked"
Content="{ext:Locale GameListHeaderDeveloper}" Content="{ext:Locale GameListSortDeveloper}"
GroupName="Sort" GroupName="Sort"
IsChecked="{Binding IsSortedByDeveloper, Mode=OneTime}" IsChecked="{Binding IsSortedByDeveloper, Mode=OneTime}"
Tag="Developer" /> Tag="Developer" />
<RadioButton <RadioButton
Checked="Sort_Checked" Checked="Sort_Checked"
Content="{ext:Locale GameListHeaderTimePlayed}" Content="{ext:Locale GameListSortTimePlayed}"
GroupName="Sort" GroupName="Sort"
IsChecked="{Binding IsSortedByTimePlayed, Mode=OneTime}" IsChecked="{Binding IsSortedByTimePlayed, Mode=OneTime}"
Tag="TotalTimePlayed" /> Tag="TotalTimePlayed" />
<RadioButton <RadioButton
Checked="Sort_Checked" Checked="Sort_Checked"
Content="{ext:Locale GameListHeaderLastPlayed}" Content="{ext:Locale GameListSortLastPlayed}"
GroupName="Sort" GroupName="Sort"
IsChecked="{Binding IsSortedByLastPlayed, Mode=OneTime}" IsChecked="{Binding IsSortedByLastPlayed, Mode=OneTime}"
Tag="LastPlayed" /> Tag="LastPlayed" />
<RadioButton <RadioButton
Checked="Sort_Checked" Checked="Sort_Checked"
Content="{ext:Locale GameListHeaderFileExtension}" Content="{ext:Locale GameListSortFileExtension}"
GroupName="Sort" GroupName="Sort"
IsChecked="{Binding IsSortedByType, Mode=OneTime}" IsChecked="{Binding IsSortedByType, Mode=OneTime}"
Tag="FileType" /> Tag="FileType" />
<RadioButton <RadioButton
Checked="Sort_Checked" Checked="Sort_Checked"
Content="{ext:Locale GameListHeaderFileSize}" Content="{ext:Locale GameListSortFileSize}"
GroupName="Sort" GroupName="Sort"
IsChecked="{Binding IsSortedBySize, Mode=OneTime}" IsChecked="{Binding IsSortedBySize, Mode=OneTime}"
Tag="FileSize" /> Tag="FileSize" />
<RadioButton <RadioButton
Checked="Sort_Checked" Checked="Sort_Checked"
Content="{ext:Locale GameListHeaderPath}" Content="{ext:Locale GameListSortPath}"
GroupName="Sort" GroupName="Sort"
IsChecked="{Binding IsSortedByPath, Mode=OneTime}" IsChecked="{Binding IsSortedByPath, Mode=OneTime}"
Tag="Path" /> Tag="Path" />

View File

@@ -46,9 +46,24 @@ namespace Ryujinx.Ava.Utilities.AppLibrary
: string.Empty; : string.Empty;
public LocaleKeys? PlayabilityStatus { get; set; } public LocaleKeys? PlayabilityStatus { get; set; }
public string LocalizedStatusTooltip =>
PlayabilityStatus.HasValue
#pragma warning disable CS8509 // It is exhaustive for any value this property can contain.
? LocaleManager.Instance[PlayabilityStatus!.Value switch
#pragma warning restore CS8509
{
LocaleKeys.CompatibilityListPlayable => LocaleKeys.CompatibilityListPlayableTooltip,
LocaleKeys.CompatibilityListIngame => LocaleKeys.CompatibilityListIngameTooltip,
LocaleKeys.CompatibilityListMenus => LocaleKeys.CompatibilityListMenusTooltip,
LocaleKeys.CompatibilityListBoots => LocaleKeys.CompatibilityListBootsTooltip,
LocaleKeys.CompatibilityListNothing => LocaleKeys.CompatibilityListNothingTooltip,
}]
: string.Empty;
public int PlayerCount { get; set; } public int PlayerCount { get; set; }
public int GameCount { get; set; } public int GameCount { get; set; }
public bool HasLdnGames => PlayerCount != 0 && GameCount != 0;
public TimeSpan TimePlayed { get; set; } public TimeSpan TimePlayed { get; set; }
public DateTime? LastPlayed { get; set; } public DateTime? LastPlayed { get; set; }
public string FileExtension { get; set; } public string FileExtension { get; set; }

View File

@@ -100,12 +100,25 @@ namespace Ryujinx.Ava.Utilities.Compat
public Optional<string> TitleId { get; } public Optional<string> TitleId { get; }
public string[] Labels { get; } public string[] Labels { get; }
public LocaleKeys? Status { get; } public LocaleKeys? Status { get; }
public LocaleKeys? StatusDescription
=> Status switch
{
LocaleKeys.CompatibilityListPlayable => LocaleKeys.CompatibilityListPlayableTooltip,
LocaleKeys.CompatibilityListIngame => LocaleKeys.CompatibilityListIngameTooltip,
LocaleKeys.CompatibilityListMenus => LocaleKeys.CompatibilityListMenusTooltip,
LocaleKeys.CompatibilityListBoots => LocaleKeys.CompatibilityListBootsTooltip,
LocaleKeys.CompatibilityListNothing => LocaleKeys.CompatibilityListNothingTooltip,
_ => null
};
public DateTime LastUpdated { get; } public DateTime LastUpdated { get; }
public string LocalizedLastUpdated => public string LocalizedLastUpdated =>
LocaleManager.FormatDynamicValue(LocaleKeys.CompatibilityListLastUpdated, LastUpdated.Humanize()); LocaleManager.FormatDynamicValue(LocaleKeys.CompatibilityListLastUpdated, LastUpdated.Humanize());
public string LocalizedStatus => LocaleManager.Instance[Status!.Value]; public string LocalizedStatus => LocaleManager.Instance[Status!.Value];
public string LocalizedStatusDescription => LocaleManager.Instance[StatusDescription!.Value];
public string FormattedTitleId => TitleId public string FormattedTitleId => TitleId
.OrElse(new string(' ', 16)); .OrElse(new string(' ', 16));

View File

@@ -64,6 +64,8 @@
VerticalAlignment="Center" VerticalAlignment="Center"
Text="{Binding LocalizedStatus}" Text="{Binding LocalizedStatus}"
Width="85" Width="85"
Background="Transparent"
ToolTip.Tip="{Binding LocalizedStatusDescription}"
Foreground="{Binding Status, Converter={x:Static helpers:PlayabilityStatusConverter.Shared}}" Foreground="{Binding Status, Converter={x:Static helpers:PlayabilityStatusConverter.Shared}}"
TextWrapping="NoWrap" /> TextWrapping="NoWrap" />
<TextBlock Grid.Column="3" <TextBlock Grid.Column="3"