From 840b5b94473ff131346275159a008f0e886d66ca Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Fri, 17 Jan 2025 15:20:55 -0600 Subject: [PATCH 1/5] feat: OPTIC-1479: Improve memory usage of Image tag --- web/libs/editor/src/tags/object/Image/ImageEntity.js | 11 +++++++++-- web/libs/editor/src/utils/feature-flags.ts | 2 ++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/web/libs/editor/src/tags/object/Image/ImageEntity.js b/web/libs/editor/src/tags/object/Image/ImageEntity.js index 2b179f60ea8c..555733e2b4b8 100644 --- a/web/libs/editor/src/tags/object/Image/ImageEntity.js +++ b/web/libs/editor/src/tags/object/Image/ImageEntity.js @@ -1,6 +1,7 @@ import { types } from "mobx-state-tree"; import { FileLoader } from "../../../utils/FileLoader"; import { clamp } from "../../../utils/utilities"; +import { FF_IMAGE_MEMORY_USAGE, isFF } from "libs/editor/src/utils/feature-flags"; const fileLoader = new FileLoader(); @@ -67,10 +68,14 @@ export const ImageEntity = types })) .actions((self) => ({ preload() { + if (isFF(FF_IMAGE_MEMORY_USAGE)) { + self.setCurrentSrc(self.src); + self.setDownloaded(true); + self.setProgress(1); + return; + } if (self.ensurePreloaded() || !self.src) return; - self.setDownloading(true); - fileLoader .download(self.src, (_t, _l, progress) => { self.setProgress(progress); @@ -87,6 +92,8 @@ export const ImageEntity = types }, ensurePreloaded() { + if (isFF(FF_IMAGE_MEMORY_USAGE)) return false; + if (fileLoader.isError(self.src)) { self.setDownloading(false); self.setError(true); diff --git a/web/libs/editor/src/utils/feature-flags.ts b/web/libs/editor/src/utils/feature-flags.ts index b9d56b4597cd..6ec9525a855f 100644 --- a/web/libs/editor/src/utils/feature-flags.ts +++ b/web/libs/editor/src/utils/feature-flags.ts @@ -218,6 +218,8 @@ export const FF_LEAP_1173 = "fflag_feat_front_leap_1173_disable_postpone_skip_sh export const FF_PER_FIELD_COMMENTS = "fflag_feat_all_leap_1430_per_field_comments_100924_short"; +export const FF_IMAGE_MEMORY_USAGE = "fflag_feat_front_optic_1479_improve_image_tag_memory_usage_short"; + Object.assign(window, { APP_SETTINGS: { ...(window.APP_SETTINGS ?? {}), From 5bb168d802dd24c3bedf061b525baa8efbff03b2 Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Fri, 17 Jan 2025 16:17:25 -0600 Subject: [PATCH 2/5] fix imports --- web/libs/editor/src/tags/object/Image/ImageEntity.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/libs/editor/src/tags/object/Image/ImageEntity.js b/web/libs/editor/src/tags/object/Image/ImageEntity.js index 555733e2b4b8..dcdd9134e600 100644 --- a/web/libs/editor/src/tags/object/Image/ImageEntity.js +++ b/web/libs/editor/src/tags/object/Image/ImageEntity.js @@ -1,7 +1,7 @@ import { types } from "mobx-state-tree"; import { FileLoader } from "../../../utils/FileLoader"; import { clamp } from "../../../utils/utilities"; -import { FF_IMAGE_MEMORY_USAGE, isFF } from "libs/editor/src/utils/feature-flags"; +import { FF_IMAGE_MEMORY_USAGE, isFF } from "../../../utils/feature-flags"; const fileLoader = new FileLoader(); From 82592c1a00197184405e331cdcf8d62ea63d388a Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Mon, 20 Jan 2025 14:57:57 -0600 Subject: [PATCH 3/5] actually preload images when required using browser apis to manage resources and avoid storing data in Maps --- .../src/tags/object/Image/ImageEntity.js | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/web/libs/editor/src/tags/object/Image/ImageEntity.js b/web/libs/editor/src/tags/object/Image/ImageEntity.js index dcdd9134e600..e5296aa48143 100644 --- a/web/libs/editor/src/tags/object/Image/ImageEntity.js +++ b/web/libs/editor/src/tags/object/Image/ImageEntity.js @@ -68,13 +68,29 @@ export const ImageEntity = types })) .actions((self) => ({ preload() { + if (self.ensurePreloaded() || !self.src) return; + if (isFF(FF_IMAGE_MEMORY_USAGE)) { - self.setCurrentSrc(self.src); - self.setDownloaded(true); - self.setProgress(1); + self.setDownloading(true); + new Promise((resolve) => { + const img = new Image(); + img.src = self.src; + img.onload = () => { + self.setCurrentSrc(self.src); + self.setDownloaded(true); + self.setProgress(1); + self.setDownloading(false); + resolve(); + }; + img.onerror = () => { + self.setError(true); + self.setDownloading(false); + resolve(); + }; + }); return; } - if (self.ensurePreloaded() || !self.src) return; + self.setDownloading(true); fileLoader .download(self.src, (_t, _l, progress) => { @@ -92,7 +108,7 @@ export const ImageEntity = types }, ensurePreloaded() { - if (isFF(FF_IMAGE_MEMORY_USAGE)) return false; + if (isFF(FF_IMAGE_MEMORY_USAGE)) return self.currentSrc !== undefined; if (fileLoader.isError(self.src)) { self.setDownloading(false); From 2eb42b3d8b55302f24803202b3fddbbf8262e325 Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Tue, 21 Jan 2025 09:46:24 -0600 Subject: [PATCH 4/5] set the Image cors based on the ImageEntityMixin --- web/libs/editor/src/tags/object/Image/ImageEntity.js | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/web/libs/editor/src/tags/object/Image/ImageEntity.js b/web/libs/editor/src/tags/object/Image/ImageEntity.js index e5296aa48143..4da06b98053c 100644 --- a/web/libs/editor/src/tags/object/Image/ImageEntity.js +++ b/web/libs/editor/src/tags/object/Image/ImageEntity.js @@ -66,6 +66,15 @@ export const ImageEntity = types /** Is image loaded using `` tag and cached by the browser */ imageLoaded: false, })) + .views((self) => ({ + get parent() { + // Get the ImageEntityMixin + return getParent(self, 2); + }, + get imageCrossOrigin() { + return self.parent?.imageCrossOrigin ?? "anonymous"; + }, + })) .actions((self) => ({ preload() { if (self.ensurePreloaded() || !self.src) return; @@ -74,6 +83,9 @@ export const ImageEntity = types self.setDownloading(true); new Promise((resolve) => { const img = new Image(); + // Get from the image tag + const crossOrigin = self.imageCrossOrigin; + if (crossOrigin) img.crossOrigin = crossOrigin; img.src = self.src; img.onload = () => { self.setCurrentSrc(self.src); From 355f905d1282515e4e3279e313e6f144b11c588c Mon Sep 17 00:00:00 2001 From: Brandon Martel Date: Wed, 22 Jan 2025 06:56:14 -0600 Subject: [PATCH 5/5] fix imports --- web/libs/editor/src/tags/object/Image/ImageEntity.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/web/libs/editor/src/tags/object/Image/ImageEntity.js b/web/libs/editor/src/tags/object/Image/ImageEntity.js index 4da06b98053c..b347c5785a3b 100644 --- a/web/libs/editor/src/tags/object/Image/ImageEntity.js +++ b/web/libs/editor/src/tags/object/Image/ImageEntity.js @@ -1,4 +1,4 @@ -import { types } from "mobx-state-tree"; +import { types, getParent } from "mobx-state-tree"; import { FileLoader } from "../../../utils/FileLoader"; import { clamp } from "../../../utils/utilities"; import { FF_IMAGE_MEMORY_USAGE, isFF } from "../../../utils/feature-flags"; @@ -86,12 +86,12 @@ export const ImageEntity = types // Get from the image tag const crossOrigin = self.imageCrossOrigin; if (crossOrigin) img.crossOrigin = crossOrigin; - img.src = self.src; img.onload = () => { self.setCurrentSrc(self.src); self.setDownloaded(true); self.setProgress(1); self.setDownloading(false); + self.setImageLoaded(true); resolve(); }; img.onerror = () => { @@ -99,6 +99,7 @@ export const ImageEntity = types self.setDownloading(false); resolve(); }; + img.src = self.src; }); return; }