From 264fdcf7cd42cb130e39cf58d4546264484f63e8 Mon Sep 17 00:00:00 2001 From: OpenClaw Agent Date: Thu, 9 Jul 2026 21:02:30 +0000 Subject: [PATCH] perf: trim editor render selection lookups --- js/ltx_director.js | 98 ++++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/js/ltx_director.js b/js/ltx_director.js index 2987641..25f6fa4 100644 --- a/js/ltx_director.js +++ b/js/ltx_director.js @@ -5967,11 +5967,12 @@ class TimelineEditor { } // --- Rendering logic --- - render() { - if (!this.canvas) return; - const width = this.canvas.offsetWidth || this._lastWidth; - const height = this.canvasHeight; - const totalFrames = this.getVisualDurationFrames(); + render() { + if (!this.canvas) return; + const width = this.canvas.offsetWidth || this._lastWidth; + const height = this.canvasHeight; + const totalFrames = this.getVisualDurationFrames(); + const selectedIdSet = new Set(this.selectedSegmentIds || []); if (!width || width <= 0) return; @@ -5999,8 +6000,8 @@ class TimelineEditor { } if (this._isDragging && this._dragTargetId) { - const dragSeg = this.timeline.segments.find(s => s.id === this._dragTargetId) || - (this.timeline.motionSegments && this.timeline.motionSegments.find(s => s.id === this._dragTargetId)); + const dragSeg = findSegmentById(this.timeline.segments, this._dragTargetId) || + findSegmentById(this.timeline.motionSegments, this._dragTargetId); if (dragSeg && (dragSeg.type === "video" || dragSeg.type === "motion_video")) { this._ensureVideoEl(dragSeg); } @@ -6051,23 +6052,23 @@ class TimelineEditor { if (this._previewSegments && previewIsMotion) renderMotionSegments = this._previewSegments; } - const sortedSegments = [...renderSegments].sort((a, b) => { - const aSel = this.selectedSegmentIds.includes(a.id) ? 1 : 0; - const bSel = this.selectedSegmentIds.includes(b.id) ? 1 : 0; - return aSel - bSel; - }); - - const sortedMotionSegments = [...renderMotionSegments].sort((a, b) => { - const aSel = this.selectedSegmentIds.includes(a.id) ? 1 : 0; - const bSel = this.selectedSegmentIds.includes(b.id) ? 1 : 0; - return aSel - bSel; - }); - - const sortedAudioSegments = [...renderAudioSegments].sort((a, b) => { - const aSel = this.selectedSegmentIds.includes(a.id) ? 1 : 0; - const bSel = this.selectedSegmentIds.includes(b.id) ? 1 : 0; - return aSel - bSel; - }); + const sortedSegments = [...renderSegments].sort((a, b) => { + const aSel = selectedIdSet.has(a.id) ? 1 : 0; + const bSel = selectedIdSet.has(b.id) ? 1 : 0; + return aSel - bSel; + }); + + const sortedMotionSegments = [...renderMotionSegments].sort((a, b) => { + const aSel = selectedIdSet.has(a.id) ? 1 : 0; + const bSel = selectedIdSet.has(b.id) ? 1 : 0; + return aSel - bSel; + }); + + const sortedAudioSegments = [...renderAudioSegments].sort((a, b) => { + const aSel = selectedIdSet.has(a.id) ? 1 : 0; + const bSel = selectedIdSet.has(b.id) ? 1 : 0; + return aSel - bSel; + }); if (this.retakeMode) { // Draw Retake Mode Filmstrip and Overlay @@ -6417,7 +6418,7 @@ class TimelineEditor { const rawEndX = ((seg.start + seg.length) / totalFrames) * width; const startX = Math.floor(rawStartX); const pxWidth = Math.max(1, Math.floor(rawEndX) - startX); - const isSelected = this.selectedSegmentIds.includes(seg.id); + const isSelected = selectedIdSet.has(seg.id); const originalSeg = this.timeline.segments.find(s => s.id === seg.id); const imgObj = originalSeg ? originalSeg.imgObj : seg.imgObj; @@ -6753,7 +6754,7 @@ class TimelineEditor { const startX = Math.floor((seg.start / totalFrames) * width); const rawEndX = ((seg.start + seg.length) / totalFrames) * width; const pxWidth = Math.max(1, Math.floor(rawEndX) - startX); - const isSelected = this.selectedSegmentIds.includes(seg.id); + const isSelected = selectedIdSet.has(seg.id); const trackY = RULER_HEIGHT + this.blockHeight + this.audioTrackHeight; if ((this._isDragging && this.selectionType === "motion" && seg.id === this._dragTargetId) || (this._ghostSegmentId && seg.id === this._ghostSegmentId)) { @@ -6779,7 +6780,7 @@ class TimelineEditor { this.ctx.fillStyle = "#000"; this.ctx.fillRect(startX, trackY + 1, pxWidth, this.motionTrackHeight - 2); - const originalSeg = this.timeline.motionSegments.find(s => s.id === seg.id); + const originalSeg = findSegmentById(this.timeline.motionSegments, seg.id); const imgObj = originalSeg ? originalSeg.imgObj : seg.imgObj; const videoEl = originalSeg ? originalSeg.videoEl : seg.videoEl; @@ -6974,7 +6975,7 @@ class TimelineEditor { const rawEndX = ((seg.start + seg.length) / totalFrames) * width; const startX = Math.floor(rawStartX); const pxWidth = Math.max(1, Math.floor(rawEndX) - startX); - const isSelected = this.selectedSegmentIds.includes(seg.id); + const isSelected = selectedIdSet.has(seg.id); const trackY = RULER_HEIGHT + this.blockHeight; if ((this._isDragging && this.selectionType === "audio" && seg.id === this._dragTargetId) || (this._ghostSegmentId && seg.id === this._ghostSegmentId)) { @@ -9840,16 +9841,19 @@ class TimelineEditor { let clickedSeg = null; let trackType = ""; - if (isMotionTrack) { - clickedSeg = this.timeline.motionSegments.find(s => cursor >= s.start && cursor <= s.start + s.length); - trackType = "motion"; - } else if (isAudioTrack) { - clickedSeg = this.timeline.audioSegments.find(s => cursor >= s.start && cursor <= s.start + s.length); - trackType = "audio"; - } else if (isImageTrack) { - clickedSeg = this.timeline.segments.find(s => cursor >= s.start && cursor <= s.start + s.length); - trackType = clickedSeg ? clickedSeg.type : ""; - } + if (isMotionTrack) { + clickedSeg = findActiveSegmentAtFrame(this.timeline.motionSegments, cursor, "motion_video"); + trackType = "motion"; + } else if (isAudioTrack) { + clickedSeg = findActiveSegmentAtFrame(this.timeline.audioSegments, cursor, "audio"); + trackType = "audio"; + } else if (isImageTrack) { + clickedSeg = findActiveSegmentAtFrame(this.timeline.segments, cursor, "image") + || findActiveSegmentAtFrame(this.timeline.segments, cursor, "video") + || findActiveSegmentAtFrame(this.timeline.segments, cursor, "text") + || findActiveSegmentAtFrame(this.timeline.segments, cursor, "ghost"); + trackType = clickedSeg ? clickedSeg.type : ""; + } if (clickedSeg) { this.showContextMenu(e.clientX, e.clientY, clickedSeg, trackType); @@ -10105,9 +10109,9 @@ class TimelineEditor { seg.prompt = text; this.commitChanges(); this.render(); - if (this.selectedIndex === this.timeline.segments.findIndex(s => s.id === seg.id)) { - this.updateUIFromSelection(); - } + if (this.selectedIndex === findSegmentIndexById(this.timeline.segments, seg.id)) { + this.updateUIFromSelection(); + } } } catch (err) { console.error("Failed to paste prompt", err); @@ -10204,9 +10208,9 @@ class TimelineEditor { seg.imgObj = img; this.commitChanges(); this.render(); - if (this.selectedIndex === this.timeline.segments.findIndex(s => s.id === seg.id)) { - this.updateUIFromSelection(); - } + if (this.selectedIndex === findSegmentIndexById(this.timeline.segments, seg.id)) { + this.updateUIFromSelection(); + } }; img.src = imgUrl; } @@ -10249,9 +10253,9 @@ class TimelineEditor { seg.imgObj = img; this.commitChanges(); this.render(); - if (this.selectedIndex === this.timeline.segments.findIndex(s => s.id === seg.id)) { - this.updateUIFromSelection(); - } + if (this.selectedIndex === findSegmentIndexById(this.timeline.segments, seg.id)) { + this.updateUIFromSelection(); + } }; img.src = imgUrl; }