diff options
| -rw-r--r-- | src/features/messages.js | 38 |
1 files changed, 22 insertions, 16 deletions
diff --git a/src/features/messages.js b/src/features/messages.js index d18a0b2..86b6c75 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -5486,6 +5486,9 @@ export function messagesFeature(ctx) { let bmp; try { bmp = await createImageBitmap(blob); } catch { return null; } const dims = { width: bmp.width, height: bmp.height }; + // the Images grid's square comes from the same decode: scrolling the + // feed fills the grid's cache, no second download + if (!/gif/i.test(blob.type) && !tileThumbs.has(url)) await tileFromBitmap(url, bmp).catch(() => {}); // small enough already, or animated (a GIF's copy would be one frame): // remember the shape and paint the original const keep = bmp.width <= MEDIA_THUMB_W * 1.25 || /gif/i.test(blob.type); @@ -10122,22 +10125,25 @@ export function messagesFeature(ctx) { if (/gif/i.test(blob.type)) return; // animated: the tile shows the original let bmp; try { bmp = await createImageBitmap(blob); } catch { return; } - try { - const side = Math.min(bmp.width, bmp.height); - const px = Math.min(TILE_PX, side); - const sq = await createImageBitmap(bmp, (bmp.width - side) / 2, (bmp.height - side) / 2, side, side, - { resizeWidth: px, resizeHeight: px, resizeQuality: 'high' }); - const c = new OffscreenCanvas(px, px); - c.getContext('2d').drawImage(sq, 0, 0); - try { sq.close(); } catch {} - let out = await c.convertToBlob({ type: 'image/webp', quality: 0.8 }); - if (!/webp/.test(out.type)) out = await c.convertToBlob({ type: 'image/jpeg', quality: 0.8 }); - tileThumbs.set(url, URL.createObjectURL(out)); - const store = await tileStore(); - await store.put(tileKey(url), new Response(out, { headers: { 'content-type': out.type } })); - const keys = await store.keys(); - if (keys.length > TILE_MAX) for (const k of keys.slice(0, keys.length - TILE_MAX + 100)) store.delete(k); - } catch {} finally { try { bmp.close(); } catch {} } + try { await tileFromBitmap(url, bmp); } catch {} finally { try { bmp.close(); } catch {} } + } + // A tile's square, cut from a decoded picture and kept (the caller closes it). + async function tileFromBitmap(url, bmp) { + if (typeof OffscreenCanvas === 'undefined' || typeof caches === 'undefined') return; + const side = Math.min(bmp.width, bmp.height); + const px = Math.min(TILE_PX, side); + const sq = await createImageBitmap(bmp, (bmp.width - side) / 2, (bmp.height - side) / 2, side, side, + { resizeWidth: px, resizeHeight: px, resizeQuality: 'high' }); + const c = new OffscreenCanvas(px, px); + c.getContext('2d').drawImage(sq, 0, 0); + try { sq.close(); } catch {} + let out = await c.convertToBlob({ type: 'image/webp', quality: 0.8 }); + if (!/webp/.test(out.type)) out = await c.convertToBlob({ type: 'image/jpeg', quality: 0.8 }); + tileThumbs.set(url, URL.createObjectURL(out)); + const store = await tileStore(); + await store.put(tileKey(url), new Response(out, { headers: { 'content-type': out.type } })); + const keys = await store.keys(); + if (keys.length > TILE_MAX) for (const k of keys.slice(0, keys.length - TILE_MAX + 100)) store.delete(k); } // newest first, a few at a time; the grid repaints as a batch lands function queueTileThumbs(urls) { |
