Skip to content

Improve the Software Catalog and Catalog Editor - #5517

Merged
Gabriel Dufresne (GabrielDuf) merged 15 commits into
mainfrom
catalog-editor-improvements
Oct 14, 2026
Merged

Gabriel Dufresne (GabrielDuf) merged 15 commits into
mainfrom
catalog-editor-improvements

Conversation

@GabrielDuf

@GabrielDuf Gabriel Dufresne (GabrielDuf) commented Oct 14, 2026 •

Copy link
Copy Markdown
Contributor

Builds on the Software Catalog (#5496). It makes the catalog easier to manage and use, and fixes problems found while reviewing it.

Software Catalog

  • Sidebar, startup and shortcuts: when the catalog is enabled, it comes first in the sidebar. It is the default startup page only when a usable catalog exists (the file exists, loads and lists at least one package). Ctrl/Cmd+1..9 and the macOS View menu follow the sidebar order, and so does the previous/next page cycle; all three use one shared page list.
  • Tile actions: installed tiles get an Update button when an update is available. Every tile gets a "More actions" menu with Update, Uninstall and Package details.
  • Version pins: an entry with a pinned version installs that version when its manager supports specific versions. The pin shows on tiles and in tooltips.
  • Live reload: while the page is open, the catalog reloads when its file is created, changed or removed. An unchanged file keeps the current tiles, so the scroll position and icons don't reset.
  • Clearer load messages: a missing catalog shows a neutral "not set up yet" message. An invalid or unreadable file gets its own message, with the path and the technical reason underneath in selectable text.
  • Reliability fixes:
    • The catalog waits for package managers to finish loading. Before this, every package showed as unavailable at startup. This adds PEInterface.AreManagersLoaded and PEInterface.ManagersLoaded.
    • The source map is fully built before it replaces the old one, so the state timer never reads it half-filled.
    • The last complete installed list is kept while the installed list reloads.
    • Install buttons no longer disable each other.
    • A package listed in several catalogs shows once when the view isn't grouped by catalog.
  • Remembered settings: view mode and sort order persist across restarts. The default view is Icons.

Catalog Editor

  • New file and New catalog: "New" is now "New file" and always confirms before it closes the open file. "New file" and "New catalog" each get a distinct icon.
  • Removing catalogs: each row of the catalog dropdown has a remove button. Removing a catalog that still has packages asks for confirmation.
  • Adding packages: "Add packages" opens Discover with the edited catalog preselected. "Pin version" lists the versions the manager offers.
  • First run: with no machine-wide catalog yet, the editor opens an empty, editable document for that path. Saving it creates the folder. On macOS, the save goes through the administrator prompt when the root-owned file isn't writable.
  • Feedback: unsaved changes show in the page subtitle. Errors open a dialog whose text can be copied, and a successful save shows a toast. These replace the status block that shrank the package list.
  • Quitting with unsaved changes: quitting while the window is hidden no longer hangs. The window comes back for the discard dialog.

Discover

  • Add selection to catalog: the always-visible catalog dropdown is gone. "Add selection to catalog" opens a dialog to pick one or more catalogs. It then reports, per catalog, what was added and what was already there.
  • Discover as startup page: "Add selection to catalog" now works right away. It used to stay disabled until the editor had been opened.

Other

  • Accessibility crash: an accessibility client (VoiceOver, UI automation) that invokes a disabled control no longer crashes the app. Only ElementNotEnabledException is caught; it is logged and the main loop resumes.
  • macOS glass toolbar: button highlights and the catalog dropdown stay inside the toolbar capsule's border. The main button is fully rounded when it has no dropdown half.

Testing

  • macOS: reproduced each issue on the previous build, then re-ran the same steps on this branch.
  • Windows x64: the UniGetUI.Windows.slnx build succeeds. UniGetUI.Tests (760), PackageEngine.Tests and Language.Tests pass. Both dotnet format whitespace and dotnet format style report no changes. Also launched and checked the app manually.

Relates to #5496

Catalog Editor
- Rename "New" to "New file", give it its own icon, and always confirm
  before it closes the open file; "New catalog" gets a distinct icon
- Remove a catalog from the selector dropdown (x per row), confirming
  when it still has packages; the list stays open between removals
- Add packages: jump to Discover with the edited catalog preselected
- Save to the machine-wide catalog on macOS through the system
  administrator prompt when the root-owned file is not writable
- Show unsaved changes in the page subtitle, errors in a dialog with
  selectable/copyable text, and a toast on save, instead of a status
  block that shrank the package list
- Rename catalog uses a rename icon; sidebar item uses catalog_add

Discover
- Drop the always-visible catalog dropdown; "Add selection to catalog"
  opens a dialog to pick one or more catalogs and reports what was
  added and what was already present in each

Software Catalog
- When enabled, list it first in the sidebar, open it by default, and
  renumber Ctrl/Cmd+1..9 (and the macOS View menu) to follow the
  sidebar order from one shared mapping
- Remember the view mode and sort order across restarts; default to
  the Icons view

macOS glass
- Keep toolbar button highlights and the catalog dropdown inside the
  capsule rim
- Round the main toolbar button fully when it has no dropdown half

Tests
- Isolate SoftwareCatalogTests settings in a temp folder, and cover
  catalog removal, multi-catalog adds, persisted view/sort and the
  shortcut order
- Quitting with unsaved Catalog Editor changes while the window is
  hidden (macOS close, tray) no longer hangs: the window is shown for
  the discard dialog and stays visible if the quit is cancelled
- With no machine-wide SoftwareCatalog.json yet, the editor opens an
  empty editable document for that path, and saving there creates the
  folder (through the macOS administrator prompt when needed)
- The Software Catalog waits for package managers to finish loading
  (new PEInterface.AreManagersLoaded / ManagersLoaded) instead of
  hiding every package as unavailable at startup
- Refreshing the catalog builds the source map before swapping it in,
  so the state timer never sees it half-filled and hides tiles
- Install buttons no longer disable each other while one package is
  being looked up

Verified on macOS by reproducing each issue on the previous build and
re-running the same steps on this one.
Software Catalog
- Keep the last complete installed list while the inventory reloads,
  so installed tiles no longer flip to a disabled Install
- Report a failed source listing as such instead of "source not
  enabled"
- Keep existing tiles when the catalog file is unchanged (no scroll
  reset or icon blink) and retry icons that could not load earlier
- Explain why an install stopped when the package became unavailable
  during its lookup
- Show a package listed in several catalogs once when not grouped
- Show and sort managers by display name; Grid and Icons views get a
  tooltip with manager, source and status

Catalog Editor
- Retry a failed load on the next visit, and explain it in the
  Discover "Add selection to catalog" tooltip
- Tell the user when the macOS administrator prompt is cancelled
- Keep the catalog dropdown closed after a cancelled removal, and keep
  the remove button's tooltip in sync with renames
- Only show load errors while the editor is on screen
- Use singular wording for single packages
Discover looked the shared catalog document up through the main
window, but as the startup page it is entered while the window is
still being constructed, so the lookup found nothing and "Add
selection to catalog" stayed disabled until the editor was visited.
Use the document passed to the page instead.
- Installing a catalog entry with a pinned Version installs that
  version when its manager supports specific versions (logged and
  ignored otherwise)
- The Software Catalog shows the pin on Tiles and in the Grid/Icons
  tooltips
- The Catalog Editor shows a Version column ("Latest" when unpinned)
  and a Pin version action (toolbar and context menu) that lists the
  versions the manager offers; managers without version support get
  an explanation instead
While the catalog page is open, its 2-second state timer now compares
the catalog file's existence, size and write time with what was last
loaded, and refreshes when they differ. A catalog an administrator
deploys, edits or removes shows up without leaving the page; an
unchanged file still keeps the existing tiles.
A missing catalog file is the normal state on most devices, so it now
shows a neutral "No software catalog has been set up on this device
yet" instead of an error. An invalid file and an unreadable file get
their own messages, and the file path plus the technical reason (for
example "Duplicate catalog identifier: a." or the access-denied
detail) appear in a smaller, selectable line under the headline.
An installed catalog package was a dead end showing only "Installed".
Tiles now show an Update button when an update is available, and
every tile gets a "More actions" menu with Update, Uninstall (after
the standard confirmation) and Package details. Details opens with the
action matching the tile (update, uninstall, or install at the pinned
version). Updates and uninstalls reuse the Installed page's launchers.
Avalonia's automation peers throw ElementNotEnabledException when an
accessibility client (VoiceOver, UI automation tools) invokes a
disabled control. On macOS the native bridge rethrows any callback
exception out of the run loop with no handler, so this ended the app
and showed the crash reporter, although the request should simply be
ignored. Avalonia 12.1.2 behaves the same.

AvaloniaAppHost now catches only that exception around the desktop
lifetime, logs it, and resumes the main loop until the lifetime's
normal exit, keeping its exit code. Every other exception still
crashes as before.
With the catalog enabled but no usable catalog (missing, empty,
invalid or unreadable file), the default startup page fell on the
catalog and the app opened on an empty or error page. The catalog is
now the default startup page only when its file loads and lists at
least one package; otherwise the usual default (Updates or Discover)
applies. The sidebar order and Ctrl/Cmd+number shortcuts stay fixed.

The previous/next page cycle is now derived from the same ordered page
list as the number shortcuts instead of two hand-written tables.
The "⋯" character is positioned by its font metrics and rendered above
the middle of the button. Draw three dots instead, centred both ways
in the button's content area.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

Catalog details actions, version loading, late manager initialization, unreadable-file handling, and localization metadata have unresolved defects.

6 open findings
What changed in this PR

Improves catalog navigation, tile actions, live reload, version pinning, editor workflows, elevated saving, and accessibility reliability.

Changes:

  • Adds catalog tile actions, pins, persistence, live reload, and startup/navigation integration.
  • Expands editor and Discover workflows with multi-catalog operations and elevated saves.
  • Adds tests, localization strings, icons, and macOS styling.
File Description
src/​UniGetUI.Tests/​WindowsAdminFileInstallerTests.cs Tests elevated Windows file copying.
src/​UniGetUI.Tests/​SoftwareCatalogTests.cs Tests catalog views, pins, navigation, and usability.
src/​UniGetUI.Tests/​CatalogEditorTests.cs Tests editor additions, removal, and first-run saving.
src/​UniGetUI.PackageEngine.PackageEngine/​PEInterface.cs Exposes manager-loading status and event.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​SoftwareCatalogPage.axaml.cs Polls for catalog changes.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​SoftwareCatalogPage.axaml Adds tile actions, pins, tooltips, and errors.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​InstalledPackagesPage.cs Exposes update and uninstall helpers.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​DiscoverSoftwarePage.cs Adds multi-catalog selection workflow.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​CatalogEditorPage.cs Expands editor commands and feedback.
src/​UniGetUI.Avalonia/​Views/​SoftwarePages/​AbstractPackagesPage.axaml.cs Adjusts standalone button rounding.
src/​UniGetUI.Avalonia/​Views/​SidebarView.axaml.cs Assigns dynamic navigation shortcuts.
src/​UniGetUI.Avalonia/​Views/​SidebarView.axaml Reorders catalog navigation and icons.
src/​UniGetUI.Avalonia/​Views/​Pages/​SettingsPages/​Interface_P.axaml.cs Aligns startup-page ordering.
src/​UniGetUI.Avalonia/​Views/​MainWindow.MacMenu.cs Generates macOS navigation menu dynamically.
src/​UniGetUI.Avalonia/​Views/​MainWindow.axaml.cs Uses shared shortcut-page ordering.
src/​UniGetUI.Avalonia/​Views/​Controls/​CatalogSelector.cs Adds catalog removal controls.
src/​UniGetUI.Avalonia/​ViewModels/​SoftwarePages/​SoftwareCatalogViewModel.cs Implements catalog state, actions, pins, and persistence.
src/​UniGetUI.Avalonia/​ViewModels/​SoftwarePages/​PackagesPageViewModel.cs Adds subtitle suffixes and install versions.
src/​UniGetUI.Avalonia/​ViewModels/​SidebarViewModel.cs Detects usable startup catalogs.
src/​UniGetUI.Avalonia/​ViewModels/​MainWindowViewModel.cs Centralizes page ordering and startup selection.
src/​UniGetUI.Avalonia/​ViewModels/​DialogPages/​CatalogEditorViewModel.cs Adds first-run, removal, and multi-catalog behavior.
src/​UniGetUI.Avalonia/​Models/​SoftwareCatalog.cs Adds usability checks and elevated saving.
src/​UniGetUI.Avalonia/​Infrastructure/​WindowsAdminFileInstaller.cs Implements UAC-backed catalog writing.
src/​UniGetUI.Avalonia/​Infrastructure/​MacAdminFileInstaller.cs Implements macOS administrator writing.
src/​UniGetUI.Avalonia/​Infrastructure/​AvaloniaAppHost.cs Recovers from disabled automation invocations.
src/​UniGetUI.Avalonia/​Assets/​Styles/​Styles.MacGlassControls.axaml Refines macOS toolbar styling.
src/​SharedAssets/​Assets/​Symbols/​rename.svg Adds rename icon.
src/​SharedAssets/​Assets/​Symbols/​document_add.svg Adds new-file icon.
src/​SharedAssets/​Assets/​Symbols/​collections_add.svg Adds new-catalog icon.
src/​SharedAssets/​Assets/​Symbols/​catalog_add.svg Adds catalog-add icon.
src/​Languages/​lang_en.json Adds new English UI strings.

🧠 Review effort: Balanced


💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/Languages/lang_en.json Resolved
…anagers

- Package details opened from a catalog tile now runs its main action:
  the window only sets ShouldProceedWithOperation, which the catalog
  ignored, so Install/Update/Uninstall just closed it. Install goes
  through the catalog's install command (pin and availability checks),
  Update and Uninstall through the Installed page launchers.
- The details window's Install variants (as administrator,
  interactive, skip hash) keep the catalog pin through a new
  InstallVersion option; LaunchAndClose used to install the latest.
- The Pin version dialog starts on the current pin, so confirming
  before the version list loads no longer clears it.
- The editor only starts a blank first-run document when the catalog
  is really missing. File.Exists is also false for a file in a folder
  the user cannot read, which opened a blank document that an elevated
  save could write over the real catalog; that now reports the load
  error instead.
- The Software Catalog refreshes once a manager that was still
  starting at the 60 s initialization timeout becomes ready; its tiles
  used to stay unavailable until a manual refresh.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Catalog actions can target an arbitrary version when multiple matching versions are installed.

0 open findings

6 resolved since last review
Previously missed (1)

In code that hasn't changed since last review

Medium severity Avoid arbitrary package version selection in Details and Uninstall

src/​UniGetUI.Avalonia/​ViewModels/​SoftwarePages/​SoftwareCatalogViewModel.cs:720

InstalledPackagesLoader intentionally retains multiple versions (InstalledPackagesLoader.cs:11-18, AbstractPackageLoader.cs:347-350), but this lookup collapses them with FirstOrDefault over an unordered snapshot. The new Details and Uninstall actions can therefore target an arbitrary installed version, and uninstalling one may leave the catalog tile installed because another matching version remains. Resolve all matching instances and define deterministic behavior (for example, uninstall all matches or select and label one version explicitly).

🧠 Review effort: Balanced

@randy-but-a-ro randy-but-a-ro Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🤖 Pull request was approved automatically: the AI review is complete and all its review threads are resolved. 🎉

Integration Details
{
	"deliveryId": "08a8d1c0-c801-11f1-8c69-d24b933f54d1",
	"headSha": "abbac9cdffa721f7a56e96faaf4384514534f961",
	"reviewer": "copilot-pull-request-reviewer[bot]"
}

@GabrielDuf
Gabriel Dufresne (GabrielDuf) merged commit d7eab2e into main Oct 14, 2026
7 checks passed
@GabrielDuf
Gabriel Dufresne (GabrielDuf) deleted the catalog-editor-improvements branch October 14, 2026 19:24
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.

2 participants