feat(gui): add a Settings → Assets tab (refresh, clear cache, auto-download, open folder)#142
feat(gui): add a Settings → Assets tab (refresh, clear cache, auto-download, open folder)#142AprilNEA wants to merge 4 commits into
Conversation
Greptile SummaryAdds a Settings → Assets tab with four controls: an auto-download toggle, a Refresh button, a Clear cache button, and a Cache location opener. The main-loop changes introduce a
Confidence Score: 5/5Safe to merge — the deferred-sync design correctly handles all edge cases flagged in previous rounds, and the new controls are well-isolated behind the channel. The main-loop changes are the most sensitive part of the PR, but the manual_pending/manual_clear deferred-sync approach has no state-machine wedge paths, no cache-wipe/download races, and empty-inventory guards are in place. The remaining finding is a stale doc comment on a private helper that does not affect runtime behavior. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant UI as "Settings Assets UI"
participant AC as "AssetControl channel"
participant ML as "Main event loop"
participant BG as "Background thread"
UI->>AC: send Refresh or ClearCache
AC->>ML: asset_ctrl_rx.recv
ML->>ML: set manual_pending true
ML->>ML: run_pending_manual_sync
alt SYNC_RUNNING in flight
ML->>ML: defer until next inventory tick
BG-->>ML: store SYNC_DONE or SYNC_FAILED
ML->>ML: inventory_rx tick calls run_pending_manual_sync
end
opt ClearCache
ML->>ML: clear_cache on filesystem
end
ML->>BG: spawn sync_assets with force true
BG-->>ML: store SYNC_DONE or SYNC_FAILED
UI->>ML: toggle auto_download OFF to ON
ML->>AC: send Refresh
Note over ML,BG: follows same deferred-sync path
Reviews (4): Last reviewed commit: "fix(gui): defer manual asset sync while ..." | Re-trigger Greptile |
A persisted on/off preference (default on, backward-compatible via serde default) for whether the GUI fetches device images from the network when a device connects. Consumed by the runtime sync and the upcoming Settings → Assets tab; off keeps the app fully offline.
A new Assets page in Settings with four controls: - Automatically download device images — a toggle gating the startup sync on the new auto_download_assets setting; off makes the app issue no asset network requests (bundled art + silhouette still render). - Refresh assets — force-fetches images for the connected devices now, bypassing the should_run policy (so a release build with bundled art can still pull updated renders between releases). - Clear cache — shows the on-disk cache size and wipes the per-user cache, then re-fetches. - Cache location — reveals the downloaded-images folder in Finder. Manual actions reach the sync (which lives on the main event loop) via a new AssetControl global channel, mirroring PairingControl. The loop keeps the latest inventory so a manual refresh syncs the current devices immediately and resets the retry backoff. Asset cache helpers (cache_size_bytes / clear_cache / reveal_cache_in_file_manager) and a `force` flag on the sync entrypoint back the buttons. Strings translated for ja/ru/zh-CN/zh-HK/zh-TW (ja/ru best-effort, English-key fallback).
- Skip the manual sync when no device is connected: a Refresh/Clear with an empty inventory used to fetch only the index, latch SYNC_DONE, and then wedge the auto-sync gate (IDLE/FAILED) so a device connecting later never got its art. (Greptile) - Compute the asset-cache size once when the Settings window opens and store it on the view, instead of re-walking the cache dir on the main thread every render. (Greptile) - Extract the macOS Finder reveal into a cfg-gated helper so the early return isn't the function's last statement on non-macOS — CI clippy flagged needless_return on the Linux build (local macOS clippy can't see that path).
A Clear arriving mid-sync used to wipe the cache (racing the running thread's writes) and skip the spawn (state still RUNNING); when that thread then stored SYNC_DONE, the auto-sync gate (IDLE/FAILED) was wedged and the art never re-fetched until a manual Refresh or restart. Queue Refresh/Clear in manual_pending/manual_clear and run them from run_pending_manual_sync only when no sync is in flight — called both from the AssetControl arm and each inventory tick, so a command issued during a sync lands once it finishes. The wipe never overlaps an in-flight download and the state machine can't wedge on SYNC_DONE.
1f833c8 to
79e2938
Compare
What
Adds a Settings → Assets tab to manage device-image assets, with four controls:
auto_download_assetssetting (default on). Off = the app makes no asset network requests at all; bundled art and the synthetic silhouette still render.should_runpolicy — so a release build that ships bundled art (and otherwise never syncs at runtime) can still pull updated renders between releases.How it's wired
The asset sync lives on the main event loop (the
AtomicU8state machine from #140). Manual actions reach it through a newAssetControlglobal channel — the same pattern asPairingControlfor the Add-Device window. The loop now:auto_download_assetssetting (read fromAppStateper snapshot);asset_ctrl_rxarm:ClearCachewipes the cache then both commands force a fresh fetch (sync_assets(.., force = true)skipsshould_run).New asset-module helpers back the buttons:
cache_size_bytes,clear_cache,reveal_cache_in_file_manager.Design notes
should_runreturns false), so fixes that only update the liveindex.json(e.g. fix(assets): match devices against every model id a depot lists #137'smodelIds) wouldn't reach those users without a Refresh. Refresh forces the fetch; the toggle, when on, doesn't change the existing release-bundle behavior (auto-sync stays gated byshould_run).auto_download_assetsis#[serde(default = "default_true")], so existing config files keep the current (auto-download) behavior;schema_versionis unchanged.i18n
New strings are translated for ja / ru / zh-CN / zh-HK / zh-TW (English msgid doubles as the key, so missing locales fall back to English). ja and ru are best-effort — corrections welcome.
Test plan
cargo test(core + gui, incl. the i18napp.ymlload),clippy -D warnings,fmtall green.Follow-up to #137 / #140.