From 0fc470a8d588cac1a51cc4b3e1a2237dc56041c9 Mon Sep 17 00:00:00 2001 From: grm Date: Fri, 18 Sep 2026 14:32:22 +0300 Subject: Special pages: a gallery page of the blog's images MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A page's kind says what it shows between its intro and outro: posts, as before, or something special. The first special kind is a gallery — every image in the files library as a masonry wall (CSS columns, no script), newest first, each linked to its full-size file. The page form lists the library's images with a Hide tick per picture; exclusions are stored (page_hidden_files) rather than inclusions so a new upload shows up without editing the page, and the design's own pictures — logo, favicon, header and background image — are never shown. Special pages keep the page chrome (menu, announcements, home, ordering) but hold no posts: the post forms skip them and a forced page id is refused. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01Sd8UPWrvyYCLj97JexNw3A --- internal/store/files.go | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) (limited to 'internal/store/files.go') diff --git a/internal/store/files.go b/internal/store/files.go index 287b4d7..a4a4fb3 100644 --- a/internal/store/files.go +++ b/internal/store/files.go @@ -79,6 +79,28 @@ func (bs *BlogStore) ListFiles(ctx context.Context, kind, q string, limit, offse return out, total, rows.Err() } +// GalleryImages lists the images a gallery page shows, newest first: every +// library image but the page's hidden ones and except (the theme's logo and +// favicon, which the caller knows). +func (bs *BlogStore) GalleryImages(ctx context.Context, pageID int64, except []uuid.UUID) ([]File, error) { + rows, err := bs.db.Query(ctx, `SELECT `+fileCols+` FROM files WHERE kind = 'image' AND id <> ALL($2) + AND NOT EXISTS (SELECT 1 FROM page_hidden_files h WHERE h.page_id=$1 AND h.file_id=files.id) + ORDER BY created_at DESC, id DESC`, pageID, except) + if err != nil { + return nil, err + } + defer rows.Close() + var out []File + for rows.Next() { + f, err := scanFile(rows) + if err != nil { + return nil, err + } + out = append(out, *f) + } + return out, rows.Err() +} + // FileMeta loads a file without its bytes. func (bs *BlogStore) FileMeta(ctx context.Context, id uuid.UUID) (*File, error) { return scanFile(bs.db.QueryRow(ctx, `SELECT `+fileCols+` FROM files WHERE id=$1`, id)) -- cgit v1.2.3