Skip to content

[WallpaperPage] XDG user folder support#124

Open
moWerk wants to merge 4 commits intoAsteroidOS:masterfrom
moWerk:wallpaperpage-user-support
Open

[WallpaperPage] XDG user folder support#124
moWerk wants to merge 4 commits intoAsteroidOS:masterfrom
moWerk:wallpaperpage-user-support

Conversation

@moWerk
Copy link
Copy Markdown
Member

@moWerk moWerk commented Mar 31, 2026

Extend WallpaperPage to show user-installed wallpapers

Depends on #123.

PR #123 introduces WatchfaceHelper and WatchfaceStorePage which
install community watchfaces — including any bundled wallpapers —
into the XDG user data directory. This PR makes those wallpapers
visible and selectable in the existing wallpaper gallery without
any additional user action.

The only change to WallpaperPage is scanning a second FolderListModel
pointing at the user wallpapers path alongside the existing system
path, merging both into a unified model. When no user wallpapers are
present the page behaves identically to before.

moWerk added 4 commits March 31, 2026 20:15
Introduces WatchfaceHelper as a QML singleton registered under
org.asteroid.settings 1.0. Provides network-backed file downloads
via QNetworkAccessManager, directory creation, watchface removal,
font cache rebuilding and launcher restart.

All filesystem writes are enforced against a whitelist of
user-writable paths mirroring what the ./watchface deploy script
writes: the XDG GenericDataLocation asteroid-launcher subtree,
~/.fonts/ and the QStandardPaths cache location. Any write outside
these paths is blocked and logged. readFile() is additionally
restricted to the cache location only, preventing arbitrary
filesystem reads from QML.

Path helpers userWatchfacePath(), userAssetPath(), userFontsPath()
and cachePath() expose the resolved paths to QML consumers.
restartSession() runs fc-cache -f synchronously before issuing
systemctl --user restart asteroid-launcher so newly installed fonts
are visible immediately after the compositor restarts.

Adds Qt5::Network to CMakeLists target_link_libraries.
WatchfaceSelector gains a second FolderListModel watching the XDG
user watchface path alongside the system path. Both are merged into
a unified ListModel via a debounced Timer to prevent double-clear
during simultaneous count changes. A HEAD probe to api.github.com
fires on Component.onCompleted and gates a persistent store footer
button that is greyed out with an alternative label when offline.

WatchfaceStorePage fetches the unofficial-watchfaces repo catalog
via the GitHub Contents API and caches the response JSON to disk.
Subsequent page opens load from cache and only hit the network on
explicit refresh. Thumbnail previews are downloaded lazily at the
device-appropriate resolution and cached permanently. Watchfaces
whose preview returns a 404 are pruned from the model silently.
Directory listings recurse into subdirectories to handle watchfaces
with nested asset structures.

Installs land in the XDG user data tree so no root access is
required. The QML file, single-resolution preview PNG, watchfaces-img
assets and fonts are fetched in parallel. The downloaded watchface is
auto-activated on install complete. A persistent footer offers a
RemorseTimer-guarded launcher restart to pick up new fonts and QML
paths — the page fades to black when the remorse timer fires and
holds until the process is killed, preventing a flash back to page
content.

Interaction model on both pages uses manual onPressed tracking with
a Dims.l(2) scroll detection threshold, matching the IntSelector
scrubber pattern. Press immediately starts an opacity animation
giving frame-one feedback. Scroll cancels and reverses the animation.
Release within threshold confirms the action. Long press triggers
deletion via RemorseTimer on both pages. Install state is conveyed
through color and opacity transitions on a per-tile circle with no
discrete timer: green animates in from press, bumps on completion,
flashes red on network failure. The selector page uses the same
circle in black to indicate the active watchface at opacity 0.2
with the press animation fading toward 0.5 over the full longpress
budget as a continuous gesture discriminator.
Community watchfaces that ship a custom wallpaper now have it
fetched into the XDG user wallpapers folder during install.
The existing _fetchDirectory call pattern handles all file types
in the wallpapers/full/ folder including jpg, png and svg.
Replaces the single system FolderListModel with a unified ListModel
populated from both the system and XDG user wallpapers paths via a
debounced Timer, matching the WatchfaceSelector pattern. Each user
wallpaper entry is verified via FileInfo.exists() before being added
to the model, guarding against phantom entries from FolderListModel
reporting a non-zero count on non-existent or deleted paths.

Thumbnail lookup checks the system thumbnail subfolder first and
falls back to full resolution for user wallpapers which have no
thumbnail. QML wallpapers remain system-only as community wallpapers
are image-only by convention.

WatchfaceStorePage already downloads wallpapers shipped by community
watchfaces into the XDG user wallpapers path, so they appear here
automatically after install without requiring a launcher restart.
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.

1 participant