fix(slicer-presets): #1581 SliceModal refresh + invalidate on local-profile delete/import

Two-part fix for the reporter's "removed profiles still show on the slice
  menu" symptom.

  Local half (real bug). LocalProfilesView's import and delete mutations
  invalidated ['localPresets'] (the management view's own query) but not
  ['slicerPresets'] (the SliceModal's unified preset query, staleTime 60s).
  A freshly-deleted preset kept rendering in the slice dropdown until that
  staleTime elapsed plus a refocus/remount. Both mutations now also call
  queryClient.invalidateQueries({queryKey: ['slicerPresets']}).

  Cloud half (opt-in cache bypass). _fetch_cloud_presets keeps a 5-minute
  per-(user, token) in-process cache (slicer_presets.py:69, balances
  "users see freshly-saved presets quickly" against "busy install doesn't
  hit Bambu Cloud once per modal open"). Users delete cloud presets in
  Bambu Studio / Bambu Handy, not in Bambuddy, so there's no event hook
  to invalidate on. Rather than shorten the TTL globally, the listing
  endpoint gains an opt-in ?refresh=true query param that bypasses both
  the cloud cache AND the 1-hour bundled-preset cache for that one call;
  the fresh result is still written back so subsequent normal callers
  keep hitting the cache.

  New SliceModal "Refresh" button. Lives in the preset section header
  next to the cloud-status banner. Calls getSlicerPresets({refresh: true})
  and writes the fresh slots into the ['slicerPresets'] cache via
  queryClient.setQueryData so the spinner stops immediately rather than
  triggering a second refetch. RefreshCw icon spins while in-flight;
  disabled during slice enqueue to prevent double-fire.
This commit is contained in:
maziggy
2026-06-02 12:42:16 +02:00
parent 396e9aa09e
commit 171848a0fc
19 changed files with 495 additions and 142 deletions
+7 -2
View File
@@ -5796,8 +5796,13 @@ export const api = {
// Unified slicer-preset listing — cloud + local + standard, deduped by name.
// Used by the SliceModal; see UnifiedPresetsResponse for the shape and
// backend/app/api/routes/slicer_presets.py for the priority rules.
getSlicerPresets: () =>
request<UnifiedPresetsResponse>('/slicer/presets'),
// `refresh` bypasses the in-process cloud and bundled-preset caches on the
// backend; the SliceModal's Refresh button passes true so a preset deleted
// in Bambu Studio or Bambu Handy shows up without the 5-min TTL wait.
getSlicerPresets: (options?: { refresh?: boolean }) =>
request<UnifiedPresetsResponse>(
options?.refresh ? '/slicer/presets?refresh=true' : '/slicer/presets',
),
// Canonical Bambu printer-model registry — "Bambu Lab <model>" → short code.
// Single source of truth shared with backend (PRINTER_MODEL_MAP); the