Skip to content

feat: library polish with window presets, plus launcher pages, store backends and per-game controls - #765

Merged
aaf2tbz merged 36 commits into
mainfrom
ui-polish
Nov 5, 2026
Merged

aaf2tbz merged 36 commits into
mainfrom
ui-polish

Conversation

@aaf2tbz

@aaf2tbz aaf2tbz commented Nov 4, 2026 •

Copy link
Copy Markdown
Collaborator

This PR combines two authors' work, described separately below. Part 1 is Mohamed's original change (6a417412, authored by him). Part 2 is my work on top of it (all later commits).

Reopened from #746 by @MohamedElGhandour. His branch still carried the old main history after today's history rewrite, so GitHub showed hundreds of unrelated commits. This branch is his change applied to current main, authored by him; the file contents are identical to his latest head (12ee4bc8).

Part 1: library and settings polish with window-size presets (@MohamedElGhandour)

Commit 6a417412, authored by Mohamed. His description, unchanged:

Summary

Library controls become cramped or disproportionately small on large displays, and Settings mixes unrelated options in a long grid. This gives the library a shared responsive layout, groups Settings into focused categories, and adds saved window-size presets that keep desktop space visible.

Changes

  • Replace tiny text/Unicode control glyphs with bundled SVG icons for search, play, edit, dropdowns, carousel navigation, downloads, Settings gears, and close buttons, with consistent sizing and alignment.
  • Stack the hero and carousel with explicit height budgets; scale controls, SVG icons, typography, and collection columns for Full HD, 2K, and 4K displays.
  • Organize Settings into General, Integrations, Storage, Updates, and Advanced, with compact tabs, larger controls, and preserved actions and confirmations.
  • Add Automatic, Compact, Full HD, 2K, and Large (4K) window presets. Apply changes immediately, fit smaller displays, and store the selection with existing UI preferences.
  • Add explicit offline preview dimensions and regression coverage for layout bounds, preset sizing/serialization, category mapping, and language-menu placement.

PR Readiness (MANDATORY)

  • Real-game launch test: N/A for this presentation/window-preference change; game launch callbacks, runtime routing, and compatibility rules are unchanged.
  • No hardcoded paths, secrets, or absolute user-home paths introduced.
  • Config/rules TOML validation: N/A; unchanged.
  • Version metadata: N/A; no version bump.
  • Bottle/runtime migration and launch behavior preserved; no migration changes.
  • User-facing behavior documented in docs/development.md.
  • Regression tests added for the new geometry and state decisions.

Local toolchain

  • GPUI formatting, build, and tests: 119 passed, 3 tests ignored.
  • Regular and FEX C backend suites: both make test commands passed.
  • Packaged native preview: binary hash recorded and deep/strict ad-hoc signature verification passed.
  • Diff/pre-commit checks passed; no new dependencies or repository-root files.
  • C++/Obj-C compilation, clang-format, CTest, shell/rule/release-workflow checks: N/A; those sources and tooling are unchanged.

Test notes

Native macOS GPUI preview on a 3840 × 2160 logical display:

Check Observed
Automatic / Large 2800 × 1700 content, normal window with desktop margins
Compact / Full HD / 2K 1360 × 860 / 1920 × 1080 / 2560 × 1440 content in the same window
Settings navigation All categories reachable; category switches close the language picker and preserve independent scrolling
Minimum 720 × 540 viewport Compact tabs and scrolling work; language picker opens upward near the bottom edge

These previews use sample artwork and do not access production credentials or write preferences. Serialization and fallback are covered by tests; production preference persistence was not exercised against the user's profile. No real-game run is claimed for this UI commit.

The C suites skipped archive-based runtime simulation and Wine facade integration because the worktree lacks the runtime archives / MetalSharp Wine app. Existing fullscreen-to-windowed transition handling was not manually exercised.

Risk

Changes are confined to the native UI and its existing preferences file. Window sizes use logical points and fit within display bounds, with a 720 × 540 minimum. Invalid or missing stored presets fall back to Automatic. Reverting this commit restores the previous UI; no game data or runtime rollback is needed.

Review follow-up — 4 November 2026

The hero title and action group now stay vertically centered on the left of the artwork using flex alignment instead of a fixed top offset. The generated backend-route inventory was refreshed, fixing the stale-inventory failure in GPUI CI without changing any route.

