fix: git commit node modules
This commit is contained in:
@@ -191,29 +191,23 @@ const WaveformLane = ({
|
||||
onSplitTrackAtTime,
|
||||
onEditClipInSubTab,
|
||||
snapValue,
|
||||
bpm
|
||||
bpm,
|
||||
scrollLeft
|
||||
}) => {
|
||||
const canvasRef = useRef(null);
|
||||
const drawWidth = Math.min(timelineWidth, viewportWidth);
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
const wrapper = canvas.parentElement ? canvas.parentElement.parentElement : null;
|
||||
|
||||
// Viewport Virtualization: canvas pixel width is strictly capped to visible window width (e.g. 1200px)
|
||||
const scrollLeft = wrapper ? wrapper.scrollLeft : 0;
|
||||
const vWidth = viewportWidth || (wrapper ? wrapper.clientWidth : 1200);
|
||||
const drawWidth = Math.min(timelineWidth, Math.max(vWidth, 1200));
|
||||
const scrollLeftVal = scrollLeft || 0;
|
||||
const vWidth = viewportWidth || 1200;
|
||||
const height = canvas.parentElement ? canvas.parentElement.clientHeight : 96;
|
||||
canvas.width = Math.min(Math.round(drawWidth * dpr), 32768);
|
||||
canvas.height = Math.min(Math.round(height * dpr), 32768);
|
||||
ctx.scale(dpr, dpr);
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
|
||||
// Position canvas element at current scrollLeft inside track container
|
||||
canvas.style.position = 'absolute';
|
||||
canvas.style.left = `${scrollLeft}px`;
|
||||
canvas.style.width = `${drawWidth}px`;
|
||||
canvas.style.height = `${height}px`;
|
||||
ctx.fillStyle = isSelected ? '#2a2a2a' : track.id % 2 === 0 ? '#181818' : '#1d1d1d';
|
||||
@@ -222,8 +216,8 @@ const WaveformLane = ({
|
||||
// Grid lines based on Snap value
|
||||
ctx.strokeStyle = 'rgba(255, 255, 255, 0.03)';
|
||||
ctx.lineWidth = 1;
|
||||
const tStart = scrollLeft / zoom;
|
||||
const tEnd = (scrollLeft + drawWidth) / zoom;
|
||||
const tStart = scrollLeftVal / zoom;
|
||||
const tEnd = (scrollLeftVal + drawWidth) / zoom;
|
||||
let gridSpacing = 1.0;
|
||||
if (snapValue && snapValue !== 'free') {
|
||||
const beatDuration = 60 / parseFloat(bpm || 120);
|
||||
@@ -456,19 +450,18 @@ const WaveformLane = ({
|
||||
ctx.lineWidth = 1;
|
||||
ctx.strokeRect(hlLeftLocal, 0, hlWidth, height);
|
||||
}
|
||||
}, [track, zoom, timelineWidth, viewportWidth, isSelected, markers, selectionMode, localSelectionTrackId, localSelLeft, localSelRight, snapValue, bpm]);
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
}, [track, zoom, timelineWidth, viewportWidth, isSelected, markers, selectionMode, localSelectionTrackId, localSelLeft, localSelRight, snapValue, bpm, scrollLeft]);
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
||||
key: "virtual-spacer",
|
||||
style: {
|
||||
width: `${timelineWidth}px`,
|
||||
height: '100%',
|
||||
position: 'relative',
|
||||
overflow: 'hidden'
|
||||
height: '1px',
|
||||
pointerEvents: 'none'
|
||||
}
|
||||
}, /*#__PURE__*/React.createElement("canvas", {
|
||||
}), /*#__PURE__*/React.createElement("canvas", {
|
||||
ref: canvasRef,
|
||||
style: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
position: 'sticky',
|
||||
left: 0,
|
||||
imageRendering: 'pixelated'
|
||||
},
|
||||
@@ -476,9 +469,7 @@ const WaveformLane = ({
|
||||
onMouseMove: e => {
|
||||
if (!canvasRef.current) return;
|
||||
const rect = canvasRef.current.getBoundingClientRect();
|
||||
const wrapper = canvasRef.current?.parentElement?.parentElement;
|
||||
const scrollLeft = wrapper ? wrapper.scrollLeft : 0;
|
||||
const x = e.clientX - rect.left + scrollLeft;
|
||||
const x = e.clientX - rect.left + (scrollLeft || 0);
|
||||
const time = x / zoom;
|
||||
const clips = track.clips && track.clips.length > 0 ? track.clips : track.buffer ? [{
|
||||
id: 'default',
|
||||
@@ -547,9 +538,7 @@ const WaveformLane = ({
|
||||
// Ignore right-click for local selection drag (context menu handles it)
|
||||
if (e.button === 2) return;
|
||||
const rect = canvasRef.current.getBoundingClientRect();
|
||||
const wrapper = canvasRef.current?.parentElement?.parentElement;
|
||||
const scrollLeft = wrapper ? wrapper.scrollLeft : 0;
|
||||
const x = e.clientX - rect.left + scrollLeft;
|
||||
const x = e.clientX - rect.left + (scrollLeft || 0);
|
||||
const time = Math.max(0, x / zoom);
|
||||
onSelectTrack(track.id);
|
||||
const clips = track.clips && track.clips.length > 0 ? track.clips : track.buffer ? [{
|
||||
@@ -686,9 +675,7 @@ const WaveformLane = ({
|
||||
},
|
||||
onDoubleClick: e => {
|
||||
const rect = canvasRef.current.getBoundingClientRect();
|
||||
const wrapper = canvasRef.current?.parentElement?.parentElement;
|
||||
const scrollLeft = wrapper ? wrapper.scrollLeft : 0;
|
||||
const x = e.clientX - rect.left + scrollLeft;
|
||||
const x = e.clientX - rect.left + (scrollLeft || 0);
|
||||
const time = Math.max(0, x / zoom);
|
||||
const clips = track.clips && track.clips.length > 0 ? track.clips : track.buffer ? [{
|
||||
id: 'default',
|
||||
@@ -711,13 +698,11 @@ const WaveformLane = ({
|
||||
e.stopPropagation();
|
||||
onSelectTrack(track.id);
|
||||
const rect = canvasRef.current.getBoundingClientRect();
|
||||
const wrapper = canvasRef.current?.parentElement?.parentElement;
|
||||
const scrollLeft = wrapper ? wrapper.scrollLeft : 0;
|
||||
const x = e.clientX - rect.left + scrollLeft;
|
||||
const x = e.clientX - rect.left + (scrollLeft || 0);
|
||||
const time = Math.max(0, x / zoom);
|
||||
if (onContextMenu) onContextMenu(e, track.id, time);
|
||||
}
|
||||
}));
|
||||
})));
|
||||
};
|
||||
const TempoTrackLane = ({
|
||||
bpm,
|
||||
@@ -726,33 +711,30 @@ const TempoTrackLane = ({
|
||||
viewportWidth,
|
||||
onPlayheadSet,
|
||||
snapValue,
|
||||
onRulerMouseDown
|
||||
onRulerMouseDown,
|
||||
scrollLeft
|
||||
}) => {
|
||||
const canvasRef = useRef(null);
|
||||
const drawWidth = Math.min(timelineWidth, viewportWidth);
|
||||
useEffect(() => {
|
||||
const canvas = canvasRef.current;
|
||||
if (!canvas) return;
|
||||
const ctx = canvas.getContext('2d');
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
const wrapper = canvas.parentElement ? canvas.parentElement.parentElement : null;
|
||||
const scrollLeft = wrapper ? wrapper.scrollLeft : 0;
|
||||
const vWidth = viewportWidth || (wrapper ? wrapper.clientWidth : 1200);
|
||||
const drawWidth = Math.min(timelineWidth, Math.max(vWidth, 1200));
|
||||
const scrollLeftVal = scrollLeft || 0;
|
||||
const height = canvas.parentElement ? canvas.parentElement.clientHeight : 40;
|
||||
canvas.width = Math.min(Math.round(drawWidth * dpr), 32768);
|
||||
canvas.height = Math.min(Math.round(height * dpr), 32768);
|
||||
ctx.scale(dpr, dpr);
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
canvas.style.position = 'absolute';
|
||||
canvas.style.left = `${scrollLeft}px`;
|
||||
canvas.style.width = `${drawWidth}px`;
|
||||
canvas.style.height = `${height}px`;
|
||||
ctx.fillStyle = '#1a1a2e';
|
||||
ctx.fillRect(0, 0, drawWidth, height);
|
||||
const beatDuration = 60 / bpm;
|
||||
const barDuration = beatDuration * 4;
|
||||
const tStart = scrollLeft / zoom;
|
||||
const tEnd = (scrollLeft + drawWidth) / zoom;
|
||||
const tStart = scrollLeftVal / zoom;
|
||||
const tEnd = (scrollLeftVal + drawWidth) / zoom;
|
||||
const firstBeat = Math.floor(tStart / beatDuration) * beatDuration;
|
||||
for (let t = firstBeat; t <= tEnd; t += beatDuration) {
|
||||
const beatNum = Math.floor(t / beatDuration) + 1;
|
||||
@@ -804,28 +786,25 @@ const TempoTrackLane = ({
|
||||
ctx.font = 'bold 10px Inter, sans-serif';
|
||||
ctx.textAlign = 'right';
|
||||
ctx.fillText(`${bpm} BPM`, drawWidth - 6, 12);
|
||||
}, [bpm, zoom, timelineWidth, viewportWidth, snapValue]);
|
||||
return /*#__PURE__*/React.createElement("div", {
|
||||
}, [bpm, zoom, timelineWidth, viewportWidth, snapValue, scrollLeft]);
|
||||
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
|
||||
key: "virtual-spacer-tempo",
|
||||
style: {
|
||||
width: `${timelineWidth}px`,
|
||||
height: '100%',
|
||||
position: 'relative',
|
||||
overflow: 'hidden'
|
||||
height: '1px',
|
||||
pointerEvents: 'none'
|
||||
}
|
||||
}, /*#__PURE__*/React.createElement("canvas", {
|
||||
}), /*#__PURE__*/React.createElement("canvas", {
|
||||
ref: canvasRef,
|
||||
style: {
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
position: 'sticky',
|
||||
left: 0,
|
||||
imageRendering: 'pixelated'
|
||||
},
|
||||
className: "cursor-crosshair",
|
||||
onMouseDown: e => {
|
||||
const wrapper = canvasRef.current?.parentElement?.parentElement;
|
||||
const scrollLeft = wrapper ? wrapper.scrollLeft : 0;
|
||||
const rect = canvasRef.current.getBoundingClientRect();
|
||||
const x = e.clientX - rect.left + scrollLeft;
|
||||
const x = e.clientX - rect.left + (scrollLeft || 0);
|
||||
const time = Math.max(0, x / zoom);
|
||||
if (e.shiftKey) {
|
||||
e.preventDefault();
|
||||
@@ -837,7 +816,7 @@ const TempoTrackLane = ({
|
||||
onPlayheadSet(time, e.shiftKey);
|
||||
}
|
||||
}
|
||||
}));
|
||||
})));
|
||||
};
|
||||
|
||||
// ── Sub-Tab Waveform Component (LOOP_EDITOR_2.md §1.2 & SUB_EDITOR.md) ──
|
||||
@@ -892,8 +871,8 @@ const SubTabWaveform = ({
|
||||
const vWidth = wrapper ? wrapper.clientWidth : 1200;
|
||||
const drawWidth = Math.min(timelineWidth, Math.max(vWidth, 1200));
|
||||
const h = canvas.parentElement ? canvas.parentElement.clientHeight : 200;
|
||||
canvas.width = Math.min(Math.round(drawWidth * dpr), 32768);
|
||||
canvas.height = Math.min(Math.round(h * dpr), 32768);
|
||||
canvas.width = Math.round(drawWidth * dpr);
|
||||
canvas.height = Math.round(h * dpr);
|
||||
ctx.scale(dpr, dpr);
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
canvas.style.position = 'absolute';
|
||||
@@ -2178,8 +2157,8 @@ const GraphEditorCanvas = ({
|
||||
const vWidth = wrapper ? wrapper.clientWidth : 1200;
|
||||
const drawWidth = Math.min(timelineWidth, Math.max(vWidth, 1200));
|
||||
const h = canvas.parentElement ? canvas.parentElement.clientHeight : 200;
|
||||
canvas.width = Math.min(Math.round(drawWidth * dpr), 32768);
|
||||
canvas.height = Math.min(Math.round(h * dpr), 32768);
|
||||
canvas.width = Math.round(drawWidth * dpr);
|
||||
canvas.height = Math.round(h * dpr);
|
||||
ctx.scale(dpr, dpr);
|
||||
ctx.imageSmoothingEnabled = false;
|
||||
canvas.style.position = 'absolute';
|
||||
@@ -2985,9 +2964,7 @@ const App = () => {
|
||||
const [localSelectionTrackId, setLocalSelectionTrackId] = useState(null);
|
||||
const [localSelectionStart, setLocalSelectionStart] = useState(null);
|
||||
const [localSelectionEnd, setLocalSelectionEnd] = useState(null);
|
||||
const [mainZoom, setMainZoom] = useState(100);
|
||||
const [subTabZoom, setSubTabZoom] = useState(100);
|
||||
let zoom = 100;
|
||||
const [zoom, setZoom] = useState(100);
|
||||
const [isLoopingSelection, setIsLoopingSelection] = useState(false);
|
||||
const [beginBar, setBeginBar] = useState(1);
|
||||
const [endBar, setEndBar] = useState(1);
|
||||
@@ -3105,7 +3082,6 @@ const App = () => {
|
||||
|
||||
// ── Tab System (LOOP_EDITOR_2.md §1) ──
|
||||
const [activeTab, setActiveTab] = useState('main');
|
||||
zoom = activeTab === 'main' ? mainZoom : subTabZoom;
|
||||
const [subTabSelectedNodeTime, setSubTabSelectedNodeTime] = useState(null);
|
||||
const [subTabNormVal, setSubTabNormVal] = useState(0);
|
||||
const [subTabGainVal, setSubTabGainVal] = useState(100);
|
||||
@@ -3266,10 +3242,12 @@ const App = () => {
|
||||
}, [activeTool, activeTab]);
|
||||
const timelineWrapperRef = useRef(null);
|
||||
const tcpContainerRef = useRef(null);
|
||||
const [scrollLeft, setScrollLeft] = useState(0);
|
||||
const handleTimelineScroll = e => {
|
||||
if (tcpContainerRef.current) {
|
||||
tcpContainerRef.current.scrollTop = e.currentTarget.scrollTop;
|
||||
}
|
||||
setScrollLeft(e.currentTarget.scrollLeft);
|
||||
};
|
||||
const handleTCPScroll = e => {
|
||||
if (timelineWrapperRef.current) {
|
||||
@@ -3821,8 +3799,8 @@ const App = () => {
|
||||
const ctx = canvas.getContext('2d');
|
||||
const dpr = window.devicePixelRatio || 1;
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
canvas.width = Math.min(Math.round(rect.width * dpr), 32768);
|
||||
canvas.height = Math.min(Math.round(rect.height * dpr), 32768);
|
||||
canvas.width = rect.width * dpr;
|
||||
canvas.height = rect.height * dpr;
|
||||
ctx.scale(dpr, dpr);
|
||||
const w = rect.width;
|
||||
const h = rect.height;
|
||||
@@ -4820,7 +4798,7 @@ const App = () => {
|
||||
}, [zoom, maxDuration, viewportWidth]);
|
||||
useEffect(() => {
|
||||
if (zoom < minZoom) {
|
||||
if (activeTab === 'main') setMainZoom(minZoom); else setSubTabZoom(minZoom);
|
||||
setZoom(minZoom);
|
||||
}
|
||||
}, [minZoom]);
|
||||
const playheadLeftPos = useMemo(() => currentTime * zoom, [currentTime, zoom]);
|
||||
@@ -4908,7 +4886,7 @@ const App = () => {
|
||||
const mouseXInCanvas = mouseXInViewport + timeline.scrollLeft;
|
||||
const anchorTime = mouseXInCanvas / zoom;
|
||||
const zoomFactor = e.deltaY > 0 ? 0.9 : 1.1;
|
||||
const updateZoom = prevZoom => {
|
||||
setZoom(prevZoom => {
|
||||
let newZoom = prevZoom * zoomFactor;
|
||||
if (newZoom < minZoom) newZoom = minZoom;
|
||||
if (newZoom > 50000) newZoom = 50000;
|
||||
@@ -4917,8 +4895,7 @@ const App = () => {
|
||||
timeline.scrollLeft = newMouseXInCanvas - mouseXInViewport;
|
||||
});
|
||||
return newZoom;
|
||||
};
|
||||
if (activeTab === 'main') setMainZoom(updateZoom(mainZoom)); else setSubTabZoom(updateZoom(subTabZoom));
|
||||
});
|
||||
} else if (e.shiftKey) {
|
||||
e.preventDefault();
|
||||
timeline.scrollLeft += e.deltaY;
|
||||
|
||||
Reference in New Issue
Block a user