[GUI] Upgrade Avalonia to 12.1.0 and enable compiled bindings (#666)

* [GUI] bump to avalonia 12

* [GUI] add compiled bindings for cards/console logs/game metas

* [GUI] enable compiled bindings across launcher XAML
This commit is contained in:
Daniel Freak
2026-07-27 23:00:51 +03:00
committed by GitHub
parent db4339f698
commit b4cc5f88ca
5 changed files with 36 additions and 24 deletions
+6 -6
View File
@@ -7,10 +7,10 @@ SPDX-License-Identifier: GPL-2.0-or-later
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally> <ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageVersion Include="Avalonia" Version="11.3.18" /> <PackageVersion Include="Avalonia" Version="12.1.0" />
<PackageVersion Include="Avalonia.Desktop" Version="11.3.18" /> <PackageVersion Include="Avalonia.Desktop" Version="12.1.0" />
<PackageVersion Include="Avalonia.Fonts.Inter" Version="11.3.18" /> <PackageVersion Include="Avalonia.Fonts.Inter" Version="12.1.0" />
<PackageVersion Include="Avalonia.Themes.Fluent" Version="11.3.18" /> <PackageVersion Include="Avalonia.Themes.Fluent" Version="12.1.0" />
<PackageVersion Include="FFmpeg.AutoGen" Version="7.1.1" /> <PackageVersion Include="FFmpeg.AutoGen" Version="7.1.1" />
<PackageVersion Include="Iced" Version="1.21.0" /> <PackageVersion Include="Iced" Version="1.21.0" />
<PackageVersion Include="Microsoft.Build.Framework" Version="17.14.8" /> <PackageVersion Include="Microsoft.Build.Framework" Version="17.14.8" />
@@ -23,8 +23,8 @@ SPDX-License-Identifier: GPL-2.0-or-later
<PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.23.0" /> <PackageVersion Include="Silk.NET.Vulkan.Extensions.EXT" Version="2.23.0" />
<PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.23.0" /> <PackageVersion Include="Silk.NET.Vulkan.Extensions.KHR" Version="2.23.0" />
<PackageVersion Include="Silk.NET.Windowing" Version="2.23.0" /> <PackageVersion Include="Silk.NET.Windowing" Version="2.23.0" />
<!-- Transitive of Avalonia.Desktop; pinned to fix GHSA-xrw6-gwf8-vvr9 --> <!-- Transitive of Avalonia.Desktop; pinned. Avalonia 12 requires 0.94.1+. -->
<PackageVersion Include="Tmds.DBus.Protocol" Version="0.21.3" /> <PackageVersion Include="Tmds.DBus.Protocol" Version="0.94.1" />
<PackageVersion Include="xunit" Version="2.9.3" /> <PackageVersion Include="xunit" Version="2.9.3" />
<PackageVersion Include="xunit.runner.visualstudio" Version="3.1.1" /> <PackageVersion Include="xunit.runner.visualstudio" Version="3.1.1" />
</ItemGroup> </ItemGroup>
+2 -1
View File
@@ -6,6 +6,7 @@ using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Controls.Templates; using Avalonia.Controls.Templates;
using Avalonia.Data; using Avalonia.Data;
using Avalonia.Input.Platform;
using Avalonia.Layout; using Avalonia.Layout;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Platform; using Avalonia.Platform;
@@ -40,7 +41,7 @@ public sealed class ConsoleWindow : Window
_searchBox = new TextBox _searchBox = new TextBox
{ {
Watermark = loc.Get("Console.SearchWatermark"), PlaceholderText = loc.Get("Console.SearchWatermark"),
Width = 320, Width = 320,
Margin = new Thickness(0, 0, 12, 0), Margin = new Thickness(0, 0, 12, 0),
}; };
+3 -3
View File
@@ -5,6 +5,8 @@ using System.Text.Json;
namespace SharpEmu.GUI; namespace SharpEmu.GUI;
public sealed record LanguageInfo(string Code, string NativeName);
/// <summary> /// <summary>
/// Loads UI strings for the launcher. Every language ships embedded in the /// Loads UI strings for the launcher. Every language ships embedded in the
/// assembly (see SharpEmu.GUI.csproj) so a release build is fully /// assembly (see SharpEmu.GUI.csproj) so a release build is fully
@@ -16,8 +18,6 @@ public sealed class Localization
{ {
public static Localization Instance { get; } = new(); public static Localization Instance { get; } = new();
public sealed record LanguageInfo(string Code, string NativeName);
private const string EmbeddedResourcePrefix = "Languages."; private const string EmbeddedResourcePrefix = "Languages.";
private const string EmbeddedResourceSuffix = ".json"; private const string EmbeddedResourceSuffix = ".json";
@@ -242,7 +242,7 @@ public sealed class Localization
result = loaded; result = loaded;
return true; return true;
} }
private bool TryLoad(string code, string json) private bool TryLoad(string code, string json)
{ {
if (TryLoad(json, out var dict)) if (TryLoad(json, out var dict))
+19 -9
View File
@@ -15,7 +15,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"
Background="{StaticResource BgBrush}" Background="{StaticResource BgBrush}"
ExtendClientAreaToDecorationsHint="True" ExtendClientAreaToDecorationsHint="True"
ExtendClientAreaChromeHints="PreferSystemChrome" WindowDecorations="Full"
ExtendClientAreaTitleBarHeightHint="44" ExtendClientAreaTitleBarHeightHint="44"
Icon="avares://SharpEmu.GUI/Assets/SharpEmu.ico" Icon="avares://SharpEmu.GUI/Assets/SharpEmu.ico"
KeyDown="OnKeyDown"> KeyDown="OnKeyDown">
@@ -84,7 +84,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<StackPanel Grid.Column="2" x:Name="LibraryToolbar" Orientation="Horizontal" Spacing="8" <StackPanel Grid.Column="2" x:Name="LibraryToolbar" Orientation="Horizontal" Spacing="8"
VerticalAlignment="Center"> VerticalAlignment="Center">
<TextBox x:Name="SearchBox" Watermark="Search library…" Width="240" VerticalAlignment="Center" /> <TextBox x:Name="SearchBox" PlaceholderText="Search library…" Width="240" VerticalAlignment="Center" />
<Button x:Name="AddFolderButton" Classes="ghost" Content=" Add folder" VerticalAlignment="Center" /> <Button x:Name="AddFolderButton" Classes="ghost" Content=" Add folder" VerticalAlignment="Center" />
<Button x:Name="RescanButton" Classes="ghost" Content="⟳ Rescan" VerticalAlignment="Center" /> <Button x:Name="RescanButton" Classes="ghost" Content="⟳ Rescan" VerticalAlignment="Center" />
<Button x:Name="OpenFileButton" Classes="ghost" Content="Open file…" VerticalAlignment="Center" /> <Button x:Name="OpenFileButton" Classes="ghost" Content="Open file…" VerticalAlignment="Center" />
@@ -148,7 +148,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
</ItemsPanelTemplate> </ItemsPanelTemplate>
</ListBox.ItemsPanel> </ListBox.ItemsPanel>
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate x:DataType="local:GameEntry" x:CompileBindings="True">
<StackPanel Width="128" Height="172" Spacing="7"> <StackPanel Width="128" Height="172" Spacing="7">
<Border Classes="coverShadow" Width="128" Height="128"> <Border Classes="coverShadow" Width="128" Height="128">
<Border Classes="coverClip"> <Border Classes="coverClip">
@@ -273,8 +273,13 @@ SPDX-License-Identifier: GPL-2.0-or-later
<local:SettingRow x:Name="LanguageRow" Label="Emulator language" <local:SettingRow x:Name="LanguageRow" Label="Emulator language"
Description="Language used throughout the launcher. Applies immediately."> Description="Language used throughout the launcher. Applies immediately.">
<ComboBox x:Name="LanguageBox" Width="160" <ComboBox x:Name="LanguageBox" Width="160"
VerticalAlignment="Center" CornerRadius="8" VerticalAlignment="Center" CornerRadius="8">
DisplayMemberBinding="{Binding NativeName}" /> <ComboBox.ItemTemplate>
<DataTemplate x:DataType="local:LanguageInfo">
<TextBlock Text="{Binding NativeName}" />
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</local:SettingRow> </local:SettingRow>
<local:SettingRow x:Name="TitleMusicRow" Label="Title music" <local:SettingRow x:Name="TitleMusicRow" Label="Title music"
@@ -498,7 +503,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto,Auto,Auto,Auto" Margin="16,12,16,8"> <Grid Grid.Row="0" ColumnDefinitions="*,Auto,Auto,Auto,Auto,Auto" Margin="16,12,16,8">
<TextBlock x:Name="ConsoleSectionTitle" Classes="sectionTitle" Text="CONSOLE" VerticalAlignment="Center" /> <TextBlock x:Name="ConsoleSectionTitle" Classes="sectionTitle" Text="CONSOLE" VerticalAlignment="Center" />
<TextBox Grid.Column="1" FontSize="12" Margin="0,0,12,0" x:Name="ConsoleSearchBox" <TextBox Grid.Column="1" FontSize="12" Margin="0,0,12,0" x:Name="ConsoleSearchBox"
Watermark="Search..." Width="320" /> PlaceholderText="Search..." Width="320" />
<CheckBox Grid.Column="2" x:Name="AutoScrollCheck" Content="Auto-scroll" IsChecked="True" <CheckBox Grid.Column="2" x:Name="AutoScrollCheck" Content="Auto-scroll" IsChecked="True"
FontSize="12" Margin="0,0,12,0" /> FontSize="12" Margin="0,0,12,0" />
<Button Grid.Column="3" x:Name="DetachConsoleButton" Classes="ghost" Content="Split" FontSize="12" <Button Grid.Column="3" x:Name="DetachConsoleButton" Classes="ghost" Content="Split" FontSize="12"
@@ -511,7 +516,7 @@ SPDX-License-Identifier: GPL-2.0-or-later
<ListBox Grid.Row="1" x:Name="ConsoleList" Classes="console" BorderThickness="0,1,0,0" <ListBox Grid.Row="1" x:Name="ConsoleList" Classes="console" BorderThickness="0,1,0,0"
BorderBrush="{StaticResource CardBorderBrush}" CornerRadius="0,0,12,12"> BorderBrush="{StaticResource CardBorderBrush}" CornerRadius="0,0,12,12">
<ListBox.ItemTemplate> <ListBox.ItemTemplate>
<DataTemplate> <DataTemplate x:DataType="local:LogLine" x:CompileBindings="True">
<TextBlock Text="{Binding Text}" Foreground="{Binding Brush}" TextWrapping="NoWrap" /> <TextBlock Text="{Binding Text}" Foreground="{Binding Brush}" TextWrapping="NoWrap" />
</DataTemplate> </DataTemplate>
</ListBox.ItemTemplate> </ListBox.ItemTemplate>
@@ -527,7 +532,9 @@ SPDX-License-Identifier: GPL-2.0-or-later
<!-- Selected game cover thumbnail --> <!-- Selected game cover thumbnail -->
<Border Grid.Column="0" Classes="coverClip" Width="56" Height="56" CornerRadius="8" <Border Grid.Column="0" Classes="coverClip" Width="56" Height="56" CornerRadius="8"
VerticalAlignment="Center"> VerticalAlignment="Center">
<Panel x:Name="SelectedCoverPanel"> <Panel x:Name="SelectedCoverPanel"
x:DataType="local:GameEntry"
x:CompileBindings="True">
<Border Background="{Binding PlaceholderBrush, FallbackValue={x:Null}}" <Border Background="{Binding PlaceholderBrush, FallbackValue={x:Null}}"
IsVisible="{Binding !HasCover, FallbackValue=False}"> IsVisible="{Binding !HasCover, FallbackValue=False}">
<TextBlock Text="{Binding Initials}" FontSize="20" FontWeight="Bold" <TextBlock Text="{Binding Initials}" FontSize="20" FontWeight="Bold"
@@ -548,7 +555,10 @@ SPDX-License-Identifier: GPL-2.0-or-later
<!-- Title id / version / size badges, right next to the <!-- Title id / version / size badges, right next to the
title. The title's own MaxWidth (not a "*" column) is title. The title's own MaxWidth (not a "*" column) is
what keeps them from drifting to the far right. --> what keeps them from drifting to the far right. -->
<StackPanel Grid.Column="1" x:Name="SelectedBadgesRow" Orientation="Horizontal" Spacing="6" <StackPanel Grid.Column="1" x:Name="SelectedBadgesRow"
x:DataType="local:GameEntry"
x:CompileBindings="True"
Orientation="Horizontal" Spacing="6"
IsVisible="False" VerticalAlignment="Center"> IsVisible="False" VerticalAlignment="Center">
<Border Classes="pill" IsVisible="{Binding HasTitleId, FallbackValue=False}"> <Border Classes="pill" IsVisible="{Binding HasTitleId, FallbackValue=False}">
<TextBlock Text="{Binding TitleId}" FontSize="10" FontWeight="SemiBold" <TextBlock Text="{Binding TitleId}" FontSize="10" FontWeight="SemiBold"
+6 -5
View File
@@ -5,6 +5,7 @@ using Avalonia;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls; using Avalonia.Controls;
using Avalonia.Input; using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Interactivity; using Avalonia.Interactivity;
using Avalonia.Media; using Avalonia.Media;
using Avalonia.Media.Imaging; using Avalonia.Media.Imaging;
@@ -591,7 +592,7 @@ public partial class MainWindow : Window
private void OnLanguageChanged() private void OnLanguageChanged()
{ {
if (LanguageBox.SelectedItem is not Localization.LanguageInfo language) if (LanguageBox.SelectedItem is not LanguageInfo language)
{ {
return; return;
} }
@@ -613,7 +614,7 @@ public partial class MainWindow : Window
LibraryTabButton.Content = loc.Get("Page.Library"); LibraryTabButton.Content = loc.Get("Page.Library");
OptionsTabButton.Content = loc.Get("Page.Options"); OptionsTabButton.Content = loc.Get("Page.Options");
SearchBox.Watermark = loc.Get("Library.SearchWatermark"); SearchBox.PlaceholderText = loc.Get("Library.SearchWatermark");
AddFolderButton.Content = loc.Get("Library.AddFolder"); AddFolderButton.Content = loc.Get("Library.AddFolder");
RescanButton.Content = loc.Get("Library.Rescan"); RescanButton.Content = loc.Get("Library.Rescan");
OpenFileButton.Content = loc.Get("Library.OpenFile"); OpenFileButton.Content = loc.Get("Library.OpenFile");
@@ -691,7 +692,7 @@ public partial class MainWindow : Window
} }
ConsoleSectionTitle.Text = loc.Get("Console.Title"); ConsoleSectionTitle.Text = loc.Get("Console.Title");
ConsoleSearchBox.Watermark = loc.Get("Console.SearchWatermark"); ConsoleSearchBox.PlaceholderText = loc.Get("Console.SearchWatermark");
AutoScrollCheck.Content = loc.Get("Console.AutoScroll"); AutoScrollCheck.Content = loc.Get("Console.AutoScroll");
DetachConsoleButton.Content = loc.Get("Console.Split"); DetachConsoleButton.Content = loc.Get("Console.Split");
CopyLogButton.Content = loc.Get("Console.Copy"); CopyLogButton.Content = loc.Get("Console.Copy");
@@ -792,7 +793,7 @@ public partial class MainWindow : Window
// Leaving F11 should restore a monitor-sized window with the // Leaving F11 should restore a monitor-sized window with the
// launcher chrome, not fall back to the design-time window size. // launcher chrome, not fall back to the design-time window size.
WindowState = WindowState.Maximized; WindowState = WindowState.Maximized;
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.PreferSystemChrome; WindowDecorations = WindowDecorations.Full;
TitleBar.IsVisible = true; TitleBar.IsVisible = true;
StatusBar.IsVisible = true; StatusBar.IsVisible = true;
if (_gameFullscreen) if (_gameFullscreen)
@@ -813,7 +814,7 @@ public partial class MainWindow : Window
else else
{ {
WindowState = WindowState.FullScreen; WindowState = WindowState.FullScreen;
ExtendClientAreaChromeHints = ExtendClientAreaChromeHints.NoChrome; WindowDecorations = WindowDecorations.None;
TitleBar.IsVisible = false; TitleBar.IsVisible = false;
StatusBar.IsVisible = false; StatusBar.IsVisible = false;
if (_isRunning && !_isStopping && !_awaitingFirstFrame && GameView.IsVisible) if (_isRunning && !_isStopping && !_awaitingFirstFrame && GameView.IsVisible)