immich/web/src/lib/managers/timeline-manager/internal/websocket-support.svelte.ts
2025-10-08 23:58:38 +00:00

85 lines
2.4 KiB
TypeScript

import type { TimelineManager } from '$lib/managers/timeline-manager/timeline-manager.svelte';
import type { Asset, PendingChange } from '$lib/managers/timeline-manager/types';
import { websocketEvents } from '$lib/stores/websocket';
import { toAsset } from '$lib/utils/timeline-util';
import { throttle } from 'lodash-es';
import type { Unsubscriber } from 'svelte/store';
export class WebsocketSupport {
#pendingChanges: PendingChange[] = [];
#unsubscribers: Unsubscriber[] = [];
#timelineManager: TimelineManager;
#processPendingChanges = throttle(() => {
const { add, update, remove } = this.#getPendingChangeBatches();
if (add.length > 0) {
this.#timelineManager.addAssets(add);
}
if (update.length > 0) {
this.#timelineManager.updateAssets(update);
}
if (remove.length > 0) {
this.#timelineManager.removeAssets(remove);
}
this.#pendingChanges = [];
}, 2500);
constructor(timeineManager: TimelineManager) {
this.#timelineManager = timeineManager;
}
connectWebsocketEvents() {
this.#unsubscribers.push(
websocketEvents.on('on_upload_success', (asset) =>
this.#addPendingChanges({ type: 'add', values: [toAsset(asset)] }),
),
websocketEvents.on('on_asset_trash', (ids) => this.#addPendingChanges({ type: 'trash', values: ids })),
websocketEvents.on('on_asset_update', (asset) =>
this.#addPendingChanges({ type: 'update', values: [toAsset(asset)] }),
),
websocketEvents.on('on_asset_delete', (id: string) => this.#addPendingChanges({ type: 'delete', values: [id] })),
);
}
disconnectWebsocketEvents() {
for (const unsubscribe of this.#unsubscribers) {
unsubscribe();
}
this.#unsubscribers = [];
}
#addPendingChanges(...changes: PendingChange[]) {
this.#pendingChanges.push(...changes);
this.#processPendingChanges();
}
#getPendingChangeBatches() {
const batch: {
add: Asset[];
update: Asset[];
remove: string[];
} = {
add: [],
update: [],
remove: [],
};
for (const { type, values } of this.#pendingChanges) {
switch (type) {
case 'add': {
batch.add.push(...values);
break;
}
case 'update': {
batch.update.push(...values);
break;
}
case 'delete':
case 'trash': {
batch.remove.push(...values);
break;
}
}
}
return batch;
}
}