Skip to content

Advanced library, offline rotation and device previews

This page documents features being developed in PR #42. It does not imply a published release or completed cross-platform QA. Run the tests and inspect the current release notes before deploying to a production library.

Bulk edits with all-or-nothing persistence

Section titled “Bulk edits with all-or-nothing persistence”

Select individual cards in the gallery, use Select page, then favourite, unfavourite, set a 0–5 rating, replace tags, or hide a selection. The toolbar retains a bounded selection across result pages and explicitly confirms hiding.

For scripts:

Terminal window
wallpaper-server bulk --ids ID1,ID2 --favorite=true --rating=4
wallpaper-server bulk --tags="landscape,calm" ID1 ID2
wallpaper-server bulk --ids ID1,ID2 --tags="" # clear tags
wallpaper-server bulk --ids ID1,ID2 --hidden=true # hide originals, never delete

The API uses an authenticated PATCH /api/wallpapers/bulk/metadata:

{
"ids": ["ID1", "ID2"],
"patch": { "favorite": true, "rating": 4, "tags": ["landscape"] }
}

The entire batch (1–200 distinct IDs) is validated and persisted once. An unknown ID, invalid rating, oversized tag or storage failure rejects the whole update. A bulk unhide validates the existing immutable cached image before publishing the visible index; refresh first if its cache is unavailable. The response includes updated and wallpapers fields.

A private, durable ID-to-source-path registry in data_dir/library.json can preserve existing IDs, favourites, tags, ratings and collection membership across renames or moves, including moves while the service is stopped.

A move is recognised only when one missing old image and one newly seen image share an exact SHA-256 content digest. If multiple sources or destinations have the same digest, the transfer is ambiguous, so the server does not guess which image owns the previous metadata. Bytes modified during a move are likewise not treated as an exact rename.

Enable stat-only source monitoring through configuration:

config.yaml
scan_interval_seconds: 60

Values must be 0 (disabled) or 15–3600. The monitor checks source paths, sizes, modification times and available filesystem identity/change-time information, excluding private trash and generated caches. It refreshes only after detecting a change and stops with the service. Unchanged libraries do not repeatedly broadcast gallery updates.

This is polling, not filesystem event subscriptions. Filesystems that do not expose reliable revision information can still miss timestamp-preserving edits; use POST /api/refresh after such changes. Network-mount and permission errors are logged without deliberately wiping the existing index.

Device compatibility and rendered previews

Section titled “Device compatibility and rendered previews”

Check how a particular wallpaper fits a physical display:

Terminal window
curl 'http://127.0.0.1:8519/api/wallpapers/IMAGE_ID/compatibility?width=3840&height=2160&fit=cover'
curl 'http://127.0.0.1:8519/api/device/recommendations?width=1179&height=2556&fit=contain&limit=10'

Both endpoints return a 0–100 heuristic score based on aspect mismatch, required upscaling and retained visible area, plus explanations and a variant_url. They do not know the viewer’s visual taste, brightness of a particular monitor, colour-management capabilities, safe areas or focal regions. The score is a geometric suitability aid, not image-quality truth.

The gallery inspector offers preset desktop, ultrawide, phone and tablet targets, a crop/contain choice, a rendered variant, and an accessible explanation. Preview requests are cancelled logically when the selected wallpaper or device changes, so stale results cannot replace the current preview.

Rendered variants are disposable: their dedicated cache is limited to 256 MiB and 1,024 entries, including temporary encoding files. Oldest-written variants are evicted automatically, including files left by previous runs. Originals and thumbnails are not part of this derivative budget. Use one server process per cache directory. Rendering is serialized and queued requests can be cancelled; an active scaling phase cannot be interrupted immediately.

When several eligible wallpapers have the same selection count, the server weights choices by 1 + (favourite ? favourite_weight : 0) + (rating × rating_weight). The default bonuses are 3 for favourites and 2 per star, preserving previous behaviour. Each weight can be configured independently from 0–20; explicit zero disables that preference. The least-used-first policy and recent-history exclusion still prevent any image from being permanently starved.

Terminal window
wallpaper-server rotation create --name "Personal favourites" \
--interval-minutes 45 --favorite-weight 8 --rating-weight 1
wallpaper-server rotation create --name "Equal chance" \
--interval-minutes 30 --favorite-weight 0 --rating-weight 0

You can also edit both settings in the browser’s Rotation profile editor. Offline workers honour the weights captured during their last explicit cache sync. Reloading a profile does not automatically refresh offline policy.

Prefetch a saved profile while the server is reachable:

Terminal window
wallpaper-server cache sync --profile PROFILE_ID --limit 24 --max-cache-mib 1024
wallpaper-server cache status --profile PROFILE_ID
wallpaper-server cache verify --profile PROFILE_ID
# No network request is made after this point:
wallpaper-server rotation run --offline --once --download-only PROFILE_ID
wallpaper-server rotation run --offline PROFILE_ID
# Remove superseded generations only after all older workers have stopped:
wallpaper-server cache prune --profile PROFILE_ID --confirm
# Or clear the entire profile cache:
wallpaper-server cache clear --profile PROFILE_ID --confirm

Each profile has a private local manifest containing the latest downloaded eligible images and its rotation policy. Offline selection honours the cached time window, enabled status, recent-history exclusions, least-used fairness and favourite/rating weights. History is written after a successful local apply or download-only selection. A failed sync does not replace the last valid manifest. New manifests record SHA-256 content digests and reject modified cached image bytes before application. By default a sync has a 1 GiB image budget, overridable using --max-cache-mib (up to 16 GiB). Old generations are not pruned automatically because already-running offline workers may still reference them. Stop old workers before explicitly pruning their files. Use cache verify to verify every cached image; legacy manifests without digests should be re-synced. Cached files are not a replacement for originals or backups.

Offline mode intentionally does not contact the server, refresh a profile, discover newly uploaded images or synchronize offline history back to the server. If you need the latest policies or images, run cache sync again while online. Offline selections, sync, prune and clear use kernel-backed inter-process locks and reload the current manifest after acquiring ownership. Locks release automatically on process exit or crash; a blocked operation times out after 30 seconds rather than overwriting another worker’s history. Use a single worker per physical display to avoid competing wallpaper policies.

Platform Supported wallpaper mechanism Display selection
Windows 8+ SystemParametersInfoW for all, native IDesktopWallpaper COM for individuals all, 1-based attached-monitor index, or exact monitor device path
macOS System Events automation via osascript all or 1-based desktop index; Automation permissions are required
Linux awww, swww, hyprpaper, GNOME, xwallpaper, feh Depends on active compositor and backend; GNOME and feh are all-display backends
Terminal window
wallpaper-server apply --file ./wide.jpg --monitor all
wallpaper-server apply --id IMAGE_ID --monitor 1
wallpaper-server next --apply --monitor DP-1
wallpaper-server previous

Native display identifiers can change after docking, reconnection or a desktop session change; a profile should not silently apply to an unintended display. Unsupported combinations return explicit errors. Windows COM availability, Linux compositor IPC compatibility and macOS permission handling must still be verified on real desktops before release.

Source folders are never destroyed by a normal delete; managed uploads go to recoverable trash, and permanent purge requires an explicit action. Bulk, profile, trash and metadata mutations require local or authenticated access. Never expose the privileged API through an unauthenticated loopback proxy.

The optional local multimodal semantic search, broader remote-image import providers, and fully managed background rotation are not automatically enabled by this guide or required for local operation. See Security and remote access and CLI guide for complete operational details.