fix(editor): drag interactions, undo history, overflow clipping
Four critical fixes: - Remove overflow:hidden on tlRef so Timeline.init's scroll survives re-renders - Don't call _renderClips() inside mousedown (was destroying event target mid-drag) - Use refs for undo history to eliminate stale closure in onClipsChanged callback - Change .tl-clip-area overflow:hidden to overflow:visible so pointer events reach clip edges
This commit is contained in:
parent
4673efac6a
commit
3dad82d992
2 changed files with 23 additions and 10 deletions
|
|
@ -94,7 +94,7 @@
|
|||
var area = document.createElement('div');
|
||||
area.className = 'tl-clip-area';
|
||||
area.dataset.trackId = t.id;
|
||||
area.style.cssText = 'flex:1;position:relative;overflow:hidden;';
|
||||
area.style.cssText = 'flex:1;position:relative;overflow:visible;';
|
||||
area.addEventListener('click', _onAreaClick);
|
||||
row.appendChild(area);
|
||||
|
||||
|
|
@ -269,8 +269,12 @@
|
|||
// Drag to move (body only)
|
||||
el.addEventListener('mousedown', function (e) {
|
||||
if (e.target === lh || e.target === rh) return;
|
||||
e.preventDefault();
|
||||
s.selectedId = clip._id;
|
||||
_renderClips();
|
||||
// Update selection highlight without destroying the element we're dragging
|
||||
s.tracksEl.querySelectorAll('.tl-clip').forEach(function (c) {
|
||||
c.style.borderColor = c.dataset.clipId === clip._id ? 'var(--accent)' : 'var(--border-strong)';
|
||||
});
|
||||
_onMoveStart(e, clip);
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ function Editor() {
|
|||
const streamCacheRef = React.useRef({});
|
||||
|
||||
const tlInitRef = React.useRef(false);
|
||||
// Refs so Timeline callbacks always read current values without stale closure issues
|
||||
const historyRef = React.useRef([[]]);
|
||||
const historyIdxRef = React.useRef(0);
|
||||
|
||||
React.useEffect(() => {
|
||||
const data = window.ZAMPP_DATA;
|
||||
|
|
@ -78,6 +81,8 @@ function Editor() {
|
|||
setCurrentSeq(seq);
|
||||
setPlayheadFrames(0);
|
||||
setSelectedClipId(null);
|
||||
historyRef.current = [clips];
|
||||
historyIdxRef.current = 0;
|
||||
setHistory([clips]);
|
||||
setHistoryIdx(0);
|
||||
setIsDirty(false);
|
||||
|
|
@ -130,9 +135,11 @@ function Editor() {
|
|||
|
||||
function handleClipsChanged(clips) {
|
||||
setCurrentSeq(prev => prev ? { ...prev, clips } : prev);
|
||||
const newHistory = history.slice(0, historyIdx + 1);
|
||||
const newHistory = historyRef.current.slice(0, historyIdxRef.current + 1);
|
||||
newHistory.push(clips.map(c => ({ ...c })));
|
||||
if (newHistory.length > 50) newHistory.shift();
|
||||
historyRef.current = newHistory;
|
||||
historyIdxRef.current = newHistory.length - 1;
|
||||
setHistory(newHistory);
|
||||
setHistoryIdx(newHistory.length - 1);
|
||||
markDirty();
|
||||
|
|
@ -173,20 +180,22 @@ function Editor() {
|
|||
}
|
||||
|
||||
function undo() {
|
||||
if (historyIdx <= 0) return;
|
||||
const idx = historyIdx - 1;
|
||||
if (historyIdxRef.current <= 0) return;
|
||||
const idx = historyIdxRef.current - 1;
|
||||
historyIdxRef.current = idx;
|
||||
setHistoryIdx(idx);
|
||||
const clips = (history[idx] || []).map(c => ({ ...c, _id: _uid() }));
|
||||
const clips = (historyRef.current[idx] || []).map(c => ({ ...c, _id: _uid() }));
|
||||
setCurrentSeq(prev => prev ? { ...prev, clips } : prev);
|
||||
renderTimelineClips(clips);
|
||||
markDirty();
|
||||
}
|
||||
|
||||
function redo() {
|
||||
if (historyIdx >= history.length - 1) return;
|
||||
const idx = historyIdx + 1;
|
||||
if (historyIdxRef.current >= historyRef.current.length - 1) return;
|
||||
const idx = historyIdxRef.current + 1;
|
||||
historyIdxRef.current = idx;
|
||||
setHistoryIdx(idx);
|
||||
const clips = (history[idx] || []).map(c => ({ ...c, _id: _uid() }));
|
||||
const clips = (historyRef.current[idx] || []).map(c => ({ ...c, _id: _uid() }));
|
||||
setCurrentSeq(prev => prev ? { ...prev, clips } : prev);
|
||||
renderTimelineClips(clips);
|
||||
markDirty();
|
||||
|
|
@ -356,7 +365,7 @@ function Editor() {
|
|||
}} />
|
||||
<span style={{ fontSize: 9, color: 'var(--text-tertiary)', fontFamily: 'monospace', width: 28 }}>{scale}px</span>
|
||||
</div>
|
||||
<div ref={tlRef} className="timeline-container" style={{ flex: 1, overflow: 'hidden' }} />
|
||||
<div ref={tlRef} className="timeline-container" style={{ flex: 1, minHeight: 0 }} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue