[WatchfacePage] Add on-device watchface store with direct install from unofficial-watchfaces#123
Open
moWerk wants to merge 5 commits intoAsteroidOS:masterfrom
Open
[WatchfacePage] Add on-device watchface store with direct install from unofficial-watchfaces#123moWerk wants to merge 5 commits intoAsteroidOS:masterfrom
moWerk wants to merge 5 commits intoAsteroidOS:masterfrom
Conversation
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.
Footer buttons on WatchfaceSelector and WatchfaceStorePage were clipped at the bottom edge on round watches. Adds a conditional spacer below the button stack sized to Dims.l(8) on round screens and zero on square screens.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR introduces the first iteration of an on-device watchface store
for AsteroidOS, allowing users to browse, install and remove community
watchfaces directly from the watch without requiring a computer.
Todo to before undraft:
- Add translations.- Polish layoutwatchface-store.mp4
What's new
Watchface Store — a new page accessible from the bottom of the
watchface selector gallery. When an IP connection is detected, the
store loads the full catalog from the unofficial-watchfaces repository
and displays all community watchfaces with their preview thumbnails.
Tapping an uninstalled watchface downloads and activates it
immediately. Long pressing an installed watchface removes it after a
remorse timer.
User-space installs — all community watchfaces install into the
XDG user data directory (~/.local/share/asteroid-launcher/) so no
root access is required. Fonts land in ~/.fonts/ and are picked up by
fontconfig without a full system restart. A launcher restart button
with a remorse timer is provided for cases where new fonts or QML
paths need to be picked up by the compositor.
Extended watchface selector — the selector now shows both system
and user-installed watchfaces in a unified gallery. Long pressing a
user-installed watchface in the selector removes it directly. The
active watchface is indicated by a subtle dark circle that doubles as
a pressure-sensitive gesture indicator — the circle deepens during
press and reaches full depth at the longpress threshold, giving
continuous visual feedback proportional to intent.
WatchfaceHelper C++ singleton — a new singleton handles all
network downloads, file writes and system calls from QML. Write access
is enforced against a path whitelist. Arbitrary filesystem reads from
QML are blocked.
Notes for reviewers
structure spec for all assets to install correctly
user request to avoid GitHub API rate limits
resolution and never re-downloaded unless the cache is cleared
the store page makes this available with a safety remorse timer