feat: include per-photo library id in /photos response

Adds a parallel `photo_libraries: Vec<i32>` array alongside `photos`
in `PhotosResponse` so clients can render per-thumbnail badges.
Populated with the scoped library id at the two main return sites;
left empty for `/favorites` since favorites are library-agnostic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Cameron
2026-04-18 17:11:57 -04:00
parent 187c5685af
commit 1f1f1ae9f6
3 changed files with 13 additions and 0 deletions

View File

@@ -102,6 +102,12 @@ pub struct PhotosResponse {
pub photos: Vec<String>,
pub dirs: Vec<String>,
/// Library id for each entry in `photos`, same length and ordering.
/// Parallel array rather than an object per row to keep the payload
/// small and backwards-compatible with older clients.
#[serde(default, skip_serializing_if = "Vec::is_empty")]
pub photo_libraries: Vec<i32>,
// Pagination metadata (only present when limit is set)
#[serde(skip_serializing_if = "Option::is_none")]
pub total_count: Option<i64>,

View File

@@ -493,9 +493,11 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
.set_attribute(KeyValue::new("total_count", total_count.to_string()));
span_context.span().set_status(Status::Ok);
let photo_libraries = vec![scoped_library.id; tagged_files.len()];
HttpResponse::Ok().json(PhotosResponse {
photos: tagged_files,
dirs: vec![],
photo_libraries,
total_count: pagination_metadata.0,
has_more: pagination_metadata.1,
next_offset: pagination_metadata.2,
@@ -778,9 +780,11 @@ pub async fn list_photos<TagD: TagDao, FS: FileSystemAccess>(
.set_attribute(KeyValue::new("total_count", total_count.to_string()));
span_context.span().set_status(Status::Ok);
let photo_libraries = vec![scoped_library.id; response_files.len()];
HttpResponse::Ok().json(PhotosResponse {
photos: response_files,
dirs,
photo_libraries,
total_count: pagination_metadata.0,
has_more: pagination_metadata.1,
next_offset: pagination_metadata.2,

View File

@@ -970,9 +970,12 @@ async fn favorites(
.collect::<Vec<String>>();
span.set_status(Status::Ok);
// Favorites are library-agnostic (shared by rel_path), so we
// intentionally leave photo_libraries empty to signal "no badge".
HttpResponse::Ok().json(PhotosResponse {
photos: favorites,
dirs: Vec::new(),
photo_libraries: Vec::new(),
total_count: None,
has_more: None,
next_offset: None,