diff --git a/sidecar/handlers_folders.go b/sidecar/handlers_folders.go index cd68660..d5a7e09 100644 --- a/sidecar/handlers_folders.go +++ b/sidecar/handlers_folders.go @@ -231,12 +231,20 @@ func handleFolderCounts(pp *ppClient) gin.HandlerFunc { go func() { defer wg.Done() defer func() { <-sem }() - // `path:` is non-recursive in PhotoPrism's q-DSL: matches - // direct children only. `merged=false` returns one row per - // File on disk, so HEIC + companion JPG count twice unless - // we dedupe by UID — which is what the old client-side - // code did, and what we keep doing here. - q := url.QueryEscape("path:" + path) + // `path:` is an exact match in PhotoPrism's q-DSL — + // it matches only photos whose `photo_path` field equals + // , not descendants. The indexer always nests photos + // under YYYY/MM, so an internal tree node like `2024` has + // zero direct children and reports a count of 0 unless we + // recurse. `path:*` is the documented wildcard form and + // matches both `` itself (no harm if empty) and every + // `/...` descendant. + // + // `merged=false` still returns one row per File on disk, + // so HEIC + companion JPG count twice unless we dedupe by + // UID — which is what the old client-side code did, and + // what we keep doing here. + q := url.QueryEscape(`path:"` + path + `*"`) resp, err := pp.call(c.Request.Context(), http.MethodGet, "/api/v1/photos?count=1000&offset=0&merged=false&q="+q, token, nil) if err != nil || !resp.OK { diff --git a/web/src/routes/+page.svelte b/web/src/routes/+page.svelte index 2431659..a50abc5 100644 --- a/web/src/routes/+page.svelte +++ b/web/src/routes/+page.svelte @@ -177,12 +177,14 @@ // scoped server-side via the q-DSL and must not be re-filtered here, // or labels / search will silently drop subfolder photos when the // store hasn't fully hydrated from the URL yet. + // + // Root (`/`) historically also restricted to `Path === ''` — i.e. + // photos sitting directly at the originals root with no subfolder. + // PhotoPrism's indexer however always nests photos under YYYY/MM, so + // that view was always empty in practice. Treat root as "the whole + // library" instead; subfolders still scope normally. function applyFolderScope(list: PpPhoto[], f: typeof filters): PpPhoto[] { - if (f.folderPath !== '/') return list; - if (f.section !== 'all-photos') return list; - if (f.heapUid) return list; - if (f.search) return list; - return list.filter((p) => !p.Path); + return list; } const pageCount = $derived(photosQuery.data?.pages.length ?? 0);