UI: Menubar & Game Context Menu Updates (ryubing/ryujinx!134)

See merge request ryubing/ryujinx!134
This commit is contained in:
Neo
2025-09-02 03:32:06 -05:00
committed by GreemDev
parent 07c7b39053
commit 3969191605
7 changed files with 523 additions and 443 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -19,7 +19,7 @@ namespace Ryujinx.Ava.Common.Locale
private readonly Dictionary<LocaleKeys, string> _localeStrings; private readonly Dictionary<LocaleKeys, string> _localeStrings;
private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues; private readonly ConcurrentDictionary<LocaleKeys, object[]> _dynamicValues;
private string _localeLanguageCode; private string _localeLanguageCode;
public string CurrentLanguageCode => _localeLanguageCode;
public static LocaleManager Instance { get; } = new(); public static LocaleManager Instance { get; } = new();
public event Action LocaleChanged; public event Action LocaleChanged;

View File

@@ -71,12 +71,12 @@
Command="{Binding OpenTitleUpdateManager}" Command="{Binding OpenTitleUpdateManager}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageTitleUpdates}" Header="{ext:Locale GameListContextMenuManageTitleUpdates}"
Icon="{ext:Icon fa-solid fa-code-compare}" /> Icon="{ext:Icon fa-solid fa-diagram-predecessor}" />
<MenuItem <MenuItem
Command="{Binding OpenDownloadableContentManager}" Command="{Binding OpenDownloadableContentManager}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuManageDlc}" Header="{ext:Locale GameListContextMenuManageDlc}"
Icon="{ext:Icon fa-solid fa-download}" /> Icon="{ext:Icon fa-solid fa-puzzle-piece}" />
<MenuItem <MenuItem
Command="{Binding OpenCheatManager}" Command="{Binding OpenCheatManager}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
@@ -92,12 +92,12 @@
Command="{Binding OpenModsDirectory}" Command="{Binding OpenModsDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenModsDirectory}" Header="{ext:Locale GameListContextMenuOpenModsDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" /> Icon="{ext:Icon fa-solid fa-folder-closed}" />
<MenuItem <MenuItem
Command="{Binding OpenSdModsDirectory}" Command="{Binding OpenSdModsDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuOpenSdModsDirectory}" Header="{ext:Locale GameListContextMenuOpenSdModsDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" Icon="{ext:Icon fa-solid fa-folder-closed}"
ToolTip.Tip="{ext:Locale GameListContextMenuOpenSdModsDirectoryToolTip}" /> ToolTip.Tip="{ext:Locale GameListContextMenuOpenSdModsDirectoryToolTip}" />
<Separator /> <Separator />
<MenuItem <MenuItem
@@ -128,12 +128,12 @@
Command="{Binding OpenPtcDirectory}" Command="{Binding OpenPtcDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementOpenPptcDirectory}" Header="{ext:Locale GameListContextMenuCacheManagementOpenPptcDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" /> Icon="{ext:Icon fa-solid fa-folder-closed}" />
<MenuItem <MenuItem
Command="{Binding OpenShaderCacheDirectory}" Command="{Binding OpenShaderCacheDirectory}"
CommandParameter="{Binding}" CommandParameter="{Binding}"
Header="{ext:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectory}" Header="{ext:Locale GameListContextMenuCacheManagementOpenShaderCacheDirectory}"
Icon="{ext:Icon fa-solid fa-folder}" /> Icon="{ext:Icon fa-solid fa-folder-closed}" />
</MenuItem> </MenuItem>
<MenuItem Header="{ext:Locale GameListContextMenuExtractData}" Icon="{ext:Icon fa-solid fa-file-export}"> <MenuItem Header="{ext:Locale GameListContextMenuExtractData}" Icon="{ext:Icon fa-solid fa-file-export}">
<MenuItem <MenuItem

View File