Merged current main while preserving the published branch history. Upstream data relocation, quit cleanup and MetalFX changes are retained; Data Location appears under Storage. The old and rewritten 1.0 release commits have identical trees and provided the common content base for reconciliation.

Flow Action Expected Observed Result
Hero Switch Compact, Full HD, 2K and Large presets Left-aligned content stays vertically centered on the hero Correct at 1360×860, 1920×1080, 2560×1440 and 2800×1700 logical points Pass
Uninstalled collection Open three sample owned games through the real C backend in an isolated validation profile Artwork, titles and Install buttons remain visible Correct at Compact and Large sizes, including a deliberately long title Pass
Search Filter for Portal, then clear One matching card, then all three cards Correct Pass
Settings Open Storage after merging upstream Data Location remains available Visible beneath MetalSharp Data Folder Pass

Added a regression for parsing and merging a sync response containing both installed and uninstalled games. The owned entries and their artwork remain available to the uninstalled collection while the Play library stays restricted to installed games.

cargo fmt --check, cargo test --locked --offline (119 passed, 3 ignored), regular/FEX C suites, route-inventory verification, DMG workflow verification and diff checks passed. A separate locally assembled QA app used the compiled frontend/backend, unchanged icon/runtime resources from the installed app, current UI assets/configs, and verified deep/strict ad-hoc code signing; binary hashes were recorded.

The card check used synthetic cached ownership data with no API key, as agreed with Mohamed. A live Steam API sync, Steam sign-in, actual installation and game launching were not performed. Standard full-Xcode packaging remains untested locally because actool is unavailable; the native QA app was assembled separately and the installed app was not changed.

UI previews

Native offline previews with sample games. Large (4K) uses a 2800 × 1700 content window and leaves desktop space visible. The first preview below predates the review alignment fix; the following screenshots show the current result.

Library and carousel — before review alignment fix

New library hero, carousel, larger controls, and SVG icons

After review — centered hero, Full HD

Full HD: hero content centered vertically on the left of the artwork

After review — centered hero, Large (4K)

Large preset: hero content remains centered vertically on the left

Uninstalled collection — sample ownership data

Real backend and native UI in an isolated validation profile, using cached sample ownership data and no API key. Artwork, Install buttons and a deliberately long title remain visible. This is a presentation check, not a live Steam API sync.

Three uninstalled sample game cards with artwork, titles and Install actions

Collection

Responsive game collection grid

Settings and window-size presets

Settings category sidebar and window-size presets

SVG icons — close-up

Text glyphs were replaced by scalable vector assets; this native-size crop shows Play, edit, dropdown, and Settings controls.

Close-up of the new SVG Play, edit, dropdown, and Settings icons

Part 2: launcher pages, store backends and per-game controls (@aaf2tbz)

Commits 27f40899…d56e9dbe (34 commits), built on top of Mohamed's commit.

Library structure

  • Removed the console emulators (PCSX2, RPCS3, shadPS4, SharpEmu).
  • Added a sliding library sidebar with a page per launcher: Steam, Ubisoft, Battle.net, Rockstar, GOG, Epic and Windows Programs, with Logs at the bottom. In narrow windows it slides over the page instead of squeezing it.
  • Replaced the header with a single row that has the page's launcher button and options. Hero art now runs down to the dock, and launchers have their own icons.
  • Each launcher page has a launcher button, setup steps and a ⋯ options menu. That menu can uninstall the launcher, and its games folder only if you opt in.
  • Launchers ask which drive their games go on and create a managed MetalSharp <Launcher> Games folder there.

Launcher backends

  • Rockstar Games Launcher: installs into and runs from the Steam prefix. Installed Steam copies of Rockstar titles are also listed on the Rockstar page. There they stay Steam games, so they launch with the Steam prefix's patches and arguments (RDR2's DX12 settings, GTA V Enhanced's Agility frontend).
  • Battle.net:
    • keeps the app on C: and finds it wherever it was installed;
    • starts games the way Battle.net's Play does;
    • uses Battle.net's own cover art.
  • Ubisoft Connect:
    • on the FEX build, starts the way the Battle.net client does: upc.exe with no switches, from its own folder;
    • games take their cover and hero from the same title's Steam store release (exact title match, keyless) instead of the EXE icon.
  • GOG:
    • setup installs gogdl with Python 3.10 or newer. It used to take macOS's 3.9, so the install failed and login later reported "gogdl auth failed";
    • Stop and uninstall no longer fail when no game is running (wineserver -k exits 1 when there is no server);
    • cards use each game's portrait cover from GOG's games database, and the hero uses its full background. Both are filled in without a sync.
  • GOG, Epic and Windows Programs: setup steps, Install Program, and custom card and hero art per game.

