Skip to content

Avalonia Port (Phase 1): MVVM Refactor + macOS Support#4524

Merged
Marc-André Moreau (mamoreau-devolutions) merged 5 commits intomainfrom
Avalonia-phase1
Mar 24, 2026
Merged

Avalonia Port (Phase 1): MVVM Refactor + macOS Support#4524
Marc-André Moreau (mamoreau-devolutions) merged 5 commits intomainfrom
Avalonia-phase1

Conversation

@GabrielDuf
Copy link
Contributor

Summary

This PR is phase 1 of the cross-platform port of UniGetUI from WinUI3 to Avalonia, targeting macOS for now.

Architecture overhaul

  • Replaced the old monolithic Views/Pages/ structure with a proper MVVM architecture (Views/ + ViewModels/)
  • All pages now follow the .axaml + .axaml.cs + ViewModel pattern

Features ported

  • All 4 software pages: Discover, Installed Packages, Software Updates, Package Bundles
  • All settings sections: General, Interface, Administrator, Backup, Experimental, Internet, Notifications, Operations, Updates, Managers
  • Dialog windows: Package Details, Install Options, Manage Ignored Updates, Operation Output, Telemetry Consent
  • Sidebar navigation with page switching

New additions

  • Homebrew package manager — new UniGetUI.PackageEngine.Managers.Homebrew project, wired into PEInterface for macOS
  • SvgIcon control — lightweight native Avalonia SVG renderer with Foreground brush support
  • MacOsNotificationBridge — macOS native notification support via NSUserNotificationCenter
  • Custom settings card controls (CheckboxCard, ComboboxCard, TextboxCard, etc.) matching the WinUI originals

Removed

  • Deleted ~19 000 lines of the previous prototype implementation that predated the MVVM restructure

@mamoreau-devolutions Marc-André Moreau (mamoreau-devolutions) merged commit 66d1935 into main Mar 24, 2026
1 check passed
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left a few recommendations but this is just a phase 1 so it can be merged and the things can be done after

The main points are:
Many UI done in code with styles, which will make it hard to have different styles for macOS and other platforms
Many things in .axaml.cs that should be in the viewmodels
Few texts missing translations maybe

Also, there is a tooon of calls to the translate function and a ton of menus and labels created in code to have the translation. We should do a MarkupExtension to allow us to bind values in axaml views and have them be translated rather than creating all the labels in the code.

}

// ── Bindable properties ───────────────────────────────────────────────────
private string _title;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not use observable properties ?


// ─── Collections ──────────────────────────────────────────────────────────
public ObservablePackageCollection FilteredPackages { get; } = new();
public ObservableCollection<SourceTreeNode> SourceNodes { get; } = new();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we use AvaloniaList like in RDM?


public bool IsListViewMode => ViewMode == 0;
public bool IsGridViewMode => ViewMode == 1;
public bool IsIconsViewMode => ViewMode == 2;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use an enum instead of int and checking if its 0,1,2 ?

public event EventHandler<PageType>? CurrentPageChanged;

// ─── Operations panel ─────────────────────────────────────────────────────
public ObservableCollection<OperationViewModel> Operations

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avalonialist again maybe

base.IsEnabled = value;
_warningBlock.Opacity = value ? 1 : 0.2;
}
get => base.IsEnabled;

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want this to be observable to be able to change it after creation and bind the UI to it ?

{
Width = 1,
Height = 30,
Margin = new global::Avalonia.Thickness(4, 4),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In many places we create elements with styles in code directly, this is ok for now but eventually a .axaml would be better for styling between macOS, windows, linux, etc

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This realllyyy needs a view model 😓

{
"light" => ThemeVariant.Light,
"dark" => ThemeVariant.Dark,
_ => ThemeVariant.Default,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is default valid ? In the styles we only seem to have dark and light 🤔

<DependentUpon>Administrator.axaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Update="Views\Pages\SettingsPages\ManagersHomepage.axaml.cs">

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use something to auto include all .axaml like we do in RDM?

{
Name = "Homebrew",
Description = CoreTools.Translate(
"The Missing Package Manager for macOS (or Linux).<br>Contains: <b>Formulae, Casks</b>"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

br> and b> in desc works??? sus

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

Labels

None yet

Development

Successfully merging this pull request may close these issues.

3 participants