@@ -2,7 +2,8 @@
x:Class="Ryujinx.Ava.RyujinxApp" x:Class="Ryujinx.Ava.RyujinxApp"
xmlns="https://github.com/avaloniaui" xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sty="using:FluentAvalonia.Styling"> xmlns:sty="using:FluentAvalonia.Styling"
xmlns:ext="clr-namespace:Ryujinx.Ava.Common.Markup">
<Application.Resources> <Application.Resources>
<ResourceDictionary> <ResourceDictionary>
<ResourceDictionary.MergedDictionaries> <ResourceDictionary.MergedDictionaries>
@@ -19,7 +20,7 @@
</Application.Styles> </Application.Styles>
<NativeMenu.Menu> <NativeMenu.Menu>
<NativeMenu> <NativeMenu>
<NativeMenuItem Header="About Ryujinx" Click="AboutRyujinx_OnClick" /> <NativeMenuItem Header="{ext:Locale MenuBarHelpAbout}" Click="AboutRyujinx_OnClick" />
</NativeMenu> </NativeMenu>
</NativeMenu.Menu> </NativeMenu.Menu>
</Application> </Application>

View File

@@ -1204,11 +1204,11 @@ namespace Ryujinx.Ava.UI.ViewModels
_rendererWaitEvent.Set(); _rendererWaitEvent.Set();
} }
private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected) private async Task LoadContentFromFolder(LocaleKeys localeMessageAddedKey, LocaleKeys localeMessageRemovedKey, LoadContentFromFolderDelegate onDirsSelected, LocaleKeys dirSelectDialogTitle)
{ {
IReadOnlyList<IStorageFolder> result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions IReadOnlyList<IStorageFolder> result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle], Title = LocaleManager.Instance[dirSelectDialogTitle],
AllowMultiple = true, AllowMultiple = true,
}); });
@@ -1505,7 +1505,7 @@ namespace Ryujinx.Ava.UI.ViewModels
{ {
IReadOnlyList<IStorageFile> result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions IReadOnlyList<IStorageFile> result = await StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.OpenFileDialogTitle], Title = LocaleManager.Instance[LocaleKeys.LoadApplicationFromFileDialogTitle],
AllowMultiple = false, AllowMultiple = false,
FileTypeFilter = new List<FilePickerFileType> FileTypeFilter = new List<FilePickerFileType>
{ {
@@ -1581,7 +1581,8 @@ namespace Ryujinx.Ava.UI.ViewModels
await LoadContentFromFolder( await LoadContentFromFolder(
LocaleKeys.AutoloadDlcAddedMessage, LocaleKeys.AutoloadDlcAddedMessage,
LocaleKeys.AutoloadDlcRemovedMessage, LocaleKeys.AutoloadDlcRemovedMessage,
ApplicationLibrary.AutoLoadDownloadableContents); ApplicationLibrary.AutoLoadDownloadableContents,
LocaleKeys.LoadDLCFromFolderDialogTitle);
} }
public async Task LoadTitleUpdatesFromFolder() public async Task LoadTitleUpdatesFromFolder()
@@ -1589,14 +1590,15 @@ namespace Ryujinx.Ava.UI.ViewModels
await LoadContentFromFolder( await LoadContentFromFolder(
LocaleKeys.AutoloadUpdateAddedMessage, LocaleKeys.AutoloadUpdateAddedMessage,
LocaleKeys.AutoloadUpdateRemovedMessage, LocaleKeys.AutoloadUpdateRemovedMessage,
ApplicationLibrary.AutoLoadTitleUpdates); ApplicationLibrary.AutoLoadTitleUpdates,
LocaleKeys.LoadTitleUpdatesFromFolderDialogTitle);
} }
public async Task OpenFolder() public async Task OpenFolder()
{ {
IReadOnlyList<IStorageFolder> result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions IReadOnlyList<IStorageFolder> result = await StorageProvider.OpenFolderPickerAsync(new FolderPickerOpenOptions
{ {
Title = LocaleManager.Instance[LocaleKeys.OpenFolderDialogTitle], Title = LocaleManager.Instance[LocaleKeys.LoadUnpackedGameFromFolderDialogTitle],
AllowMultiple = false, AllowMultiple = false,
}); });

View File

@@ -39,36 +39,29 @@
Header="{ext:Locale MenuBarFileOpenUnpacked}" Header="{ext:Locale MenuBarFileOpenUnpacked}"
Icon="{ext:Icon fa-solid fa-folder-open}" Icon="{ext:Icon fa-solid fa-folder-open}"
IsEnabled="{Binding EnableNonGameRunningControls}" /> IsEnabled="{Binding EnableNonGameRunningControls}" />
<MenuItem
Command="{Binding LoadDlcFromFolder}"
Header="{ext:Locale MenuBarFileLoadDlcFromFolder}"
Icon="{ext:Icon fa-solid fa-download}"
IsEnabled="{Binding EnableNonGameRunningControls}" />
<MenuItem <MenuItem
Command="{Binding LoadTitleUpdatesFromFolder}" Command="{Binding LoadTitleUpdatesFromFolder}"
Header="{ext:Locale MenuBarFileLoadTitleUpdatesFromFolder}" Header="{ext:Locale MenuBarFileLoadTitleUpdatesFromFolder}"
Icon="{ext:Icon fa-solid fa-code-compare}" Icon="{ext:Icon fa-solid fa-diagram-predecessor}"
IsEnabled="{Binding EnableNonGameRunningControls}" /> IsEnabled="{Binding EnableNonGameRunningControls}" />
<MenuItem Header="{ext:Locale MenuBarFileOpenApplet}" IsEnabled="{Binding IsAppletMenuActive}" Icon="{ext:Icon fa-solid fa-microchip}">
<MenuItem <MenuItem
Name="MiiAppletMenuItem" Command="{Binding LoadDlcFromFolder}"
Header="{ext:Locale MenuBarFileOpenAppletOpenMiiApplet}" Header="{ext:Locale MenuBarFileLoadDlcFromFolder}"
Icon="{ext:Icon fa-solid fa-person}" Icon="{ext:Icon fa-solid fa-puzzle-piece}"
ToolTip.Tip="{ext:Locale MenuBarFileOpenAppletOpenMiiAppletToolTip}" /> IsEnabled="{Binding EnableNonGameRunningControls}" />
</MenuItem>
<Separator /> <Separator />
<MenuItem <MenuItem
Command="{Binding OpenRyujinxFolder}" Command="{Binding OpenRyujinxFolder}"
Header="{ext:Locale MenuBarFileOpenEmuFolder}" Header="{ext:Locale MenuBarFileOpenEmuFolder}"
Icon="{ext:Icon fa-solid fa-folder-closed}" /> Icon="{ext:Icon fa-solid fa-folder-closed}" />
<MenuItem
Command="{Binding OpenScreenshotsFolder}"
Header="{ext:Locale MenuBarFileOpenScreenshotsFolder}"
Icon="{ext:Icon fa-solid fa-desktop}" />
<MenuItem <MenuItem
Command="{Binding OpenLogsFolder}" Command="{Binding OpenLogsFolder}"
Header="{ext:Locale MenuBarFileOpenLogsFolder}" Header="{ext:Locale MenuBarFileOpenLogsFolder}"
Icon="{ext:Icon fa-solid fa-file-lines}" /> Icon="{ext:Icon fa-solid fa-terminal}" />
<MenuItem
Command="{Binding OpenScreenshotsFolder}"
Header="{ext:Locale MenuBarFileOpenScreenshotsFolder}"
Icon="{ext:Icon fa-solid fa-image}" />
<Separator /> <Separator />
<MenuItem <MenuItem
Name="CloseRyujinxMenuItem" Name="CloseRyujinxMenuItem"
@@ -132,11 +125,6 @@
Icon="{ext:Icon fa-solid fa-globe}" Icon="{ext:Icon fa-solid fa-globe}"
Classes="withCheckbox"> Classes="withCheckbox">
</MenuItem> </MenuItem>
<MenuItem
Name="ToggleFileTypesMenuItem"
Padding="-10,0,0,0"
Header="{ext:Locale MenuBarShowFileTypes}" />
<Separator />
<MenuItem <MenuItem
Name="OpenSettingsMenuItem" Name="OpenSettingsMenuItem"
Padding="0" Padding="0"
@@ -222,20 +210,25 @@
<MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromFile}" Icon="{ext:Icon fa-solid fa-file-code}" /> <MenuItem Command="{Binding InstallFirmwareFromFile}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromFile}" Icon="{ext:Icon fa-solid fa-file-code}" />
<MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromDirectory}" Icon="{ext:Icon fa-solid fa-folder-closed}" /> <MenuItem Command="{Binding InstallFirmwareFromFolder}" Header="{ext:Locale MenuBarActionsInstallFirmwareFromDirectory}" Icon="{ext:Icon fa-solid fa-folder-closed}" />
</MenuItem> </MenuItem>
<MenuItem Header="{ext:Locale MenuBarActionsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}"> <MenuItem Header="{ext:Locale MenuBarActionsManageFileTypes}" IsVisible="{Binding ManageFileTypesVisible}" Icon="{ext:Icon fa-solid fa-clipboard}">
<MenuItem Name="InstallFileTypesMenuItem" Header="{ext:Locale MenuBarActionsInstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered, Converter={x:Static BoolConverters.Not}}" /> <MenuItem Name="InstallFileTypesMenuItem" Header="{ext:Locale MenuBarActionsInstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered, Converter={x:Static BoolConverters.Not}}" Icon="{ext:Icon fa-solid fa-square-plus}" />
<MenuItem Name="UninstallFileTypesMenuItem" Header="{ext:Locale MenuBarActionsUninstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered}" /> <MenuItem Name="UninstallFileTypesMenuItem" Header="{ext:Locale MenuBarActionsUninstallFileTypes}" IsEnabled="{Binding AreMimeTypesRegistered}" Icon="{ext:Icon fa-solid fa-square-minus}" />
</MenuItem> </MenuItem>
<Separator /> <Separator />
<MenuItem Header="{ext:Locale MenuBarActionsTools}" Icon="{ext:Icon fa-solid fa-toolbox}">
<MenuItem
Name="MiiAppletMenuItem" Header="{ext:Locale MenuBarActionsOpenMiiEditor}" Icon="{ext:Icon fa-solid fa-face-grin-wide}" ToolTip.Tip="{ext:Locale MenuBarActionsOpenMiiEditorToolTip}" />
<MenuItem Name="XciTrimmerMenuItem" Header="{ext:Locale MenuBarActionsXCITrimmer}" Icon="{ext:Icon fa-solid fa-scissors}" /> <MenuItem Name="XciTrimmerMenuItem" Header="{ext:Locale MenuBarActionsXCITrimmer}" Icon="{ext:Icon fa-solid fa-scissors}" />
</MenuItem> </MenuItem>
</MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarView}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarView}">
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarViewWindow}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarViewWindow}" Icon="{ext:Icon fa-solid fa-window-restore}">
<MenuItem Name="WindowSize720PMenuItem" Header="{ext:Locale MenuBarViewWindow720}" CommandParameter="1280 720" /> <MenuItem Name="WindowSize720PMenuItem" Header="{ext:Locale MenuBarViewWindow720}" CommandParameter="1280 720" />
<MenuItem Name="WindowSize1080PMenuItem" Header="{ext:Locale MenuBarViewWindow1080}" CommandParameter="1920 1080" /> <MenuItem Name="WindowSize1080PMenuItem" Header="{ext:Locale MenuBarViewWindow1080}" CommandParameter="1920 1080" />
<MenuItem Name="WindowSize1440PMenuItem" Header="{ext:Locale MenuBarViewWindow1440}" CommandParameter="2560 1440" /> <MenuItem Name="WindowSize1440PMenuItem" Header="{ext:Locale MenuBarViewWindow1440}" CommandParameter="2560 1440" />
<MenuItem Name="WindowSize2160PMenuItem" Header="{ext:Locale MenuBarViewWindow2160}" CommandParameter="3840 2160" /> <MenuItem Name="WindowSize2160PMenuItem" Header="{ext:Locale MenuBarViewWindow2160}" CommandParameter="3840 2160" />
</MenuItem> </MenuItem>
<MenuItem Name="ToggleFileTypesMenuItem" Header="{ext:Locale MenuBarShowFileTypes}" Icon="{ext:Icon fa-solid fa-tags}" />
</MenuItem> </MenuItem>
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelp}"> <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelp}">
<MenuItem <MenuItem
@@ -258,12 +251,6 @@
IsEnabled="{Binding IsRyuLdnEnabled}"/> IsEnabled="{Binding IsRyuLdnEnabled}"/>
<Separator /> <Separator />
<MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelpFaqAndGuides}" Icon="{ext:Icon fa-solid fa-question}" > <MenuItem VerticalAlignment="Center" Header="{ext:Locale MenuBarHelpFaqAndGuides}" Icon="{ext:Icon fa-solid fa-question}" >
<MenuItem
Name="FaqMenuItem"
Header="{ext:Locale MenuBarHelpFaq}"
Icon="{ext:Icon fa-brands fa-gitlab}"
CommandParameter="{x:Static common:SharedConstants.FaqWikiUrl}"
ToolTip.Tip="{ext:Locale MenuBarHelpFaqTooltip}" />
<MenuItem <MenuItem
Name="SetupGuideMenuItem" Name="SetupGuideMenuItem"
Header="{ext:Locale MenuBarHelpSetup}" Header="{ext:Locale MenuBarHelpSetup}"
@@ -276,6 +263,12 @@
Icon="{ext:Icon fa-brands fa-gitlab}" Icon="{ext:Icon fa-brands fa-gitlab}"
CommandParameter="{x:Static common:SharedConstants.MultiplayerWikiUrl}" CommandParameter="{x:Static common:SharedConstants.MultiplayerWikiUrl}"
ToolTip.Tip="{ext:Locale MenuBarHelpMultiplayerTooltip}" /> ToolTip.Tip="{ext:Locale MenuBarHelpMultiplayerTooltip}" />
<MenuItem
Name="FaqMenuItem"
Header="{ext:Locale MenuBarHelpFaq}"
Icon="{ext:Icon fa-brands fa-gitlab}"
CommandParameter="{x:Static common:SharedConstants.FaqWikiUrl}"
ToolTip.Tip="{ext:Locale MenuBarHelpFaqTooltip}" />
</MenuItem> </MenuItem>
</MenuItem> </MenuItem>
</Menu> </Menu>

