fix(sidebar): paginate folder counts; drop bogus all:true from labels query
Two distinct bugs were causing left-sidebar badges to under-report: 1. sidecar/folders/counts hard-capped each PP /photos call at count=1000 and deduped UIDs from that single page. Any folder with >1000 file rows under it (typical for a multi-year root scan with HEIC sidecars) silently lost everything past row 1000. On this library the root badge reported 912 while the year subfolders summed to 1175. Loop offsets instead, breaking when PP returns a short page. 2. The Labels-badge query passed all:true label:* to PP, which 400s with "Unable to do that" - none of the other bucket queries prefix all:true. Drop it; the scoped() helper already injects the user's path clause when applicable. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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<number>(() => ({
|
||||
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:<slug>` 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<number | undefined>(
|
||||
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<number | undefined>(() => {
|
||||
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;
|
||||
|
||||
Reference in New Issue
Block a user