From 86aba8f4b1a8a89dd5e0f70ed2002fa798592e31 Mon Sep 17 00:00:00 2001 From: vcoppe Date: Sun, 4 Oct 2026 08:26:15 +0200 Subject: [PATCH] progress --- website/src/lib/engine.ts | 49 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/website/src/lib/engine.ts b/website/src/lib/engine.ts index 92585b49b..0a7539154 100644 --- a/website/src/lib/engine.ts +++ b/website/src/lib/engine.ts @@ -278,3 +278,52 @@ class Engine { } export const engine = new Engine(); + +export type FileStatesCallback = (files: Map>) => void; + +/** + * Tells when file stores appear and disappear, so that their subscribers know when to + * subscribe and unsubscribe. `onFilesAdded` is called with the stores of the new files only + * (including the ones already present when the observer is created). + */ +export class FileStateCollectionObserver { + private _fileIds = new Set(); + private _onFilesAdded: FileStatesCallback; + private _onFileRemoved: (fileId: string) => void; + private _onDestroy: () => void; + private _unsubscribe: () => void; + + constructor( + onFilesAdded: FileStatesCallback, + onFileRemoved: (fileId: string) => void, + onDestroy: () => void + ) { + this._onFilesAdded = onFilesAdded; + this._onFileRemoved = onFileRemoved; + this._onDestroy = onDestroy; + + this._unsubscribe = engine.files.subscribe((files) => { + this._fileIds.forEach((fileId) => { + if (!files.has(fileId)) { + this._onFileRemoved(fileId); + this._fileIds.delete(fileId); + } + }); + const newFiles = new Map>(); + files.forEach((store, fileId) => { + if (!this._fileIds.has(fileId)) { + newFiles.set(fileId, store); + this._fileIds.add(fileId); + } + }); + if (newFiles.size > 0) { + this._onFilesAdded(newFiles); + } + }); + } + + destroy() { + this._onDestroy(); + this._unsubscribe(); + } +}