Skip to content

Add cross-platform Avalonia Mods Manager with Linux AppImage support - #1280

Closed
Zexyen wants to merge 1 commit into
OpenKH:masterfrom
Zexyen:avalonia
Closed

Add cross-platform Avalonia Mods Manager with Linux AppImage support#1280
Zexyen wants to merge 1 commit into
OpenKH:masterfrom
Zexyen:avalonia

Conversation

@Zexyen

@Zexyen Zexyen commented Aug 20, 2026

Copy link
Copy Markdown

Important

This is a Massive PR that is still under testing and revision. I've extensively tested the Avalonia frontend on Linux, but regression testing still needs to be done on windows to confirm no bugs are brought forward.

Summary

This PR introduces a cross-platform Avalonia frontend for the OpenKH Mods Manager, bringing native Mods Manager support to Linux while keeping the existing WPF application as the default Windows experience.

The Avalonia frontend reuses the existing Mods Manager models, services, and view models wherever possible. Avalonia-specific views and compatibility services fill the places where the existing application was tied directly to WPF.

In addition to the UI port, this PR adds the supporting work needed for the full modding workflow on Linux:

  • Steam library and game discovery.
  • Steam and Proton-aware game launching.
  • Automatic Steam launch-option configuration for Panacea and LuaBackend.
  • Panacea quick-launch support for the Steam releases.
  • Linux-safe path handling during mod compilation.
  • Writable configuration storage for packaged applications.
  • AppImage packaging and Linux CI.
  • Headless Avalonia tests that run on Linux.
  • Explicit handling for features that remain Windows-only.
  • A separately publishable Avalonia build for Windows.

Build and release model

Platform Frontend Status
Windows Existing WPF Mods Manager Retained as the default Windows build
Windows Avalonia Mods Manager Available as an optional, separate build
Linux Avalonia Mods Manager Primary Linux build, distributed as an AppImage

The existing Windows application remains OpenKh.Tools.ModsManager.csproj; Avalonia does not replace it.

The cross-platform frontend is a separate project in OpenKh.Tools.ModsManager.Avalonia.csproj. Both projects are included independently in OpenKh.sln.


What changed

Avalonia Mods Manager frontend

A complete Avalonia frontend has been added under OpenKh.Tools.ModsManager.Avalonia, including:

  • The main Mods Manager window and navigation.
  • The first-run setup wizard.
  • Mod list and mod detail views.
  • Mod search and browsing.
  • An integrated in-window mod installation dialog.
  • Installation progress UI.
  • Collection settings and optional collection mod details.
  • Preset management.
  • The YAML generator.
  • Debugging and notepad windows.
  • File and folder selectors.
  • Task status controls.
  • Dark and light theme support.

The application starts through Program.BuildAvaloniaApp(). Application initialization, command integration, and theme selection are handled by App.

The primary UI is implemented by MainWindow, while the new in-window installation flow is provided by InstallModView.

Shared WPF and Avalonia logic

The Avalonia project links the existing Mods Manager models, services, interfaces, extensions, and view models through OpenKh.Tools.ModsManager.Avalonia.csproj.

This keeps core behavior in one place instead of maintaining separate WPF and Avalonia implementations. WPF-specific views and services that construct WPF windows directly are excluded and replaced by Avalonia equivalents.

The existing WPF application remains supported and has been regression-built after the shared changes.

Avalonia compatibility layer

A new shared project, OpenKh.Tools.Common.Avalonia, provides Avalonia implementations for UI behavior expected by the existing view models, including:

  • Dialog ownership and active-window lookup.
  • Message boxes.
  • File dialogs.
  • Command re-evaluation.
  • Relay and asynchronous commands.
  • Application dispatcher compatibility.
  • Image compatibility helpers.
  • WPF-compatible enums used by shared code.
  • Visibility conversion.

This keeps the initial port focused and allows the existing view models to serve both frontends with minimal duplication.


Linux, Steam, and Proton support

Steam discovery

SteamService discovers Steam installations, additional library folders, supported games, account configuration files, and app-specific launch options.

The setup and launch flows use this information through SetupWizardViewModel and MainViewModel.

