From fa446ab353a0d8c78b9b76ba89580bd7eb945db0 Mon Sep 17 00:00:00 2001 From: admin Date: Mon, 25 May 2026 22:16:40 +0200 Subject: [PATCH] =?UTF-8?q?fix(feed):=20resolve=20word=E2=86=92object=20li?= =?UTF-8?q?nks=20for=20picture=20lookup=20on=20word-type=20cards?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Word-type placeholders in sentences (type='word') were never matched against object_pictures, so those cards always had no image. Now queries object_words by word_id to find associated objects, adds them to resolvedObjectIds, and pickPicture checks wordObjectMap as a fallback. Co-Authored-By: Claude Sonnet 4.6 --- src/routes/feed.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/routes/feed.js b/src/routes/feed.js index ba928eb..622bfd4 100644 --- a/src/routes/feed.js +++ b/src/routes/feed.js @@ -88,6 +88,7 @@ router.get('/', requireJwt, async (req, res, next) => { // 6. Resolve UUIDs → words (direct) or via objects→words const placeholderMap = {}; // uuid → { de, en, sv } + const wordObjectMap = {}; // wordId → objectId (for picture lookup) if (uuidArr.length) { // Direct word lookup const wordRes = await query( @@ -123,6 +124,17 @@ router.get('/', requireJwt, async (req, res, next) => { } }); } + + // For word-type placeholders: find linked objects so we can load their pictures + const wordUuids = uuidArr.filter(u => placeholderMap[u]?.type === 'word'); + if (wordUuids.length) { + const wObjRes = await query( + `SELECT DISTINCT ON (ow.word_id) ow.word_id, ow.object_id + FROM object_words ow WHERE ow.word_id = ANY($1)`, + [wordUuids] + ); + wObjRes.rows.forEach(r => { wordObjectMap[r.word_id] = r.object_id; }); + } } // 7. Fetch statement→word links (positive + negative) @@ -163,6 +175,8 @@ router.get('/', requireJwt, async (req, res, next) => { ); objCheckRes.rows.forEach(r => resolvedObjectIds.add(r.id)); } + // Also include objects linked to word-type placeholders + Object.values(wordObjectMap).forEach(oid => resolvedObjectIds.add(oid)); const pictureMap = {}; // objectId → { url, blurhash } if (resolvedObjectIds.size) { @@ -181,9 +195,12 @@ router.get('/', requireJwt, async (req, res, next) => { } // Pick first available picture across all placeholders in the pair + // Checks both direct object UUIDs and word-type UUIDs linked to objects function pickPicture(pairUuids) { for (const u of pairUuids) { if (pictureMap[u]) return pictureMap[u]; + const oid = wordObjectMap[u]; + if (oid && pictureMap[oid]) return pictureMap[oid]; } return null; }