From 40a5ff783a83d7952066773b327e531d8e4bcd99 Mon Sep 17 00:00:00 2001 From: Paul Kaplan Date: Thu, 14 Feb 2019 13:07:56 -0500 Subject: [PATCH] Fix loading single frame gifs by removing onDone in favor of indices Because the `onFrame` callback could do async work, it was possible for onDone to try to submit the costumes before the onFrame had produced any. This was subject to browsers different timing treatments of setTimeout vs. promise resolution. This makes the gif-decoder use the same style of progress API as the file uploader --- src/lib/file-uploader.js | 11 +++++------ src/lib/gif-decoder.js | 12 ++++-------- 2 files changed, 9 insertions(+), 14 deletions(-) diff --git a/src/lib/file-uploader.js b/src/lib/file-uploader.js index 628a1a552..15a018541 100644 --- a/src/lib/file-uploader.js +++ b/src/lib/file-uploader.js @@ -118,15 +118,14 @@ const costumeUpload = function (fileData, fileType, storage, handleCostume, hand } case 'image/gif': { let costumes = []; - const onFrame = (frameNumber, dataUrl) => { + gifDecoder(fileData, (frameNumber, dataUrl, numFrames) => { costumeUpload(dataUrl, 'image/png', storage, costumes_ => { costumes = costumes.concat(costumes_); + if (frameNumber === numFrames - 1) { + handleCostume(costumes); + } }, handleError); - }; - const onDone = () => { - handleCostume(costumes); - }; - gifDecoder(fileData, {onFrame, onDone}); + }); return; // Abandon this load, do not try to load gif itself } default: diff --git a/src/lib/gif-decoder.js b/src/lib/gif-decoder.js index 91466eaa4..d53a6205b 100644 --- a/src/lib/gif-decoder.js +++ b/src/lib/gif-decoder.js @@ -1,9 +1,10 @@ import {GifReader} from 'omggif'; -export default (arrayBuffer, {onFrame, onDone}) => { +export default (arrayBuffer, onFrame) => { const canvas = document.createElement('canvas'); const ctx = canvas.getContext('2d'); const gifReader = new GifReader(new Uint8Array(arrayBuffer)); + const numFrames = gifReader.numFrames(); canvas.width = gifReader.width; canvas.height = gifReader.height; @@ -14,7 +15,6 @@ export default (arrayBuffer, {onFrame, onDone}) => { const framePixels = []; gifReader.decodeAndBlitFrameRGBA(i, framePixels); const {x, y, width, height, disposal} = gifReader.frameInfo(i); - for (let row = 0; row < height; row++) { for (let column = 0; column < width; column++) { const indexOffset = 4 * (x + (y * canvas.width)); @@ -47,16 +47,12 @@ export default (arrayBuffer, {onFrame, onDone}) => { break; } - onFrame(i, dataUrl); + onFrame(i, dataUrl, numFrames); - if (i < gifReader.numFrames() - 1) { + if (i < numFrames - 1) { setTimeout(() => { loadFrame(i + 1); }); - } else { - setTimeout(() => { - onDone(); - }); } };