* feat(P2-005): migrate CustomRichTextBox (FLogger) and CustomScrollViewer to Avalonia (#18)
CustomRichTextBox:
- Replace WPF RichTextBox / FlowDocument / Hyperlink with AvaloniaEdit.TextEditor
- FLogger converted to static class; removes ITextFormatter / BrushConverter / _previous offset
- Per-segment colouring implemented via LogColorizer : DocumentColorizingTransformer
- LogSegment record tracks offset, length, IBrush, and optional link URL
- Append/Text/Link methods marshal to Dispatcher.UIThread.InvokeAsync (DispatcherPriority.Background)
- Link click handler stubs TODO(P4-001) (OS file manager integration)
- GetBrush() caches parsed Color.Parse(hexString) -> SolidColorBrush per hex string
CustomScrollViewer:
- Replace WPF DependencyProperty / FrameworkPropertyMetadata with Avalonia AttachedProperty<double>
- Changed from ScrollViewer subclass to static helper class
- VerticalOffsetProperty uses AvaloniaProperty.RegisterAttached + Changed.AddClassHandler
- Offset set via ScrollViewer.Offset.WithY(); two-way sync via ScrollChanged event
- Formatter-clean GetVerticalOffset/SetVerticalOffset accessors added
Package updates (FModel.csproj):
- Replace deprecated AvaloniaEdit 0.10.12 with Avalonia.AvaloniaEdit 11.3.0
(old package unlisted on NuGet; new namespace is AvaloniaEdit.* not ICSharpCode.AvalonEdit.*)
- Serilog 4.3.0 -> 4.3.1 (patch)
Closes#18
* fix(P2-005): address post-review findings in CustomRichTextBox and CustomScrollViewer
CustomScrollViewer:
- Register VerticalOffsetProperty with BindingMode.TwoWay so bare {Binding ScrollPosition}
in XAML preserves tab scroll-position across tab switches (matches WPF BindsTwoWayByDefault)
- Replace null! with null in _subscribed.Add (no nullable context; operator was semantic no-op)
CustomRichTextBox:
- Move ScrollToEnd() call to end of Append dispatch lambda so it fires once per log event
rather than once per Text()/Link() segment (n calls per exception → 1 call per Append)
- Replace dead guard Document.LineCount > 0 with Document.TextLength > 0 in ScrollToEnd()
(TextDocument always has LineCount >= 1; the old guard was never false)
* fix(P2-005): fix CustomScrollViewer subscription and CWT null marker
- Move ScrollChanged subscription before the epsilon guard so viewers
starting at offset 0.0 still subscribe on their first property set;
previously the early return prevented subscription entirely in the
common initial case where bound value == viewer.Offset.Y == 0.0
- Replace null with a static readonly _marker object as the
ConditionalWeakTable value; null is technically accepted on .NET 8
but a non-null sentinel is clearer and avoids platform ambiguity
* feat(P2-004): migrate all 19 converters from WPF to Avalonia (#17)
Migrates every converter in FModel/Views/Resources/Converters/ off
System.Windows.Data / System.Windows.Markup / System.Windows.Shell
and onto Avalonia.Data.Converters equivalents.
Changes by converter:
Simple using-swap only (IValueConverter interface unchanged):
AnyItemMeetsConditionConverter, CommitMessageConverter,
DateTimeToDateConverter, FolderToSeparatorTagConverter,
GameFileMeetsConditionConverter, InvertBooleanConverter,
IsNullToBoolReversedConverter, RelativeDateTimeConverter,
StringToGameConverter, TrimRightToLeftConverter
BoolToRenderModeConverter:
System.Windows.Media.BitmapScalingMode → Avalonia.Media.Imaging.BitmapInterpolationMode
(NearestNeighbor → None, Linear → HighQuality);
typed helper method return type updated accordingly.
BorderThicknessToStrokeThicknessConverter:
System.Windows.Thickness → Avalonia.Thickness (same properties).
InvertBoolToVisibilityConverter:
Visibility.Visible/Collapsed/Hidden → bool; Avalonia uses IsVisible (bool).
Hidden concept does not exist on Avalonia — both Collapsed and Hidden map to false.
RatioConverter:
Removed MarkupExtension base class (PresentationFramework — Windows-only).
Added Instance singleton; use {x:Static converters:RatioConverter.Instance} in XAML.
RatioToGridLengthConverter:
System.Windows.GridLength/GridUnitType → Avalonia.GridLength/GridUnitType.
IMultiValueConverter signature: object[] → IList<object?>, ConvertBack removed.
StatusToTaskbarStateConverter:
Stubbed out — System.Windows.Shell.TaskbarItemProgressState has no cross-platform
Avalonia equivalent. Returns null; tracked by TODO(P2-015).
MarkupExtension removed; added Instance singleton.
TabSizeConverter:
System.Windows.Controls.TabControl → Avalonia.Controls.TabControl.
ActualWidth → Bounds.Width; Items.Count → ItemCount.
IMultiValueConverter: object[] → IList<object?>, ConvertBack removed.
FileToGeometryConverter:
System.Windows.Media.{Geometry,Brush} → Avalonia.Media.{Geometry,IBrush}.
Application.Current.FindResource → Application.Current.TryGetResource(key, null, out var r).
IMultiValueConverter: object[] → IList<object?>, ConvertBack removed.
FolderToGeometryConverter:
Same Geometry/IBrush/TryGetResource changes as FileToGeometryConverter.
Already migrated (no changes):
BoolToToggleConverter, CaseInsensitiveStringEqualsConverter,
EndpointToTypeConverter, EnumToStringConverter, IsNotZeroConverter,
MultiParameterConverter, SizeToStringConverter
Build: 1266 errors baseline → 1174 after this commit (92 fewer).
Zero errors introduced in Converters/.
* fix(P2-004): address PR #71 review findings
M1 (PR comment): FolderToGeometryConverter — remove duplicate if condition
(copy-paste artifact: identical guard appeared twice consecutively)
M2 (PR comment): TabSizeConverter — two fixes
- divisor guard: return 0 when ItemCount == 0 to prevent divide-by-zero
- double.Parse now uses CultureInfo.InvariantCulture (XAML ConverterParameter
values are always invariant-culture strings; avoids FormatException on
locales that use comma as decimal separator)
PR comment: BoolToRenderModeConverter — typed helper Convert(bool) now
implements the mapping directly instead of delegating to the interface
method with null culture; eliminates fragile null-culture call chain
m2: StatusToTaskbarStateConverter — reverted from IMultiValueConverter back
to IValueConverter to match the original WPF single-value binding contract
(EStatusKind → TaskbarItemProgressState was always a single-value binding);
also removed unused System.Collections.Generic using
m1: Aligned all ten 'simple-swap' IValueConverter implementations to use
Avalonia-idiomatic nullable signatures (object? value, object? parameter,
object? return) matching the Avalonia interface definition; previously these
retained the non-nullable WPF-era signatures which were inconsistent with the
nine converters already updated in the same commit
S1: Renamed InvertBoolToVisibilityConverter class → InvertBoolConverter to
reflect that it returns bool (for IsVisible) not WPF Visibility;
file rename is deferred pending terminal access
* feat(P2-003): migrate all 10 dialog Windows from WPF/AdonisUI to Avalonia
Resolves#16 [P2-003] Migrate all 11 XAML view windows to Avalonia Window.
Views migrated (XAML + code-behind):
- About: root Window, AdonisUI namespace/styles removed
- AesManager: root Window, BoolToVisibility→IsVisible, ListView→DataGrid
- AudioPlayer: root Window, CSCore TODO stubs, OpenFileDialog TODO stub
- BackupManager: root Window, IsNotZeroConverter for IsEnabled binding
- CustomDir: root Window, AdonisUI removals
- DirectorySelector: root Window, AdonisUI removals, Visibility→IsVisible
- ImageMerger: root Window, BitmapImage→Avalonia Bitmap, WPF dialogs→TODO stubs
- SearchView: root Window, ListView+GridView→DataGrid x2, ContextMenus
- SettingsView: root Window, DataTriggers→IsVisible/HyperlinkButton/converters,
SelectedItemChanged→SelectionChanged, VistaFolderBrowserDialog→TODO stub
- UpdateView: root Window, adonisControls:SplitButton→SplitButton+MenuFlyout
Support:
- FModel.csproj: add Avalonia.Controls.DataGrid v11.3.12
- Add IsNotZeroConverter (Avalonia.Data.Converters IValueConverter)
* chore(P2-003): apply post-push refinements to migrated view files
* fix: address review findings from Avalonia migration code review
Critical:
- MainWindow.xaml.cs: unsubscribe all PropertyChanged handlers in OnClosing to
prevent memory leak and use-after-free on restart (C2)
- MainWindow.xaml.cs: remove ConfigureAwait(false) from async void OnLoaded —
continuation must stay on Avalonia UI thread (C1)
Major:
- MainWindow.xaml: replace WPF KeyboardNavigation.TabNavigation with
Avalonia IsTabStop="False" on the feature-preview CheckBox (M3)
- MainWindow.xaml.cs: guard PixelDensity against zero in OnLoaded (m2)
- MainWindow.xaml.cs: add _syncingSelection re-entrancy guard to SyncSelection
to prevent infinite SelectionChanged event loop (m4)
- App.xaml.cs: add try/catch inside ShowErrorDialog async lambda to prevent
silent exception swallowing; add TaskScheduler.UnobservedTaskException
handler in OnFrameworkInitializationCompleted (M1, S1)
- App.xaml.cs: remove redundant Environment.Exit(0) from AppExit handler (m1)
- Helper.cs: null-guard GetWindow<T> return value; add comment re: Show() race (S2)
Views (review fixes):
- SettingsView.xaml.cs: replace TryBrowse/OnBrowseMappings stubs with real
StorageProvider implementations (OpenFolderPickerAsync, OpenFilePickerAsync)
- ImageMerger.xaml.cs: fix async void + MemoryStream disposal in OnExport
- UpdateView.xaml: fix Grid nesting of ItemsControl + empty-state TextBlock;
add IsNotZeroConverter-based empty-state visibility
- CustomDir.xaml/cs, DirectorySelector.xaml/cs: cancel button handlers
- Converters: migrate System.Windows.Data IValueConverter usings to
Avalonia.Data.Converters for BoolToToggleConverter, EndpointToTypeConverter,
EnumToStringConverter, IsNotZeroConverter, SizeToStringConverter
* fix: address second-round review findings
C1 - SettingsView.xaml.cs: replace WPF editor ShowDialog() calls with
async void stubs + TODO(P2-016) comments; DictionaryEditor and
EndpointEditor are not yet migrated to Avalonia so these used the
WPF synchronous ShowDialog() which is unavailable and returns the
wrong type
C2 - UpdateView.xaml: add TODO noting CommitsView is still a WPF
System.Windows.Data.ListCollectionView; once UpdateViewModel is
migrated the Count binding should be replaced with a dedicated
HasNoCommits bool property for reliable INPC notification
M1+S1 - Helper.cs: null-guard GetOpenedWindow result in OpenWindow<T>
to prevent NRE if the window deregisters between IsWindowOpen and
the dereference
M2 - MainWindow.xaml.cs: add TODO tech-debt comment on the double
UpdateStatusLabel dispatch when Kind changes; note consolidation
into a single UpdateStatusUI() for a later pass
M3 - ImageMerger.xaml.cs: replace ContinueWith(..., FromCurrentSync-
Context()) with try/finally after await Task.Run; eliminates the
synchronization-context capture hazard when called via ConfigureAwait
m1 - App.xaml.cs: UnobservedTaskException now calls ShowErrorDialog
for unexpected faults; silently absorbs OperationCanceledException;
SetObserved() moved before the early-return guard
m2 - IsNotZeroConverter.cs: fix 2-space indentation to 4-space to
match rest of codebase
m3 - EndpointToTypeConverter.cs: replace misleading NotImplemented-
Exception with ArgumentException carrying a descriptive message
* fix: address third-round review findings
- App.xaml.cs: check all InnerExceptions for OperationCanceledException,
not just InnerException[0], so a mixed AggregateException is never
silently absorbed (m1)
- Helper.cs: add Dispatcher.UIThread.RunJobs() between Show() and the
window-registry lookup in GetWindow<T> to close the registration race
on first open (S1); also add missing System.Collections.Generic using
that caused a pre-existing IEnumerable<> CS0246 error
- SettingsView.xaml.cs: clarify EndpointEditor TODO comments — original
WPF code used ShowDialog() (modal), so migration target is
ShowDialog(this), not Show() (m2)
* fix: add missing System.Linq using in App.xaml.cs
InnerExceptions.All() is a LINQ extension method. The project has no
implicit usings, so the explicit using was required. The build check
after the previous commit only grepped for Helper.cs errors, so the
CS1061 on App.xaml.cs was not caught until the follow-up review.
* fix: address PR reviewer findings across six view files
C1 - AudioPlayer.xaml: replace undeclared adonisUi:Brushes.ForegroundBrush
DynamicResource (compile error) with Fill="White", consistent with all
other icon paths in the file.
C2 - SettingsView.xaml.cs: fix OnBrowseMappings storing into non-existent
UserSettings.Default.MappingsPath; now sets
_applicationView.SettingsView.MappingEndpoint.FilePath which is the
property the XAML TextBox is bound to (compile error + silent data loss).
C3 - UpdateView.xaml: remove WPF-only ItemsControl.GroupStyle / GroupStyle /
GroupItem / HeaderStringFormat block (XAML parse failure on Avalonia).
Date grouping will be re-added alongside the CommitsView ViewModel
migration (see existing TODO). Also fix FallbackValue=False → 0 so
IsNotZeroConverter receives the expected int type when the binding
target can't be resolved.
M1 - ImageMerger.xaml.cs (UpButton case): remove spurious
SelectedItems.Add(indices) call which was adding the raw int[] to the
selected-items collection. Items are already marked IsSelected=true
inside the move loop; the Add call was a no-op at best and a runtime
inconsistency at worst.
M2 - DirectorySelector.xaml: remove self-referential
Width={Binding ActualWidth, ElementName=OkGuysButWhoFuckingAsked}
(control binding its own width to itself — produces binding warnings
and has no useful effect; layout is determined by content/padding).
m1 - SearchView.xaml.cs: restore WPF DataTrigger behavior — subscribe to
PropertyChanged on each SearchViewModel and update the corresponding
TextBox.Watermark when HasRegexEnabled toggles, giving 'Write your
regex pattern...' vs 'Write your pattern...' hint text.
* fix: unsubscribe PropertyChanged handlers in SearchView on close
SearchVm and RefVm are application-lifetime singletons. Subscribing
anonymous lambdas capturing 'this' (the window's TextBox fields)
meant each closed-and-reopened SearchView was kept permanently
alive by the singletons' PropertyChanged invocation lists.
Fix: promote the handlers to named local functions, cache the VM
references at construction time, and unsubscribe both handlers in
the Closed event so the window becomes eligible for GC immediately
after it is closed.
Also adds the required 'using System.ComponentModel' for the
PropertyChangedEventArgs parameter type.
* fix: migrate WPF converters to Avalonia.Data.Converters interfaces
CaseInsensitiveStringEqualsConverter: replace System.Windows.Data.IValueConverter
with Avalonia.Data.Converters.IValueConverter. Avalonia cannot call WPF converter
implementations, so any SettingsView.xaml binding using this converter would fail
silently at runtime. Also null-guards value/parameter before calling .ToString()
to avoid NREs on binding fallback values.
MultiParameterConverter: replace System.Windows.Data.IMultiValueConverter with
Avalonia.Data.Converters.IMultiValueConverter. The Avalonia interface takes
IList<object?> rather than object[], so update the signature accordingly. Return
values.ToArray() to preserve the same object[] snapshot that the WPF
values.Clone() call produced, keeping CommandParameter multi-binding callers in
SearchView.xaml working. Avalonia's IMultiValueConverter has no ConvertBack, so
that method is removed.
* chore: update identity, branding, and CI for FModel Linux fork
- README.md: complete rewrite with fork identity disclaimer, upstream
attribution, updated links, and removal of sponsorship section
- NOTICE: add upstream FModel GPL-3 attribution; update library list
(add Avalonia/AvaloniaEdit/Svg.Skia/Twizzle.ImGui-Bundle.NET, remove
AdonisUI/AutoUpdater.NET/CSCore/ImGui.NET/Ookii.Dialogs.Wpf)
- Constants.cs: update ISSUE_LINK and GH_REPO to r6e/FModel-Linux;
clear DISCORD_LINK pending app registration
- FModel.csproj: add opt-in USE_FMODEL_API build flag
(-p:UseFModelApi=true) for upstream api.fmodel.app integration
- FModelApiEndpoint.cs: gate all api.fmodel.app calls behind
#if USE_FMODEL_API; rewrite CheckForUpdatesAsync to use GitHub
Releases API and return GitHubRelease? for caller-side notification
- GitHubApiEndpoint.cs: add GetLatestReleaseAsync() for /releases/latest
- GitHubResponse.cs: add TagName/HtmlUrl/Body to GitHubRelease; replace
AutoUpdater.DownloadUpdate with Process.Start(UseShellExecute=true)
- MainWindow.xaml.cs: surface update availability via FLogger [WRN] entry
at startup when a newer GitHub release is found
- DiscordService.cs: disable RPC (empty APP_ID, early-return guard)
pending Discord application registration for the fork
- About.xaml: version label reads 'FModel Linux {0}'; dual credit lines
for Asval (original) and Rob Trame (Linux port)
- AboutViewModel.cs: update description, contributors, and references
list to reflect current Avalonia-based dependency set
- .github/workflows: target ubuntu-latest, linux-x64, net8.0; remove
fmodel.app deploy steps; rename artifact to FModel-Linux.zip
- .github/ISSUE_TEMPLATE: update assignee and remove Discord link
- .github/FUNDING.yml: note donation link points to upstream project
* Fix whitespace issues
* chore: address PR review feedback
- NOTICE: remove orphaned MS-PL and BSD 3-Clause license texts; the
index already lists only MIT and Apache 2.0, and no current dependency
uses either of those licenses
- GitHubResponse.cs: guard against null Asset/BrowserDownloadUrl in
Download(); log a warning via Serilog instead of NullReferenceException
or re-throwing InvalidOperationException
- MainWindow.xaml.cs: run update check in a background Task.Run to
avoid blocking startup; post FLogger notification back on
Dispatcher.UIThread; swallow exceptions so a failed check never
impacts startup
- FModelApiEndpoint.cs: log a warning when the current application
version string cannot be parsed, matching the existing behaviour for
an unparseable latest-release tag
- .github/workflows: add `permissions: contents: write` to both
main.yml and qa.yml (GitHub Advanced Security finding)
* chore: address second round of PR review feedback
- NOTICE: add missing direct NuGet dependencies —
EpicManifestParser.ZlibngDotNetDecompressor, Serilog.Sinks.Console,
Serilog.Sinks.File, and SkiaSharp.HarfBuzz — each with their
respective copyright notice and license (MIT / Apache 2.0)
- FModelApiEndpoint.cs: remove now-unused _applicationView property
(CheckForUpdatesAsync was refactored to use GitHubApi directly;
_applicationView is dead code outside of #if USE_FMODEL_API blocks)
- DiscordService.cs: fix DiscordRpcClient being constructed at
field-init time with an empty APP_ID string; make _client nullable
and only instantiate when APP_ID is non-empty; update all call sites
to use null-safe pattern matching (_client is not { IsInitialized:
true }) so callers are safe without runtime client construction
* chore: address third round of PR review feedback
- MenuCommand.cs: guard Help_Discord action against empty DISCORD_LINK;
Process.Start with an empty FileName throws at runtime, so the action
is now a no-op when no Discord server URL is configured
- qa.yml: zip the full publish output directory (./FModel/bin/Publish/)
rather than just the single executable; --no-self-contained publishes
companion files (*.deps.json, *.runtimeconfig.json) that are required
at runtime alongside the PublishSingleFile output
- main.yml: same fix — zip ./FModel/bin/Publish/ so the release artifact
includes all required publish outputs, not just the executable
* Update FModel/ViewModels/ApiEndpoints/FModelApiEndpoint.cs
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* feat(#14): migrate App.xaml + App.xaml.cs to Avalonia bootstrap
- App.xaml: replace WPF/AdonisUI xmlns with Avalonia xmlns=https://github.com/avaloniaui; add FluentTheme; remove AdonisUI MergedDictionaries and BooleanToVisibilityConverter (Views/Resources/* will be re-added as they are migrated in later issues)
- App.xaml.cs: inherit Avalonia.Application; OnFrameworkInitializationCompleted replaces OnStartup; AppExit wired via IClassicDesktopStyleApplicationLifetime.Exit; AdonisUI MessageBox replaced with inline Avalonia Window dialog; P/Invokes guarded with OperatingSystem.IsWindows(); GetRegistryValue guarded for Linux (P3-006 will replace fully)
- Program.cs (new): Avalonia entry point with BuildAvaloniaApp + Main; AppDomain.UnhandledException registered to drive ShowErrorDialog
- AssemblyInfo.cs: remove WPF ThemeInfoAttribute (no Avalonia equivalent)
- FModel.csproj: StartupObject -> FModel.Program; add Serilog.Sinks.Console 6.1.1 (needed for AnsiConsoleTheme in debug logger); exclude Properties/Resources.resx + Designer.cs (WPF boilerplate, unreferenced)
Closes#14
* fix(#14): address code review findings in App bootstrap
[C1] Replace AppDomain.UnhandledException with Dispatcher.UIThread
.UnhandledExceptionFilter — fires on UI thread, allows Handled=true
[C2] Wrap dialog.Show() fallback in try/catch; return early if app is
shutting down to avoid silent crash
[M1] Add TODO(#15) comment for desktop.MainWindow assignment
[M2] Change Dispatcher.UIThread.Post → InvokeAsync; restructure
ShowErrorDialog to only use tcs.Task in the modeless path
[M3] Restore Environment.Exit(0) in AppExit to preserve original
termination behaviour until proper cancellation is in place
[m2] Add SolidColorBrush resources (AccentColorBrush, AlertColorBrush,
ErrorColorBrush) alongside Color resources in App.xaml
* fix(#14): address second-pass review findings
[m1/s1] Move Dispatcher.UIThread.UnhandledExceptionFilter subscription
to after Log.Logger is configured; Log.Error calls inside the
handler were no-ops when exceptions occurred during the ~80-line
init block (settings load, directory creation)
[m2] Attach .ContinueWith(OnlyOnFaulted) to the InvokeAsync task in
ShowErrorDialog so secondary exceptions in the error-handling
path (UserSettings.Delete, Restart) are logged rather than
silently swallowed as unobserved task faults
* Address review feedback
Update .gitmodules URL from FabianFG/CUE4Parse to
r6e/CUE4Parse-Linux and pin to commit 06fbf1ac which adds
Linux-compatible libdetex.so and libtegra_swizzle_x64.so
alongside the Windows DLLs, with RID-aware loading in
DetexHelper and PlatformDeswizzlers.
Closes#10
Autoupdater.NET.Official requires WPF for its built-in download dialog
and cannot be used on Linux. Cross-platform replacement is tracked
in #51 (P4-005).
Closes#9 in r6e/FModel-Linux
VirtualizingWrapPanel is a WPF-only third-party panel control.
Replacement with Avalonia's built-in WrapPanel or a community
virtualized panel is tracked in Phase 2 UI migration work.
Closes#6 in r6e/FModel-Linux
CSCore uses WASAPI, DirectSound and MediaFoundation APIs that are
unavailable on Linux. Call-site replacement with a cross-platform
audio backend (OpenTK.Audio.OpenAL) is tracked in #40 (P3-013).
Closes#13 in r6e/FModel-Linux
Ookii.Dialogs.Wpf depends on PresentationFramework and cannot be
restored on Linux. Call-site replacement with Avalonia StorageProvider
is tracked in #48 (P4-004).
Closes#11 in r6e/FModel-Linux
- Remove AvalonEdit 6.3.1.120 (WPF-only text editor)
- Add AvaloniaEdit 0.10.12 (Avalonia port, API-compatible)
Existing .xshd syntax definition files (Changelog.xshd, Cpp.xshd,
Ini.xshd, etc.) are format-compatible with AvaloniaEdit and require
no changes at this stage.
Closes#12 in r6e/FModel-Linux
* chore: replace AdonisUI with Avalonia UI packages
- Remove AdonisUI 1.17.1 (WPF-only)
- Remove AdonisUI.ClassicTheme 1.17.1 (WPF-only)
- Add Avalonia 11.3.12 (core framework)
- Add Avalonia.Desktop 11.3.12 (desktop host)
- Add Avalonia.Themes.Fluent 11.3.12 (cross-platform theme)
Closes#8 in r6e/FModel-Linux
* chore: add Avalonia.Fonts.Inter for consistent Linux font rendering
Without this package, Avalonia falls back to the system fontconfig font
on Linux, which varies by distro and can produce missing glyphs on
minimal CI runners. Inter gives a consistent cross-platform baseline.
- Change TargetFramework from net8.0-windows to net8.0
- Remove UseWPF (not used by Avalonia)
- Change OutputType from WinExe to Exe (cross-platform)
- Remove hardcoded RuntimeIdentifier win-x64 (supply at publish time)
Closes#7 in r6e/FModel-Linux
* Fix HTML tags in some Quests DisplayName.
* New Backups & Hotfixes API
* fix backups being null
---------
Co-authored-by: GhostScissors <79089473+GhostScissors@users.noreply.github.com>
* 'The Dark Pictures Anthology: House of Ashes' Wwise support
* AnyItemMeetsConditionConverter.ConditionMode
---------
Co-authored-by: Asval <asval.contactme@gmail.com>
+ filter by types, find by references (UE5+), and a lot of other improvements
Co-authored-by: Asval <asval.contactme@gmail.com>
Co-authored-by: LongerWarrior <LongerWarrior@gmail.com>