diff --git a/app/templates/index.html b/app/templates/index.html index cabd883..7a25747 100644 --- a/app/templates/index.html +++ b/app/templates/index.html @@ -2918,7 +2918,7 @@ {/* Left Column: TCP */}
setSelectedTrackId(track.id)} - className={`w-[300px] sticky left-0 z-10 p-2.5 flex flex-col justify-between bg-[#1e1e1e] border-r border-zinc-900 shrink-0 cursor-pointer border-l-4 overflow-hidden ${isSelected ? 'border-cyan-500 bg-[#252525]' : 'border-transparent hover:bg-zinc-800/20'}`} + className={`w-[300px] sticky left-0 z-30 p-2.5 flex flex-col justify-between bg-[#1e1e1e] border-r border-zinc-900 shrink-0 cursor-pointer border-l-4 overflow-hidden ${isSelected ? 'border-cyan-500 bg-[#252525]' : 'border-transparent hover:bg-zinc-800/20'}`} >
diff --git a/app/templates/original_workspace.txt b/app/templates/original_workspace.txt new file mode 100644 index 0000000..6b8c3de --- /dev/null +++ b/app/templates/original_workspace.txt @@ -0,0 +1,303 @@ +
+ {/* ══ LEFT COLUMN: TCP PANEL ══ */} +
+ Kênh + + {/* Timeline Toolbar */} +
+ + + + + {/* Separator */} +
+ + {/* Quick Actions (Glue, Cut, Copy, Paste) */} + + + + +
+ + {/* Snap Section */} +
+
+ Snap + +
+
+ {/* Right Side: Time Ruler */} +
+ {Array.from({ length: Math.ceil(maxDuration) }).map((_, i) => { + const sec = i; + const x = sec * zoom; + return ( +
+ {formatTime(sec)} +
+ ); + })} +
+
+ + {/* [ZONE A] Tempo Track Row */} +
+ {/* Left Side: Tempo TCP */} +
+
+
+ TM + Tempo Track +
+
+ setBpm(e.target.value)} + onBlur={() => localStorage.setItem('studio_bpm', bpm)} + className="w-12 bg-zinc-800 border border-zinc-700 rounded text-[10px] text-zinc-300 text-center font-mono focus:outline-none focus:border-purple-500" + min="40" + max="300" + /> + BPM +
+
+
+ {/* Right Side: Tempo Lane */} +
+ +
+
+ + {/* [ZONE B] Dynamic Track List Workspace */} +
+ {tracks.map((track, idx) => { + const isSelected = selectedTrackId === track.id; + return ( +
+ {/* Left Column: TCP */} +
setSelectedTrackId(track.id)} + className={`w-[300px] sticky left-0 z-10 p-2.5 flex flex-col justify-between bg-[#1e1e1e] border-r border-zinc-900 shrink-0 cursor-pointer border-l-4 overflow-hidden ${isSelected ? 'border-cyan-500 bg-[#252525]' : 'border-transparent hover:bg-zinc-800/20'}`} + > +
+
+ {(idx+1).toString().padStart(2, '0')} +
+ + {track.name} + +
+ +
+ + +
+
+ +
e.stopPropagation()}> + Mô phỏng: + + +
+ +
e.stopPropagation()}> +
+ updateTrackVolume(track.id, v)} /> + Gain: {Math.round(track.volume * 100)}% +
+ +
+ loadFileOnTrack(track.id, e.target.files[0])} + /> + +
+
+
+ + {/* Right Column: Waveform Lane */} +
e.preventDefault()} + onDrop={(e) => { + e.preventDefault(); + if (e.dataTransfer.files[0]) { + loadFileOnTrack(track.id, e.dataTransfer.files[0]); + } + }} + onMouseEnter={() => setHoveredTrackId(track.id)} + > + + + {track.buffer && ( +
+ +
+ )} +
+
+ ); + })} + + {/* Bottom Drop Zone to create new track */} +
+
+
{ + if (draggedClipRef.current) { + const newId = addNewTrack(); + setHoveredTrackId(newId); + } + }} + onClick={addNewTrack} + > + + Kéo clip xuống đây hoặc Click để tạo Track mới + +
+
+ + {/* Selection Overlay - only for Global mode (LOOP_EDITOR.md §1.2: local draws on canvas per-track) */} + {selectionMode !== 'local' && selLeft !== null && selRight !== null && selRight > selLeft && ( +
+
handleHandleDragStart(e, 'left')} + title="Kéo giãn mốc bắt đầu"> +
+
+
handleHandleDragStart(e, 'right')} + title="Kéo giãn mốc kết thúc"> +
+
+
+ )} + + {/* Playhead */} +
+
+
+
+
+
+ + {/* ── Footer ── */}