From be71617f984793634e0c8646e92560505f91a40b Mon Sep 17 00:00:00 2001 From: Maxime BAUMANN Date: Fri, 2 Dec 2022 15:50:04 +0100 Subject: [PATCH] fix: Multipart images loading --- package.json | 2 +- src/draw-zone/hooks.ts | 51 ++++++++++++++++++++++++++++++++++-------- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/package.json b/package.json index ae0b017..5385835 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@psycle/repsycle", - "version": "0.0.33", + "version": "0.0.34", "description": "Psycle Research front-end toolkit", "author": "Psycle Research", "keywords": [ diff --git a/src/draw-zone/hooks.ts b/src/draw-zone/hooks.ts index f94d5e2..1946de4 100644 --- a/src/draw-zone/hooks.ts +++ b/src/draw-zone/hooks.ts @@ -5,16 +5,49 @@ import { MAX_SCALE, SCALE_STEP } from './constants' import { memoize } from 'lodash' async function preloadImage(src: string): Promise { - const ev = await new Promise((resolve, reject) => { - const image = new Image() - image.onload = resolve - image.onerror = reject - image.src = src + return await new Promise((resolve, reject) => { + // Use an iframe as a workarounf for multipart/x-mixed-replace images size compute + // An ordinary image would load the multipart/x-mixed-replace twice and increase payload size + const iframe = document.createElement('iframe') + + iframe.onload = () => { + if (!iframe.contentWindow) { + reject('No content window') + iframe.remove() + } else { + const image = new Image() + iframe.contentWindow.document.body.appendChild(image) + + image.onload = (ev) => { + const target = ev.target as HTMLImageElement + const { width, height } = target + + image.remove() + iframe.remove() + + resolve({ width, height }) + } + image.onerror = () => { + reject('Failed to load image') + image.remove() + iframe.remove() + } + image.src = src + } + } + + const html = `` + + if (typeof iframe.srcdoc !== 'undefined') { + iframe.srcdoc = html + } else if (iframe.contentWindow) { + iframe.contentWindow.document.open() + iframe.contentWindow.document.write(html) + iframe.contentWindow.document.close() + } + + document.body.appendChild(iframe) }) - - const target = ev.target as HTMLImageElement - const { width, height } = target - return { width, height } } const preloadImageMemo = memoize(preloadImage)