Changeset 28bf7f0 in Klonkt


Ignore:
Timestamp:
06/30/2026 03:26:08 PM (2 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
28f797d
Parents:
4d1aefb
Message:

fix(editor): animated WebP covers skip the crop editor (were flattened to a static frame)

The post editor's image editor (Cropper.js -> canvas) flattens an animated image to one frame.
Animated GIFs already bypassed it; animated WebP did not, so an animated WebP cover became static.
Detect an animated WebP (VP8X animation flag) client-side and upload it directly, like GIFs —
preserving the animation. Combined with the thumbnail fix, animated covers now move on-site.

  • src/views/pages/post-edit.ejs — isAnimatedWebpFile() + bypass the crop editor for animated WebP

Co-Authored-By: Claude <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/post-edit.ejs

    r4d1aefb r28bf7f0  
    12061206  }
    12071207
     1208  // True for an animated WebP (VP8X chunk with the animation flag set) — like a GIF it must skip
     1209  // the canvas editor, otherwise it'd be flattened to a single static frame.
     1210  async function isAnimatedWebpFile(file) {
     1211    if (!file || file.type !== 'image/webp') return false;
     1212    try {
     1213      const b = new Uint8Array(await file.slice(0, 40).arrayBuffer());
     1214      return b.length >= 21 && String.fromCharCode(b[12], b[13], b[14], b[15]) === 'VP8X' && (b[20] & 0x02) !== 0;
     1215    } catch (_) { return false; }
     1216  }
     1217
    12081218  // Opens the editor for a chosen file; resolves with an edited File,
    1209   // or null if the user cancels. Animated GIFs are not sent through the
     1219  // or null if the user cancels. Animated images (GIF / animated WebP) are NOT sent through the
    12101220  // canvas editor (they would become static) — those upload directly.
    12111221  async function openImageEditor(file) {
    12121222    if (!file || !file.type || !file.type.startsWith('image/')) return file;
    1213     if (file.type === 'image/gif') return file; // preserve animation
     1223    if (file.type === 'image/gif') return file;               // preserve animation
     1224    if (await isAnimatedWebpFile(file)) return file;          // animated WebP → preserve animation
    12141225    try { await ensureCropper(); } catch (_) { return file; } // editor unavailable → upload directly
    12151226
Note: See TracChangeset for help on using the changeset viewer.