aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
Diffstat (limited to 'src/features')
-rw-r--r--src/features/messages.js38
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) {