Per-game controls

  • The hero's graphics picker now also appears for GOG, Epic and Windows Programs games, using each source's own engine list. Windows Programs offer no Auto option; an app saved as Auto shows as OpenGL, which is what it runs on. The picker has no "Graphics" label on any page.
  • Game settings open as a centered overlay on every page and at any window size. The ✕ or a click outside closes it. GOG and Epic games get the settings button, with Choose EXE saving through their own backend.
  • The ⋯ menu on GOG and Epic pages can uninstall a single installed game. Only the game is removed:
    • GOG deletes the game's folder and download manifest. The game stays in the library as not installed, and the GOG prefix is kept.
    • Epic lets Legendary remove the game. It no longer deletes the game's bottle, which holds its saves and settings.

Art

  • Wide hero from portrait art: the cover sits in the center, slightly stretched, over a lightly blurred backdrop that darkens toward the edges, with a crossfade on both sides.
  • Startup cleanup fix: the art cache's cleanup at launch could delete a generated wide hero that the first page was already showing, which left that hero blank for the whole session (Overwatch on Battle.net). The cleanup now keeps wide heroes of art still in use, and the hero checks its file exists.

Testing

  • Regular and FEX C backend suites pass (make test for both variants).
  • cargo fmt --check passes, and cargo test --locked gives 123 passed, 3 ignored. That includes new tests for the wide hero, the cache sweep and the Rockstar page.
  • The rest of the GPUI Preview workflow passes locally: route inventory check, dock-art fixtures, C backend build, and the isolated startup/shutdown tests. The route inventory was refreshed (d56e9dbe); only source line numbers moved, and the routes are unchanged (254).
  • Backend behavior was checked against throwaway homes:
    • GOG setup on an external drive;
    • gogdl repair, with the environment rebuilt on Python 3.15;
    • GOG games-database art for a real library: 6 of 6 games;
    • GOG stop-all on an idle prefix;
    • GOG per-game uninstall on a fake install, where the other game, the prefix's saves and the library entry were kept.
  • Used in the installed FEX build during development: the launcher pages, GOG setup and art, and the settings overlay.
  • Not tested:
    • Epic per-game uninstall;
    • live launches of the Steam-copy Rockstar titles from the Rockstar page;
    • packaging, which needs the C++ host build and runs for the first time in CI.

Rebuilt on current main from MohamedElGhandour/MetalSharp-fork codex/ui-polish (12ee4bc8), which still carried the old main history. Includes the follow-up that addresses the library review feedback.
@aaf2tbz

aaf2tbz commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator Author

Re-opened after a botched repo issue.

@aaf2tbz

aaf2tbz commented Nov 4, 2026

Copy link
Copy Markdown
Collaborator Author

Extending this pr into a full on visual change for multiple items. thanks for all of your work.

