From 697df7e9467ee8aea01928dab08aaad3a43d9781 Mon Sep 17 00:00:00 2001 From: Fedor Indutny <79877362+indutny-signal@users.noreply.github.com> Date: Mon, 30 Sep 2024 16:59:55 -0700 Subject: [PATCH] Fix adding sticker in media editor --- ts/components/MediaEditor.tsx | 7 +++++-- ts/components/UsernameLinkModalBody.tsx | 10 ++-------- ts/util/loadImage.ts | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+), 10 deletions(-) create mode 100644 ts/util/loadImage.ts diff --git a/ts/components/MediaEditor.tsx b/ts/components/MediaEditor.tsx index 3a1e8f92ac39..5803b0a73dcd 100644 --- a/ts/components/MediaEditor.tsx +++ b/ts/components/MediaEditor.tsx @@ -56,6 +56,7 @@ import { Theme } from '../util/theme'; import { ThemeType } from '../types/Util'; import { arrow } from '../util/keyboard'; import { canvasToBytes } from '../util/canvasToBytes'; +import { loadImage } from '../util/loadImage'; import { getConversationSelector } from '../state/selectors/conversations'; import { hydrateRanges } from '../types/BodyRange'; import { useConfirmDiscard } from '../hooks/useConfirmDiscard'; @@ -1213,17 +1214,19 @@ export function MediaEditor({ i18n={i18n} installedPacks={installedPacks} knownPacks={[]} - onPickSticker={(_packId, _stickerId, src: string) => { + onPickSticker={async (_packId, _stickerId, src: string) => { if (!fabricCanvas) { return; } + const img = await loadImage(src); + const STICKER_SIZE_RELATIVE_TO_CANVAS = 4; const size = Math.min(imageState.width, imageState.height) / STICKER_SIZE_RELATIVE_TO_CANVAS; - const sticker = new MediaEditorFabricSticker(src); + const sticker = new MediaEditorFabricSticker(img); sticker.scaleToHeight(size); sticker.setPositionByOrigin( new fabric.Point( diff --git a/ts/components/UsernameLinkModalBody.tsx b/ts/components/UsernameLinkModalBody.tsx index ee6372cac468..3ced2c609701 100644 --- a/ts/components/UsernameLinkModalBody.tsx +++ b/ts/components/UsernameLinkModalBody.tsx @@ -17,6 +17,7 @@ import { IMAGE_PNG } from '../types/MIME'; import { strictAssert } from '../util/assert'; import { drop } from '../util/drop'; import { splitText } from '../util/splitText'; +import { loadImage } from '../util/loadImage'; import { Button, ButtonVariant } from './Button'; import { Modal } from './Modal'; import { ConfirmationDialog } from './ConfirmationDialog'; @@ -373,14 +374,7 @@ export async function _generateImageBlob({ ); const svgURL = `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`; - const img = new Image(); - await new Promise((resolve, reject) => { - img.addEventListener('load', resolve); - img.addEventListener('error', () => - reject(new Error('Failed to load image')) - ); - img.src = svgURL; - }); + const img = await loadImage(svgURL); context.drawImage(img, 0, 0, PRINT_WIDTH, PRINT_HEIGHT); diff --git a/ts/util/loadImage.ts b/ts/util/loadImage.ts new file mode 100644 index 000000000000..a3474159442a --- /dev/null +++ b/ts/util/loadImage.ts @@ -0,0 +1,21 @@ +// Copyright 2024 Signal Messenger, LLC +// SPDX-License-Identifier: AGPL-3.0-only + +import { explodePromise } from './explodePromise'; + +export async function loadImage(src: string): Promise { + const { promise, resolve, reject } = explodePromise(); + + const img = new Image(); + img.addEventListener('load', () => resolve(), { once: true }); + img.addEventListener( + 'error', + () => reject(new Error('Image failed to load')), + { once: true } + ); + img.src = src; + + await promise; + + return img; +}