Automatic Steam launch options

Panacea and LuaBackend are native Windows DLLs loaded by the Windows game executables. When those executables run through Proton, Wine must be told to prefer the installed native DLLs over its built-in replacements.

After Panacea or LuaBackend is installed, the Mods Manager now offers to add the required Steam launch options automatically:

WINEDLLOVERRIDES="version,dinput8=n,b" %command%

The workflow is implemented by SetupWizardViewModel.OfferSteamLaunchOptions() and SteamService.EnsureLaunchOptions().

It:

  • Detects whether the required option is already present.
  • Locates each Steam account's localconfig.vdf.
  • Adds or updates the game-specific LaunchOptions entry.
  • Preserves existing launch options and game arguments.
  • Asks for confirmation before modifying Steam configuration.
  • Explains when Steam must be restarted to pick up external changes.
  • Shows the exact value to enter manually if automatic configuration is unavailable.

The prompt is triggered from the relevant Panacea and LuaBackend installation flows in SetupWizardViewModel, SetupWizardViewModel, and SetupWizardViewModel.

Panacea support for the Steam launcher

The Panacea DLL now recognizes both Steam and Epic launcher functions.

During OpenKH::Initialize(), Panacea scans for both implementations. It selects the Steam launcher when available and falls back to the Epic launcher otherwise. The Steam hook is represented by LaunchGameSteam, with launcher selection performed in OpenKH.cpp.

This allows Panacea's existing quick-launch flow to work with the current Steam releases without breaking the Epic path.

Reliable quick launch under Proton

Immediately closing the launcher after requesting a game launch can race Steam's Proton session tracking. The new game may start while the launcher's Wine session is shutting down, which can leave Steam stuck on Launching or prevent it from registering the game process correctly.

Panacea now detects Wine/Proton through IsRunningUnderWine(). When quick-launching under Proton, QuickBootHook():

  1. Starts the selected game through the Steam or Epic launcher function.
  2. Waits for a Kingdom Hearts game process to appear.
  3. Uses a bounded timeout so a failed launch cannot keep the launcher alive forever.
  4. Gives Steam a short additional period to register the new process.
  5. Exits the launcher after the process handoff is complete.

Game-process detection is handled by IsGameProcessRunning().

Linux game launching

MainViewModel.RunGame() now accounts for both the current platform and selected storefront.

On Linux:

  • Steam games are launched through Steam instead of starting their Windows executables directly.
  • Steam app IDs and launch URIs are used so Steam can establish the correct Proton environment.
  • Unsupported direct executable launches produce actionable guidance instead of failing silently.
  • Epic Games Store launch actions are unavailable because Linux has no native EGS client.

Wine-compatible game paths

The Mods Manager itself uses native Linux paths, but configuration read by games under Proton must use Windows-compatible paths.

WinePathUtil.ToGamePath() converts native Linux paths to Wine's Z: drive format. WinePathUtil.ToGamePathForwardSlashes() provides a forward-slash form suitable for TOML without additional escaping.

These conversions are used when writing configuration consumed by the Windows game processes and LuaBackend.


Cross-platform behavior

Platform capabilities

PlatformCapabilities provides one place to describe features that are currently Windows-only.

On Linux, the UI hides or bypasses:

  • PCSX2 live process injection.
  • Epic Games Store integration.
  • Native in-place self-update.
  • Direct Windows-native Panacea operations that cannot run on the Linux host.

These features remain available to the existing WPF application and to Avalonia when running on Windows.

Mod asset paths

Mod metadata commonly uses Windows-style separators regardless of the host operating system.

PatcherProcessor.Context.NormalizeSeparators() now normalizes those paths on Unix-like systems before resolving original, source, destination, and package-map locations.

For example, bgm\music050.win32.scd resolves as bgm/music050.win32.scd on Linux instead of becoming a filename containing a literal backslash.

Writable packaged configuration

An AppImage runs from an immutable mounted filesystem, so its installation directory cannot be assumed to be writable.

ConfigurationService.GetWritableStoragePath() now uses the installation directory when possible and falls back to the user's application-data directory when necessary.

