fix: PIANO_ROLL activeTracks resolves main tracks, not section
When PIANO_ROLL sub-tab is opened from SECTION-TAB, activeTab switches to midi_xxx, so activeTracks fell back to main project tracks. Section trackIds don't exist in main tracks -> dropdown empty, ghost layers empty, instrument data wrong. Fix: check subTabs for PIANO_ROLL type, resolve parent section tab from parent_tab_id, return its tracks.
This commit is contained in:
@@ -7315,9 +7315,15 @@ const App = () => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
const activeTracks = useMemo(() => {
|
const activeTracks = useMemo(() => {
|
||||||
const st = sessionTabs.find(s => s.id === activeTab);
|
var st = sessionTabs.find(s => s.id === activeTab);
|
||||||
return st ? st.tracks : tracks;
|
if (st) return st.tracks;
|
||||||
}, [activeTab, sessionTabs, tracks]);
|
var pr = subTabs.find(s => s.id === activeTab && s.type === 'PIANO_ROLL');
|
||||||
|
if (pr && pr.parent_tab_id && pr.parent_tab_id.startsWith('session_')) {
|
||||||
|
var parentSt = sessionTabs.find(s => s.id === pr.parent_tab_id);
|
||||||
|
if (parentSt) return parentSt.tracks;
|
||||||
|
}
|
||||||
|
return tracks;
|
||||||
|
}, [activeTab, sessionTabs, subTabs, tracks]);
|
||||||
const activeTracksRef = useRef([]);
|
const activeTracksRef = useRef([]);
|
||||||
activeTracksRef.current = activeTracks;
|
activeTracksRef.current = activeTracks;
|
||||||
const sessionTabsRef = useRef(sessionTabs);
|
const sessionTabsRef = useRef(sessionTabs);
|
||||||
|
|||||||
@@ -216,7 +216,7 @@ buffer:track.buffer,startTime:track.startTime||0,clips:track.clips?track.clips.m
|
|||||||
const[activeTab,setActiveTab]=useState('main');const[subTabSelectedNodeTime,setSubTabSelectedNodeTime]=useState(null);const[subTabNormVal,setSubTabNormVal]=useState(0);const[subTabGainVal,setSubTabGainVal]=useState(100);const[subTabPitchVal,setSubTabPitchVal]=useState(0);const[subTabs,setSubTabs]=useState([]);// [{id, label, trackId, startTime, endTime, buffer, effects, currentTime, selectionStart, selectionEnd, isPlaying}, ...]
|
const[activeTab,setActiveTab]=useState('main');const[subTabSelectedNodeTime,setSubTabSelectedNodeTime]=useState(null);const[subTabNormVal,setSubTabNormVal]=useState(0);const[subTabGainVal,setSubTabGainVal]=useState(100);const[subTabPitchVal,setSubTabPitchVal]=useState(0);const[subTabs,setSubTabs]=useState([]);// [{id, label, trackId, startTime, endTime, buffer, effects, currentTime, selectionStart, selectionEnd, isPlaying}, ...]
|
||||||
const[sessionTabs,setSessionTabs]=useState([]);// [{id, name, tracks}, ...]
|
const[sessionTabs,setSessionTabs]=useState([]);// [{id, name, tracks}, ...]
|
||||||
const[tabContextMenu,setTabContextMenu]=useState(null);// { x, y, tabId, tabType }
|
const[tabContextMenu,setTabContextMenu]=useState(null);// { x, y, tabId, tabType }
|
||||||
const handleSetTabColor=(tabId,tabType,color)=>{if(tabType==='session'){setSessionTabs(prev=>prev.map(s=>s.id===tabId?{...s,color:color}:s));const tab=sessionTabs.find(s=>s.id===tabId);if(tab){setTracks(prev=>prev.map(t=>{if(!t.sections||t.sections.length===0)return t;return{...t,sections:t.sections.map(s=>{if(s.sectionId===tab.sectionId){return{...s,color:color};}return s;})};}));}}else{setSubTabs(prev=>prev.map(s=>s.id===tabId?{...s,color:color}:s));}};const activeTracks=useMemo(()=>{const st=sessionTabs.find(s=>s.id===activeTab);return st?st.tracks:tracks;},[activeTab,sessionTabs,tracks]);const activeTracksRef=useRef([]);activeTracksRef.current=activeTracks;const sessionTabsRef=useRef(sessionTabs);sessionTabsRef.current=sessionTabs;const[selectionCleared,setSelectionCleared]=useState(false);// LOOP_EDITOR_2.md §4.2
|
const handleSetTabColor=(tabId,tabType,color)=>{if(tabType==='session'){setSessionTabs(prev=>prev.map(s=>s.id===tabId?{...s,color:color}:s));const tab=sessionTabs.find(s=>s.id===tabId);if(tab){setTracks(prev=>prev.map(t=>{if(!t.sections||t.sections.length===0)return t;return{...t,sections:t.sections.map(s=>{if(s.sectionId===tab.sectionId){return{...s,color:color};}return s;})};}));}}else{setSubTabs(prev=>prev.map(s=>s.id===tabId?{...s,color:color}:s));}};const activeTracks=useMemo(()=>{var st=sessionTabs.find(s=>s.id===activeTab);if(st)return st.tracks;var pr=subTabs.find(s=>s.id===activeTab&&s.type==='PIANO_ROLL');if(pr&&pr.parent_tab_id&&pr.parent_tab_id.startsWith('session_')){var parentSt=sessionTabs.find(s=>s.id===pr.parent_tab_id);if(parentSt)return parentSt.tracks;}return tracks;},[activeTab,sessionTabs,subTabs,tracks]);const activeTracksRef=useRef([]);activeTracksRef.current=activeTracks;const sessionTabsRef=useRef(sessionTabs);sessionTabsRef.current=sessionTabs;const[selectionCleared,setSelectionCleared]=useState(false);// LOOP_EDITOR_2.md §4.2
|
||||||
// ── Temp Edit Tab (LOOP_EDITOR_2.md §1.2 Sub Tab) ──
|
// ── Temp Edit Tab (LOOP_EDITOR_2.md §1.2 Sub Tab) ──
|
||||||
const[tempTabActive,setTempTabActive]=useState(false);const[tempTabBuffer,setTempTabBuffer]=useState(null);const[tempTabTrackId,setTempTabTrackId]=useState(null);const[tempTabOrigStart,setTempTabOrigStart]=useState(0);const[tempTabOrigEnd,setTempTabOrigEnd]=useState(0);const tempTabCanvasRef=useRef(null);// Effect parameters for temp tab
|
const[tempTabActive,setTempTabActive]=useState(false);const[tempTabBuffer,setTempTabBuffer]=useState(null);const[tempTabTrackId,setTempTabTrackId]=useState(null);const[tempTabOrigStart,setTempTabOrigStart]=useState(0);const[tempTabOrigEnd,setTempTabOrigEnd]=useState(0);const tempTabCanvasRef=useRef(null);// Effect parameters for temp tab
|
||||||
const[tempTabEffects,setTempTabEffects]=useState({reverse:false,gainDb:0,fadeInMs:0,fadeOutMs:0});// ── Auth / User State ──
|
const[tempTabEffects,setTempTabEffects]=useState({reverse:false,gainDb:0,fadeInMs:0,fadeOutMs:0});// ── Auth / User State ──
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
### [2026-07-28 07:56] Task: Fix PIANO_ROLL activeTracks + instrument auto-assign trong SECTION-TAB
|
||||||
|
- **Tóm tắt thay đổi:** Fix `activeTracks` useMemo: khi `activeTab` là PIANO_ROLL sub-tab từ SECTION-TAB (`parent_tab_id` bắt đầu `session_`), trả về tracks của section tab thay vì main tracks. Trước đây `activeTracks` luôn trả về main tracks khi activeTab !== session_xxx → dropdown MIDI item rỗng, track name không hiển thị, instrument lookup sai. Fix: check `subTabs` cho PIANO_ROLL type để resolve đúng parent session tracks.
|
||||||
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js`
|
||||||
|
- **Ghi chú/Test (nếu có):** `npm run build` pass. Cần restart server + clear browser cache.
|
||||||
|
---
|
||||||
|
|
||||||
### [2026-07-28 07:47] Task: Sync MIDI item editing + ghost notes từ MAIN vào SECTION-TAB
|
### [2026-07-28 07:47] Task: Sync MIDI item editing + ghost notes từ MAIN vào SECTION-TAB
|
||||||
- **Tóm tắt thay đổi:** Fix `handleEditSectionInTab` xoá `midiItems: []` khi clone section tracks. SECTION-TAB giờ giữ nguyên MIDI items từ section data → dropdown MIDI item switcher hoạt động, ghost notes extract từ các track khác trong section, instrument settings được preserve. Piano Roll Tab dùng chung component `PianoRollTabEditor` nên tất cả tính năng (ghost, session sync, CC lane, export, AI) đều hoạt động trên cả MAIN và SECTION-TAB.
|
- **Tóm tắt thay đổi:** Fix `handleEditSectionInTab` xoá `midiItems: []` khi clone section tracks. SECTION-TAB giờ giữ nguyên MIDI items từ section data → dropdown MIDI item switcher hoạt động, ghost notes extract từ các track khác trong section, instrument settings được preserve. Piano Roll Tab dùng chung component `PianoRollTabEditor` nên tất cả tính năng (ghost, session sync, CC lane, export, AI) đều hoạt động trên cả MAIN và SECTION-TAB.
|
||||||
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js`
|
- **Các file ảnh hưởng:** `app/static/js/app.jsx`, `app/static/js/app.precompiled.js`
|
||||||
|
|||||||
Reference in New Issue
Block a user