Their Sharp Library sources, GPUI views, backend routes and runtime code
are removed. The backend deletes <home>/emulators on start.
A closeable sidebar (open by default) lists Steam, Ubisoft, Battle.net,
Rockstar, GOG, Epic and Windows Programs, with Logs at the bottom. Each
page uses the Steam Deck library view with its own games, so Ubisoft
Connect games leave the Steam page. Launcher buttons and the
Library/Collection toggle sit on each page under the header. The header
keeps the logo, search, theme and settings with no background or divider,
over the page's hero art.
The pages list what the Sharp Library has installed (GOG and Epic games,
programs adopted from Windows installers, GameJolt games) in the deck
view. Play and Stop use the Sharp Library's own actions; Collection opens
that source's Sharp Library view with sign-in, installs and tools.
Each page installs, launches or stops its launcher and lists the games
it installed. Their games launch, pick graphics and save executables
through /rockstar and /battlenet routes, like Ubisoft Connect games.
The Rockstar Games Launcher installs into and runs from the Steam
prefix; Stop ends only its own processes. Battle.net returns with its
own prefix, set up and run like Ubisoft Connect. Both list the games
they installed (Steam copies stay on Steam) and launch them through
/rockstar and /battlenet routes on each build's graphics lane.
The launcher button sits between the logo and search, and the
Library/Collection switch between search and the theme icon, all in one
row that shrinks with the window. The hero art now runs down behind the
dock heading and fades across the cards. Battle.net, Rockstar, GOG and
Epic get icons drawn after their launchers' marks.
GOG and Epic pages walk through Create Prefix and Login in the middle of
the page, then list every owned game; Play installs one that isn't
downloaded and shows its progress. Windows Programs has an Install
Program button for .exe and .msi installers; .msi files run through
msiexec. A [...] button on the hero and the selected card sets the
entry's own card and hero art.
The sidebar slides open and closed and is narrow enough to end left of
the header's launcher button. Install, prefix and launch buttons in the
middle of a page share one size that scales with the window. The game
settings panel opens to the right of its button with its bottom level
with the button.
Installing Ubisoft Connect, Battle.net or the Rockstar Games Launcher,
or creating the GOG or Epic prefix, first asks for this Mac or an
external drive; the backend keeps that launcher's games in a
"MetalSharp <Name> Games" folder there. GOG and Epic downloads go
into it without a folder picker.
GET /library-locations lists this Mac and writable external drives with
the saved choice per launcher; POST /library-locations/set creates
"MetalSharp <Name> Games" in ~/Games or at the drive's root. GOG and
Epic install there by default. Ubisoft Connect and Battle.net see the
folder as Y: in their prefixes and the Rockstar Games Launcher as R: in
the Steam prefix, without taking over a drive letter the user set up.
The middle setup button keeps one size on every page; the empty page
grows with its text instead of squeezing it. The hero's Play, art,
graphics and settings buttons stay on one line, shortening Play and the
graphics label in narrow windows, and the game settings panel opens to
whichever side has room. Below 1180 points wide the sidebar slides over
the page instead of shrinking the dock's cards, and closes after a page
is picked.
Picking a page in the sidebar while it covered the hero also pressed the
Play button underneath and launched the game.
Every launcher button gets the ⚙ Steam's has. Steam keeps Fix Steam;
Ubisoft Connect, Battle.net, Rockstar, GOG and Epic offer Uninstall,
which asks first and can also delete that launcher's MetalSharp games
folder. GOG and Epic get a header button for their setup steps.
POST /launchers/uninstall stops the launcher and removes its prefix (for
Rockstar, only the launcher's folders inside the Steam prefix), its
caches, bottles and saved executables. With delete_games it also
deletes the launcher's MetalSharp games folder, only after checking it
is the real folder MetalSharp created on a mounted drive.
Run from an external drive, Battle.net's built-in browser crashes and
restarts under Wine. The installer now starts with the default C:
folder, the drive dialog says to keep it there and install games to Y:,
and MetalSharp finds the app from its Uninstall entry instead of
reporting it missing when it was installed elsewhere.
Battle.net caches its catalog and art locally: each catalog fragment
lists a product's install uids and names its 600x800 key art by the
cached file's hash. The Battle.net library now reports that file as
card_art_path, and the library uses it for the card and as the hero's
fallback after SteamGridDB.
A launcher cover (Battle.net's key art) stretched across the wide hero
was enlarged far past its resolution. Portrait hero art now goes
through a generated 1920x820 version: the cover blurred and darkened
behind the cover itself at full height, its edges faded in. Images are
recognised by content, since launcher caches store them without file
extensions.
--exec="launch_uid <uid>" only selects the game in current Battle.net
clients. Battle.net's own Play runs the game's executable with
"-uid <uid>" while the client is signed in; MetalSharp now does the
same after starting the client.
On MetalSharp Wine, Connect now starts like the Battle.net client: upc.exe
with no switches, from its own folder, through the shared store launcher
with only its Mullion lane applied. The GPU registry import before launch
is left to the x86_64 runtime, which keeps its CEF switches.
wineserver -k exits 1 when the prefix has no server, which GOG took as a failed stop:
uninstalling GOG then said a game was still running. Use the shared prefix stop, which
counts that as stopped.
heroic-gogdl needs Python 3.10, and setup took macOS's /usr/bin/python3 (3.9), so pip
failed. The next try saw the environment, wrote the gogdl wrapper anyway and carried on:
logging in then failed with "gogdl auth failed".

Setup now uses the first python3 that is 3.10 or newer (Homebrew's first), rebuilds an
environment made with an older one, and only counts gogdl as there when the wrapper's
gogdl is. The GOG page asks to finish setup while gogdl is missing, and skips the drive
question when GOG already has a folder.
GOG's product background is the store page's faded backdrop, cropped into the cards and
behind the hero. Sync now also saves the games database's vertical cover (coverUrl, for
cards) and full background (heroUrl, for the hero). Libraries synced before keep the old
image until the next sync. The GOG hero gets a dim over all of it, and GOG cards a darker
shade.
Listing the GOG library fills in coverUrl and heroUrl from GOG's games database for games
that don't have them yet (up to 12 per listing), so a library synced before keeps none of
the store page's faded art.
With the games database's background it isn't needed, and it stopped where the hero ends,
leaving a hard line across the art behind the library row.
…o label

The GOG hero now has the graphics picker (GOG's engines, saved per game as Collection does)
and the game settings button, with Choose EXE saving through GOG. The picker drops its
"Graphics" label on every page.

The game settings panel stays to the right of its gear in a small window: it narrows to the
room there, one setting per line, and opens to the left only when not even that fits.
…roes

A portrait cover's wide hero now has the cover in the centre, a little wider, over a lighter
blur that darkens toward the edges, crossfading into it on both sides.

The startup sweep deleted last session's wide heroes while the first page could already be
showing one, leaving that hero blank for the session (Overwatch on Battle.net). The sweep
keeps wide heroes of art still in the index, and the hero checks its file is there.
The game settings panel opens in the middle of the window over a dimmed backdrop, on every
page and at any window size; the x or a click around it closes it.

Epic games get the hero's graphics picker (saved to the game's bottle, which an installed
game gets if it has none) and the game settings button, with Choose EXE saving through Epic.
Installed Steam copies of Rockstar titles are listed on the Rockstar page as well as Steam's.
They stay Steam games there, so Play, the graphics picker and game settings go through the
Steam path with its patches (RDR2's DX12 settings, GTA V Enhanced's Agility frontend) and
arguments.
Ubisoft Connect gives no cover art, so cards showed the game's 256px EXE icon. A Ubisoft game
also sold on Steam (matched by exact title through the store's keyless search) now uses that
release's 600x900 cover and library hero, ahead of Ubisoft's page art and the EXE icon.
…game

The [...] menu on the GOG and Epic pages has Uninstall... for an installed game, with a
confirmation.

Only the game goes. GOG deletes the game's folder and its download manifest and keeps the
game in the library as not installed (it was dropped from the list until the next sync); the
GOG prefix stays. Epic lets Legendary remove the game and no longer deletes the game's
bottle, which holds its saves and settings.
Sharp Library apps and Game Jolt games on the Windows Programs page get the graphics picker
(Game Jolt's native games don't), offering what Collection offers each and saving through the
same calls. Deck entries carry their engine choices, which the picker uses.
An app's engine choices are the build's engines and OpenGL; an app saved as Auto launches
with no graphics route, which is OpenGL, so it reads as OpenGL in the hero and in Collection.
@aaf2tbz

aaf2tbz commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator Author
Screenshot 2026-11-04 at 10 51 01 PM Screenshot 2026-11-04 at 10 54 53 PM Screenshot 2026-11-04 at 10 55 13 PM Screenshot 2026-11-04 at 10 55 23 PM Screenshot 2026-11-04 at 10 55 43 PM Screenshot 2026-11-04 at 10 56 43 PM

@aaf2tbz

aaf2tbz commented Nov 5, 2026

Copy link
Copy Markdown
Collaborator Author
Screenshot 2026-11-04 at 10 58 21 PM

The GOG and Epic backends moved; the routes are unchanged (254).
@aaf2tbz aaf2tbz changed the title feat: polish library and settings with window size presets feat: library polish with window presets, plus launcher pages, store backends and per-game controls Nov 5, 2026
README.md takes main's feature table (Battle.net and Rockstar rows in place of GameJolt and
Emulation).
@aaf2tbz
aaf2tbz merged commit e4c2284 into main Nov 5, 2026
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.

2 participants