perf(web): batch folder counts, bounded scroll scan, adaptive thumbs, lazy preview
Six-item frontend performance pass on the SvelteKit app.
P1 — Move per-folder photo counts to a new sidecar endpoint and defer
the fetch to requestIdleCallback. The old client-side path fired one
/photos?count=1000 per folder from the browser (≈1 MB JSON × N folders)
on every cold sidebar mount; the new POST /api/sidecar/folders/counts
fans out over loopback with bounded concurrency and returns a single
{path: count} payload of a few KB.
P2 — Bound the visibleRange scroll-scan around the previous visible
band instead of sweeping every shell from index 0 on each scroll-rAF.
Falls back to a full sweep on cache miss (filter reset, programmatic
jump) so behaviour is unchanged at the edges.
P3 — Adaptive thumbnail size + srcset. PhotoTile now picks the smallest
PhotoPrism tile_* variant (100/224/500) that covers the user's grid
preset at the current DPR. Adds decoding="async".
P4 — Lift the selection check above the {#each} loop. Mostly readability
— SvelteSet.has() is already per-key reactive — but keeps the hot loop
body terse.
P5 — Split dedupedAll / photos derivations so filter-store mutations
(search-as-you-type, section toggles) don't re-walk every loaded page;
only the cheap folder-scope filter re-runs.
P6 — Dynamic-import PreviewOverlay on first preview.uid !== null and
cache the loaded module; closing the overlay leaves the component
mounted with its internal {#if} collapsing the DOM.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -28,11 +28,14 @@ func newPPClient(base string) *ppClient {
|
||||
|
||||
// ppResp is the trimmed projection of an HTTP response that callers
|
||||
// actually consume. Status + raw body are exposed so handlers can mirror
|
||||
// PhotoPrism's status code or parse the body themselves.
|
||||
// PhotoPrism's status code or parse the body themselves. Header is
|
||||
// retained for callers that need `X-Count` / `X-Limit` / `X-Offset` on
|
||||
// list endpoints — PhotoPrism exposes total-match counts there.
|
||||
type ppResp struct {
|
||||
OK bool
|
||||
Status int
|
||||
Body []byte
|
||||
Header http.Header
|
||||
}
|
||||
|
||||
// call issues an authenticated request against PhotoPrism. body is
|
||||
@@ -78,6 +81,7 @@ func (c *ppClient) call(ctx context.Context, method, urlPath, token string, body
|
||||
OK: resp.StatusCode >= 200 && resp.StatusCode < 300,
|
||||
Status: resp.StatusCode,
|
||||
Body: buf,
|
||||
Header: resp.Header,
|
||||
}, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user