This covers:

  • Mods Manager settings.
  • Enabled mod lists.
  • Collection selections.
  • Presets.
  • Window placement.

Shared mod downloads and images

DownloadableModsService was refactored so download behavior can be shared by both frontends.

Frontend-specific image handling is separated into:

This prevents WPF image types from leaking into the cross-platform build.

Setup wizard navigation

WizardPageStackService and SetupWizardViewModel were updated so the same setup logic works in both frontends.

The Avalonia wizard uses a page host instead of the WPF/Xceed wizard control, while preserving the existing view-model-driven branching in SetupWizardWindow.


Linux packaging and CI

AppImage packaging

build-linux-modsmanager.sh now:

  • Publishes the Avalonia project for linux-x64.
  • Produces a self-contained deployment.
  • Assembles the AppDir layout.
  • Adds the desktop entry, application icon, and AppRun entry point.
  • Downloads appimagetool when it is not already available.
  • Supports environments without FUSE by running appimagetool in extraction mode.
  • Produces openkh-modsmanager-x86_64.AppImage.
  • Includes Panacea and its native dependencies when they are available from the current OpenKH release archive.

Panacea remains a Windows DLL, but it is intentionally included in the Linux package because the Kingdom Hearts executables themselves continue to run as Windows applications through Proton.

Packaging metadata lives under packaging.

GitHub Actions

The Linux workflow in .github/workflows/dotnet-linux.yml:

  1. Checks out the repository and submodules.
  2. Installs .NET 8.
  3. Builds the Avalonia Mods Manager in Release mode.
  4. Runs the Linux-compatible headless tests.
  5. Builds the AppImage.
  6. Uploads the AppImage as a workflow artifact.

The existing Windows workflow in .github/workflows/dotnet.yml continues to build and package the WPF Mods Manager as part of the normal OpenKH Windows release.

Both workflows now use current versions of the official checkout and .NET setup actions.


Tests

A new Linux-compatible test project has been added under OpenKh.Tests.ModsManager.Avalonia. It targets platform-neutral .NET 8 and uses Avalonia.Headless.XUnit.

The test suite covers:

  • Loading application resources and styles.
  • Loading reusable control XAML.
  • Constructing the mod search window through Avalonia's runtime loader.
  • Headless XAML construction for the setup wizard, YAML generator, presets, notepad, debugging, progress, source-copy, target-selection, and work-in-progress windows.
  • Linux platform capability values.
  • Wine Z: path conversion.
  • TOML-friendly Wine paths.
  • Linux normalization of Windows-style mod asset paths.
  • Original, source, and destination path resolution on Linux.

The headless application is configured by TestApp.BuildAvaloniaApp().


Known platform differences

These differences are intentional and should not be treated as regressions:

Feature Windows Linux
WPF frontend Yes, default No
Avalonia frontend Optional Yes, default
Steam game discovery Yes Yes
Proton/Wine path generation Not required Yes
Epic Games Store integration Yes No
PCSX2 live memory injection Yes No
Native in-place self-update Yes No; replace the AppImage instead
Panacea files for Windows games Yes Packaged for games running under Proton
Mod installation and compilation Yes Yes

Validation performed

Automated

  • Avalonia Mods Manager Release build succeeds.
  • Avalonia build reports 0 warnings and 0 errors.
  • Existing WPF Mods Manager Release build succeeds.
  • WPF build reports 0 warnings and 0 errors.
  • Linux headless tests pass: 10 passed, 0 failed, 0 skipped.
  • Avalonia linux-x64 publish succeeds.
  • Avalonia win-x64 publish succeeds.
  • Avalonia XAML runtime-loader warning is resolved.
  • No broad warning suppression remains.
  • CRLF-aware diff and whitespace validation passes.

Manual

  • The Avalonia application launches from the built package.
  • The Linux build has been manually verified.
  • Windows behavior has been manually verified.
  • Core Mods Manager workflows have been tested on the produced build.

Reviewer checklist

