Mulimage 2.0 #1

Merged
dtoro merged 64 commits from new into main 2026-05-21 22:48:55 +02:00
Showing only changes of commit fc5f30fad1 - Show all commits

View File

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