diff --git a/web/src/lib/components/layout/LeftSidebar.svelte b/web/src/lib/components/layout/LeftSidebar.svelte index 4f55131..d2a60ff 100644 --- a/web/src/lib/components/layout/LeftSidebar.svelte +++ b/web/src/lib/components/layout/LeftSidebar.svelte @@ -141,17 +141,12 @@ const reviewCountQuery = scopedCountQuery('review', 'review:true'); const hiddenCountQuery = scopedCountQuery('hidden', 'hidden:true'); const archivedCountQuery = scopedCountQuery('archived', 'archived:true'); - // Labels is special: `configQuery.count.labels` is the number of distinct - // label categories (PhotoPrism's roll-up), not the number of photos that - // carry a label. The Tags surface wants picture counts everywhere, so we - // always run a `countPhotos('label:*')` query regardless of the admin/ - // BasePath shape and never fall back to the category-count. - const labelsCountQuery = createQuery(() => ({ - queryKey: ['photos', 'scoped-count', 'labels', userBasePath(), isAdminUser], - queryFn: () => countPhotos(scoped('label:*')), - enabled: isAuthenticated(), - staleTime: 60_000 - })); + // Labels: PhotoPrism's q-DSL has no "has any label" predicate + // (`label:*` matches every photo, `label:` only matches the + // named label), so the sidebar uses `configQuery.count.labels` — the + // precomputed count of distinct label slugs. Same source the + // `tagCategoryCount('labels')` sub-row already uses, so the parent + // Tags badge sums the same numbers the sub-rows display. function bucketCount( key: 'favorites' | 'review' | 'hidden' | 'archived', @@ -303,7 +298,7 @@ const hiddenBadge = $derived(bucketCount('hidden', hiddenCountQuery)); const archivedBadge = $derived(bucketCount('archived', archivedCountQuery)); const labelsBadge = $derived( - labelsCountQuery.isPending ? undefined : labelsCountQuery.data + configQuery.data?.count?.labels ); const createMut = createMutation(() => ({ @@ -586,13 +581,13 @@ // section/route ViewItem shape. ]; - // Total badge for the "Tags" header row. Rolls up labels + keywords + - // people + ratings + colors. Labels flows through countPhotos (scoped); - // keywords/people/ratings/colors are library-wide and only contribute - // when we're in admin-without-BasePath mode (their sources don't scope). + // Total badge for the "Tags" header row. Sum of the same per-category + // counts the sub-rows render (labels/people: distinct slugs/subjects, + // keywords: distinct keywords, ratings/colors: photos carrying each + // mark). Library-wide numbers — the badge is a quick "how many tags + // exist?" rollup, not a per-user-visible count. const tagsTotal = $derived.by(() => { if (labelsBadge === undefined) return undefined; - if (wantScoped) return labelsBadge; const keywords = keywordsQuery.data?.length ?? 0; const people = configQuery.data?.count?.people ?? 0; return labelsBadge + keywords + people + ratingsCount + colorsCount;