0
0
Fork 0
mirror of https://github.com/GreemDev/Ryujinx.git synced 2025-01-09 22:52:00 +00:00

UI: Abstract applet launch logic for future potential applets

Optimize locale loading (remove always loading english, that was only needed with the old system)
This commit is contained in:
Evan Husted 2024-12-25 00:56:01 -06:00
parent e6644626fc
commit 412d4065b8
3 changed files with 81 additions and 55 deletions

View file

@ -0,0 +1,64 @@
using LibHac.Common;
using LibHac.Ncm;
using LibHac.Ns;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.HLE;
using Ryujinx.HLE.FileSystem;
using Ryujinx.UI.App.Common;
namespace Ryujinx.UI.Common.Helper
{
public readonly struct AppletMetadata
{
private readonly ContentManager _contentManager;
public string Name { get; }
public ulong ProgramId { get; }
public string Version { get; }
public AppletMetadata(ContentManager contentManager, string name, ulong programId, string version = "1.0.0")
: this(name, programId, version)
{
_contentManager = contentManager;
}
public AppletMetadata(string name, ulong programId, string version = "1.0.0")
{
Name = name;
ProgramId = programId;
Version = version;
}
public string GetContentPath(ContentManager contentManager)
=> (contentManager ?? _contentManager)
.GetInstalledContentPath(ProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
public bool CanStart(ContentManager contentManager, out ApplicationData appData, out BlitStruct<ApplicationControlProperty> appControl)
{
contentManager ??= _contentManager;
if (contentManager == null)
{
appData = null;
appControl = new BlitStruct<ApplicationControlProperty>(0);
return false;
}
appData = new()
{
Name = Name,
Id = ProgramId,
Path = GetContentPath(contentManager)
};
if (string.IsNullOrEmpty(appData.Path))
{
appControl = new BlitStruct<ApplicationControlProperty>(0);
return false;
}
appControl = StructHelpers.CreateCustomNacpData(Name, Version);
return true;
}
}
}

View file

@ -1,7 +1,6 @@
using Gommon; using Gommon;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.UI.Common.Configuration; using Ryujinx.UI.Common.Configuration;
using System; using System;
@ -17,7 +16,6 @@ namespace Ryujinx.Ava.Common.Locale
private const string DefaultLanguageCode = "en_US"; private const string DefaultLanguageCode = "en_US";
private readonly Dictionary<LocaleKeys, string> _localeStrings; private readonly Dictionary<LocaleKeys, string> _localeStrings;
private Dictionary<LocaleKeys, string> _localeDefaultStrings;
private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues; private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues;
private string _localeLanguageCode; private string _localeLanguageCode;
@ -27,7 +25,6 @@ namespace Ryujinx.Ava.Common.Locale
public LocaleManager() public LocaleManager()
{ {
_localeStrings = new Dictionary<LocaleKeys, string>(); _localeStrings = new Dictionary<LocaleKeys, string>();
_localeDefaultStrings = new Dictionary<LocaleKeys, string>();
_dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>(); _dynamicValues = new ConcurrentDictionary<LocaleKeys, object[]>();
Load(); Load();
@ -38,8 +35,6 @@ namespace Ryujinx.Ava.Common.Locale
var localeLanguageCode = !string.IsNullOrEmpty(ConfigurationState.Instance.UI.LanguageCode.Value) ? var localeLanguageCode = !string.IsNullOrEmpty(ConfigurationState.Instance.UI.LanguageCode.Value) ?
ConfigurationState.Instance.UI.LanguageCode.Value : CultureInfo.CurrentCulture.Name.Replace('-', '_'); ConfigurationState.Instance.UI.LanguageCode.Value : CultureInfo.CurrentCulture.Name.Replace('-', '_');
// Load en_US as default, if the target language translation is missing or incomplete.
LoadDefaultLanguage();
LoadLanguage(localeLanguageCode); LoadLanguage(localeLanguageCode);
// Save whatever we ended up with. // Save whatever we ended up with.
@ -66,26 +61,14 @@ namespace Ryujinx.Ava.Common.Locale
} }
catch catch
{ {
// If formatting failed use the default text instead. // If formatting the text failed,
if (_localeDefaultStrings.TryGetValue(key, out value)) // continue to the below line & return the text without formatting.
try
{
return string.Format(value, dynamicValue);
}
catch
{
// If formatting the default text failed return the key.
return key.ToString();
}
} }
return value; return value;
} }
// If the locale doesn't contain the key return the default one. return key.ToString(); // If the locale text doesn't exist return the key.
return _localeDefaultStrings.TryGetValue(key, out string defaultValue)
? defaultValue
: key.ToString(); // If the locale text doesn't exist return the key.
} }
set set
{ {
@ -114,11 +97,6 @@ namespace Ryujinx.Ava.Common.Locale
return this[key]; return this[key];
} }
private void LoadDefaultLanguage()
{
_localeDefaultStrings = LoadJsonLanguage(DefaultLanguageCode);
}
public void LoadLanguage(string languageCode) public void LoadLanguage(string languageCode)
{ {
var locale = LoadJsonLanguage(languageCode); var locale = LoadJsonLanguage(languageCode);
@ -126,7 +104,7 @@ namespace Ryujinx.Ava.Common.Locale
if (locale == null) if (locale == null)
{ {
_localeLanguageCode = DefaultLanguageCode; _localeLanguageCode = DefaultLanguageCode;
locale = _localeDefaultStrings; locale = LoadJsonLanguage(_localeLanguageCode);
} }
else else
{ {
@ -167,15 +145,16 @@ namespace Ryujinx.Ava.Common.Locale
if (!Enum.TryParse<LocaleKeys>(locale.ID, out var localeKey)) if (!Enum.TryParse<LocaleKeys>(locale.ID, out var localeKey))
continue; continue;
localeStrings[localeKey] = var str = locale.Translations.TryGetValue(languageCode, out string val) && !string.IsNullOrEmpty(val)
locale.Translations.TryGetValue(languageCode, out string val) && !string.IsNullOrEmpty(val)
? val ? val
: locale.Translations[DefaultLanguageCode]; : locale.Translations[DefaultLanguageCode];
if (string.IsNullOrEmpty(localeStrings[localeKey])) if (string.IsNullOrEmpty(str))
{ {
throw new Exception($"Locale key '{locale.ID}' has no valid translations for desired language {languageCode}! {DefaultLanguageCode} is an empty string or null"); throw new Exception($"Locale key '{locale.ID}' has no valid translations for desired language {languageCode}! {DefaultLanguageCode} is an empty string or null");
} }
localeStrings[localeKey] = str;
} }
return localeStrings; return localeStrings;

View file

@ -3,8 +3,6 @@ using Avalonia.Controls;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Threading; using Avalonia.Threading;
using Gommon; using Gommon;
using LibHac.Ncm;
using LibHac.Tools.FsSystem.NcaUtils;
using Ryujinx.Ava.Common.Locale; using Ryujinx.Ava.Common.Locale;
using Ryujinx.Ava.UI.Helpers; using Ryujinx.Ava.UI.Helpers;
using Ryujinx.Ava.UI.ViewModels; using Ryujinx.Ava.UI.ViewModels;
@ -12,8 +10,6 @@ using Ryujinx.Ava.UI.Windows;
using Ryujinx.Common; using Ryujinx.Common;
using Ryujinx.Common.Utilities; using Ryujinx.Common.Utilities;
using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption; using Ryujinx.HLE.HOS.Services.Nfc.AmiiboDecryption;
using Ryujinx.HLE;
using Ryujinx.UI.App.Common;
using Ryujinx.UI.Common; using Ryujinx.UI.Common;
using Ryujinx.UI.Common.Configuration; using Ryujinx.UI.Common.Configuration;
using Ryujinx.UI.Common.Helper; using Ryujinx.UI.Common.Helper;
@ -124,26 +120,13 @@ namespace Ryujinx.Ava.UI.Views.Main
ViewModel.LoadConfigurableHotKeys(); ViewModel.LoadConfigurableHotKeys();
} }
public static readonly AppletMetadata MiiApplet = new("miiEdit", 0x0100000000001009);
public async void OpenMiiApplet(object sender, RoutedEventArgs e) public async void OpenMiiApplet(object sender, RoutedEventArgs e)
{ {
const string AppletName = "miiEdit"; if (MiiApplet.CanStart(ViewModel.ContentManager, out var appData, out var nacpData))
const ulong AppletProgramId = 0x0100000000001009;
const string AppletVersion = "1.0.0";
string contentPath = ViewModel.ContentManager.GetInstalledContentPath(AppletProgramId, StorageId.BuiltInSystem, NcaContentType.Program);
if (!string.IsNullOrEmpty(contentPath))
{ {
ApplicationData applicationData = new() await ViewModel.LoadApplication(appData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
{
Name = AppletName,
Id = AppletProgramId,
Path = contentPath
};
var nacpData = StructHelpers.CreateCustomNacpData(AppletName, AppletVersion);
await ViewModel.LoadApplication(applicationData, ViewModel.IsFullScreen || ViewModel.StartGamesInFullscreen, nacpData);
} }
} }