editando patterns na playlist
Deploy / Deploy (push) Successful in 1m55s
Details
Deploy / Deploy (push) Successful in 1m55s
Details
This commit is contained in:
parent
6bb8cb8dad
commit
f7c81dd1de
|
|
@ -188,10 +188,6 @@ export function renderAudioEditor() {
|
|||
|
||||
if (!audioEditor || !existingTrackContainer) return;
|
||||
|
||||
// ✅ Salva o scroll atual (senão toda edição “pula” pro início)
|
||||
const prevScrollLeft = existingTrackContainer.scrollLeft || 0;
|
||||
const prevScrollTop = existingTrackContainer.scrollTop || 0;
|
||||
|
||||
_ensureGlobalPlaylistSelectionFields();
|
||||
_installPlaylistKeybindOnce();
|
||||
|
||||
|
|
@ -808,47 +804,22 @@ export function renderAudioEditor() {
|
|||
newTrackContainer.addEventListener("mousedown", (e) => {
|
||||
document.getElementById("timeline-context-menu").style.display = "none";
|
||||
document.getElementById("ruler-context-menu").style.display = "none";
|
||||
|
||||
const clipElement = e.target.closest(".timeline-clip");
|
||||
const isBasslineClip =
|
||||
!!(clipElement && clipElement.classList.contains("bassline-clip"));
|
||||
|
||||
// ✅ limpa seleções ao clicar no vazio (sem mexer no RMB)
|
||||
|
||||
if (!clipElement && e.button !== 2) {
|
||||
if (appState.global.selectedClipId) {
|
||||
appState.global.selectedClipId = null;
|
||||
}
|
||||
if (appState.global.selectedPlaylistClipId) {
|
||||
appState.global.selectedPlaylistClipId = null;
|
||||
appState.global.selectedPlaylistPatternIndex = null;
|
||||
}
|
||||
|
||||
newTrackContainer
|
||||
.querySelectorAll(".timeline-clip.selected")
|
||||
.forEach((c) => c.classList.remove("selected"));
|
||||
}
|
||||
|
||||
const currentPixelsPerSecond = getPixelsPerSecond();
|
||||
const handle = e.target.closest(".clip-resize-handle");
|
||||
const patternHandle = e.target.closest(".pattern-resize-handle");
|
||||
|
||||
// ✅ se clicou num clip de áudio, deseleciona a pattern da playlist
|
||||
if (clipElement && !isBasslineClip && e.button === 0) {
|
||||
if (appState.global.selectedPlaylistClipId) {
|
||||
appState.global.selectedPlaylistClipId = null;
|
||||
appState.global.selectedPlaylistPatternIndex = null;
|
||||
newTrackContainer
|
||||
.querySelectorAll(".bassline-clip.selected")
|
||||
.querySelectorAll(".timeline-clip.selected")
|
||||
.forEach((c) => c.classList.remove("selected"));
|
||||
}
|
||||
}
|
||||
|
||||
// Slice Tool (áudio apenas)
|
||||
if (
|
||||
appState.global.sliceToolActive &&
|
||||
clipElement &&
|
||||
!clipElement.classList.contains("bassline-clip")
|
||||
) {
|
||||
const currentPixelsPerSecond = getPixelsPerSecond();
|
||||
const handle = e.target.closest(".clip-resize-handle");
|
||||
|
||||
// Slice Tool
|
||||
if (appState.global.sliceToolActive && clipElement && !clipElement.classList.contains("bassline-clip")) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const clipId = clipElement.dataset.clipId;
|
||||
|
|
@ -872,193 +843,14 @@ export function renderAudioEditor() {
|
|||
return;
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// ✅ BASSLINE / PATTERN CLIPS (drag horizontal + resize L/R)
|
||||
// =========================================================
|
||||
if (isBasslineClip && e.button === 0) {
|
||||
e.preventDefault();
|
||||
|
||||
_ensureGlobalPlaylistSelectionFields();
|
||||
|
||||
const patternIndex = Number(clipElement.dataset.patternIndex ?? 0);
|
||||
const plClipId = String(clipElement.dataset.plClipId || "");
|
||||
if (!plClipId) return;
|
||||
|
||||
// seleção visual/estado
|
||||
appState.global.selectedPlaylistClipId = plClipId;
|
||||
appState.global.selectedPlaylistPatternIndex = patternIndex;
|
||||
|
||||
// desmarca seleção de áudio se tiver
|
||||
if (appState.global.selectedClipId) {
|
||||
appState.global.selectedClipId = null;
|
||||
newTrackContainer
|
||||
.querySelectorAll(".timeline-clip.selected")
|
||||
.forEach((c) => c.classList.remove("selected"));
|
||||
}
|
||||
|
||||
newTrackContainer
|
||||
.querySelectorAll(".bassline-clip.selected")
|
||||
.forEach((c) => c.classList.remove("selected"));
|
||||
clipElement.classList.add("selected");
|
||||
|
||||
// (opcional) sync de seleção
|
||||
sendActionSafe({
|
||||
type: "SELECT_PLAYLIST_PATTERN_CLIP",
|
||||
patternIndex,
|
||||
clipId: plClipId,
|
||||
});
|
||||
|
||||
const model = _getPlaylistClipModel(patternIndex, plClipId);
|
||||
if (!model) return;
|
||||
|
||||
const initialMouseX = e.clientX;
|
||||
const initialScrollLeft = scrollEl.scrollLeft;
|
||||
|
||||
const initialPosTicks = Number(model.pos || 0);
|
||||
const initialLenTicks = Math.max(
|
||||
PL_MIN_LEN_TICKS,
|
||||
Number(model.len || PL_MIN_LEN_TICKS)
|
||||
);
|
||||
const initialEndTicks = initialPosTicks + initialLenTicks;
|
||||
|
||||
const previewUpdate = (posTicks, lenTicks) => {
|
||||
const leftPx = _ticksToPx(posTicks, stepWidthPx);
|
||||
const widthPx = Math.max(1, _ticksToPx(lenTicks, stepWidthPx));
|
||||
clipElement.style.left = `${leftPx}px`;
|
||||
clipElement.style.width = `${widthPx}px`;
|
||||
// mantém grid alinhado com a timeline
|
||||
clipElement.style.backgroundPosition = `-${leftPx}px 0px`;
|
||||
};
|
||||
|
||||
// ---------- RESIZE ----------
|
||||
if (patternHandle) {
|
||||
const handleType = patternHandle.classList.contains("left")
|
||||
? "left"
|
||||
: "right";
|
||||
|
||||
clipElement.classList.add("dragging");
|
||||
|
||||
const onMouseMove = (moveEvent) => {
|
||||
const deltaPx =
|
||||
(moveEvent.clientX - initialMouseX) +
|
||||
(scrollEl.scrollLeft - initialScrollLeft);
|
||||
|
||||
const deltaTicks = _pxToTicks(deltaPx, stepWidthPx);
|
||||
|
||||
let newPos = initialPosTicks;
|
||||
let newLen = initialLenTicks;
|
||||
|
||||
if (handleType === "right") {
|
||||
let newEnd = _snapTicks(initialEndTicks + deltaTicks, PL_SNAP_TICKS);
|
||||
newEnd = Math.max(initialPosTicks + PL_MIN_LEN_TICKS, newEnd);
|
||||
newLen = newEnd - initialPosTicks;
|
||||
} else {
|
||||
newPos = _snapTicks(initialPosTicks + deltaTicks, PL_SNAP_TICKS);
|
||||
newPos = Math.max(0, newPos);
|
||||
newPos = Math.min(newPos, initialEndTicks - PL_MIN_LEN_TICKS);
|
||||
newLen = initialEndTicks - newPos;
|
||||
}
|
||||
|
||||
previewUpdate(newPos, newLen);
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
clipElement.classList.remove("dragging");
|
||||
document.removeEventListener("mousemove", onMouseMove);
|
||||
document.removeEventListener("mouseup", onMouseUp);
|
||||
|
||||
// converte estado final (px -> ticks) com snap
|
||||
const finalLeftPx = clipElement.offsetLeft;
|
||||
const finalWidthPx = clipElement.offsetWidth;
|
||||
|
||||
let finalPos = _pxToTicks(finalLeftPx, stepWidthPx);
|
||||
let finalLen = _pxToTicks(finalWidthPx, stepWidthPx);
|
||||
|
||||
finalPos = _snapTicks(finalPos, PL_SNAP_TICKS);
|
||||
finalLen = _snapTicks(finalLen, PL_SNAP_TICKS);
|
||||
|
||||
finalPos = Math.max(0, finalPos);
|
||||
finalLen = Math.max(PL_MIN_LEN_TICKS, finalLen);
|
||||
|
||||
_updatePlaylistClipLocal(patternIndex, plClipId, {
|
||||
pos: finalPos,
|
||||
len: finalLen,
|
||||
});
|
||||
|
||||
sendActionSafe({
|
||||
type: "UPDATE_PLAYLIST_PATTERN_CLIP",
|
||||
patternIndex,
|
||||
clipId: plClipId,
|
||||
pos: finalPos,
|
||||
len: finalLen,
|
||||
});
|
||||
|
||||
renderAudioEditor();
|
||||
restartAudioEditorIfPlaying();
|
||||
};
|
||||
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
return;
|
||||
}
|
||||
|
||||
// ---------- DRAG (horizontal apenas) ----------
|
||||
clipElement.classList.add("dragging");
|
||||
|
||||
const onMouseMove = (moveEvent) => {
|
||||
const deltaPx =
|
||||
(moveEvent.clientX - initialMouseX) +
|
||||
(scrollEl.scrollLeft - initialScrollLeft);
|
||||
|
||||
let newPos = initialPosTicks + _pxToTicks(deltaPx, stepWidthPx);
|
||||
newPos = _snapTicks(newPos, PL_SNAP_TICKS);
|
||||
newPos = Math.max(0, newPos);
|
||||
|
||||
previewUpdate(newPos, initialLenTicks);
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
clipElement.classList.remove("dragging");
|
||||
document.removeEventListener("mousemove", onMouseMove);
|
||||
document.removeEventListener("mouseup", onMouseUp);
|
||||
|
||||
const finalLeftPx = clipElement.offsetLeft;
|
||||
let finalPos = _pxToTicks(finalLeftPx, stepWidthPx);
|
||||
finalPos = _snapTicks(finalPos, PL_SNAP_TICKS);
|
||||
finalPos = Math.max(0, finalPos);
|
||||
|
||||
_updatePlaylistClipLocal(patternIndex, plClipId, {
|
||||
pos: finalPos,
|
||||
len: initialLenTicks,
|
||||
});
|
||||
|
||||
sendActionSafe({
|
||||
type: "UPDATE_PLAYLIST_PATTERN_CLIP",
|
||||
patternIndex,
|
||||
clipId: plClipId,
|
||||
pos: finalPos,
|
||||
len: initialLenTicks,
|
||||
});
|
||||
|
||||
renderAudioEditor();
|
||||
restartAudioEditorIfPlaying();
|
||||
};
|
||||
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
return;
|
||||
}
|
||||
|
||||
// =========================================================
|
||||
// Resize Handle (ÁUDIO)
|
||||
// =========================================================
|
||||
// Resize Handle
|
||||
if (handle) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
const clipId = clipElement.dataset.clipId;
|
||||
const clip = appState.audio.clips.find((c) => c.id == clipId);
|
||||
if (!clip || !clip.buffer) return;
|
||||
|
||||
|
||||
const handleType = handle.classList.contains("left") ? "left" : "right";
|
||||
const initialMouseX = e.clientX;
|
||||
const secondsPerStep = getSecondsPerStep();
|
||||
|
|
@ -1067,10 +859,9 @@ export function renderAudioEditor() {
|
|||
const initialStartTime = clip.startTimeInSeconds;
|
||||
const initialDuration = clip.durationInSeconds;
|
||||
const initialOffset = clip.offset || 0;
|
||||
const initialOriginalDuration =
|
||||
clip.originalDuration || clip.buffer.duration;
|
||||
const initialOriginalDuration = clip.originalDuration || clip.buffer.duration;
|
||||
const bufferStartTime = initialStartTime - initialOffset;
|
||||
|
||||
|
||||
const onMouseMove = (moveEvent) => {
|
||||
const deltaX = moveEvent.clientX - initialMouseX;
|
||||
if (appState.global.resizeMode === "trim") {
|
||||
|
|
@ -1081,125 +872,71 @@ export function renderAudioEditor() {
|
|||
newEndTime = Math.max(initialStartTime + secondsPerStep, newEndTime);
|
||||
const maxEndTime = bufferStartTime + initialOriginalDuration;
|
||||
newEndTime = Math.min(newEndTime, maxEndTime);
|
||||
clipElement.style.width = `${
|
||||
(newEndTime - initialStartTime) * currentPixelsPerSecond
|
||||
}px`;
|
||||
clipElement.style.width = `${(newEndTime - initialStartTime) * currentPixelsPerSecond}px`;
|
||||
} else if (handleType === "left") {
|
||||
let newLeftPx = initialLeftPx + deltaX;
|
||||
let newStartTime = newLeftPx / currentPixelsPerSecond;
|
||||
newStartTime = quantizeTime(newStartTime);
|
||||
const minStartTime =
|
||||
initialStartTime + initialDuration - secondsPerStep;
|
||||
const minStartTime = initialStartTime + initialDuration - secondsPerStep;
|
||||
newStartTime = Math.min(newStartTime, minStartTime);
|
||||
newStartTime = Math.max(bufferStartTime, newStartTime);
|
||||
const newLeftFinalPx = newStartTime * currentPixelsPerSecond;
|
||||
const newWidthFinalPx =
|
||||
(initialStartTime + initialDuration - newStartTime) *
|
||||
currentPixelsPerSecond;
|
||||
const newWidthFinalPx = (initialStartTime + initialDuration - newStartTime) * currentPixelsPerSecond;
|
||||
clipElement.style.left = `${newLeftFinalPx}px`;
|
||||
clipElement.style.width = `${newWidthFinalPx}px`;
|
||||
}
|
||||
} else if (appState.global.resizeMode === "stretch") {
|
||||
if (handleType === "right") {
|
||||
let newWidthPx = initialWidthPx + deltaX;
|
||||
let newDuration = newWidthPx / currentPixelsPerSecond;
|
||||
let newEndTime = quantizeTime(initialStartTime + newDuration);
|
||||
newEndTime = Math.max(initialStartTime + secondsPerStep, newEndTime);
|
||||
clipElement.style.width = `${
|
||||
(newEndTime - initialStartTime) * currentPixelsPerSecond
|
||||
}px`;
|
||||
} else if (handleType === "left") {
|
||||
let newLeftPx = initialLeftPx + deltaX;
|
||||
let newStartTime = newLeftPx / currentPixelsPerSecond;
|
||||
newStartTime = quantizeTime(newStartTime);
|
||||
const minStartTime =
|
||||
initialStartTime + initialDuration - secondsPerStep;
|
||||
newStartTime = Math.min(newStartTime, minStartTime);
|
||||
const newLeftFinalPx = newStartTime * currentPixelsPerSecond;
|
||||
const newWidthFinalPx =
|
||||
(initialStartTime + initialDuration - newStartTime) *
|
||||
currentPixelsPerSecond;
|
||||
clipElement.style.left = `${newLeftFinalPx}px`;
|
||||
clipElement.style.width = `${newWidthFinalPx}px`;
|
||||
}
|
||||
if (handleType === "right") {
|
||||
let newWidthPx = initialWidthPx + deltaX;
|
||||
let newDuration = newWidthPx / currentPixelsPerSecond;
|
||||
let newEndTime = quantizeTime(initialStartTime + newDuration);
|
||||
newEndTime = Math.max(initialStartTime + secondsPerStep, newEndTime);
|
||||
clipElement.style.width = `${(newEndTime - initialStartTime) * currentPixelsPerSecond}px`;
|
||||
} else if (handleType === "left") {
|
||||
let newLeftPx = initialLeftPx + deltaX;
|
||||
let newStartTime = newLeftPx / currentPixelsPerSecond;
|
||||
newStartTime = quantizeTime(newStartTime);
|
||||
const minStartTime = initialStartTime + initialDuration - secondsPerStep;
|
||||
newStartTime = Math.min(newStartTime, minStartTime);
|
||||
const newLeftFinalPx = newStartTime * currentPixelsPerSecond;
|
||||
const newWidthFinalPx = (initialStartTime + initialDuration - newStartTime) * currentPixelsPerSecond;
|
||||
clipElement.style.left = `${newLeftFinalPx}px`;
|
||||
clipElement.style.width = `${newWidthFinalPx}px`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const onMouseUp = () => {
|
||||
const onMouseUp = (upEvent) => {
|
||||
document.removeEventListener("mousemove", onMouseMove);
|
||||
document.removeEventListener("mouseup", onMouseUp);
|
||||
const finalLeftPx = clipElement.offsetLeft;
|
||||
const finalWidthPx = clipElement.offsetWidth;
|
||||
const newStartTime = finalLeftPx / currentPixelsPerSecond;
|
||||
const newDuration = finalWidthPx / currentPixelsPerSecond;
|
||||
|
||||
|
||||
if (appState.global.resizeMode === "trim") {
|
||||
const newOffset = newStartTime - bufferStartTime;
|
||||
if (handleType === "right") {
|
||||
updateAudioClipProperties(clipId, {
|
||||
durationInSeconds: newDuration,
|
||||
pitch: 0,
|
||||
});
|
||||
sendActionSafe({
|
||||
type: "UPDATE_AUDIO_CLIP",
|
||||
clipId,
|
||||
props: { durationInSeconds: newDuration, pitch: 0 },
|
||||
});
|
||||
} else {
|
||||
updateAudioClipProperties(clipId, {
|
||||
startTimeInSeconds: newStartTime,
|
||||
durationInSeconds: newDuration,
|
||||
offset: newOffset,
|
||||
pitch: 0,
|
||||
});
|
||||
sendActionSafe({
|
||||
type: "UPDATE_AUDIO_CLIP",
|
||||
clipId,
|
||||
props: {
|
||||
startTimeInSeconds: newStartTime,
|
||||
durationInSeconds: newDuration,
|
||||
offset: newOffset,
|
||||
pitch: 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
const newOffset = newStartTime - bufferStartTime;
|
||||
if(handleType === "right") {
|
||||
updateAudioClipProperties(clipId, { durationInSeconds: newDuration, pitch: 0 });
|
||||
sendActionSafe({ type: "UPDATE_AUDIO_CLIP", clipId, props: { durationInSeconds: newDuration, pitch: 0 } });
|
||||
} else {
|
||||
updateAudioClipProperties(clipId, { startTimeInSeconds: newStartTime, durationInSeconds: newDuration, offset: newOffset, pitch: 0 });
|
||||
sendActionSafe({ type: "UPDATE_AUDIO_CLIP", clipId, props: { startTimeInSeconds: newStartTime, durationInSeconds: newDuration, offset: newOffset, pitch: 0 } });
|
||||
}
|
||||
} else {
|
||||
const newPlaybackRate = initialOriginalDuration / newDuration;
|
||||
const newPitch = 12 * Math.log2(newPlaybackRate);
|
||||
if (handleType === "right") {
|
||||
updateAudioClipProperties(clipId, {
|
||||
durationInSeconds: newDuration,
|
||||
pitch: newPitch,
|
||||
offset: 0,
|
||||
});
|
||||
sendActionSafe({
|
||||
type: "UPDATE_AUDIO_CLIP",
|
||||
clipId,
|
||||
props: { durationInSeconds: newDuration, pitch: newPitch, offset: 0 },
|
||||
});
|
||||
} else {
|
||||
updateAudioClipProperties(clipId, {
|
||||
startTimeInSeconds: newStartTime,
|
||||
durationInSeconds: newDuration,
|
||||
pitch: newPitch,
|
||||
offset: 0,
|
||||
});
|
||||
sendActionSafe({
|
||||
type: "UPDATE_AUDIO_CLIP",
|
||||
clipId,
|
||||
props: {
|
||||
startTimeInSeconds: newStartTime,
|
||||
durationInSeconds: newDuration,
|
||||
pitch: newPitch,
|
||||
offset: 0,
|
||||
},
|
||||
});
|
||||
}
|
||||
const newPlaybackRate = initialOriginalDuration / newDuration;
|
||||
const newPitch = 12 * Math.log2(newPlaybackRate);
|
||||
if(handleType === "right") {
|
||||
updateAudioClipProperties(clipId, { durationInSeconds: newDuration, pitch: newPitch, offset: 0 });
|
||||
sendActionSafe({ type: "UPDATE_AUDIO_CLIP", clipId, props: { durationInSeconds: newDuration, pitch: newPitch, offset: 0 } });
|
||||
} else {
|
||||
updateAudioClipProperties(clipId, { startTimeInSeconds: newStartTime, durationInSeconds: newDuration, pitch: newPitch, offset: 0 });
|
||||
sendActionSafe({ type: "UPDATE_AUDIO_CLIP", clipId, props: { startTimeInSeconds: newStartTime, durationInSeconds: newDuration, pitch: newPitch, offset: 0 } });
|
||||
}
|
||||
}
|
||||
restartAudioEditorIfPlaying();
|
||||
renderAudioEditor();
|
||||
};
|
||||
|
||||
document.addEventListener("mousemove", onMouseMove);
|
||||
document.addEventListener("mouseup", onMouseUp);
|
||||
return;
|
||||
|
|
@ -1209,9 +946,8 @@ export function renderAudioEditor() {
|
|||
if (clipElement && !clipElement.classList.contains("bassline-clip")) {
|
||||
const clipId = clipElement.dataset.clipId;
|
||||
|
||||
const clipModel = appState.audio.clips.find(
|
||||
(c) => String(c.id) === String(clipId)
|
||||
);
|
||||
// 🔑 pega o clip no estado pra ter o tempo inicial real
|
||||
const clipModel = appState.audio.clips.find(c => String(c.id) === String(clipId));
|
||||
const initialStartTime = Number(clipModel?.startTimeInSeconds || 0);
|
||||
|
||||
e.preventDefault();
|
||||
|
|
@ -1225,13 +961,8 @@ export function renderAudioEditor() {
|
|||
const deltaX = moveEvent.clientX - initialMouseX;
|
||||
clipElement.style.transform = `translateX(${deltaX}px)`;
|
||||
|
||||
const overElement = document.elementFromPoint(
|
||||
moveEvent.clientX,
|
||||
moveEvent.clientY
|
||||
);
|
||||
const overLane = overElement
|
||||
? overElement.closest(".audio-track-lane")
|
||||
: null;
|
||||
const overElement = document.elementFromPoint(moveEvent.clientX, moveEvent.clientY);
|
||||
const overLane = overElement ? overElement.closest(".audio-track-lane") : null;
|
||||
if (overLane && overLane !== lastOverLane) {
|
||||
if (lastOverLane) lastOverLane.classList.remove("drag-over");
|
||||
overLane.classList.add("drag-over");
|
||||
|
|
@ -1251,24 +982,15 @@ export function renderAudioEditor() {
|
|||
|
||||
const newTrackId = finalLane.dataset.trackId;
|
||||
|
||||
const deltaX =
|
||||
(upEvent.clientX - initialMouseX) +
|
||||
(scrollEl.scrollLeft - initialScrollLeft);
|
||||
// ✅ delta do mouse + delta de scroll durante o drag (se houver)
|
||||
const deltaX = (upEvent.clientX - initialMouseX) + (scrollEl.scrollLeft - initialScrollLeft);
|
||||
|
||||
let newStartTime =
|
||||
initialStartTime + deltaX / currentPixelsPerSecond;
|
||||
let newStartTime = initialStartTime + (deltaX / currentPixelsPerSecond);
|
||||
newStartTime = Math.max(0, newStartTime);
|
||||
newStartTime = quantizeTime(newStartTime);
|
||||
|
||||
updateAudioClipProperties(clipId, {
|
||||
trackId: newTrackId,
|
||||
startTimeInSeconds: newStartTime,
|
||||
});
|
||||
sendActionSafe({
|
||||
type: "UPDATE_AUDIO_CLIP",
|
||||
clipId,
|
||||
props: { trackId: newTrackId, startTimeInSeconds: newStartTime },
|
||||
});
|
||||
updateAudioClipProperties(clipId, { trackId: newTrackId, startTimeInSeconds: newStartTime });
|
||||
sendActionSafe({ type: "UPDATE_AUDIO_CLIP", clipId, props: { trackId: newTrackId, startTimeInSeconds: newStartTime } });
|
||||
renderAudioEditor();
|
||||
};
|
||||
|
||||
|
|
@ -1277,6 +999,7 @@ export function renderAudioEditor() {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
// Seek na Pista
|
||||
const timelineContainer = e.target.closest(".timeline-container");
|
||||
if (timelineContainer) {
|
||||
|
|
@ -1289,7 +1012,7 @@ export function renderAudioEditor() {
|
|||
const newTime = absoluteX / currentPixelsPerSecond;
|
||||
sendAction({ type: "SET_SEEK_TIME", seekTime: newTime });
|
||||
};
|
||||
handleSeek(e);
|
||||
handleSeek(e);
|
||||
const onMouseMoveSeek = (moveEvent) => handleSeek(moveEvent);
|
||||
const onMouseUpSeek = () => {
|
||||
document.removeEventListener("mousemove", onMouseMoveSeek);
|
||||
|
|
@ -1374,22 +1097,8 @@ export function renderAudioEditor() {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
// ✅ Restaura o scroll anterior após reconstruir o container
|
||||
// (evita “voltar pro início” depois de mover/redimensionar/deletar)
|
||||
try {
|
||||
newTrackContainer.scrollLeft = prevScrollLeft;
|
||||
newTrackContainer.scrollTop = prevScrollTop;
|
||||
|
||||
// mantém régua alinhada (caso ela suporte scrollLeft)
|
||||
const mainRuler = tracksParent.querySelector(".timeline-ruler");
|
||||
if (mainRuler) mainRuler.scrollLeft = prevScrollLeft;
|
||||
} catch (err) {
|
||||
// silencioso: não pode quebrar a DAW
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
export function updateAudioEditorUI() {
|
||||
const playBtn = document.getElementById("audio-editor-play-btn");
|
||||
if (!playBtn) return;
|
||||
|
|
|
|||
Loading…
Reference in New Issue