feat: wire up album filtering to photo queue

Album selection now controls which photos are displayed.
Uses POST /api/search/random with albumIds filter (Immich v3
compatible) instead of the removed GET /api/albums/{id} assets.

- Add albumIds parameter to fetchRandomAssets/fetchRandomAssetIds
- syncFromAlbums: fetch random assets filtered by selected albums
- syncFromAllPhotos: preserve existing global random behavior
- Album mode reshuffles on exhaustion instead of re-fetching
- 24h resync checks album assetCounts for changes before re-fetch
- requestSync + albums_changed action triggers queue rebuild on save
- timerWakeCycle respects album selection
- Discard stale pre-renders on album change

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-03 22:46:17 -04:00
parent 739dc403ba
commit 679e9e1721
6 changed files with 202 additions and 41 deletions

View File

@@ -87,14 +87,18 @@ std::vector<String> ImmichClient::fetchAlbumAssetIds(const String& albumId) {
return ids;
}
std::vector<String> ImmichClient::fetchRandomAssetIds(int count) {
std::vector<String> ImmichClient::fetchRandomAssetIds(int count,
const std::vector<String>& albumIds) {
std::vector<String> ids;
String url = buildUrl("/api/search/random");
// Build POST body — filter to images only (excludes videos, audio)
JsonDocument reqDoc;
reqDoc["size"] = count;
reqDoc["type"] = "IMAGE";
if (!albumIds.empty()) {
JsonArray arr = reqDoc["albumIds"].to<JsonArray>();
for (auto& id : albumIds) arr.add(id);
}
String body;
serializeJson(reqDoc, body);
@@ -118,7 +122,6 @@ std::vector<String> ImmichClient::fetchRandomAssetIds(int count) {
String id = asset["id"].as<String>();
if (id.length() == 0) continue;
// Filter out RAW/DNG files — their previews work but we prefer actual photos
String filename = asset["originalFileName"] | "";
filename.toLowerCase();
if (filename.endsWith(".dng") || filename.endsWith(".raw") ||
@@ -133,18 +136,23 @@ std::vector<String> ImmichClient::fetchRandomAssetIds(int count) {
ids.push_back(id);
}
Serial.printf("[immich] Fetched %d random assets (skipped %d RAW)\n",
ids.size(), skippedRaw);
Serial.printf("[immich] Fetched %d random assets%s (skipped %d RAW)\n",
ids.size(), albumIds.empty() ? "" : " from albums", skippedRaw);
return ids;
}
std::vector<RandomAsset> ImmichClient::fetchRandomAssets(int count) {
std::vector<RandomAsset> ImmichClient::fetchRandomAssets(int count,
const std::vector<String>& albumIds) {
std::vector<RandomAsset> assets;
String url = buildUrl("/api/search/random");
JsonDocument reqDoc;
reqDoc["size"] = count;
reqDoc["type"] = "IMAGE";
if (!albumIds.empty()) {
JsonArray albumArr = reqDoc["albumIds"].to<JsonArray>();
for (auto& aid : albumIds) albumArr.add(aid);
}
String body;
serializeJson(reqDoc, body);
@@ -178,8 +186,8 @@ std::vector<RandomAsset> ImmichClient::fetchRandomAssets(int count) {
assets.push_back(ra);
}
Serial.printf("[immich] Fetched %d random assets with dates (skipped %d RAW)\n",
assets.size(), skippedRaw);
Serial.printf("[immich] Fetched %d random assets with dates%s (skipped %d RAW)\n",
assets.size(), albumIds.empty() ? "" : " from albums", skippedRaw);
return assets;
}