View File

@@ -61,6 +61,14 @@ namespace Ryujinx.Ava.UI.Views.Main
WindowSize1080PMenuItem.Command = WindowSize1080PMenuItem.Command =
WindowSize1440PMenuItem.Command = WindowSize1440PMenuItem.Command =
WindowSize2160PMenuItem.Command = Commands.Create<string>(ChangeWindowSize); WindowSize2160PMenuItem.Command = Commands.Create<string>(ChangeWindowSize);
LocaleManager.Instance.LocaleChanged += OnLocaleChanged;
}
private void OnLocaleChanged()
{
ChangeLanguageMenuItem.ItemsSource = GenerateLanguageMenuItems();
Menu.Close();
} }
private IEnumerable<CheckBox> GenerateToggleFileTypeItems() => private IEnumerable<CheckBox> GenerateToggleFileTypeItems() =>
@@ -80,6 +88,7 @@ namespace Ryujinx.Ava.UI.Views.Main
const string LocalePath = "Ryujinx/Assets/Locale.json"; const string LocalePath = "Ryujinx/Assets/Locale.json";
string languageJson = EmbeddedResources.ReadAllText(LocalePath); string languageJson = EmbeddedResources.ReadAllText(LocalePath);
string currentLanguageCode = LocaleManager.Instance.CurrentLanguageCode;
LocalesJson locales = JsonHelper.Deserialize(languageJson, LocalesJsonContext.Default.LocalesJson); LocalesJson locales = JsonHelper.Deserialize(languageJson, LocalesJsonContext.Default.LocalesJson);
@@ -105,7 +114,7 @@ namespace Ryujinx.Ava.UI.Views.Main
Padding = new Thickness(15, 0, 0, 0), Padding = new Thickness(15, 0, 0, 0),
Margin = new Thickness(3, 0, 3, 0), Margin = new Thickness(3, 0, 3, 0),
HorizontalAlignment = HorizontalAlignment.Stretch, HorizontalAlignment = HorizontalAlignment.Stretch,
Header = languageName, Header = language == currentLanguageCode ? $"{languageName} ✔" : languageName,
Command = Commands.Create(() => MainWindowViewModel.ChangeLanguage(language)) Command = Commands.Create(() => MainWindowViewModel.ChangeLanguage(language))
}; };