feat: media processing pipeline, spatial indexing, canvas-based video rendering
- Background media worker: polls media_jobs table, runs ffprobe+ffmpeg with concurrency limit, generates video posters, emits socket events - Non-blocking video upload: stores file + enqueues job, returns immediately - Poster hydration on board load: GET /boards/:id injects poster/dimensions from DB into canvas_state video objects - SpatialGrid: fixed-cell (512px) spatial hash for O(nearby) culling instead of O(all) item scanning, eliminates setTimeout violations - Canvas-based video rendering: draws video frames to offscreen canvas then uploads to GPU, completely eliminates GL_INVALID_OPERATION errors from PixiJS VideoSource auto-update mechanism - Server poster upgrade path: culling ticker and applyProcessedMedia() both upgrade client-captured posters to server posters when available - Pause restores server poster (paused video behaves like an image) - Selection drag-end persistence: onObjectDragEnd broadcasts + saves + undo - Live media:job:update socket handler patches scene data + VideoSprite dimensions without broadcast fanout
This commit is contained in:
@@ -41,6 +41,7 @@ export class SelectionManager {
|
||||
private _onSelectionChange: ((ids: string[]) => void) | null = null;
|
||||
private _onItemTransform: ((item: SceneItem) => void) | null = null;
|
||||
private _onItemsTransform: ((items: SceneItem[]) => void) | null = null;
|
||||
private _onObjectDragEnd: ((ids: string[]) => void) | null = null;
|
||||
|
||||
// Pointer state
|
||||
private _pointerDown = false;
|
||||
@@ -122,6 +123,11 @@ export class SelectionManager {
|
||||
this._onItemsTransform = fn;
|
||||
}
|
||||
|
||||
/** Called when object drag ends (for persist/save/spatial refresh). */
|
||||
set onObjectDragEnd(fn: (ids: string[]) => void) {
|
||||
this._onObjectDragEnd = fn;
|
||||
}
|
||||
|
||||
/** Called on double-click of a text item (for inline editing). */
|
||||
set onDoubleClickText(fn: (item: SceneItem) => void) {
|
||||
this._onDoubleClickText = fn;
|
||||
@@ -313,6 +319,7 @@ export class SelectionManager {
|
||||
|
||||
// Notify change (positions updated)
|
||||
this._emitChange();
|
||||
this._onObjectDragEnd?.(Array.from(this.selectedIds));
|
||||
} else if (this._rubberBanding) {
|
||||
// Finish rubber band selection
|
||||
const currentWorld = this._viewport.toWorld(e.global.x, e.global.y);
|
||||
|
||||
Reference in New Issue
Block a user