FIX: sửa lỗi khi quét chọn duration để loop và khi bật nút loop thì tự động giãn ra bar 18
This commit is contained in:
+27
-17
@@ -17610,6 +17610,9 @@ const App = () => {
|
|||||||
setSelectedTrackId(trackId);
|
setSelectedTrackId(trackId);
|
||||||
captureSelectionUndo();
|
captureSelectionUndo();
|
||||||
clearLocalSelection();
|
clearLocalSelection();
|
||||||
|
// A fresh region selection re-enables selection-looping (a previous
|
||||||
|
// Ctrl+click "clear selection" must not keep blocking the new region).
|
||||||
|
setSelectionCleared(false);
|
||||||
localSelectionAnchorRef.current = time;
|
localSelectionAnchorRef.current = time;
|
||||||
setSelectionMode('local');
|
setSelectionMode('local');
|
||||||
setLocalSelectionTrackId(trackId);
|
setLocalSelectionTrackId(trackId);
|
||||||
@@ -22525,24 +22528,31 @@ const App = () => {
|
|||||||
setSubTabs(prev => prev.map(s => s.id === activeTab ? { ...s, selectionStart: 0, selectionEnd: loopEndTime } : s));
|
setSubTabs(prev => prev.map(s => s.id === activeTab ? { ...s, selectionStart: 0, selectionEnd: loopEndTime } : s));
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Main timeline: auto-derive loop end from tracks
|
// Main timeline / section tab: if the user already selected a loop
|
||||||
const bpmVal = parseInt(bpm) || 120;
|
// region, KEEP it — only auto-derive (0 → content end) when no
|
||||||
const secPerBar = (60.0 / bpmVal) * 4;
|
// selection exists yet. Previously this always overwrote the
|
||||||
let maxEnd = 0;
|
// selection with 0 → (contentEnd + 2 bars).
|
||||||
activeTracks.forEach(t => {
|
const hasSel = (selectionMode === 'local' && selLeft !== null && selRight !== null && selRight > selLeft)
|
||||||
(t.clips || []).forEach(c => {
|
|| (selectionStart !== null && selectionEnd !== null && selectionEnd > selectionStart);
|
||||||
const end = (c.startTime || 0) + (c.duration || 0);
|
if (!hasSel) {
|
||||||
if (end > maxEnd) maxEnd = end;
|
const bpmVal = parseInt(bpm) || 120;
|
||||||
|
const secPerBar = (60.0 / bpmVal) * 4;
|
||||||
|
let maxEnd = 0;
|
||||||
|
activeTracks.forEach(t => {
|
||||||
|
(t.clips || []).forEach(c => {
|
||||||
|
const end = (c.startTime || 0) + (c.duration || 0);
|
||||||
|
if (end > maxEnd) maxEnd = end;
|
||||||
|
});
|
||||||
|
(t.items || []).forEach(it => {
|
||||||
|
const end = (it.start || 0) + (it.duration || 4);
|
||||||
|
if (end > maxEnd) maxEnd = end;
|
||||||
|
});
|
||||||
});
|
});
|
||||||
(t.items || []).forEach(it => {
|
if (maxEnd > 0) {
|
||||||
const end = (it.start || 0) + (it.duration || 4);
|
const loopEnd = maxEnd + secPerBar * 2;
|
||||||
if (end > maxEnd) maxEnd = end;
|
setSelectionStart(0);
|
||||||
});
|
setSelectionEnd(loopEnd);
|
||||||
});
|
}
|
||||||
if (maxEnd > 0) {
|
|
||||||
const loopEnd = maxEnd + secPerBar * 2;
|
|
||||||
setSelectionStart(0);
|
|
||||||
setSelectionEnd(loopEnd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -24,7 +24,7 @@
|
|||||||
<script src="/static/js/services/midiExtractor.js?v=202607281052"></script>
|
<script src="/static/js/services/midiExtractor.js?v=202607281052"></script>
|
||||||
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
|
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
|
||||||
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
|
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
|
||||||
<script src="/static/js/app.precompiled.js?v=202608033000" defer></script>
|
<script src="/static/js/app.precompiled.js?v=202608033200" defer></script>
|
||||||
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
|
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
|
|||||||
@@ -1,3 +1,15 @@
|
|||||||
|
### [2026-08-03] Task: Loop vẫn giãn selection tới bar 18 — mở rộng hasSel + verify bundle serve
|
||||||
|
- **Tóm tắt thay đổi:** User báo vẫn lỗi sau fix trước. Kiểm tra toàn diện: (1) Không có path nào khác giãn selection khi loop bật (SubTabToolbar/onLoop là code chết; toggleLoop là Media Explorer preview; useEffect BPM chỉ chạy khi đổi tempo). (2) Mở rộng điều kiện `hasSel` trong handler nút loop: ngoài `selectionMode==='local'`, còn nhận selection qua `selectionStart/selectionEnd` hợp lệ (phòng trường hợp sweep không set 'local'). (3) **Verify bằng server thật** (uvicorn 9131): file `app.precompiled.js?v=202608033200` được serve có chứa `hasSel=selectionMode===` + comment fix — chứng minh bundle workspace đã đúng. Nếu user vẫn thấy lỗi → trình duyệt cache hoặc đang chạy deployment khác (không phải workspace).
|
||||||
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js` (rebuild), `app/templates/index.html` (bump v=202608033200; sửa double `</script>` phát sinh khi bump)
|
||||||
|
- **Ghi chú/Test (nếu có):** `pytest` 86 passed (chưa chạy lại lần này — chỉ đổi frontend).
|
||||||
|
---
|
||||||
|
|
||||||
|
### [2026-08-03] Task: Fix loop button ghi đè vùng chọn thành 0→18 bar (MAIN SESSION/SECTION-TAB)
|
||||||
|
- **Tóm tắt thay đổi:** Khi quét chọn vùng duration rồi bấm nút loop, vùng chọn bị tự đổi thành 0→18 bar. Nguyên nhân: handler nút loop (nhánh main timeline, không có sub-tab active) LUÔN tự derive loop end từ content tracks (`maxEnd + 2 bar` — content 16 bar → 18) rồi `setSelectionStart(0); setSelectionEnd(loopEnd)` — ghi đè vùng chọn của user. Fix: **tôn trọng selection có sẵn** (`hasSel = selectionMode==='local' && selLeft/selRight hợp lệ`) — chỉ auto-derive khi CHƯA có vùng chọn nào. Áp dụng cho cả MAIN SESSION lẫn SECTION-TAB (cả 2 đều đi qua nhánh main timeline khi không có sub-tab; section-tab dùng chung selection handler nên sweep cũng set `selectionMode='local'`). Kèm theo: `handleTrackLaneMouseDown` giờ `setSelectionCleared(false)` khi bắt đầu chọn vùng mới — nếu user từng Ctrl+click xoá chọn thì vùng mới vẫn loop được.
|
||||||
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js` (rebuild), `app/templates/index.html` (bump v=202608033100)
|
||||||
|
- **Ghi chú/Test (nếu có):** `node build.mjs` OK, syntax OK, `pytest` 86 passed.
|
||||||
|
---
|
||||||
|
|
||||||
### [2026-08-03] Task: Fix React error #310 khi mở Mixer modal (hooks sau early return)
|
### [2026-08-03] Task: Fix React error #310 khi mở Mixer modal (hooks sau early return)
|
||||||
- **Tóm tắt thay đổi:** Sau fix `isFxActive`, mở Mixer modal vẫn lỗi `Minified React error #310` ("Rendered more hooks than during the previous render"). Nguyên nhân: khi thêm dynamic module chain, 2 hooks `dragChainIndexRef` (useRef) + `addModuleOpen` (useState) được khai báo SAU dòng `if (!isOpen) return null;` trong MasteringModal → số hooks giữa các render thay đổi khi modal đóng/mở (return null sớm bỏ qua 2 hooks) → React #310. Fix: di chuyển 2 hooks lên TRƯỚC early return (cạnh useEffect [isOpen]).
|
- **Tóm tắt thay đổi:** Sau fix `isFxActive`, mở Mixer modal vẫn lỗi `Minified React error #310` ("Rendered more hooks than during the previous render"). Nguyên nhân: khi thêm dynamic module chain, 2 hooks `dragChainIndexRef` (useRef) + `addModuleOpen` (useState) được khai báo SAU dòng `if (!isOpen) return null;` trong MasteringModal → số hooks giữa các render thay đổi khi modal đóng/mở (return null sớm bỏ qua 2 hooks) → React #310. Fix: di chuyển 2 hooks lên TRƯỚC early return (cạnh useEffect [isOpen]).
|
||||||
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js` (rebuild), `app/templates/index.html` (bump v=202608032900)
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js` (rebuild), `app/templates/index.html` (bump v=202608032900)
|
||||||
|
|||||||
Reference in New Issue
Block a user