summaryrefslogtreecommitdiff
path: root/apps/web/src/services/renderer/nodes/sticker-node.ts
diff options
context:
space:
mode:
Diffstat (limited to 'apps/web/src/services/renderer/nodes/sticker-node.ts')
-rw-r--r--apps/web/src/services/renderer/nodes/sticker-node.ts53
1 files changed, 33 insertions, 20 deletions
diff --git a/apps/web/src/services/renderer/nodes/sticker-node.ts b/apps/web/src/services/renderer/nodes/sticker-node.ts
index a2fb0170..acf638eb 100644
--- a/apps/web/src/services/renderer/nodes/sticker-node.ts
+++ b/apps/web/src/services/renderer/nodes/sticker-node.ts
@@ -6,29 +6,46 @@ export interface StickerNodeParams extends VisualNodeParams {
stickerId: string;
}
-export class StickerNode extends VisualNode<StickerNodeParams> {
- private image?: HTMLImageElement;
- private readyPromise: Promise<void>;
+interface CachedStickerSource {
+ source: HTMLImageElement;
+ width: number;
+ height: number;
+}
- constructor(params: StickerNodeParams) {
- super(params);
- this.readyPromise = this.load();
- }
+const stickerSourceCache = new Map<string, Promise<CachedStickerSource>>();
- private async load() {
- const image = new Image();
- this.image = image;
+function loadStickerSource(stickerId: string): Promise<CachedStickerSource> {
+ const cached = stickerSourceCache.get(stickerId);
+ if (cached) return cached;
+
+ const promise = (async (): Promise<CachedStickerSource> => {
const url = resolveStickerId({
- stickerId: this.params.stickerId,
+ stickerId,
options: { width: 200, height: 200 },
});
+ const image = new Image();
+
await new Promise<void>((resolve, reject) => {
image.onload = () => resolve();
image.onerror = () =>
- reject(new Error(`Failed to load sticker: ${this.params.stickerId}`));
+ reject(new Error(`Failed to load sticker: ${stickerId}`));
image.src = url;
});
+
+ return { source: image, width: 200, height: 200 };
+ })();
+
+ stickerSourceCache.set(stickerId, promise);
+ return promise;
+}
+
+export class StickerNode extends VisualNode<StickerNodeParams> {
+ private cachedSource: Promise<CachedStickerSource>;
+
+ constructor(params: StickerNodeParams) {
+ super(params);
+ this.cachedSource = loadStickerSource(params.stickerId);
}
async render({ renderer, time }: { renderer: CanvasRenderer; time: number }) {
@@ -38,17 +55,13 @@ export class StickerNode extends VisualNode<StickerNodeParams> {
return;
}
- await this.readyPromise;
-
- if (!this.image) {
- return;
- }
+ const { source, width, height } = await this.cachedSource;
this.renderVisual({
renderer,
- source: this.image,
- sourceWidth: 200,
- sourceHeight: 200,
+ source,
+ sourceWidth: width,
+ sourceHeight: height,
});
}
}