fix: bulk label apply, instant archive removal, per-photo state, drop sidebar counts

Issue 1 — colors/labels not applying in bulk:
- sidecar validColors only accepted 4 of the 8 UI swatches, so teal/blue/
  purple/pink returned "invalid color" and rolled back the whole bulk txn.
  Add teal, blue, purple, pink to validColors.
- Add invalidateFacets() and call it on the success path of bulk marks,
  patchTargets, and single-photo edits so the Colors/Ratings/Notes facet
  sections refresh immediately instead of waiting out staleTime.

Issue 2 — archived photos linger in the grid:
- Add a UI-only removedIds set to the bulkAction store; archive/delete/
  restore/keep call markRemoved() on success so tiles vanish instantly,
  cleared once the server-reconcile refetch lands (no cache eviction).

Issue 3 — per-photo progress state:
- Wire startBulk/doneBulk/failBulk into all metadata applies, bulk
  (BulkMetadataSidebar) and single (RightSidebar), so colors/ratings/
  notes/dates/keywords show the spinner -> check -> X overlay.

Issue 4 — remove Left-sidebar count badges:
- Drop count badges from root folder, Archive, heaps, Notes, and the
  folder tree, plus the now-dead count queries and unused imports. Facet
  drill-panel counts are unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-08 00:21:04 +02:00
parent a13e171295
commit ccf2c6b7c7
8 changed files with 161 additions and 251 deletions

View File

@@ -32,6 +32,23 @@ export function invalidatePhotos(uids: string[]): void {
}
}
/**
* Refresh the sidebar facet sections after a metadata mutation. The Colors /
* Ratings panels read `['marks']` + `['photos','marks-pool']`; Notes reads
* `['photos','with-notes']`; keywords / labels / people read their own keys.
* Optimistic cache writes keep the active tile in sync, but the facet panels
* sit on separate queries that otherwise stay stale until their staleTime
* expires — so call this on the success path of any marks/keyword/note apply.
*/
export function invalidateFacets(): void {
void queryClient.invalidateQueries({ queryKey: ['marks'] });
void queryClient.invalidateQueries({ queryKey: ['photos', 'marks-pool'] });
void queryClient.invalidateQueries({ queryKey: ['photos', 'with-notes'] });
void queryClient.invalidateQueries({ queryKey: ['photos', 'keywords'] });
void queryClient.invalidateQueries({ queryKey: ['labels'] });
void queryClient.invalidateQueries({ queryKey: ['subjects'] });
}
export function invalidateAllPhotoCaches(): void {
void queryClient.invalidateQueries({ queryKey: ['photos'] });
void queryClient.invalidateQueries({ queryKey: ['marks'] });
@@ -75,6 +92,7 @@ export async function patchTargets(
});
invalidatePhotos(ids);
invalidateFacets();
if (errors.length) {
toast.error(`${label} · ${updated.length} ok, ${errors.length} failed`, { id: tid });