Existing Windows WPF application

  • Confirm the WPF Mods Manager remains in the standard Windows release archive.
  • Run the WPF setup wizard.
  • Verify existing configuration migration and persistence.
  • Verify Steam and EGS installation detection.
  • Install, update, enable, disable, reorder, compile, and remove a mod.
  • Verify Panacea installation and removal where supported.
  • Verify PCSX2 behavior where supported.
  • Verify the existing Windows self-update flow.

Linux Avalonia application

  • Launch the generated AppImage on a clean Linux desktop.
  • Complete first-run setup.
  • Verify the default Steam library and at least one additional library.
  • Verify supported game discovery.
  • Verify Proton/Wine path generation.
  • Search for and install a mod.
  • Enable, disable, reorder, compile, update, and remove a mod.
  • Restart the AppImage and verify settings and enabled mods persist.
  • Run the AppImage from a read-only location and confirm data is written to user storage.
  • Verify file and folder dialogs under the target desktop environment.
  • Verify dark and light themes.
  • Verify the AppImage icon and desktop metadata.

Panacea and Proton

  • Install Panacea for a Steam copy through the setup wizard.
  • Confirm the Mods Manager offers to add the required Wine DLL overrides automatically.
  • Confirm existing Steam launch options are preserved.
  • Confirm existing arguments following %command% remain intact.
  • Test updating localconfig.vdf with Steam closed.
  • Verify the restart guidance when Steam is running.
  • Confirm matching configurations are updated for every applicable local Steam account.
  • Confirm manual instructions appear when no matching Steam configuration is found.
  • Verify both version.dll/Panacea and dinput8.dll/LuaBackend load under Proton.
  • Quick-launch a Steam game through Panacea on Windows.
  • Quick-launch a Steam game through Panacea under Proton.
  • Confirm Steam transitions from the launcher to the game without becoming stuck on Launching.
  • Confirm a failed launch does not leave the launcher alive indefinitely.
  • Confirm Epic quick launch still uses the fallback hook on Windows.

Optional Windows Avalonia build

  • Publish the Avalonia project for win-x64.
  • Confirm it launches independently from the WPF executable.
  • Verify setup, mod search, installation, and compilation.
  • Confirm Windows-only capability flags remain enabled where appropriate.
  • Confirm the optional Avalonia build does not replace or conflict with the WPF release layout.

Packaging and CI

  • Confirm .github/workflows/dotnet-linux.yml passes on the final PR commit.
  • Confirm .github/workflows/dotnet.yml passes on the final PR commit.
  • Download and launch the AppImage produced by CI, not only a local artifact.
  • Verify Panacea and its required native dependencies are included in the CI artifact.
  • Verify packaging emits a clear warning if the release archive cannot be downloaded.
  • Confirm the Linux artifact name and retention settings are acceptable.
  • Compile a mod containing Windows-style asset paths and verify the output structure on Linux.

Shared code review

Because this PR changes shared behavior in addition to adding a frontend, reviewers should pay particular attention to:


Potential follow-up work

The following items are outside the scope of the initial Linux port and can be handled separately:

  • Publish the Windows Avalonia build as an official optional CI artifact.
  • Attach the AppImage to rolling GitHub releases once the Linux build is considered stable.
  • Add UI interaction tests beyond XAML construction and platform behavior.
  • Gradually replace compatibility APIs with framework-neutral abstractions.
  • Introduce compiled Avalonia bindings after the port stabilizes.
  • Add Linux artifacts for architectures beyond linux-x64.
  • Add an AppImage-appropriate update flow.

Screenshots

Main Mods Manager window on Linux

Main Mods Manager UI on Linux

Setup wizard and Steam discovery

Setup wizard and Steam discovery

Integrated mod installation dialog

Integrated mod installation dialog

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 2bfc019f-a00c-4bb9-839b-aedefee23189

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@TopazTK

TopazTK commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

@Yokimitsuro has been working on something like this for a while on the OpenKH Discord Server.
I would like the two PRs to be combined wherever possible, if possible.

@TopazTK

TopazTK commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Looking onto this a little, a few concerns:

I myself don't do Linux a lot, so I will be tagging along @KHOmega for testing and assessment whether this PR is useful or detrimental for Linux and Windows folks alike,

@TopazTK

TopazTK commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

I did not originally want to mention this since OpenKH is not Re:Fined and does not share its policies or code of conduct, but this PR has a lot of the telltale signs of being generated artificially. I do apologize if this isn't the case and if it isn't I sincerely ask to be provided with evidence, as I cannot support this PR personally due to my personal alignment when it comes to Generative AI being used in important projects that a lot of people rely on.

Even though I am no longer a part of the devteam, I do believe that my opinion will still matter just a tiny bit hopefully.

@KHOmega

KHOmega commented Aug 20, 2026

Copy link
Copy Markdown

Can we look into the code on how certain notes for the end user are formatted?

This doesn't look like it was typed by a person, as several comments feel robotic.

There are also some factors, such as Epic Games Store integration being a regression on Linux.

Epic Games Store isn't available on Linux.

Current versions of OpenKH work as intended when running the game via Heroic or Lutris, sans Build and Run and Run Only as current implementation can't call WINE to open those programs.

I can not in good faith support this without proof that these changes were made without the use of generative AI, as there are very big tell tale signs of it being used so.

@TopazTK

TopazTK commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Looking further, you stated that the WPF interface is left intact for Windows, and Avalonia is used for Linux. This decision baffles me as Avalonia is cross-platform and its biggest asset is being cross-platform.

Having two separate frontends on one program doesn't just make an overengineered hard to maintain program TWICE as overengineered and hard to maintain, but it also makes it so that bugs and glitches have twice the risk of popping up and being missed, whilst also adding onto the libraries called and referenced by the program.

I would support a single frontend approach, replacing WPF with Avalonia completely as @Yokimitsuro has done in his fork.

@Zexyen

Zexyen commented Aug 20, 2026

Copy link
Copy Markdown
Author

Looking further, you stated that the WPF interface is left intact for Windows, and Avalonia is used for Linux. This decision baffles me as Avalonia is cross-platform and its biggest asset is being cross-platform.

Apologies, I should've more specifically mentioned that this was a PoC and not really meant to be submitted as is.

Having two separate frontends on one program doesn't just make an overengineered hard to maintain program TWICE as overengineered and hard to maintain, but it also makes it so that bugs and glitches have twice the risk of popping up and being missed, whilst also adding onto the libraries called and referenced by the program.

I would support a single frontend approach, replacing WPF with Avalonia completely as @Yokimitsuro has done in his fork.

I agree completely and would like to help @Yokimitsuro with that where possible.

Current versions of OpenKH work as intended when running the game via Heroic or Lutris, sans Build and Run and Run Only as current implementation can't call WINE to open those programs.

They should work the same as the WINE Version (no Build and Run and Run Only support as that directly calls steam to launch the game)

I can not in good faith support this without proof that these changes were made without the use of generative AI, as there are very big tell tale signs of it being used so.

Some changes were created with AI Tooling (Comments & some of the work with panacea). C# isn't my strong suit (don't really use it much at work). If that causes issues with this PR please let me know and I will go ahead & close this PR.

@TopazTK

TopazTK commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Apologies, I should've more specifically mentioned that this was a PoC and not really meant to be submitted as is.

Then... why did you submit it as is? You could have made the PR in a way which only used Avalonia. This decision seems backwards even as a PoC.

I agree completely and would like to help @Yokimitsuro with that where possible.

His branch is mostly complete, and from what I can see in my personal opinion, more feature complete than this one. I'd advise reaching out to him in the OpenKH server if possible.

Some changes were created with AI Tooling (Comments & some of the work with panacea). C# isn't my strong suit (don't really use it much at work).

I do not believe the "some" claim. I can say like at least 75% of the code was made without human intervention.

If that causes issues with this PR please let me know and I will go ahead & close this PR.

I am not one of the decision makers anymore, so I have no say in this. But I will say I will not be supporting this PR going further for failure to disclose your LLM usage, failure to make the PR properly, and unless proven otherwise failure to properly disclose how much AI tooling was used in this codebase.

@Zexyen Zexyen closed this Aug 20, 2026
@TopazTK

TopazTK commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

An extremely childish response to a fair list of criticism and concerns. If you cannot handle feedback, don't contribute to open-source software.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants