Skip to content

feat(gui): add a Settings → Assets tab (refresh, clear cache, auto-download, open folder)#142

Open
AprilNEA wants to merge 4 commits into
masterfrom
feat/assets-settings
Open

feat(gui): add a Settings → Assets tab (refresh, clear cache, auto-download, open folder)#142
AprilNEA wants to merge 4 commits into
masterfrom
feat/assets-settings

Conversation

@AprilNEA
Copy link
Copy Markdown
Owner

@AprilNEA AprilNEA commented Jun 5, 2026

What

Adds a Settings → Assets tab to manage device-image assets, with four controls:

Control Behavior
Automatically download device images (toggle) Gates the automatic startup sync on a new persisted auto_download_assets setting (default on). Off = the app makes no asset network requests at all; bundled art and the synthetic silhouette still render.
Refresh assets (button) Force-fetches images for the connected devices now, bypassing the should_run policy — so a release build that ships bundled art (and otherwise never syncs at runtime) can still pull updated renders between releases.
Clear cache (button) Shows the on-disk cache size and wipes the per-user cache, then re-fetches. The read-only app bundle is a separate tier and keeps serving.
Cache location (button) Reveals the downloaded-images folder in Finder.

How it's wired

The asset sync lives on the main event loop (the AtomicU8 state machine from #140). Manual actions reach it through a new AssetControl global channel — the same pattern as PairingControl for the Add-Device window. The loop now:

  • keeps the latest inventory, so a manual Refresh syncs the current devices immediately and resets the retry backoff;
  • gates the automatic sync on the auto_download_assets setting (read from AppState per snapshot);
  • handles a new asset_ctrl_rx arm: ClearCache wipes the cache then both commands force a fresh fetch (sync_assets(.., force = true) skips should_run).

New asset-module helpers back the buttons: cache_size_bytes, clear_cache, reveal_cache_in_file_manager.

Design notes

  • The toggle does double duty. It's a privacy/offline control (off = zero asset network traffic) and — combined with the Refresh button — the answer to a real gap: a release build with bundled assets never syncs at runtime (should_run returns false), so fixes that only update the live index.json (e.g. fix(assets): match devices against every model id a depot lists #137's modelIds) 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 by should_run).
  • No "Fetch all". The full asset set is ~600 MB of devices a user mostly doesn't own and would never see; the runtime model stays "fetch what's connected." Refresh covers the only sensible case.
  • Back-compat: auto_download_assets is #[serde(default = "default_true")], so existing config files keep the current (auto-download) behavior; schema_version is 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

Follow-up to #137 / #140.

@AprilNEA AprilNEA added type: feature New feature request area: gui Graphical user interface area: assets Icons, images, and bundled assets area: config Configuration files, persistence, and settings labels Jun 5, 2026
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Jun 5, 2026

Greptile Summary

Adds 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 latest_inv snapshot and a deferred-sync mechanism (manual_pending/manual_clear + run_pending_manual_sync) that ensures cache wipes never race an in-flight download and that the state machine cannot wedge on SYNC_DONE.

  • main.rs: New AssetControl global + unbounded channel mirrors PairingControl; run_pending_manual_sync is called from both the AssetControl arm and every inventory tick so deferred commands land as soon as the running sync finishes.
  • asset/mod.rs: Three new helpers — cache_size_bytes (recursive walk), clear_cache (NotFound-tolerant remove_dir_all), reveal_cache_in_file_manager (macOS open, no-op elsewhere).
  • config.rs / state.rs: Back-compat auto_download_assets field with serde(default = "default_true") and an atomic-save setter.

Confidence Score: 5/5

Safe 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

Filename Overview
crates/openlogi-core/src/config.rs Adds auto_download_assets: bool to AppSettings with #[serde(default = "default_true")] and a matching Default impl — clean, back-compat, no schema-version bump needed.
crates/openlogi-gui/locales/app.yml Adds i18n strings for the new Assets tab across ja/ru/zh-CN/zh-HK/zh-TW; English msgids serve as fallbacks for any missing locales. No structural issues.
crates/openlogi-gui/src/asset/mod.rs Adds cache_size_bytes (recursive dir walk), clear_cache (remove_dir_all with NotFound tolerant), and reveal_cache_in_file_manager (macOS-only open, no-op elsewhere). All three are well-guarded.
crates/openlogi-gui/src/main.rs Core event-loop changes: adds AssetControl global + channel, latest_inv snapshot, manual_pending/manual_clear deferred-sync flags, and run_pending_manual_sync helper. The deferred-sync approach correctly prevents the cache wipe from racing an in-flight download and avoids the SYNC_DONE wedge from the prior review.
crates/openlogi-gui/src/state.rs Adds set_auto_download_assets setter with early-return guard and atomic save — straightforward, consistent with other setters in the file.
crates/openlogi-gui/src/windows/settings.rs Adds the Assets settings page with four controls. One stale doc comment on cache_size_description claims it runs on every render, but it is now computed once in SettingsView::new().

Sequence Diagram

sequenceDiagram
    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
Loading

Fix All in Codex Fix All in Claude Code

Reviews (4): Last reviewed commit: "fix(gui): defer manual asset sync while ..." | Re-trigger Greptile

Comment thread crates/openlogi-gui/src/main.rs Outdated
Comment thread crates/openlogi-gui/src/windows/settings.rs
Comment thread crates/openlogi-gui/src/main.rs
AprilNEA added 4 commits June 5, 2026 21:48
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.
@AprilNEA AprilNEA force-pushed the feat/assets-settings branch from 1f833c8 to 79e2938 Compare June 5, 2026 13:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: assets Icons, images, and bundled assets area: config Configuration files, persistence, and settings area: gui Graphical user interface type: feature New feature request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant