From b46a2c45f2c3b3a4eb578b9b70ec996f188aea4c Mon Sep 17 00:00:00 2001 From: 3dtours Date: Thu, 23 Jul 2026 17:58:44 +0700 Subject: [PATCH] =?UTF-8?q?feat:=20c=C3=A0i=20=C4=91=E1=BA=B7t=20tools=20c?= =?UTF-8?q?ho=20AI=20th=E1=BB=B1c=20hi=E1=BB=87n=20t=E1=BA=A1o=20MIDI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/static/js/app.jsx | 502 +++++++++++++++++++++++++++---- app/static/js/app.precompiled.js | 17 +- app/storage/sonicforge.db | Bin 45056 -> 45056 bytes package.json | 2 +- 4 files changed, 461 insertions(+), 60 deletions(-) diff --git a/app/static/js/app.jsx b/app/static/js/app.jsx index c90dca7..53d11a4 100644 --- a/app/static/js/app.jsx +++ b/app/static/js/app.jsx @@ -3160,57 +3160,53 @@ const PluginManagerModal = ({ isOpen, onClose, pluginsData }) => { }; const vsts = localData?.vst_instruments || []; const sfs = localData?.soundfonts || []; - return React.createElement('div', { - className: 'fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm', - onClick: onClose - }, React.createElement('div', { - className: 'bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200', - onClick: e => e.stopPropagation() - }, React.createElement('div', { - className: 'flex justify-between items-center pb-4 border-b border-[#383838]' - }, React.createElement('h3', { - className: 'text-lg font-bold text-cyan-400' - }, 'Plugin Manager (SoundFont / VSTi)'), React.createElement('button', { - onClick: onClose, - className: 'text-slate-400 hover:text-slate-200' - }, '✕')), React.createElement('div', { - className: 'mt-4 space-y-4' - }, React.createElement('div', null, React.createElement('h4', { - className: 'text-sm font-bold text-purple-400 mb-2 uppercase' - }, 'VST Instruments'), vsts.length === 0 ? React.createElement('p', { - className: 'text-xs text-zinc-500' - }, 'No VST instruments available on server.') : React.createElement('div', { - className: 'grid grid-cols-1 gap-1' - }, vsts.map((v, i) => React.createElement('div', { - key: i, - className: 'flex items-center justify-between bg-[#1e1e1e] px-3 py-2 rounded border border-[#333]' - }, React.createElement('span', { - className: 'text-xs font-semibold text-slate-200' - }, v.id), React.createElement('span', { - className: 'text-[10px] text-cyan-400 bg-cyan-950/40 px-1.5 py-0.5 rounded' - }, v.type))))), React.createElement('div', null, React.createElement('h4', { - className: 'text-sm font-bold text-amber-400 mb-2 uppercase' - }, 'SoundFonts'), sfs.length === 0 ? React.createElement('p', { - className: 'text-xs text-zinc-500' - }, 'No SoundFonts available.') : React.createElement('div', { - className: 'space-y-1' - }, sfs.map((sf, i) => React.createElement('div', { - key: i, - className: 'flex items-center justify-between bg-[#1e1e1e] px-3 py-2 rounded border border-[#333]' - }, React.createElement('span', { - className: 'text-xs text-slate-200' - }, sf.name))))), React.createElement('div', { - className: 'pt-4 border-t border-[#383838]' - }, React.createElement('h4', { - className: 'text-sm font-bold text-emerald-400 mb-2 uppercase' - }, 'Upload SoundFont'), React.createElement('input', { - type: 'file', - accept: '.sf2,.sf3', - onChange: handleUploadSF, - className: 'w-full text-xs text-zinc-400 file:mr-2 file:py-1 file:px-3 file:rounded file:border-0 file:text-xs file:font-semibold file:bg-emerald-700 file:text-white hover:file:bg-emerald-600' - }), sfUploadStatus && React.createElement('p', { - className: 'text-xs mt-1 text-zinc-400' - }, sfUploadStatus)))))); + return ( +
+
e.stopPropagation()}> +
+

Plugin Manager (SoundFont / VSTi)

+ +
+
+
+

VST Instruments

+ {vsts.length === 0 ? ( +

No VST instruments available on server.

+ ) : ( +
+ {vsts.map((v, i) => ( +
+ {v.id} + {v.type} +
+ ))} +
+ )} +
+
+

SoundFonts

+ {sfs.length === 0 ? ( +

No SoundFonts available.

+ ) : ( +
+ {sfs.map((sf, i) => ( +
+ {sf.name} +
+ ))} +
+ )} +
+
+

Upload SoundFont

+ + {sfUploadStatus &&

{sfUploadStatus}

} +
+
+
+
+ ); }; const ProfileModal = ({ @@ -3881,6 +3877,313 @@ const SystemManagerModal = ({ className: "px-2 py-1 bg-red-700/60 hover:bg-red-600 rounded text-xs" }, "Xóa"))))))))); }; + +const DEFAULT_PRESETS = [ + { + id: "preset_epic_orchestra_intro", + name: "Epic Orchestra Intro (8 Bars)", + keywords: ["epic orchestra", "epic orchestral", "hoành tráng", "nhạc phim epic"], + category: "Orchestral / Film Score", + default_bars: 8, + default_bpm: 130, + default_scale: "C Minor", + system_instruction_template: "You are a professional Epic Orchestral film composer. Create a powerful, dramatic 8-bar intro composition.\nThe required structure to return via the `generate_multitrack_midi` tool consists of 5 tracks:\n1. Strings Ensemble: Plays staccato 16th notes in the low register (C2, G2) driving the rhythm (Ostinato).\n2. Brass Section: Plays the main swelling melodic theme (Horn/Trumpet swells) in the C3-C5 range.\n3. Epic Percussion / Taiko: Hits heavily on beats 1 and 3, featuring a snare roll accent at bars 4 and 8.\n4. Synth Bass/Pad: Holds smooth octave foundation layers (Legato).\n5. Orchestral Drums/Cymbals: Crashes on bar 1 and bar 5.\nEnsure the duration of each track is precisely 8 bars (32 beats).", + is_user_defined: false, + created_at: "2026-07-23T16:00:00Z" + }, + { + id: "preset_pop_piano_chords", + name: "Pop Piano Chords (4 Bars)", + keywords: ["pop piano", "piano chords", "ballad piano", "hợp âm piano"], + category: "Pop / Ballad", + default_bars: 4, + default_bpm: 90, + default_scale: "C Major", + system_instruction_template: "You are a professional Pop Piano player. Generate a beautiful 4-bar piano chord progression (e.g. C - G - Am - F) with pleasant chord voicing and simple accompaniment. Return the MIDI notes via `generate_multitrack_midi` function on a track named 'Pop Piano'. Ensure the duration of the track is precisely 4 bars (16 beats).", + is_user_defined: false, + created_at: "2026-07-23T16:00:00Z" + }, + { + id: "preset_cyberpunk_synth", + name: "Cyberpunk Synthwave (8 Bars)", + keywords: ["cyberpunk synth", "synthwave", "cyberpunk", "futuristic synth"], + category: "Electronic / Synthwave", + default_bars: 8, + default_bpm: 120, + default_scale: "A Minor", + system_instruction_template: "You are a Synthwave producer. Generate a driving 8-bar cyberpunk synth bassline and lead melody. Return MIDI notes via `generate_multitrack_midi` containing:\n1. Synth Bass: driving eighth notes on pitch A1, C2, G1.\n2. Synth Lead: arpeggiated melodic line in high register C4-E5.\nEnsure the duration of each track is precisely 8 bars (32 beats).", + is_user_defined: false, + created_at: "2026-07-23T16:00:00Z" + } +]; + +const AIPresetModal = ({ isOpen, onClose }) => { + if (!isOpen) return null; + + const [presets, setPresets] = React.useState(() => { + const local = localStorage.getItem('daw_ai_prompt_presets'); + return local ? JSON.parse(local) : DEFAULT_PRESETS; + }); + + const [search, setSearch] = React.useState(''); + const [filterCategory, setFilterCategory] = React.useState('ALL'); + const [editingPreset, setEditingPreset] = React.useState(null); // preset object or 'new' + + // Form states + const [formName, setFormName] = React.useState(''); + const [formKeywords, setFormKeywords] = React.useState(''); + const [formCategory, setFormCategory] = React.useState('Orchestral / Film Score'); + const [formBars, setFormBars] = React.useState(8); + const [formBpm, setFormBpm] = React.useState(120); + const [formScale, setFormScale] = React.useState('C Minor'); + const [formTemplate, setFormTemplate] = React.useState(''); + + const savePresets = (newPresets) => { + setPresets(newPresets); + localStorage.setItem('daw_ai_prompt_presets', JSON.stringify(newPresets)); + }; + + const handleEdit = (p) => { + setEditingPreset(p); + setFormName(p.name); + setFormKeywords(p.keywords.join(', ')); + setFormCategory(p.category); + setFormBars(p.default_bars); + setFormBpm(p.default_bpm); + setFormScale(p.default_scale); + setFormTemplate(p.system_instruction_template); + }; + + const handleNew = () => { + setEditingPreset('new'); + setFormName(''); + setFormKeywords(''); + setFormCategory('Orchestral / Film Score'); + setFormBars(8); + setFormBpm(120); + setFormScale('C Minor'); + setFormTemplate(''); + }; + + const handleDelete = (id) => { + const updated = presets.filter(p => p.id !== id); + savePresets(updated); + showToast('Đã xóa preset.', 'info'); + }; + + const handleSaveForm = (e) => { + e.preventDefault(); + if (!formName.trim() || !formTemplate.trim()) { + showToast('Vui lòng điền đầy đủ tên và mẫu gợi ý.', 'warning'); + return; + } + + const keywordsArray = formKeywords.split(',').map(k => k.trim()).filter(Boolean); + const presetObj = { + id: editingPreset === 'new' ? 'preset_' + Date.now() : editingPreset.id, + name: formName.trim(), + keywords: keywordsArray, + category: formCategory, + default_bars: parseInt(formBars) || 8, + default_bpm: parseInt(formBpm) || 120, + default_scale: formScale, + system_instruction_template: formTemplate.trim(), + is_user_defined: true, + created_at: editingPreset === 'new' ? new Date().toISOString() : editingPreset.created_at + }; + + let updated; + if (editingPreset === 'new') { + updated = [...presets, presetObj]; + } else { + updated = presets.map(p => p.id === presetObj.id ? presetObj : p); + } + + savePresets(updated); + setEditingPreset(null); + showToast('Đã lưu preset thành công!', 'success'); + }; + + const categories = ['ALL', ...new Set(presets.map(p => p.category))]; + + const filtered = presets.filter(p => { + const matchesSearch = p.name.toLowerCase().includes(search.toLowerCase()) || + p.keywords.some(k => k.toLowerCase().includes(search.toLowerCase())); + const matchesCategory = filterCategory === 'ALL' || p.category === filterCategory; + return matchesSearch && matchesCategory; + }); + + return /*#__PURE__*/React.createElement("div", { + className: "fixed inset-0 z-50 flex items-center justify-center bg-black/75 backdrop-blur-sm p-4 animate-fade-in" + }, /*#__PURE__*/React.createElement("div", { + className: "bg-[#18181b] border border-zinc-800 rounded-xl shadow-2xl w-full max-w-4xl max-h-[85vh] flex flex-col overflow-hidden text-zinc-100" + }, /*#__PURE__*/React.createElement("div", { + className: "p-4 border-b border-zinc-800 flex items-center justify-between shrink-0 bg-[#202024]" + }, /*#__PURE__*/React.createElement("h2", { + className: "text-sm font-bold tracking-wider uppercase text-purple-400 flex items-center gap-1.5" + }, /*#__PURE__*/React.createElement("i", { + "data-lucide": "sliders", + className: "w-4 h-4" + }), "AI Prompt Preset Manager"), /*#__PURE__*/React.createElement("button", { + onClick: () => { setEditingPreset(null); onClose(); }, + className: "text-zinc-400 hover:text-zinc-200 transition" + }, /*#__PURE__*/React.createElement("i", { + "data-lucide": "x", + className: "w-4 h-4" + }))), /*#__PURE__*/React.createElement("div", { + className: "flex-1 overflow-y-auto p-4 flex gap-4 min-h-0" + }, !editingPreset ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", { + className: "flex-1 flex flex-col min-w-0" + }, /*#__PURE__*/React.createElement("div", { + className: "flex items-center gap-2 mb-3 shrink-0" + }, /*#__PURE__*/React.createElement("input", { + type: "text", + placeholder: "Tìm kiếm preset hoặc từ khóa...", + value: search, + onChange: e => setSearch(e.target.value), + className: "flex-1 bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600" + }), /*#__PURE__*/React.createElement("select", { + value: filterCategory, + onChange: e => setFilterCategory(e.target.value), + className: "bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600" + }, categories.map(c => /*#__PURE__*/React.createElement("option", { + key: c, + value: c + }, c === 'ALL' ? 'Tất cả danh mục' : c))), /*#__PURE__*/React.createElement("button", { + onClick: handleNew, + className: "px-3 py-1 bg-purple-700 hover:bg-purple-600 text-white rounded text-xs font-bold flex items-center gap-1.5 shadow transition shrink-0" + }, /*#__PURE__*/React.createElement("i", { + "data-lucide": "plus", + className: "w-3.5 h-3.5" + }), "Tạo mới")), /*#__PURE__*/React.createElement("div", { + className: "flex-1 border border-zinc-800 rounded bg-[#0f0f12] overflow-y-auto" + }, filtered.length === 0 ? /*#__PURE__*/React.createElement("div", { + className: "p-8 text-center text-zinc-500 text-xs italic" + }, "Không tìm thấy preset nào.") : /*#__PURE__*/React.createElement("table", { + className: "w-full text-left text-xs border-collapse" + }, /*#__PURE__*/React.createElement("thead", { + className: "bg-[#1f1f23] text-zinc-400 font-bold border-b border-zinc-800" + }, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", { + className: "p-2.5 w-1/4" + }, "Tên Preset"), /*#__PURE__*/React.createElement("th", { + className: "p-2.5 w-1/4" + }, "Từ khóa kích hoạt"), /*#__PURE__*/React.createElement("th", { + className: "p-2.5 w-1/6" + }, "Số Bar"), /*#__PURE__*/React.createElement("th", { + className: "p-2.5 w-1/6" + }, "BPM"), /*#__PURE__*/React.createElement("th", { + className: "p-2.5 w-1/6 text-right" + }, "Hành động"))), /*#__PURE__*/React.createElement("tbody", null, filtered.map(p => /*#__PURE__*/React.createElement("tr", { + key: p.id, + className: "border-b border-zinc-800/50 hover:bg-zinc-850" + }, /*#__PURE__*/React.createElement("td", { + className: "p-2.5 font-semibold text-purple-300" + }, p.name), /*#__PURE__*/React.createElement("td", { + className: "p-2.5 text-zinc-400 font-mono text-[11px] truncate max-w-[150px]" + }, p.keywords.join(', ')), /*#__PURE__*/React.createElement("td", { + className: "p-2.5 text-zinc-400" + }, p.default_bars, " Bars"), /*#__PURE__*/React.createElement("td", { + className: "p-2.5 text-zinc-400" + }, p.default_bpm, " BPM"), /*#__PURE__*/React.createElement("td", { + className: "p-2.5 text-right flex items-center justify-end gap-1.5 h-full" + }, /*#__PURE__*/React.createElement("button", { + type: "button", + onClick: () => handleEdit(p), + className: "px-2 py-0.5 bg-zinc-850 hover:bg-zinc-700 text-zinc-300 rounded border border-zinc-700 text-[10px]" + }, "Sửa"), /*#__PURE__*/React.createElement("button", { + type: "button", + onClick: () => handleDelete(p.id), + className: "px-2 py-0.5 bg-red-950/40 hover:bg-red-800 text-red-400 rounded border border-red-900 text-[10px]" + }, "Xóa"))))))))) : /*#__PURE__*/React.createElement("form", { + onSubmit: handleSaveForm, + className: "flex-1 flex flex-col gap-3 min-w-0" + }, /*#__PURE__*/React.createElement("div", { + className: "text-xs font-bold text-zinc-400 shrink-0 border-b border-zinc-800 pb-1" + }, editingPreset === 'new' ? "TẠO PRESET MỚI" : `SỬA PRESET: ${editingPreset.name}`), /*#__PURE__*/React.createElement("div", { + className: "grid grid-cols-2 gap-3" + }, /*#__PURE__*/React.createElement("div", { + className: "flex flex-col gap-1" + }, /*#__PURE__*/React.createElement("label", { + className: "text-[10px] uppercase font-bold text-zinc-500" + }, "Tên Preset"), /*#__PURE__*/React.createElement("input", { + type: "text", + value: formName, + onChange: e => setFormName(e.target.value), + className: "bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200" + })), /*#__PURE__*/React.createElement("div", { + className: "flex flex-col gap-1" + }, /*#__PURE__*/React.createElement("label", { + className: "text-[10px] uppercase font-bold text-zinc-500" + }, "Danh mục"), /*#__PURE__*/React.createElement("input", { + type: "text", + value: formCategory, + onChange: e => setFormCategory(e.target.value), + className: "bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200" + }))), /*#__PURE__*/React.createElement("div", { + className: "flex flex-col gap-1" + }, /*#__PURE__*/React.createElement("label", { + className: "text-[10px] uppercase font-bold text-zinc-500" + }, "Từ khóa kích hoạt (ngăn cách bằng dấu phẩy)"), /*#__PURE__*/React.createElement("input", { + type: "text", + value: formKeywords, + onChange: e => setFormKeywords(e.target.value), + placeholder: "Ví dụ: epic orchestra, hoành tráng, nhạc phim epic", + className: "bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200" + })), /*#__PURE__*/React.createElement("div", { + className: "grid grid-cols-3 gap-3" + }, /*#__PURE__*/React.createElement("div", { + className: "flex flex-col gap-1" + }, /*#__PURE__*/React.createElement("label", { + className: "text-[10px] uppercase font-bold text-zinc-500" + }, "Số Bars mặc định"), /*#__PURE__*/React.createElement("input", { + type: "number", + value: formBars, + onChange: e => setFormBars(e.target.value), + className: "bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200" + })), /*#__PURE__*/React.createElement("div", { + className: "flex flex-col gap-1" + }, /*#__PURE__*/React.createElement("label", { + className: "text-[10px] uppercase font-bold text-zinc-500" + }, "BPM mặc định"), /*#__PURE__*/React.createElement("input", { + type: "number", + value: formBpm, + onChange: e => setFormBpm(e.target.value), + className: "bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200" + })), /*#__PURE__*/React.createElement("div", { + className: "flex flex-col gap-1" + }, /*#__PURE__*/React.createElement("label", { + className: "text-[10px] uppercase font-bold text-zinc-500" + }, "Âm giai (Scale) mặc định"), /*#__PURE__*/React.createElement("input", { + type: "text", + value: formScale, + onChange: e => setFormScale(e.target.value), + className: "bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200" + }))), /*#__PURE__*/React.createElement("div", { + className: "flex flex-col gap-1 flex-1 min-h-0" + }, /*#__PURE__*/React.createElement("label", { + className: "text-[10px] uppercase font-bold text-zinc-500" + }, "System Prompt Template / Luật soạn nhạc"), /*#__PURE__*/React.createElement("textarea", { + value: formTemplate, + onChange: e => setFormTemplate(e.target.value), + rows: 6, + className: "flex-1 bg-zinc-900 border border-zinc-700 rounded p-2.5 text-xs outline-none focus:border-purple-600 text-zinc-200 font-mono resize-none" + })), /*#__PURE__*/React.createElement("div", { + className: "flex items-center justify-end gap-2 shrink-0 pt-2 border-t border-zinc-800" + }, /*#__PURE__*/React.createElement("button", { + type: "button", + onClick: () => setEditingPreset(null), + className: "px-3 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-400 border border-zinc-700 rounded text-xs transition" + }, "Quay lại"), /*#__PURE__*/React.createElement("button", { + type: "submit", + className: "px-3 py-1.5 bg-purple-700 hover:bg-purple-600 text-white rounded text-xs font-bold shadow transition" + }, "Lưu Preset")))), /*#__PURE__*/React.createElement("div", { + className: "p-4 border-t border-zinc-800 flex justify-end shrink-0 bg-[#202024]" + }, /*#__PURE__*/React.createElement("button", { + onClick: () => { setEditingPreset(null); onClose(); }, + className: "px-4 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 border border-zinc-700 rounded text-xs font-bold shadow transition" + }, "Đóng")))); +}; + const PianoRollTabEditor = ({ st, zoom, bpm, viewportWidth, onClose, onUpdateNotes, onSaveNotes, setSubTabs }) => { const [activeRollTool, setActiveRollTool] = React.useState('select'); const [snapVal, setSnapVal] = React.useState('1/16'); @@ -5079,6 +5382,7 @@ const App = () => { const [profileModalOpen, setProfileModalOpen] = useState(false); const [systemManagerModalOpen, setSystemManagerModalOpen] = useState(false); const [aiConfigModalOpen, setAiConfigModalOpen] = useState(false); + const [aiPresetModalOpen, setAiPresetModalOpen] = useState(false); const [pluginManagerModalOpen, setPluginManagerModalOpen] = useState(false); const [pluginsData, setPluginsData] = useState(null); useEffect(() => { @@ -10206,6 +10510,20 @@ const App = () => { const dawContext = window.AIGateway.buildAIPromptContext({ tracks, bpm, selectedTrackId, currentTime, selLeft, selRight }); + + let matchedInstruction = ''; + try { + const localPresets = localStorage.getItem('daw_ai_prompt_presets'); + const presets = localPresets ? JSON.parse(localPresets) : DEFAULT_PRESETS; + const matched = presets.find(p => p.keywords.some(kw => prompt.toLowerCase().includes(kw.toLowerCase()))); + if (matched) { + matchedInstruction = matched.system_instruction_template; + setAiActionLog(prev => [...prev, { type: 'status', text: ` 🎯 Khớp Preset: "${matched.name}". Tự động tối ưu gợi ý...`, time: Date.now() }]); + } + } catch (e) { + console.error("Lỗi khi tìm preset:", e); + } + const result = await window.AIGateway.executeAIPrompt({ prompt: prompt, provider: provider.name || 'default', @@ -10213,7 +10531,8 @@ const App = () => { apiKey: apiKey, baseUrl: baseUrl.replace(/\/chat\/completions$/, '').replace(/\/$/, ''), dawContext, - tools: window.AIGateway.DEFAULT_TOOLS + tools: window.AIGateway.DEFAULT_TOOLS, + systemInstruction: matchedInstruction }); const hasText = !!result.textResponse; const hasCalls = result.functionCalls && result.functionCalls.length > 0; @@ -11028,6 +11347,69 @@ const App = () => { pushAction('AI_FADE_OUT', track.id, beforeSnap, afterSnap); }, 50); return { success: true, trackId: track.id, clipId: clip.id, duration_seconds: duration }; + }, + generateMultitrackMidi: (args) => { + const { composition_title, bpm: aiBpm, total_bars, tracks: aiTracks } = args; + if (aiBpm) { + setBpm(aiBpm.toString()); + } + const bpmVal = aiBpm || parseInt(bpm) || 120; + const secondsPerBeat = 60.0 / bpmVal; + const secondsPerBar = secondsPerBeat * 4; + const durationSec = total_bars * secondsPerBar; + + updateActiveTracks(prev => { + let updatedTracks = [...prev]; + aiTracks.forEach(aiTrack => { + let targetTrack = updatedTracks.find( + t => t.name.toLowerCase() === aiTrack.track_name.toLowerCase() + ); + if (!targetTrack) { + const newId = (updatedTracks.length + 1).toString(); + const colors = ['#0f766e', '#1d4ed8', '#701a75', '#a21caf', '#b45309']; + const selectColor = colors[updatedTracks.length % colors.length]; + targetTrack = { + id: newId, + name: aiTrack.track_name, + type: 'MIDI', + volumeDb: 0, + pan: 0, + muted: false, + solo: false, + color: selectColor, + markers: [], + serverFileId: null, + clips: [], + sections: [], + midiItems: [], + isArmed: false, + monitoringEnabled: true, + inputSource: { deviceType: 'NONE', deviceId: '' } + }; + updatedTracks.push(targetTrack); + } + const itemStartTimeSec = currentTime; + const newMidiItem = { + id: 'item_ai_' + Date.now() + '_' + Math.random().toString(36).substr(2, 5), + name: `${composition_title || 'AI Theme'} - ${aiTrack.track_name}`, + startTime: itemStartTimeSec, + duration: durationSec, + notes: aiTrack.notes.map((note, index) => ({ + id: `note_ai_${Date.now()}_${index}`, + pitch: note.pitch, + start_beat: note.start_beat, + duration_beats: note.duration_beats, + velocity: note.velocity || 0.8, + pan: 0.0 + })) + }; + targetTrack.midiItems = [...(targetTrack.midiItems || []), newMidiItem]; + }); + return updatedTracks; + }); + + showToast(`Đã nạp ${aiTracks.length} tracks MIDI thế hệ AI!`, 'success'); + return { success: true }; } }; window.DAWCommandDispatcher.registerDAWCommands(api); @@ -11295,6 +11677,10 @@ const App = () => { label: 'Config AI Providers...', icon: 'settings', action: () => setAiConfigModalOpen(true) + }, { + label: 'AI MIDI Preset Manager...', + icon: 'sliders', + action: () => setAiPresetModalOpen(true) }, { label: 'DSP Tools Panel', icon: 'wrench', @@ -11990,6 +12376,15 @@ const App = () => { })), " AI Copilot"), /*#__PURE__*/React.createElement("div", { className: "flex items-center gap-1" }, /*#__PURE__*/React.createElement("button", { + onClick: () => setAiPresetModalOpen(true), + className: "text-zinc-600 hover:text-zinc-300 mr-0.5", + title: "Preset Manager" + }, /*#__PURE__*/React.createElement("span", { + className: "inline-flex items-center shrink-0" + }, /*#__PURE__*/React.createElement("i", { + "data-lucide": "sliders", + className: "w-3 h-3" + }))), /*#__PURE__*/React.createElement("button", { onClick: () => { setAiActionLog([]); showToast('Đã xoá nhật ký AI.', 'info'); @@ -13772,6 +14167,9 @@ const App = () => { isOpen: pluginManagerModalOpen, onClose: () => setPluginManagerModalOpen(false), pluginsData: pluginsData + }), /*#__PURE__*/React.createElement(AIPresetModal, { + isOpen: aiPresetModalOpen, + onClose: () => setAiPresetModalOpen(false) })); }; const root = ReactDOM.createRoot(document.getElementById('root')); diff --git a/app/static/js/app.precompiled.js b/app/static/js/app.precompiled.js index a2c57aa..8540705 100644 --- a/app/static/js/app.precompiled.js +++ b/app/static/js/app.precompiled.js @@ -107,10 +107,13 @@ let working=[...merged];let dragIdx=working.findIndex(n=>n.time===newNode.time&& subTabAnchorRef.current=startTime;setSelectedNodeTime(null);onSelectRange(startTime,startTime);onPlayheadSet(startTime);const handleMouseMove=moveEvent=>{const currentX=moveEvent.clientX-rect.left+scrollLeft;const ct=Math.max(0,Math.min(wallDuration,currentX/zoom));const anchor=subTabAnchorRef.current??startTime;onSelectRange(Math.min(anchor,ct),Math.max(anchor,ct));};const handleMouseUp=()=>{document.removeEventListener('mousemove',handleMouseMove);document.removeEventListener('mouseup',handleMouseUp);};document.addEventListener('mousemove',handleMouseMove);document.addEventListener('mouseup',handleMouseUp);};const handleContextMenuInternal=e=>{e.preventDefault();e.stopPropagation();const canvas=canvasRef.current;const rect=canvas.getBoundingClientRect();const parent=canvas.parentElement;const scrollContainer=parent?parent.parentElement:null;const scrollLeft=scrollContainer?scrollContainer.scrollLeft:0;const x=e.clientX-rect.left+scrollLeft;const clickTime=Math.max(0,Math.min(buffer.duration/(speed||1.0),x/zoom));onContextMenu(e,clickTime);};// Double-click on automation curve to create a new node const handleDoubleClick=e=>{const canvas=canvasRef.current;if(!canvas||!buffer)return;if(activeTool!=='select'&&activeTool!=='pen')return;const rect=canvas.getBoundingClientRect();const parent=canvas.parentElement;const scrollContainer=parent?parent.parentElement:null;const scrollLeft=scrollContainer?scrollContainer.scrollLeft:0;const x=e.clientX-rect.left+scrollLeft;const clickTime=Math.max(0,Math.min(buffer.duration/(speed||1.0),x/zoom));const isPan=(graphMode||'volume')==='pan';const curNodes=isPan?panningNodes:volumeNodes;const cTop=8;const cHeight=rect.height-16;const valFromY=y=>{if(isPan)return Math.max(-1,Math.min(1,-(y-cTop)/cHeight*2+1));const yOff=(y-cTop)/cHeight;return yOff<=2/3?Math.max(0,Math.min(3,3*(1-yOff*3/2))):Math.max(-30,Math.min(0,-30*(yOff-2/3)*3));};// Interpolate value at click position from existing curve let interpolatedVal=valFromY(e.clientY-rect.top);if(curNodes.length>=2){const sorted=[...curNodes].sort((a,b)=>a.time-b.time);for(let i=0;i=sorted[i].time&&clickTime<=sorted[i+1].time){const t=(clickTime-sorted[i].time)/(sorted[i+1].time-sorted[i].time);const v1=isPan?sorted[i].pan:sorted[i].db;const v2=isPan?sorted[i+1].pan:sorted[i+1].db;interpolatedVal=v1+t*(v2-v1);break;}}}const newNode=isPan?{time:+Math.round(clickTime*10)/10,pan:+Math.round(interpolatedVal*20)/20}:{time:+Math.round(clickTime*10)/10,db:+Math.round(interpolatedVal*2)/2};const merged=(()=>{const map=new Map();curNodes.forEach(n=>map.set(n.time,n));map.set(newNode.time,newNode);return Array.from(map.values()).sort((a,b)=>a.time-b.time);})();if(onUpdateNodes)onUpdateNodes(merged);};return/*#__PURE__*/React.createElement("div",{style:{width:`${timelineWidth}px`,height:'100%',position:'relative',overflow:'hidden'}},/*#__PURE__*/React.createElement("canvas",{ref:canvasRef,style:{position:'absolute',top:0,left:0,imageRendering:'pixelated'},className:"cursor-crosshair rounded border border-zinc-800",onMouseDown:handleMouseDown,onDoubleClick:handleDoubleClick,onContextMenu:handleContextMenuInternal,onMouseMove:e=>{if(canvasRef.current&&e.altKey&&onSpeedChange){const rect=canvasRef.current.getBoundingClientRect();const parent=canvasRef.current.parentElement;const scrollContainer=parent?parent.parentElement:null;const scrollLeft=scrollContainer?scrollContainer.scrollLeft:0;const mx=e.clientX-rect.left+scrollLeft;const wClip=buffer.duration/speed*zoom;const tolerance=8;canvasRef.current.style.cursor=Math.abs(mx-wClip)<=tolerance&&!isStretchingRef.current?'ew-resize':'crosshair';}else if(canvasRef.current&&!isStretchingRef.current){const rect=canvasRef.current.getBoundingClientRect();const parent=canvasRef.current.parentElement;const scrollContainer=parent?parent.parentElement:null;const scrollLeft=scrollContainer?scrollContainer.scrollLeft:0;const mx=e.clientX-rect.left+scrollLeft;const wClipPx=buffer.duration/(speed||1.0)*zoom;const cH=canvasRef.current.height/(window.devicePixelRatio||1)-16;const btnX=wClipPx-28-4;const btnY=8+cH-14-2;const overBtn=mx>=btnX&&mx<=btnX+28&&e.clientY-rect.top>=btnY&&e.clientY-rect.top<=btnY+14;canvasRef.current.style.cursor=overBtn?'pointer':'crosshair';}}}));};const SubTabToolbar=({st,activeTool,setActiveTool,handleSubTabNormalizeWithValue,handleSubTabGainWithValue,handleSubTabPitch,handleSubTabStretch,handleSubTabFade,onPlayPause,onStop,onRewind,onForward,onLoop,onRecord,onRateChange,onCut,onCopy,onPaste,onGlue,snapValue,onSnapChange})=>{const isPlaying=st?.isPlaying||false;const isLooping=st?.isLooping||false;const isRecording=st?.isRecording||false;return/*#__PURE__*/React.createElement("div",{className:"daw-header flex h-16 items-center px-4 border-b daw-border gap-3 bg-zinc-800"},/*#__PURE__*/React.createElement("div",{className:"flex items-center space-x-1 border-r border-zinc-700 pr-3"},/*#__PURE__*/React.createElement("button",{className:`p-1 rounded ${activeTool==='select'?'bg-cyan-700':'bg-zinc-700'}`,onClick:()=>setActiveTool('select'),title:"Select Tool"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"mouse-pointer",className:"w-4 h-4"}))),/*#__PURE__*/React.createElement("button",{className:`p-1 rounded ${activeTool==='grab'?'bg-cyan-700':'bg-zinc-700'}`,onClick:()=>setActiveTool('grab'),title:"Grab Tool"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"hand",className:"w-4 h-4"}))),/*#__PURE__*/React.createElement("button",{className:`p-1 rounded ${activeTool==='razor'?'bg-cyan-700':'bg-zinc-700'}`,onClick:()=>setActiveTool('razor'),title:"Razor Tool"},/*#__PURE__*/React.createElement("svg",{className:"w-4 h-4 text-orange-400",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"},/*#__PURE__*/React.createElement("path",{d:"M6 3h12a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}),/*#__PURE__*/React.createElement("path",{d:"M4 9h16l-3 9H7z"}),/*#__PURE__*/React.createElement("circle",{cx:"12",cy:"6",r:"1"}))),/*#__PURE__*/React.createElement("button",{className:`p-1 rounded ${activeTool==='pen'?'bg-cyan-700':'bg-zinc-700'}`,onClick:()=>setActiveTool('pen'),title:"Pen Tool"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"pen-tool",className:"w-4 h-4"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-4 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:onGlue,className:"p-0.5 rounded text-zinc-400 hover:bg-zinc-800 hover:text-purple-400 transition",title:"Glue Clips"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"link",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:onCut,className:"p-0.5 rounded text-zinc-400 hover:bg-zinc-800 hover:text-red-400 transition",title:"Cut (Ctrl+X)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:onCopy,className:"p-0.5 rounded text-zinc-400 hover:bg-zinc-800 hover:text-blue-400 transition",title:"Copy (Ctrl+C)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:onPaste,className:"p-0.5 rounded text-zinc-400 hover:bg-zinc-800 hover:text-emerald-400 transition",title:"Paste (Ctrl+V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 border-r border-zinc-700 pr-3"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Snap"),/*#__PURE__*/React.createElement("select",{value:snapValue||'free',onChange:e=>onSnapChange(e.target.value),className:"bg-zinc-850 text-zinc-300 text-xs px-1 py-0.5 rounded border border-zinc-800 focus:outline-none font-mono"},/*#__PURE__*/React.createElement("option",{value:"free"},"Free"),/*#__PURE__*/React.createElement("option",{value:"1"},"1"),/*#__PURE__*/React.createElement("option",{value:"1/2"},"1/2"),/*#__PURE__*/React.createElement("option",{value:"1/4"},"1/4"),/*#__PURE__*/React.createElement("option",{value:"1/8"},"1/8"),/*#__PURE__*/React.createElement("option",{value:"1/16"},"1/16"),/*#__PURE__*/React.createElement("option",{value:"1/32"},"1/32"))),/*#__PURE__*/React.createElement("div",{className:"flex items-center space-x-2 flex-1 overflow-x-auto no-scrollbar"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-400"},"Normalize:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"0",value:st.effects?.normalizeDb||0,step:"0.1",onChange:e=>handleSubTabNormalizeWithValue(st.id,parseFloat(e.target.value)),className:"w-20 h-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 w-10 text-right"},st.effects?.normalizeDb||0," dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-400"},"Gain:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-40",max:"24",value:st.effects?.gainDb||0,step:"0.1",onChange:e=>handleSubTabGainWithValue(st.id,parseFloat(e.target.value)),className:"w-20 h-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 w-10 text-right"},st.effects?.gainDb||0," dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-400"},"Pitch:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"12",value:st.effects?.pitch||0,step:"0.1",onChange:e=>handleSubTabPitch(st.id,parseFloat(e.target.value)),className:"w-20 h-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 w-10 text-right"},st.effects?.pitch||0," st")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-400"},"Stretch:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"50",max:"200",value:st.effects?.speedStretch||100,step:"1",onChange:e=>handleSubTabStretch(st.id,parseInt(e.target.value)),className:"w-20 h-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 w-10 text-right"},st.effects?.speedStretch||100,"%"))),/*#__PURE__*/React.createElement("div",{className:"flex items-center space-x-1 border-r border-zinc-700 pr-3"},/*#__PURE__*/React.createElement("button",{onClick:()=>handleSubTabFade(st.id,'in'),className:"px-2 py-1 text-xs rounded hover:bg-zinc-700"},"Fade In"),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSubTabFade(st.id,'out'),className:"px-2 py-1 text-xs rounded hover:bg-zinc-700"},"Fade Out")),/*#__PURE__*/React.createElement("div",{className:"flex items-center space-x-1 border-r border-zinc-700 pr-3"},/*#__PURE__*/React.createElement("button",{onClick:onRewind,className:"w-8 h-8 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Rewind"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-back",className:"w-4 h-4"}))),/*#__PURE__*/React.createElement("button",{onClick:onPlayPause,className:`w-8 h-8 flex items-center justify-center rounded border transition ${isPlaying?'bg-emerald-600 text-black border-emerald-500 hover:bg-emerald-500':'bg-cyan-600 text-white border-cyan-500 hover:bg-cyan-500'}`,title:isPlaying?"Pause":"Play"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":isPlaying?'pause':'play',className:"w-4 h-4 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:onStop,className:"w-8 h-8 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Stop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"square",className:"w-4 h-4 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:onForward,className:"w-8 h-8 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Forward"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-forward",className:"w-4 h-4"}))),/*#__PURE__*/React.createElement("button",{onClick:onLoop,className:`w-8 h-8 flex items-center justify-center rounded border transition ${isLooping?'bg-amber-600 text-black border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-200 border-zinc-700 hover:bg-zinc-700'}`,title:isLooping?"Loop On":"Loop Off"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-4 h-4"}))),/*#__PURE__*/React.createElement("button",{onClick:onRecord,className:`w-8 h-8 flex items-center justify-center rounded border transition ${isRecording?'bg-red-600 text-white border-red-500':'bg-zinc-800 text-zinc-200 border-zinc-700 hover:bg-zinc-700'}`,title:isRecording?"Recording":"Record"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:"w-4 h-4"})))),/*#__PURE__*/React.createElement("div",{className:"flex items-center space-x-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-400"},"Rate:"),/*#__PURE__*/React.createElement("select",{value:st.playbackRate||1,onChange:e=>onRateChange(parseFloat(e.target.value)),className:"bg-zinc-700 text-zinc-100 text-xs px-1 py-0.5 rounded border border-zinc-600"},/*#__PURE__*/React.createElement("option",{value:"0.5"},"0.5x"),/*#__PURE__*/React.createElement("option",{value:"0.75"},"0.75x"),/*#__PURE__*/React.createElement("option",{value:"1"},"1x"),/*#__PURE__*/React.createElement("option",{value:"1.25"},"1.25x"),/*#__PURE__*/React.createElement("option",{value:"1.5"},"1.5x"),/*#__PURE__*/React.createElement("option",{value:"2"},"2x"))));};// ── Graph Editor Canvas for Volume/Pan/Fade Automation ── -const GraphEditorCanvas=({buffer,zoom,timelineWidth,volumeNodes,panningNodes,fadeInLen,fadeOutLen,onUpdateNodes,graphMode})=>{const canvasRef=useRef(null);const isDraggingNode=useRef(false);const dragNodeIdx=useRef(-1);const isCreatingNode=useRef(false);const getNodes=()=>graphMode==='pan'?panningNodes:volumeNodes;const nodeLabel=n=>graphMode==='pan'?`${n.pan.toFixed(2)}`:`${n.db.toFixed(1)}dB`;const nodeY=(n,h)=>{if(graphMode==='pan')return(1-(n.pan+1)/2)*h;const zeroY=2/3*h;return n.db>=0?zeroY-n.db/3*(2/3*h):zeroY+-n.db/30*(1/3*h);};const nodeValFromY=(y,h)=>{if(graphMode==='pan')return-(y/h*2-1);const yOff=y/h;return yOff<=2/3?3*(1-yOff*3/2):-30*(yOff-2/3)*3;};useEffect(()=>{const canvas=canvasRef.current;if(!canvas||!buffer)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=wrapper?wrapper.clientWidth:1200;const drawWidth=Math.min(timelineWidth,Math.max(vWidth,1200));const h=canvas.parentElement?canvas.parentElement.clientHeight:200;canvas.width=Math.round(drawWidth*dpr);canvas.height=Math.round(h*dpr);ctx.scale(dpr,dpr);ctx.imageSmoothingEnabled=false;canvas.style.position='absolute';canvas.style.left=`${scrollLeft}px`;canvas.style.width=`${drawWidth}px`;canvas.style.height=`${h}px`;ctx.fillStyle='#1a1a2e';ctx.fillRect(0,0,drawWidth,h);ctx.strokeStyle='#2a2a4e';ctx.lineWidth=0.5;for(let t=0;t<=buffer.duration;t+=0.5){const x=t/buffer.duration*drawWidth;ctx.beginPath();ctx.moveTo(x,0);ctx.lineTo(x,h);ctx.stroke();}for(let i=0;i<=10;i++){const y=i/10*h;ctx.beginPath();ctx.moveTo(0,y);ctx.lineTo(drawWidth,y);ctx.stroke();}if(fadeInLen>0){const fadeX=fadeInLen/buffer.duration*drawWidth;ctx.fillStyle='rgba(16, 185, 129, 0.12)';ctx.fillRect(0,0,fadeX,h);}if(fadeOutLen>0){const fadeX=(buffer.duration-fadeOutLen)/buffer.duration*drawWidth;const fadeW=fadeOutLen/buffer.duration*drawWidth;ctx.fillStyle='rgba(239, 68, 68, 0.12)';ctx.fillRect(fadeX,0,fadeW,h);}const nodes=getNodes();if(nodes.length>0){ctx.strokeStyle=graphMode==='pan'?'#a855f7':'#06b6d4';ctx.lineWidth=2;ctx.beginPath();nodes.forEach((n,i)=>{const x=n.time/buffer.duration*drawWidth;const y=nodeY(n,h);if(i===0)ctx.moveTo(x,y);else ctx.lineTo(x,y);});ctx.stroke();nodes.forEach((n,i)=>{const x=n.time/buffer.duration*drawWidth;const y=nodeY(n,h);ctx.fillStyle=graphMode==='pan'?'#a855f7':'#06b6d4';ctx.beginPath();ctx.arc(x,y,5,0,Math.PI*2);ctx.fill();ctx.fillStyle='#e4e4e7';ctx.font='9px monospace';ctx.fillText(nodeLabel(n),x+8,y+3);});}else{ctx.fillStyle='#52525b';ctx.font='11px sans-serif';ctx.textAlign='center';ctx.fillText(graphMode==='pan'?'Click to add Pan points':'Click to add Volume points',drawWidth/2,h/2);ctx.textAlign='start';}const zeroY=graphMode==='pan'?h/2:nodeY({db:0},h);ctx.strokeStyle=graphMode==='pan'?'#a855f744':'#06b6d444';ctx.lineWidth=1;ctx.setLineDash([4,4]);ctx.beginPath();ctx.moveTo(0,zeroY);ctx.lineTo(drawWidth,zeroY);ctx.stroke();ctx.setLineDash([]);},[buffer,zoom,timelineWidth,volumeNodes,panningNodes,fadeInLen,fadeOutLen,graphMode]);const handleMouseDown=e=>{const canvas=canvasRef.current;if(!canvas||!buffer)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const y=e.clientY-rect.top;const time=x/rect.width*buffer.duration;const val=nodeValFromY(y,rect.height);const nodes=getNodes();const snapped=Math.max(-30,Math.min(3,val));const snappedPan=Math.max(-1,Math.min(1,val));const threshold=12/rect.width*buffer.duration;const nearIdx=nodes.findIndex(n=>Math.abs(n.time-time)=0){isDraggingNode.current=true;dragNodeIdx.current=nearIdx;return;}const newNode=graphMode==='pan'?{time:+time.toFixed(3),pan:+snappedPan.toFixed(2)}:{time:+time.toFixed(3),db:+snapped.toFixed(1)};const sorted=[...nodes,newNode].sort((a,b)=>a.time-b.time);onUpdateNodes(sorted);const newIdx=sorted.findIndex(n=>n.time===newNode.time&&(graphMode==='pan'?n.pan:n.db)===(graphMode==='pan'?newNode.pan:newNode.db));isDraggingNode.current=true;dragNodeIdx.current=newIdx;isCreatingNode.current=true;};const handleMouseMove=e=>{if(!isDraggingNode.current||dragNodeIdx.current<0)return;const canvas=canvasRef.current;if(!canvas)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const y=e.clientY-rect.top;const time=Math.max(0,Math.min(buffer.duration,x/rect.width*buffer.duration));const val=nodeValFromY(y,rect.height);const nodes=[...getNodes()];nodes[dragNodeIdx.current]=graphMode==='pan'?{time:+time.toFixed(3),pan:+Math.max(-1,Math.min(1,val)).toFixed(2)}:{time:+time.toFixed(3),db:+Math.max(-30,Math.min(3,val)).toFixed(1)};onUpdateNodes(nodes.sort((a,b)=>a.time-b.time));};const handleMouseUp=()=>{isDraggingNode.current=false;dragNodeIdx.current=-1;isCreatingNode.current=false;};const handleContextMenu=e=>{e.preventDefault();const canvas=canvasRef.current;if(!canvas||!buffer)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const time=x/rect.width*buffer.duration;const threshold=12/rect.width*buffer.duration;const nodes=getNodes();const nearIdx=nodes.findIndex(n=>Math.abs(n.time-time)=0)onUpdateNodes(nodes.filter((_,i)=>i!==nearIdx));};return/*#__PURE__*/React.createElement("div",{style:{width:`${timelineWidth}px`,height:'100%',position:'relative',overflow:'hidden'}},/*#__PURE__*/React.createElement("canvas",{ref:canvasRef,style:{position:'absolute',top:0,left:0,imageRendering:'pixelated'},className:"cursor-crosshair rounded border border-zinc-700",onMouseDown:handleMouseDown,onMouseMove:handleMouseMove,onMouseUp:handleMouseUp,onMouseLeave:handleMouseUp,onContextMenu:handleContextMenu}));};const AuthModal=({isOpen,mode,forceMandatory,onClose,onSuccess})=>{if(!isOpen)return null;const[activeTab,setActiveTab]=useState(mode||'login');const[username,setUsername]=useState('admin');const[email,setEmail]=useState('');const[password,setPassword]=useState('');const[oldPassword,setOldPassword]=useState('');const[newPassword,setNewPassword]=useState('');const[error,setError]=useState('');const[loading,setLoading]=useState(false);useEffect(()=>{if(mode)setActiveTab(mode);if(mode==='force_change'&&!oldPassword){setOldPassword('admin123');}},[mode]);const handleSubmit=async e=>{e.preventDefault();setError('');setLoading(true);try{if(activeTab==='login'){const targetUsername=username.trim()||'admin';const targetPwd=password.trim()||'admin123';const res=await window.SonicAPI.login(targetUsername,targetPwd);localStorage.setItem('sonic_token',res.access_token);localStorage.setItem('sonic_user',JSON.stringify(res.user));if(res.user&&res.user.must_change_password){setOldPassword(targetPwd);}onSuccess(res.user,res.access_token);}else if(activeTab==='register'){const res=await window.SonicAPI.register(username.trim(),email.trim(),password.trim());localStorage.setItem('sonic_token',res.access_token);localStorage.setItem('sonic_user',JSON.stringify(res.user));onSuccess(res.user,res.access_token);}else if(activeTab==='force_change'){const res=await window.SonicAPI.changePassword(oldPassword.trim(),newPassword.trim());localStorage.setItem('sonic_token',res.access_token);const user=JSON.parse(localStorage.getItem('sonic_user')||'{}');user.must_change_password=false;localStorage.setItem('sonic_user',JSON.stringify(user));onSuccess(user,res.access_token);}}catch(err){setError(err.message||(activeTab==='login'?'Tài khoản hoặc mật khẩu không chính xác. (Nếu bạn đã đổi mật khẩu trước đó, vui lòng nhập mật khẩu mới mà bạn đã tạo)':'Thao tác không thành công'));}finally{setLoading(false);}};const isForceMode=activeTab==='force_change';const canClose=!forceMandatory&&!isForceMode;return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-md"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-md p-6 text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-4 border-b border-[#383838]"},/*#__PURE__*/React.createElement("h3",{className:"text-lg font-bold text-teal-400"},isForceMode?'⚠️ Bắt Buộc Đổi Mật Khẩu Khởi Tạo':activeTab==='login'?'🔐 Đăng Nhập Hệ Thống':'📝 Đăng Ký Tài Khoản'),canClose&&/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),error&&/*#__PURE__*/React.createElement("div",{className:"mt-4 p-3 bg-red-900/40 border border-red-700 rounded-lg text-red-200 text-sm"},error),/*#__PURE__*/React.createElement("form",{onSubmit:handleSubmit,className:"mt-4 space-y-4"},isForceMode?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("p",{className:"text-xs text-amber-400 bg-amber-950/60 p-2.5 border border-amber-800/80 rounded leading-relaxed"},"🔒 Tài khoản của bạn đang dùng mật khẩu khởi tạo mặc định. Để bảo mật hệ thống, bạn phải đổi mật khẩu mới trước khi tiếp tục."),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Mật khẩu hiện tại (Mặc định: admin123)"),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:"current-password",required:true,value:oldPassword,onChange:e=>setOldPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Mật khẩu mới"),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:"new-password",required:true,value:newPassword,onChange:e=>setNewPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"}))):/*#__PURE__*/React.createElement(React.Fragment,null,activeTab==='login'?/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Tên đăng nhập ",/*#__PURE__*/React.createElement("span",{className:"text-teal-400 font-normal"},"(Tùy chọn - Admin có thể bỏ trống)")),/*#__PURE__*/React.createElement("input",{type:"text",placeholder:"Mặc định: admin",value:username,onChange:e=>setUsername(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"})):/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Tên đăng nhập"),/*#__PURE__*/React.createElement("input",{type:"text",required:true,value:username,onChange:e=>setUsername(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"})),activeTab==='register'&&/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Email"),/*#__PURE__*/React.createElement("input",{type:"email",required:true,value:email,onChange:e=>setEmail(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Mật khẩu ",activeTab==='login'&&/*#__PURE__*/React.createElement("span",{className:"text-amber-400 font-normal"},"(Lần đầu: admin123)")),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:activeTab==='login'?'current-password':'new-password',required:true,value:password,onChange:e=>setPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"}))),/*#__PURE__*/React.createElement("button",{type:"submit",disabled:loading,className:"w-full py-2 bg-teal-600 hover:bg-teal-500 text-white font-semibold rounded-lg shadow transition duration-150"},loading?'Đang xác thực...':isForceMode?'Đổi Mật Khẩu Ngay':activeTab==='login'?'Đăng Nhập System':'Tạo Tài Khoản Mới'),activeTab==='login'&&!isForceMode&&/*#__PURE__*/React.createElement("button",{type:"button",onClick:()=>{setUsername('admin');setPassword('admin123');setError('');},className:"w-full mt-2 py-1.5 bg-amber-950/60 hover:bg-amber-900/80 text-amber-300 border border-amber-800/60 text-xs font-semibold rounded-lg transition flex items-center justify-center gap-1.5"},"🔑 Điền Nhanh Tài Khoản Admin (admin / admin123)")),!isForceMode&&/*#__PURE__*/React.createElement("div",{className:"mt-4 pt-4 border-t border-[#383838] text-center text-xs text-slate-400"},activeTab==='login'?/*#__PURE__*/React.createElement("span",null,"Chưa có tài khoản? ",/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab('register'),className:"text-teal-400 hover:underline"},"Đăng ký ngay")):/*#__PURE__*/React.createElement("span",null,"Đã có tài khoản? ",/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab('login'),className:"text-teal-400 hover:underline"},"Đăng nhập")))));};const AIConfigModal=({isOpen,onClose,onConfigSaved})=>{if(!isOpen)return null;const defaultProvidersList=[{id:'openai_default',name:'OpenAI Official',provider_type:'openai',api_base_url:'https://api.openai.com/v1',api_key:'',model_name:'gpt-4o',temperature:0.7,is_active:true},{id:'openai_compat_default',name:'OpenAI Compatible (Ollama/LocalAI/DeepSeek)',provider_type:'openai_compatible',api_base_url:'http://localhost:11434/v1',api_key:'ollama',model_name:'deepseek-r1',temperature:0.7,is_active:false},{id:'anthropic_default',name:'Anthropic Claude',provider_type:'anthropic',api_base_url:'https://api.anthropic.com/v1',api_key:'',model_name:'claude-3-5-sonnet',temperature:0.7,is_active:false},{id:'gemini_default',name:'Google Gemini',provider_type:'gemini',api_base_url:'https://generativelanguage.googleapis.com',api_key:'',model_name:'gemini-1.5-pro',temperature:0.7,is_active:false}];const[providers,setProviders]=useState(defaultProvidersList);const[selectedId,setSelectedId]=useState('openai_default');const[msg,setMsg]=useState('');const[error,setError]=useState('');const[loading,setLoading]=useState(false);useEffect(()=>{if(isOpen)loadConfigs();},[isOpen]);const loadConfigs=async()=>{setLoading(true);setError('');try{const data=await window.SonicAPI.getAIConfigs();if(data&&data.providers){setProviders(data.providers);if(data.providers.length>0)setSelectedId(data.providers[0].id);}}catch(err){setError(err.message||'Lỗi nạp cấu hình AI');}finally{setLoading(false);}};const handleSave=async e=>{e.preventDefault();setMsg('');setError('');setLoading(true);try{const res=await window.SonicAPI.saveAIConfigs(providers);setMsg(res.message||'Đã lưu cấu hình AI Providers thành công!');if(onConfigSaved)onConfigSaved(providers);}catch(err){setError(err.message||'Lỗi khi lưu cấu hình AI');}finally{setLoading(false);}};const updateProviderField=(id,field,value)=>{setProviders(prev=>prev.map(p=>p.id===id?{...p,[field]:value}:p));};const activeProvider=providers.find(p=>p.id===selectedId)||providers[0];return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm select-none"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-4 border-b border-[#383838]"},/*#__PURE__*/React.createElement("h3",{className:"text-lg font-bold text-cyan-400 flex items-center gap-2"},"🤖 Quản Lý & Cấu Hình AI Providers"),/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),msg&&/*#__PURE__*/React.createElement("div",{className:"mt-3 p-2 bg-emerald-950/60 border border-emerald-700 text-emerald-300 rounded text-xs"},msg),error&&/*#__PURE__*/React.createElement("div",{className:"mt-3 p-2 bg-red-950/60 border border-red-700 text-red-300 rounded text-xs"},error),/*#__PURE__*/React.createElement("div",{className:"mt-4 grid grid-cols-3 gap-4"},/*#__PURE__*/React.createElement("div",{className:"space-y-1.5 border-r border-[#383838] pr-3"},/*#__PURE__*/React.createElement("span",{className:"text-xs uppercase font-bold text-slate-400 block mb-2"},"Providers"),providers.map(p=>/*#__PURE__*/React.createElement("button",{key:p.id,tabIndex:0,onClick:()=>setSelectedId(p.id),onKeyDown:e=>{if(e.key===' '){e.preventDefault();updateProviderField(p.id,'is_active',!p.is_active);}},className:`w-full text-left px-3 py-2 rounded-lg text-xs font-semibold flex items-center justify-between transition ${selectedId===p.id?'bg-cyan-600 text-white shadow':'bg-[#1e1e1e] text-slate-300 hover:bg-[#2e2e2e]'}`},/*#__PURE__*/React.createElement("span",{className:"truncate"},p.name),p.is_active&&/*#__PURE__*/React.createElement("span",{className:"w-2 h-2 rounded-full bg-emerald-400"}))),/*#__PURE__*/React.createElement("div",{className:"flex gap-1 mt-2"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();const newId='provider_'+Date.now();setProviders(prev=>[...prev,{id:newId,name:'New Provider',provider_type:'openai_compatible',api_base_url:'https://api.openai.com/v1',api_key:'',model_name:'gpt-4o-mini',temperature:0.7,is_active:false}]);setSelectedId(newId);},className:"flex-1 px-2 py-1 bg-emerald-700 hover:bg-emerald-600 text-white text-xs font-bold rounded"},"+ Thêm"),providers.length>1&&/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();if(confirm(`Xóa provider "${providers.find(p=>p.id===selectedId)?.name}"?`)){setProviders(prev=>{const filtered=prev.filter(p=>p.id!==selectedId);if(filtered.length>0)setSelectedId(filtered[0].id);return filtered;});}},className:"px-2 py-1 bg-red-800 hover:bg-red-700 text-white text-xs font-bold rounded"},"Xóa"),providers.length>1&&/*#__PURE__*/React.createElement("button",{onClick:function(e){e.stopPropagation();var provs=providers.slice();var pos=-1;for(var pi=0;pi0){var tmp=provs[pos];provs[pos]=provs[pos-1];provs[pos-1]=tmp;setProviders(provs);}},className:"px-2 py-1 bg-zinc-700 hover:bg-zinc-600 text-white text-xs font-bold rounded",title:"Di chuyển lên"},"▲"),providers.length>1&&/*#__PURE__*/React.createElement("button",{onClick:function(e){e.stopPropagation();var provs=providers.slice();var pos=-1;for(var pi=0;piupdateProviderField(activeProvider.id,'name',e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-cyan-500"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold text-slate-400 mb-1"},"API Base URL (Endpoint)"),/*#__PURE__*/React.createElement("input",{type:"text",value:activeProvider.api_base_url||'',onChange:e=>updateProviderField(activeProvider.id,'api_base_url',e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs font-mono text-cyan-300 focus:outline-none focus:border-cyan-500",placeholder:"https://api.openai.com/v1"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold text-slate-400 mb-1"},"API Key Cá Nhân"),/*#__PURE__*/React.createElement("input",{type:"password",value:activeProvider.api_key||'',onChange:e=>updateProviderField(activeProvider.id,'api_key',e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs font-mono text-slate-200 focus:outline-none focus:border-cyan-500",placeholder:"sk-..."})),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-3"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold text-slate-400 mb-1"},"Model Name"),/*#__PURE__*/React.createElement("input",{type:"text",value:activeProvider.model_name||'',onChange:e=>updateProviderField(activeProvider.id,'model_name',e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs font-mono text-amber-300 focus:outline-none focus:border-cyan-500"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold text-slate-400 mb-1"},"Temperature"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.1",min:"0",max:"2",value:activeProvider.temperature??0.7,onChange:e=>updateProviderField(activeProvider.id,'temperature',parseFloat(e.target.value)),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-cyan-500"}))),/*#__PURE__*/React.createElement("div",{className:"pt-2 flex items-center justify-between"},/*#__PURE__*/React.createElement("label",{className:"flex items-center gap-2 cursor-pointer text-xs text-slate-300"},/*#__PURE__*/React.createElement("input",{type:"checkbox",checked:activeProvider.is_active,onChange:e=>updateProviderField(activeProvider.id,'is_active',e.target.checked),className:"rounded accent-cyan-500"}),"Kích hoạt Provider này"),/*#__PURE__*/React.createElement("button",{type:"submit",disabled:loading,className:"px-4 py-1.5 bg-cyan-600 hover:bg-cyan-500 text-white font-semibold text-xs rounded-lg shadow transition"},loading?'Đang lưu...':'Lưu Cấu Hình AI'))))));};const ProfileModal=({isOpen,onClose,tracks,setTracks,setSelectedTrackId,projectName,setProjectName,currentProjectId,setCurrentProjectId,showToast})=>{if(!isOpen)return null;const[activeTab,setActiveTab]=useState('account');const[profile,setProfile]=useState(null);const[oldPassword,setOldPassword]=useState('');const[newPassword,setNewPassword]=useState('');const[msg,setMsg]=useState('');const[error,setError]=useState('');const[loading,setLoading]=useState(false);const[dragOfs,setDragOfs]=useState({x:0,y:0});const dragRef=useRef({active:false,startX:0,startY:0,ofsX:0,ofsY:0});// Projects list state +const GraphEditorCanvas=({buffer,zoom,timelineWidth,volumeNodes,panningNodes,fadeInLen,fadeOutLen,onUpdateNodes,graphMode})=>{const canvasRef=useRef(null);const isDraggingNode=useRef(false);const dragNodeIdx=useRef(-1);const isCreatingNode=useRef(false);const getNodes=()=>graphMode==='pan'?panningNodes:volumeNodes;const nodeLabel=n=>graphMode==='pan'?`${n.pan.toFixed(2)}`:`${n.db.toFixed(1)}dB`;const nodeY=(n,h)=>{if(graphMode==='pan')return(1-(n.pan+1)/2)*h;const zeroY=2/3*h;return n.db>=0?zeroY-n.db/3*(2/3*h):zeroY+-n.db/30*(1/3*h);};const nodeValFromY=(y,h)=>{if(graphMode==='pan')return-(y/h*2-1);const yOff=y/h;return yOff<=2/3?3*(1-yOff*3/2):-30*(yOff-2/3)*3;};useEffect(()=>{const canvas=canvasRef.current;if(!canvas||!buffer)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=wrapper?wrapper.clientWidth:1200;const drawWidth=Math.min(timelineWidth,Math.max(vWidth,1200));const h=canvas.parentElement?canvas.parentElement.clientHeight:200;canvas.width=Math.round(drawWidth*dpr);canvas.height=Math.round(h*dpr);ctx.scale(dpr,dpr);ctx.imageSmoothingEnabled=false;canvas.style.position='absolute';canvas.style.left=`${scrollLeft}px`;canvas.style.width=`${drawWidth}px`;canvas.style.height=`${h}px`;ctx.fillStyle='#1a1a2e';ctx.fillRect(0,0,drawWidth,h);ctx.strokeStyle='#2a2a4e';ctx.lineWidth=0.5;for(let t=0;t<=buffer.duration;t+=0.5){const x=t/buffer.duration*drawWidth;ctx.beginPath();ctx.moveTo(x,0);ctx.lineTo(x,h);ctx.stroke();}for(let i=0;i<=10;i++){const y=i/10*h;ctx.beginPath();ctx.moveTo(0,y);ctx.lineTo(drawWidth,y);ctx.stroke();}if(fadeInLen>0){const fadeX=fadeInLen/buffer.duration*drawWidth;ctx.fillStyle='rgba(16, 185, 129, 0.12)';ctx.fillRect(0,0,fadeX,h);}if(fadeOutLen>0){const fadeX=(buffer.duration-fadeOutLen)/buffer.duration*drawWidth;const fadeW=fadeOutLen/buffer.duration*drawWidth;ctx.fillStyle='rgba(239, 68, 68, 0.12)';ctx.fillRect(fadeX,0,fadeW,h);}const nodes=getNodes();if(nodes.length>0){ctx.strokeStyle=graphMode==='pan'?'#a855f7':'#06b6d4';ctx.lineWidth=2;ctx.beginPath();nodes.forEach((n,i)=>{const x=n.time/buffer.duration*drawWidth;const y=nodeY(n,h);if(i===0)ctx.moveTo(x,y);else ctx.lineTo(x,y);});ctx.stroke();nodes.forEach((n,i)=>{const x=n.time/buffer.duration*drawWidth;const y=nodeY(n,h);ctx.fillStyle=graphMode==='pan'?'#a855f7':'#06b6d4';ctx.beginPath();ctx.arc(x,y,5,0,Math.PI*2);ctx.fill();ctx.fillStyle='#e4e4e7';ctx.font='9px monospace';ctx.fillText(nodeLabel(n),x+8,y+3);});}else{ctx.fillStyle='#52525b';ctx.font='11px sans-serif';ctx.textAlign='center';ctx.fillText(graphMode==='pan'?'Click to add Pan points':'Click to add Volume points',drawWidth/2,h/2);ctx.textAlign='start';}const zeroY=graphMode==='pan'?h/2:nodeY({db:0},h);ctx.strokeStyle=graphMode==='pan'?'#a855f744':'#06b6d444';ctx.lineWidth=1;ctx.setLineDash([4,4]);ctx.beginPath();ctx.moveTo(0,zeroY);ctx.lineTo(drawWidth,zeroY);ctx.stroke();ctx.setLineDash([]);},[buffer,zoom,timelineWidth,volumeNodes,panningNodes,fadeInLen,fadeOutLen,graphMode]);const handleMouseDown=e=>{const canvas=canvasRef.current;if(!canvas||!buffer)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const y=e.clientY-rect.top;const time=x/rect.width*buffer.duration;const val=nodeValFromY(y,rect.height);const nodes=getNodes();const snapped=Math.max(-30,Math.min(3,val));const snappedPan=Math.max(-1,Math.min(1,val));const threshold=12/rect.width*buffer.duration;const nearIdx=nodes.findIndex(n=>Math.abs(n.time-time)=0){isDraggingNode.current=true;dragNodeIdx.current=nearIdx;return;}const newNode=graphMode==='pan'?{time:+time.toFixed(3),pan:+snappedPan.toFixed(2)}:{time:+time.toFixed(3),db:+snapped.toFixed(1)};const sorted=[...nodes,newNode].sort((a,b)=>a.time-b.time);onUpdateNodes(sorted);const newIdx=sorted.findIndex(n=>n.time===newNode.time&&(graphMode==='pan'?n.pan:n.db)===(graphMode==='pan'?newNode.pan:newNode.db));isDraggingNode.current=true;dragNodeIdx.current=newIdx;isCreatingNode.current=true;};const handleMouseMove=e=>{if(!isDraggingNode.current||dragNodeIdx.current<0)return;const canvas=canvasRef.current;if(!canvas)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const y=e.clientY-rect.top;const time=Math.max(0,Math.min(buffer.duration,x/rect.width*buffer.duration));const val=nodeValFromY(y,rect.height);const nodes=[...getNodes()];nodes[dragNodeIdx.current]=graphMode==='pan'?{time:+time.toFixed(3),pan:+Math.max(-1,Math.min(1,val)).toFixed(2)}:{time:+time.toFixed(3),db:+Math.max(-30,Math.min(3,val)).toFixed(1)};onUpdateNodes(nodes.sort((a,b)=>a.time-b.time));};const handleMouseUp=()=>{isDraggingNode.current=false;dragNodeIdx.current=-1;isCreatingNode.current=false;};const handleContextMenu=e=>{e.preventDefault();const canvas=canvasRef.current;if(!canvas||!buffer)return;const rect=canvas.getBoundingClientRect();const x=e.clientX-rect.left;const time=x/rect.width*buffer.duration;const threshold=12/rect.width*buffer.duration;const nodes=getNodes();const nearIdx=nodes.findIndex(n=>Math.abs(n.time-time)=0)onUpdateNodes(nodes.filter((_,i)=>i!==nearIdx));};return/*#__PURE__*/React.createElement("div",{style:{width:`${timelineWidth}px`,height:'100%',position:'relative',overflow:'hidden'}},/*#__PURE__*/React.createElement("canvas",{ref:canvasRef,style:{position:'absolute',top:0,left:0,imageRendering:'pixelated'},className:"cursor-crosshair rounded border border-zinc-700",onMouseDown:handleMouseDown,onMouseMove:handleMouseMove,onMouseUp:handleMouseUp,onMouseLeave:handleMouseUp,onContextMenu:handleContextMenu}));};const AuthModal=({isOpen,mode,forceMandatory,onClose,onSuccess})=>{if(!isOpen)return null;const[activeTab,setActiveTab]=useState(mode||'login');const[username,setUsername]=useState('admin');const[email,setEmail]=useState('');const[password,setPassword]=useState('');const[oldPassword,setOldPassword]=useState('');const[newPassword,setNewPassword]=useState('');const[error,setError]=useState('');const[loading,setLoading]=useState(false);useEffect(()=>{if(mode)setActiveTab(mode);if(mode==='force_change'&&!oldPassword){setOldPassword('admin123');}},[mode]);const handleSubmit=async e=>{e.preventDefault();setError('');setLoading(true);try{if(activeTab==='login'){const targetUsername=username.trim()||'admin';const targetPwd=password.trim()||'admin123';const res=await window.SonicAPI.login(targetUsername,targetPwd);localStorage.setItem('sonic_token',res.access_token);localStorage.setItem('sonic_user',JSON.stringify(res.user));if(res.user&&res.user.must_change_password){setOldPassword(targetPwd);}onSuccess(res.user,res.access_token);}else if(activeTab==='register'){const res=await window.SonicAPI.register(username.trim(),email.trim(),password.trim());localStorage.setItem('sonic_token',res.access_token);localStorage.setItem('sonic_user',JSON.stringify(res.user));onSuccess(res.user,res.access_token);}else if(activeTab==='force_change'){const res=await window.SonicAPI.changePassword(oldPassword.trim(),newPassword.trim());localStorage.setItem('sonic_token',res.access_token);const user=JSON.parse(localStorage.getItem('sonic_user')||'{}');user.must_change_password=false;localStorage.setItem('sonic_user',JSON.stringify(user));onSuccess(user,res.access_token);}}catch(err){setError(err.message||(activeTab==='login'?'Tài khoản hoặc mật khẩu không chính xác. (Nếu bạn đã đổi mật khẩu trước đó, vui lòng nhập mật khẩu mới mà bạn đã tạo)':'Thao tác không thành công'));}finally{setLoading(false);}};const isForceMode=activeTab==='force_change';const canClose=!forceMandatory&&!isForceMode;return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/80 backdrop-blur-md"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-md p-6 text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-4 border-b border-[#383838]"},/*#__PURE__*/React.createElement("h3",{className:"text-lg font-bold text-teal-400"},isForceMode?'⚠️ Bắt Buộc Đổi Mật Khẩu Khởi Tạo':activeTab==='login'?'🔐 Đăng Nhập Hệ Thống':'📝 Đăng Ký Tài Khoản'),canClose&&/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),error&&/*#__PURE__*/React.createElement("div",{className:"mt-4 p-3 bg-red-900/40 border border-red-700 rounded-lg text-red-200 text-sm"},error),/*#__PURE__*/React.createElement("form",{onSubmit:handleSubmit,className:"mt-4 space-y-4"},isForceMode?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("p",{className:"text-xs text-amber-400 bg-amber-950/60 p-2.5 border border-amber-800/80 rounded leading-relaxed"},"🔒 Tài khoản của bạn đang dùng mật khẩu khởi tạo mặc định. Để bảo mật hệ thống, bạn phải đổi mật khẩu mới trước khi tiếp tục."),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Mật khẩu hiện tại (Mặc định: admin123)"),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:"current-password",required:true,value:oldPassword,onChange:e=>setOldPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Mật khẩu mới"),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:"new-password",required:true,value:newPassword,onChange:e=>setNewPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"}))):/*#__PURE__*/React.createElement(React.Fragment,null,activeTab==='login'?/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Tên đăng nhập ",/*#__PURE__*/React.createElement("span",{className:"text-teal-400 font-normal"},"(Tùy chọn - Admin có thể bỏ trống)")),/*#__PURE__*/React.createElement("input",{type:"text",placeholder:"Mặc định: admin",value:username,onChange:e=>setUsername(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"})):/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Tên đăng nhập"),/*#__PURE__*/React.createElement("input",{type:"text",required:true,value:username,onChange:e=>setUsername(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"})),activeTab==='register'&&/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Email"),/*#__PURE__*/React.createElement("input",{type:"email",required:true,value:email,onChange:e=>setEmail(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold mb-1 text-slate-400"},"Mật khẩu ",activeTab==='login'&&/*#__PURE__*/React.createElement("span",{className:"text-amber-400 font-normal"},"(Lần đầu: admin123)")),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:activeTab==='login'?'current-password':'new-password',required:true,value:password,onChange:e=>setPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-2 text-sm focus:outline-none focus:border-teal-500"}))),/*#__PURE__*/React.createElement("button",{type:"submit",disabled:loading,className:"w-full py-2 bg-teal-600 hover:bg-teal-500 text-white font-semibold rounded-lg shadow transition duration-150"},loading?'Đang xác thực...':isForceMode?'Đổi Mật Khẩu Ngay':activeTab==='login'?'Đăng Nhập System':'Tạo Tài Khoản Mới'),activeTab==='login'&&!isForceMode&&/*#__PURE__*/React.createElement("button",{type:"button",onClick:()=>{setUsername('admin');setPassword('admin123');setError('');},className:"w-full mt-2 py-1.5 bg-amber-950/60 hover:bg-amber-900/80 text-amber-300 border border-amber-800/60 text-xs font-semibold rounded-lg transition flex items-center justify-center gap-1.5"},"🔑 Điền Nhanh Tài Khoản Admin (admin / admin123)")),!isForceMode&&/*#__PURE__*/React.createElement("div",{className:"mt-4 pt-4 border-t border-[#383838] text-center text-xs text-slate-400"},activeTab==='login'?/*#__PURE__*/React.createElement("span",null,"Chưa có tài khoản? ",/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab('register'),className:"text-teal-400 hover:underline"},"Đăng ký ngay")):/*#__PURE__*/React.createElement("span",null,"Đã có tài khoản? ",/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab('login'),className:"text-teal-400 hover:underline"},"Đăng nhập")))));};const AIConfigModal=({isOpen,onClose,onConfigSaved})=>{if(!isOpen)return null;const defaultProvidersList=[{id:'openai_default',name:'OpenAI Official',provider_type:'openai',api_base_url:'https://api.openai.com/v1',api_key:'',model_name:'gpt-4o',temperature:0.7,is_active:true},{id:'openai_compat_default',name:'OpenAI Compatible (Ollama/LocalAI/DeepSeek)',provider_type:'openai_compatible',api_base_url:'http://localhost:11434/v1',api_key:'ollama',model_name:'deepseek-r1',temperature:0.7,is_active:false},{id:'anthropic_default',name:'Anthropic Claude',provider_type:'anthropic',api_base_url:'https://api.anthropic.com/v1',api_key:'',model_name:'claude-3-5-sonnet',temperature:0.7,is_active:false},{id:'gemini_default',name:'Google Gemini',provider_type:'gemini',api_base_url:'https://generativelanguage.googleapis.com',api_key:'',model_name:'gemini-1.5-pro',temperature:0.7,is_active:false}];const[providers,setProviders]=useState(defaultProvidersList);const[selectedId,setSelectedId]=useState('openai_default');const[msg,setMsg]=useState('');const[error,setError]=useState('');const[loading,setLoading]=useState(false);useEffect(()=>{if(isOpen)loadConfigs();},[isOpen]);const loadConfigs=async()=>{setLoading(true);setError('');try{const data=await window.SonicAPI.getAIConfigs();if(data&&data.providers){setProviders(data.providers);if(data.providers.length>0)setSelectedId(data.providers[0].id);}}catch(err){setError(err.message||'Lỗi nạp cấu hình AI');}finally{setLoading(false);}};const handleSave=async e=>{e.preventDefault();setMsg('');setError('');setLoading(true);try{const res=await window.SonicAPI.saveAIConfigs(providers);setMsg(res.message||'Đã lưu cấu hình AI Providers thành công!');if(onConfigSaved)onConfigSaved(providers);}catch(err){setError(err.message||'Lỗi khi lưu cấu hình AI');}finally{setLoading(false);}};const updateProviderField=(id,field,value)=>{setProviders(prev=>prev.map(p=>p.id===id?{...p,[field]:value}:p));};const activeProvider=providers.find(p=>p.id===selectedId)||providers[0];return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm select-none"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-4 border-b border-[#383838]"},/*#__PURE__*/React.createElement("h3",{className:"text-lg font-bold text-cyan-400 flex items-center gap-2"},"🤖 Quản Lý & Cấu Hình AI Providers"),/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),msg&&/*#__PURE__*/React.createElement("div",{className:"mt-3 p-2 bg-emerald-950/60 border border-emerald-700 text-emerald-300 rounded text-xs"},msg),error&&/*#__PURE__*/React.createElement("div",{className:"mt-3 p-2 bg-red-950/60 border border-red-700 text-red-300 rounded text-xs"},error),/*#__PURE__*/React.createElement("div",{className:"mt-4 grid grid-cols-3 gap-4"},/*#__PURE__*/React.createElement("div",{className:"space-y-1.5 border-r border-[#383838] pr-3"},/*#__PURE__*/React.createElement("span",{className:"text-xs uppercase font-bold text-slate-400 block mb-2"},"Providers"),providers.map(p=>/*#__PURE__*/React.createElement("button",{key:p.id,tabIndex:0,onClick:()=>setSelectedId(p.id),onKeyDown:e=>{if(e.key===' '){e.preventDefault();updateProviderField(p.id,'is_active',!p.is_active);}},className:`w-full text-left px-3 py-2 rounded-lg text-xs font-semibold flex items-center justify-between transition ${selectedId===p.id?'bg-cyan-600 text-white shadow':'bg-[#1e1e1e] text-slate-300 hover:bg-[#2e2e2e]'}`},/*#__PURE__*/React.createElement("span",{className:"truncate"},p.name),p.is_active&&/*#__PURE__*/React.createElement("span",{className:"w-2 h-2 rounded-full bg-emerald-400"}))),/*#__PURE__*/React.createElement("div",{className:"flex gap-1 mt-2"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();const newId='provider_'+Date.now();setProviders(prev=>[...prev,{id:newId,name:'New Provider',provider_type:'openai_compatible',api_base_url:'https://api.openai.com/v1',api_key:'',model_name:'gpt-4o-mini',temperature:0.7,is_active:false}]);setSelectedId(newId);},className:"flex-1 px-2 py-1 bg-emerald-700 hover:bg-emerald-600 text-white text-xs font-bold rounded"},"+ Thêm"),providers.length>1&&/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();if(confirm(`Xóa provider "${providers.find(p=>p.id===selectedId)?.name}"?`)){setProviders(prev=>{const filtered=prev.filter(p=>p.id!==selectedId);if(filtered.length>0)setSelectedId(filtered[0].id);return filtered;});}},className:"px-2 py-1 bg-red-800 hover:bg-red-700 text-white text-xs font-bold rounded"},"Xóa"),providers.length>1&&/*#__PURE__*/React.createElement("button",{onClick:function(e){e.stopPropagation();var provs=providers.slice();var pos=-1;for(var pi=0;pi0){var tmp=provs[pos];provs[pos]=provs[pos-1];provs[pos-1]=tmp;setProviders(provs);}},className:"px-2 py-1 bg-zinc-700 hover:bg-zinc-600 text-white text-xs font-bold rounded",title:"Di chuyển lên"},"▲"),providers.length>1&&/*#__PURE__*/React.createElement("button",{onClick:function(e){e.stopPropagation();var provs=providers.slice();var pos=-1;for(var pi=0;piupdateProviderField(activeProvider.id,'name',e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-cyan-500"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold text-slate-400 mb-1"},"API Base URL (Endpoint)"),/*#__PURE__*/React.createElement("input",{type:"text",value:activeProvider.api_base_url||'',onChange:e=>updateProviderField(activeProvider.id,'api_base_url',e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs font-mono text-cyan-300 focus:outline-none focus:border-cyan-500",placeholder:"https://api.openai.com/v1"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold text-slate-400 mb-1"},"API Key Cá Nhân"),/*#__PURE__*/React.createElement("input",{type:"password",value:activeProvider.api_key||'',onChange:e=>updateProviderField(activeProvider.id,'api_key',e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs font-mono text-slate-200 focus:outline-none focus:border-cyan-500",placeholder:"sk-..."})),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-3"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold text-slate-400 mb-1"},"Model Name"),/*#__PURE__*/React.createElement("input",{type:"text",value:activeProvider.model_name||'',onChange:e=>updateProviderField(activeProvider.id,'model_name',e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs font-mono text-amber-300 focus:outline-none focus:border-cyan-500"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-xs font-semibold text-slate-400 mb-1"},"Temperature"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.1",min:"0",max:"2",value:activeProvider.temperature??0.7,onChange:e=>updateProviderField(activeProvider.id,'temperature',parseFloat(e.target.value)),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-cyan-500"}))),/*#__PURE__*/React.createElement("div",{className:"pt-2 flex items-center justify-between"},/*#__PURE__*/React.createElement("label",{className:"flex items-center gap-2 cursor-pointer text-xs text-slate-300"},/*#__PURE__*/React.createElement("input",{type:"checkbox",checked:activeProvider.is_active,onChange:e=>updateProviderField(activeProvider.id,'is_active',e.target.checked),className:"rounded accent-cyan-500"}),"Kích hoạt Provider này"),/*#__PURE__*/React.createElement("button",{type:"submit",disabled:loading,className:"px-4 py-1.5 bg-cyan-600 hover:bg-cyan-500 text-white font-semibold text-xs rounded-lg shadow transition"},loading?'Đang lưu...':'Lưu Cấu Hình AI'))))));};const PluginManagerModal=({isOpen,onClose,pluginsData})=>{if(!isOpen)return null;const[localData,setLocalData]=React.useState(pluginsData);const[sfUploadStatus,setSfUploadStatus]=React.useState('');React.useEffect(()=>{if(isOpen&&!localData){window.SonicAPI.listPlugins().then(data=>setLocalData(data)).catch(()=>setLocalData({vst_instruments:[],soundfonts:[]}));}},[isOpen]);const handleUploadSF=async e=>{const file=e.target.files?.[0];if(!file)return;setSfUploadStatus('Uploading...');try{const result=await window.SonicAPI.uploadSoundFont(file);setSfUploadStatus('Uploaded: '+result.name);// Refresh plugin list +const data=await window.SonicAPI.listPlugins();setLocalData(data);}catch(err){setSfUploadStatus('Error: '+err.message);}};const vsts=localData?.vst_instruments||[];const sfs=localData?.soundfonts||[];return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm",onClick:onClose},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-4 border-b border-[#383838]"},/*#__PURE__*/React.createElement("h3",{className:"text-lg font-bold text-cyan-400"},"Plugin Manager (SoundFont / VSTi)"),/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),/*#__PURE__*/React.createElement("div",{className:"mt-4 space-y-4"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("h4",{className:"text-sm font-bold text-purple-400 mb-2 uppercase"},"VST Instruments"),vsts.length===0?/*#__PURE__*/React.createElement("p",{className:"text-xs text-zinc-500"},"No VST instruments available on server."):/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-1 gap-1"},vsts.map((v,i)=>/*#__PURE__*/React.createElement("div",{key:i,className:"flex items-center justify-between bg-[#1e1e1e] px-3 py-2 rounded border border-[#333]"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-slate-200"},v.id),/*#__PURE__*/React.createElement("span",{className:"text-[10px] text-cyan-400 bg-cyan-950/40 px-1.5 py-0.5 rounded"},v.type))))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("h4",{className:"text-sm font-bold text-amber-400 mb-2 uppercase"},"SoundFonts"),sfs.length===0?/*#__PURE__*/React.createElement("p",{className:"text-xs text-zinc-500"},"No SoundFonts available."):/*#__PURE__*/React.createElement("div",{className:"space-y-1"},sfs.map((sf,i)=>/*#__PURE__*/React.createElement("div",{key:i,className:"flex items-center justify-between bg-[#1e1e1e] px-3 py-2 rounded border border-[#333]"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-slate-200"},sf.name))))),/*#__PURE__*/React.createElement("div",{className:"pt-4 border-t border-[#383838]"},/*#__PURE__*/React.createElement("h4",{className:"text-sm font-bold text-emerald-400 mb-2 uppercase"},"Upload SoundFont"),/*#__PURE__*/React.createElement("input",{type:"file",accept:".sf2,.sf3",onChange:handleUploadSF,className:"w-full text-xs text-zinc-400 file:mr-2 file:py-1 file:px-3 file:rounded file:border-0 file:text-xs file:font-semibold file:bg-emerald-700 file:text-white hover:file:bg-emerald-600"}),sfUploadStatus&&/*#__PURE__*/React.createElement("p",{className:"text-xs mt-1 text-zinc-400"},sfUploadStatus)))));};const ProfileModal=({isOpen,onClose,tracks,setTracks,setSelectedTrackId,projectName,setProjectName,currentProjectId,setCurrentProjectId,showToast})=>{if(!isOpen)return null;const[activeTab,setActiveTab]=useState('account');const[profile,setProfile]=useState(null);const[oldPassword,setOldPassword]=useState('');const[newPassword,setNewPassword]=useState('');const[msg,setMsg]=useState('');const[error,setError]=useState('');const[loading,setLoading]=useState(false);const[dragOfs,setDragOfs]=useState({x:0,y:0});const dragRef=useRef({active:false,startX:0,startY:0,ofsX:0,ofsY:0});// Projects list state const[projectsList,setProjectsList]=useState([]);const[loadingProjects,setLoadingProjects]=useState(false);// Files list state const[filesList,setFilesList]=useState([]);const[loadingFiles,setLoadingFiles]=useState(false);// Confirmation modal state -const[confirmModal,setConfirmModal]=useState(null);const handleDragStart=e=>{const r=dragRef.current;r.active=true;r.startX=e.clientX;r.startY=e.clientY;r.ofsX=dragOfs.x;r.ofsY=dragOfs.y;const onMove=ev=>{if(!r.active)return;setDragOfs({x:r.ofsX+ev.clientX-r.startX,y:r.ofsY+ev.clientY-r.startY});};const onUp=()=>{r.active=false;document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);};useEffect(()=>{if(isOpen){fetchProfile();if(activeTab==='projects')fetchProjects();if(activeTab==='files')fetchFiles();}},[isOpen,activeTab]);const fetchProfile=async()=>{try{const data=await window.SonicAPI.getProfile();setProfile(data);}catch(e){setError(e.message||'Không thể tải thông tin profile');}};const fetchProjects=async()=>{setLoadingProjects(true);try{const data=await window.SonicAPI.listCloudProjects();setProjectsList(data||[]);}catch(e){showToast(e.message||'Không thể tải danh sách dự án','error');}finally{setLoadingProjects(false);}};const fetchFiles=async()=>{setLoadingFiles(true);try{const activeFileIds=tracks.map(t=>t.serverFileId).filter(Boolean);const data=await window.SonicAPI.listMyFiles(activeFileIds);setFilesList(data||[]);}catch(e){showToast(e.message||'Không thể tải danh sách tệp tin','error');}finally{setLoadingFiles(false);}};const handleOpenProject=async projectId=>{setAppWarningModal({title:"Mở dự án",message:"Bạn có muốn mở dự án này? Các thay đổi chưa lưu trên workspace hiện tại sẽ bị mất.",isAlert:false,onConfirm:async()=>{try{const proj=await window.SonicAPI.getCloudProject(projectId);const parsed=JSON.parse(proj.data_json);let restoredTracks=[];let restoredBpm=bpm;let restoredSessionTabs=[];if(parsed.main_session){const result=deserializeProjectFromSchema(parsed);restoredTracks=result.tracks;restoredBpm=result.bpm;restoredSessionTabs=result.sessionTabs;}else{restoredTracks=(parsed.tracks||[]).map(t=>{const{height:_h,...rest}=t;return{...rest,buffer:null,channelInfo:t.channelInfo||null,clips:t.clips||[],serverFileId:t.serverFileId||null};});}setTracks(restoredTracks);setBpm(restoredBpm.toString());setSelectedTrackId(restoredTracks[0]?.id||'1');setProjectName(proj.name);setCurrentProjectId(proj.id);if(restoredSessionTabs.length>0){setSessionTabs(restoredSessionTabs);}localStorage.setItem('sonic_project_name',proj.name);localStorage.setItem('sonic_project_id',proj.id);showToast(`Đã nạp dự án "${proj.name}" thành công!`,"success");}catch(e){showToast(e.message||"Lỗi khi nạp dự án","error");}}});};const handleDeleteProject=async(projectId,e)=>{e.stopPropagation();setConfirmModal({title:"Xóa dự án Cloud",message:"Bạn có chắc chắn muốn xóa dự án này khỏi Cloud? Hành động này không thể hoàn tác.",onConfirm:async()=>{try{await window.SonicAPI.deleteCloudProject(projectId);showToast("Đã xóa dự án thành công!","success");fetchProjects();fetchProfile();}catch(err){showToast(err.message||"Lỗi khi xóa dự án","error");}}});};const handleDeleteFile=async fileId=>{if(!confirm(`Bạn có chắc chắn muốn xóa tệp tin ${fileId}?`))return;try{await window.SonicAPI.deleteMyFile(fileId);showToast("Đã xóa tệp tin thành công!","success");fetchFiles();fetchProfile();}catch(err){showToast(err.message||"Lỗi khi xóa tệp tin","error");}};const handleCleanUnusedFiles=async()=>{const unusedFiles=filesList.filter(f=>!f.is_in_use);if(unusedFiles.length===0){showToast("Không có tập tin rác nào để dọn dẹp.","info");return;}if(!confirm(`Bạn có chắc chắn muốn xóa tất cả ${unusedFiles.length} tập tin rác để giải phóng dung lượng?`))return;let successCount=0;for(const file of unusedFiles){try{await window.SonicAPI.deleteMyFile(file.file_id);successCount++;}catch(e){console.error("Lỗi xóa file rác: ",file.file_id,e);}}showToast(`Đã dọn dẹp thành công ${successCount}/${unusedFiles.length} tập tin rác!`,"success");fetchFiles();fetchProfile();};const handleChangePassword=async e=>{e.preventDefault();setMsg('');setError('');setLoading(true);try{const res=await window.SonicAPI.changePassword(oldPassword,newPassword);setMsg(res.message||'Đổi mật khẩu thành công!');setOldPassword('');setNewPassword('');}catch(err){setError(err.message||'Lỗi khi đổi mật khẩu');}finally{setLoading(false);}};const modalStyle={left:`calc(50% + ${dragOfs.x}px)`,top:`calc(50% + ${dragOfs.y}px)`,transform:'translate(-50%, -50%)'};return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{key:"backdrop",className:"fixed inset-0 z-40 bg-black/70 backdrop-blur-sm",onClick:onClose}),confirmModal&&/*#__PURE__*/React.createElement("div",{key:"confirm-overlay",className:"fixed inset-0 z-[60] flex items-center justify-center bg-black/50"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-lg shadow-2xl p-5 max-w-sm w-full text-slate-200"},/*#__PURE__*/React.createElement("h4",{className:"text-sm font-bold text-rose-400 mb-2"},confirmModal.title),/*#__PURE__*/React.createElement("p",{className:"text-xs text-slate-300 mb-4"},confirmModal.message),/*#__PURE__*/React.createElement("div",{className:"flex justify-end gap-2"},/*#__PURE__*/React.createElement("button",{onClick:()=>setConfirmModal(null),className:"px-3 py-1.5 bg-zinc-700 hover:bg-zinc-600 text-slate-300 rounded text-xs font-semibold"},"Hủy"),/*#__PURE__*/React.createElement("button",{onClick:()=>{const fn=confirmModal.onConfirm;setConfirmModal(null);fn();},className:"px-3 py-1.5 bg-rose-700 hover:bg-rose-600 text-white rounded text-xs font-semibold"},"Xác nhận xóa")))),/*#__PURE__*/React.createElement("div",{key:"dialog",className:"fixed z-50 bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200 flex flex-col max-h-[85vh]",style:modalStyle},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-3 border-b border-[#383838] shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:handleDragStart},/*#__PURE__*/React.createElement("h3",{className:"text-md font-bold text-teal-400 flex items-center gap-1.5"},"👤 Hồ Sơ Cá Nhân & Quản Lý Dự Án"),/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),/*#__PURE__*/React.createElement("div",{className:"flex gap-2 border-b border-[#383838] py-2 shrink-0 text-xs font-semibold"},[/*#__PURE__*/React.createElement("button",{key:"tab-acc",onClick:()=>setActiveTab('account'),className:`px-3 py-1.5 rounded transition ${activeTab==='account'?'bg-teal-950/60 text-teal-300 border border-teal-800':'text-slate-400 hover:text-slate-200'}`},"Tài Khoản"),/*#__PURE__*/React.createElement("button",{key:"tab-proj",onClick:()=>setActiveTab('projects'),className:`px-3 py-1.5 rounded transition ${activeTab==='projects'?'bg-teal-950/60 text-teal-300 border border-teal-800':'text-slate-400 hover:text-slate-200'}`},"Dự Án Cloud"),/*#__PURE__*/React.createElement("button",{key:"tab-files",onClick:()=>setActiveTab('files'),className:`px-3 py-1.5 rounded transition ${activeTab==='files'?'bg-teal-950/60 text-teal-300 border border-teal-800':'text-slate-400 hover:text-slate-200'}`},"Tập Tin Của Tôi")]),/*#__PURE__*/React.createElement("div",{className:"flex-1 overflow-y-auto pt-4 space-y-4 pr-1 min-h-[300px]"},activeTab==='account'&&profile?[/*#__PURE__*/React.createElement("div",{key:"quota-info",className:"bg-[#1e1e1e] p-4 rounded-lg border border-[#333] grid grid-cols-2 gap-4 text-xs"},[/*#__PURE__*/React.createElement("div",{key:"username"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-500 block"},"Tên người dùng"),/*#__PURE__*/React.createElement("span",{className:"font-bold text-teal-300 text-sm"},profile.username)]),/*#__PURE__*/React.createElement("div",{key:"role"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-500 block"},"Vai trò"),/*#__PURE__*/React.createElement("span",{className:"uppercase font-semibold text-amber-400"},profile.role)]),/*#__PURE__*/React.createElement("div",{key:"email"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-500 block"},"Email"),/*#__PURE__*/React.createElement("span",null,profile.email)]),/*#__PURE__*/React.createElement("div",{key:"quota"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-500 block"},"Dung lượng Quota"),/*#__PURE__*/React.createElement("span",{className:"font-semibold text-slate-200"},`${profile.quota.used_mb} MB / ${profile.quota.storage_limit_mb} MB`)])]),/*#__PURE__*/React.createElement("div",{key:"progress"},[/*#__PURE__*/React.createElement("div",{className:"flex justify-between text-xs mb-1"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-400"},"Tiến trình sử dụng bộ nhớ Server"),/*#__PURE__*/React.createElement("span",{className:"font-bold text-teal-400"},`${(profile.quota.used_mb/profile.quota.storage_limit_mb*100).toFixed(1)}%`)]),/*#__PURE__*/React.createElement("div",{className:"w-full h-2 bg-slate-800 rounded-full overflow-hidden"},[/*#__PURE__*/React.createElement("div",{className:"h-full bg-teal-500 rounded-full transition-all duration-300",style:{width:`${Math.min(100,profile.quota.used_mb/profile.quota.storage_limit_mb*100)}%`}})])]),/*#__PURE__*/React.createElement("form",{key:"pwd-form",onSubmit:handleChangePassword,className:"pt-4 border-t border-[#383838] space-y-3"},[/*#__PURE__*/React.createElement("h4",{className:"text-xs font-bold text-slate-300 uppercase"},"Thay Đổi Mật Khẩu"),msg&&/*#__PURE__*/React.createElement("div",{className:"p-2 bg-emerald-950/60 border border-emerald-700 text-emerald-300 rounded text-xs"},msg),error&&/*#__PURE__*/React.createElement("div",{className:"p-2 bg-red-950/60 border border-red-700 text-red-300 rounded text-xs"},error),/*#__PURE__*/React.createElement("div",{key:"old"},[/*#__PURE__*/React.createElement("label",{className:"block text-xs text-slate-400 mb-1"},"Mật khẩu cũ"),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:"current-password",required:true,value:oldPassword,onChange:e=>setOldPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs focus:outline-none focus:border-teal-500"})]),/*#__PURE__*/React.createElement("div",{key:"new"},[/*#__PURE__*/React.createElement("label",{className:"block text-xs text-slate-400 mb-1"},"Mật khẩu mới"),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:"new-password",required:true,value:newPassword,onChange:e=>setNewPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs focus:outline-none focus:border-teal-500"})]),/*#__PURE__*/React.createElement("button",{type:"submit",disabled:loading,className:"w-full py-1.5 bg-teal-600 hover:bg-teal-500 text-white font-semibold text-xs rounded transition"},loading?'Đang cập nhật...':'Cập Nhật Mật Khẩu')])]:activeTab==='projects'?[loadingProjects?/*#__PURE__*/React.createElement("div",{key:"loading",className:"text-center py-8 text-xs text-zinc-500"},"Đang tải danh sách dự án..."):projectsList.length===0?/*#__PURE__*/React.createElement("div",{key:"empty",className:"text-center py-8 text-xs text-zinc-500"},"Bạn chưa có dự án nào lưu trên Cloud."):/*#__PURE__*/React.createElement("div",{key:"list",className:"space-y-1.5"},[projectsList.map(proj=>/*#__PURE__*/React.createElement("div",{key:proj.id,onClick:()=>handleOpenProject(proj.id),className:"flex items-center justify-between p-3 bg-[#1e1e1e] hover:bg-zinc-800 rounded border border-zinc-800 transition cursor-pointer text-xs group"},[/*#__PURE__*/React.createElement("div",{key:"meta"},[/*#__PURE__*/React.createElement("div",{className:"font-bold text-slate-200 group-hover:text-teal-400"},proj.name),/*#__PURE__*/React.createElement("div",{className:"text-[10px] text-zinc-500 mt-0.5"},`Dung lượng: ${proj.size_mb} MB | Cập nhật: ${new Date(proj.updated_at*1000).toLocaleString()}`)]),/*#__PURE__*/React.createElement("div",{key:"actions",className:"flex items-center gap-1.5"},[/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();handleOpenProject(proj.id);},className:"px-2.5 py-1 bg-teal-800/80 hover:bg-teal-700 text-teal-200 rounded font-semibold text-[10px]"},"MỞ"),/*#__PURE__*/React.createElement("button",{onClick:e=>handleDeleteProject(proj.id,e),className:"px-2 py-1 bg-rose-950/60 hover:bg-rose-900/80 text-rose-300 rounded font-semibold text-[10px]"},"XÓA")])]))])]:activeTab==='files'?[/*#__PURE__*/React.createElement("div",{key:"cleanup-header",className:"flex items-center justify-between bg-zinc-900/60 p-2.5 rounded border border-zinc-800 text-xs shrink-0 mb-3"},[/*#__PURE__*/React.createElement("span",{className:"text-zinc-400 text-[10px]"},"💡 Các tập tin không dùng trong dự án nào sẽ được đánh dấu 'Không dùng' và có thể xóa để giải phóng dung lượng."),/*#__PURE__*/React.createElement("button",{onClick:handleCleanUnusedFiles,className:"px-2.5 py-1 bg-rose-700 hover:bg-rose-600 text-white rounded font-bold text-[10px] uppercase flex items-center gap-1"},"🧹 Dọn dẹp tệp rác")]),loadingFiles?/*#__PURE__*/React.createElement("div",{key:"loading",className:"text-center py-8 text-xs text-zinc-500"},"Đang tải danh sách tập tin..."):filesList.length===0?/*#__PURE__*/React.createElement("div",{key:"empty",className:"text-center py-8 text-xs text-zinc-500"},"Chưa có tập tin nào tải lên hoặc tạo ra."):/*#__PURE__*/React.createElement("div",{key:"list",className:"space-y-1.5"},[filesList.map(file=>/*#__PURE__*/React.createElement("div",{key:file.file_id,className:"flex items-center justify-between p-3 bg-[#1e1e1e] rounded border border-zinc-800 text-xs"},[/*#__PURE__*/React.createElement("div",{key:"meta",className:"max-w-[70%]"},[/*#__PURE__*/React.createElement("div",{className:"font-semibold text-slate-300 truncate"},file.original_name||file.file_id),/*#__PURE__*/React.createElement("div",{className:"text-[10px] text-zinc-500 mt-0.5"},`Loại: ${file.type} | Dung lượng: ${file.size_mb} MB | Tạo lúc: ${new Date(file.created_at*1000).toLocaleString()}`)]),/*#__PURE__*/React.createElement("div",{key:"actions",className:"flex items-center gap-2"},[file.is_in_use?/*#__PURE__*/React.createElement("span",{className:"px-2 py-0.5 bg-emerald-950 text-emerald-400 border border-emerald-900 rounded text-[9px] uppercase font-bold font-mono"},"Đang dùng"):/*#__PURE__*/React.createElement("span",{className:"px-2 py-0.5 bg-zinc-850 text-zinc-400 border border-zinc-700 rounded text-[9px] uppercase font-bold font-mono"},"Không dùng"),!file.is_in_use&&/*#__PURE__*/React.createElement("button",{onClick:()=>handleDeleteFile(file.file_id),className:"px-2 py-0.5 bg-rose-950 hover:bg-rose-900 text-rose-300 rounded font-semibold text-[10px] border border-rose-900"},"Xóa")])]))])]:null)));};const SaveProjectModal=({isOpen,onClose,onSave})=>{if(!isOpen)return null;const[name,setName]=useState('');const handleSubmit=e=>{e.preventDefault();if(!name.trim())return;onSave(name.trim());onClose();};return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-md p-6 text-slate-200"},/*#__PURE__*/React.createElement("h3",{className:"text-sm font-bold text-teal-400 mb-4 uppercase"},"Đặt tên dự án"),/*#__PURE__*/React.createElement("form",{onSubmit:handleSubmit,className:"space-y-4"},[/*#__PURE__*/React.createElement("input",{key:"name-input",type:"text",placeholder:"Nhập tên dự án...",required:true,value:name,onChange:e=>setName(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-teal-500 font-bold",autoFocus:true}),/*#__PURE__*/React.createElement("div",{key:"actions",className:"flex justify-end gap-2 text-xs"},[/*#__PURE__*/React.createElement("button",{key:"cancel",type:"button",onClick:onClose,className:"px-3 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded"},"Hủy"),/*#__PURE__*/React.createElement("button",{key:"save",type:"submit",className:"px-3 py-1.5 bg-teal-600 hover:bg-teal-500 text-white rounded font-semibold"},"Lưu")])])));};const SaveAsModal=({isOpen,onClose,projectName,onSaveCloud,onSaveLocal})=>{if(!isOpen)return null;const[name,setName]=useState(projectName||'');const[saveType,setSaveType]=useState('cloud');const handleSubmit=e=>{e.preventDefault();if(!name.trim())return;if(saveType==='cloud'){onSaveCloud(name.trim());}else{onSaveLocal(name.trim());}onClose();};return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-md p-6 text-slate-200"},/*#__PURE__*/React.createElement("h3",{className:"text-sm font-bold text-teal-400 mb-4 uppercase"},"Lưu dưới tên khác (Save As...)"),/*#__PURE__*/React.createElement("form",{onSubmit:handleSubmit,className:"space-y-4"},[/*#__PURE__*/React.createElement("div",{key:"name-block"},[/*#__PURE__*/React.createElement("label",{className:"block text-[10px] text-zinc-400 uppercase font-bold mb-1"},"Tên dự án mới"),/*#__PURE__*/React.createElement("input",{type:"text",placeholder:"Nhập tên mới...",required:true,value:name,onChange:e=>setName(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-teal-500 font-bold",autoFocus:true})]),/*#__PURE__*/React.createElement("div",{key:"type-block"},[/*#__PURE__*/React.createElement("label",{className:"block text-[10px] text-zinc-400 uppercase font-bold mb-1.5"},"Phương thức lưu trữ"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-2 text-xs"},[/*#__PURE__*/React.createElement("button",{key:"btn-cloud",type:"button",onClick:()=>setSaveType('cloud'),className:`py-2 rounded border flex flex-col items-center gap-1 font-semibold transition ${saveType==='cloud'?'bg-teal-950/60 border-teal-500 text-teal-300':'bg-zinc-800 border-zinc-700 hover:bg-zinc-750 text-zinc-400'}`},[/*#__PURE__*/React.createElement("span",{key:"title"},"☁️ Lưu Cloud"),/*#__PURE__*/React.createElement("span",{key:"desc",className:"text-[9px] font-normal text-zinc-500"},"Lưu lên server cá nhân")]),/*#__PURE__*/React.createElement("button",{key:"btn-local",type:"button",onClick:()=>setSaveType('local'),className:`py-2 rounded border flex flex-col items-center gap-1 font-semibold transition ${saveType==='local'?'bg-teal-950/60 border-teal-500 text-teal-300':'bg-zinc-800 border-zinc-700 hover:bg-zinc-750 text-zinc-400'}`},[/*#__PURE__*/React.createElement("span",{key:"title"},"💾 Tải về máy (.sfs)"),/*#__PURE__*/React.createElement("span",{key:"desc",className:"text-[9px] font-normal text-zinc-500"},"Tải tệp JSON dự án về máy")])])]),/*#__PURE__*/React.createElement("div",{key:"actions",className:"flex justify-end gap-2 text-xs pt-2"},[/*#__PURE__*/React.createElement("button",{key:"cancel",type:"button",onClick:onClose,className:"px-3 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded"},"Hủy"),/*#__PURE__*/React.createElement("button",{key:"save",type:"submit",className:"px-3 py-1.5 bg-teal-600 hover:bg-teal-500 text-white rounded font-semibold"},"Thực hiện lưu")])])));};const SystemManagerModal=({isOpen,onClose})=>{if(!isOpen)return null;const[users,setUsers]=useState([]);const[loading,setLoading]=useState(true);const[msg,setMsg]=useState('');const[error,setError]=useState('');const[editingQuotaUser,setEditingQuotaUser]=useState(null);const[newQuotaMb,setNewQuotaMb]=useState(500);useEffect(()=>{if(isOpen)loadUsers();},[isOpen]);const loadUsers=async()=>{setLoading(true);setError('');try{const data=await window.SonicAPI.listUsers();setUsers(data);}catch(err){setError(err.message||'Không thể tải danh sách người dùng hệ thống');}finally{setLoading(false);}};const handleSaveQuota=async userId=>{try{await window.SonicAPI.updateUserQuota(userId,parseInt(newQuotaMb));setMsg('Đã cập nhật hạn mức Quota thành công!');setEditingQuotaUser(null);loadUsers();}catch(err){setError(err.message||'Lỗi cập nhật Quota');}};const handleToggleRole=async user=>{const nextRole=user.role==='admin'?'standard':'admin';try{await window.SonicAPI.updateUserRole(user.id,nextRole,user.is_active);setMsg(`Đã đổi vai trò người dùng ${user.username} thành ${nextRole}`);loadUsers();}catch(err){setError(err.message||'Lỗi cập nhật vai trò');}};const handleDeleteUser=async userId=>{if(!confirm('Bạn có chắc chắn muốn xóa người dùng này khỏi hệ thống?'))return;try{await window.SonicAPI.deleteUser(userId);setMsg('Đã xóa người dùng thành công');loadUsers();}catch(err){setError(err.message||'Lỗi khi xóa người dùng');}};return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-4xl p-6 text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-4 border-b border-[#383838]"},/*#__PURE__*/React.createElement("h3",{className:"text-lg font-bold text-amber-400"},"⚙️ Quản Lý Hệ Thống & Phân Quyền Admin"),/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),msg&&/*#__PURE__*/React.createElement("div",{className:"mt-3 p-2 bg-emerald-950/60 border border-emerald-700 text-emerald-300 rounded text-xs"},msg),error&&/*#__PURE__*/React.createElement("div",{className:"mt-3 p-2 bg-red-950/60 border border-red-700 text-red-300 rounded text-xs"},error),/*#__PURE__*/React.createElement("div",{className:"mt-4 overflow-x-auto max-h-96 no-scrollbar"},loading?/*#__PURE__*/React.createElement("div",{className:"py-8 text-center text-slate-400 text-xs"},"Đang tải thông tin hệ thống..."):/*#__PURE__*/React.createElement("table",{className:"w-full text-left text-xs border-collapse"},/*#__PURE__*/React.createElement("thead",null,/*#__PURE__*/React.createElement("tr",{className:"border-b border-[#383838] text-slate-400 bg-[#1e1e1e]"},/*#__PURE__*/React.createElement("th",{className:"p-3"},"Tên Người Dùng"),/*#__PURE__*/React.createElement("th",{className:"p-3"},"Email"),/*#__PURE__*/React.createElement("th",{className:"p-3"},"Vai Trò"),/*#__PURE__*/React.createElement("th",{className:"p-3"},"Dung Lượng Sử Dụng"),/*#__PURE__*/React.createElement("th",{className:"p-3"},"Hạn Mức Quota"),/*#__PURE__*/React.createElement("th",{className:"p-3 text-right"},"Thao Tác"))),/*#__PURE__*/React.createElement("tbody",{className:"divide-y divide-[#333]"},users.map(u=>/*#__PURE__*/React.createElement("tr",{key:u.id,className:"hover:bg-[#2e2e2e]"},/*#__PURE__*/React.createElement("td",{className:"p-3 font-semibold text-teal-300"},u.username,u.must_change_password&&/*#__PURE__*/React.createElement("span",{className:"ml-2 text-xs bg-amber-900/60 text-amber-300 px-1.5 py-0.5 rounded"},"Mật khẩu gốc")),/*#__PURE__*/React.createElement("td",{className:"p-3 text-slate-300"},u.email),/*#__PURE__*/React.createElement("td",{className:"p-3 uppercase font-bold text-amber-400"},u.role),/*#__PURE__*/React.createElement("td",{className:"p-3"},u.used_mb," MB"),/*#__PURE__*/React.createElement("td",{className:"p-3"},editingQuotaUser===u.id?/*#__PURE__*/React.createElement("div",{className:"flex items-center space-x-1"},/*#__PURE__*/React.createElement("input",{type:"number",value:newQuotaMb,onChange:e=>setNewQuotaMb(e.target.value),className:"w-16 bg-[#1e1e1e] border border-[#444] rounded px-1 py-0.5 text-xs text-slate-200"}),/*#__PURE__*/React.createElement("span",null,"MB"),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSaveQuota(u.id),className:"px-2 py-0.5 bg-teal-600 rounded text-xs"},"Lưu")):/*#__PURE__*/React.createElement("span",{className:"font-semibold"},u.quota_mb," MB")),/*#__PURE__*/React.createElement("td",{className:"p-3 text-right space-x-2"},/*#__PURE__*/React.createElement("button",{onClick:()=>{setEditingQuotaUser(u.id);setNewQuotaMb(u.quota_mb);},className:"px-2 py-1 bg-slate-700 hover:bg-slate-600 rounded text-xs"},"Sửa Quota"),/*#__PURE__*/React.createElement("button",{onClick:()=>handleToggleRole(u),className:"px-2 py-1 bg-amber-700/60 hover:bg-amber-600 rounded text-xs"},"Đổi Role"),u.role!=='admin'&&/*#__PURE__*/React.createElement("button",{onClick:()=>handleDeleteUser(u.id),className:"px-2 py-1 bg-red-700/60 hover:bg-red-600 rounded text-xs"},"Xóa")))))))));};const PianoRollTabEditor=({st,zoom,bpm,viewportWidth,onClose,onUpdateNotes,onSaveNotes,setSubTabs})=>{const[activeRollTool,setActiveRollTool]=React.useState('select');const[snapVal,setSnapVal]=React.useState('1/16');const[ccMode,setCcMode]=React.useState('velocity');const[rollZoom,setRollZoom]=React.useState(60);// local horizontal zoom factor +const[confirmModal,setConfirmModal]=useState(null);const handleDragStart=e=>{const r=dragRef.current;r.active=true;r.startX=e.clientX;r.startY=e.clientY;r.ofsX=dragOfs.x;r.ofsY=dragOfs.y;const onMove=ev=>{if(!r.active)return;setDragOfs({x:r.ofsX+ev.clientX-r.startX,y:r.ofsY+ev.clientY-r.startY});};const onUp=()=>{r.active=false;document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);};useEffect(()=>{if(isOpen){fetchProfile();if(activeTab==='projects')fetchProjects();if(activeTab==='files')fetchFiles();}},[isOpen,activeTab]);const fetchProfile=async()=>{try{const data=await window.SonicAPI.getProfile();setProfile(data);}catch(e){setError(e.message||'Không thể tải thông tin profile');}};const fetchProjects=async()=>{setLoadingProjects(true);try{const data=await window.SonicAPI.listCloudProjects();setProjectsList(data||[]);}catch(e){showToast(e.message||'Không thể tải danh sách dự án','error');}finally{setLoadingProjects(false);}};const fetchFiles=async()=>{setLoadingFiles(true);try{const activeFileIds=tracks.map(t=>t.serverFileId).filter(Boolean);const data=await window.SonicAPI.listMyFiles(activeFileIds);setFilesList(data||[]);}catch(e){showToast(e.message||'Không thể tải danh sách tệp tin','error');}finally{setLoadingFiles(false);}};const handleOpenProject=async projectId=>{setAppWarningModal({title:"Mở dự án",message:"Bạn có muốn mở dự án này? Các thay đổi chưa lưu trên workspace hiện tại sẽ bị mất.",isAlert:false,onConfirm:async()=>{try{const proj=await window.SonicAPI.getCloudProject(projectId);const parsed=JSON.parse(proj.data_json);let restoredTracks=[];let restoredBpm=bpm;let restoredSessionTabs=[];if(parsed.main_session){const result=deserializeProjectFromSchema(parsed);restoredTracks=result.tracks;restoredBpm=result.bpm;restoredSessionTabs=result.sessionTabs;}else{restoredTracks=(parsed.tracks||[]).map(t=>{const{height:_h,...rest}=t;return{...rest,buffer:null,channelInfo:t.channelInfo||null,clips:t.clips||[],serverFileId:t.serverFileId||null};});}setTracks(restoredTracks);setBpm(restoredBpm.toString());setSelectedTrackId(restoredTracks[0]?.id||'1');setProjectName(proj.name);setCurrentProjectId(proj.id);if(restoredSessionTabs.length>0){setSessionTabs(restoredSessionTabs);}localStorage.setItem('sonic_project_name',proj.name);localStorage.setItem('sonic_project_id',proj.id);showToast(`Đã nạp dự án "${proj.name}" thành công!`,"success");}catch(e){showToast(e.message||"Lỗi khi nạp dự án","error");}}});};const handleDeleteProject=async(projectId,e)=>{e.stopPropagation();setConfirmModal({title:"Xóa dự án Cloud",message:"Bạn có chắc chắn muốn xóa dự án này khỏi Cloud? Hành động này không thể hoàn tác.",onConfirm:async()=>{try{await window.SonicAPI.deleteCloudProject(projectId);showToast("Đã xóa dự án thành công!","success");fetchProjects();fetchProfile();}catch(err){showToast(err.message||"Lỗi khi xóa dự án","error");}}});};const handleDeleteFile=async fileId=>{if(!confirm(`Bạn có chắc chắn muốn xóa tệp tin ${fileId}?`))return;try{await window.SonicAPI.deleteMyFile(fileId);showToast("Đã xóa tệp tin thành công!","success");fetchFiles();fetchProfile();}catch(err){showToast(err.message||"Lỗi khi xóa tệp tin","error");}};const handleCleanUnusedFiles=async()=>{const unusedFiles=filesList.filter(f=>!f.is_in_use);if(unusedFiles.length===0){showToast("Không có tập tin rác nào để dọn dẹp.","info");return;}if(!confirm(`Bạn có chắc chắn muốn xóa tất cả ${unusedFiles.length} tập tin rác để giải phóng dung lượng?`))return;let successCount=0;for(const file of unusedFiles){try{await window.SonicAPI.deleteMyFile(file.file_id);successCount++;}catch(e){console.error("Lỗi xóa file rác: ",file.file_id,e);}}showToast(`Đã dọn dẹp thành công ${successCount}/${unusedFiles.length} tập tin rác!`,"success");fetchFiles();fetchProfile();};const handleChangePassword=async e=>{e.preventDefault();setMsg('');setError('');setLoading(true);try{const res=await window.SonicAPI.changePassword(oldPassword,newPassword);setMsg(res.message||'Đổi mật khẩu thành công!');setOldPassword('');setNewPassword('');}catch(err){setError(err.message||'Lỗi khi đổi mật khẩu');}finally{setLoading(false);}};const modalStyle={left:`calc(50% + ${dragOfs.x}px)`,top:`calc(50% + ${dragOfs.y}px)`,transform:'translate(-50%, -50%)'};return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{key:"backdrop",className:"fixed inset-0 z-40 bg-black/70 backdrop-blur-sm",onClick:onClose}),confirmModal&&/*#__PURE__*/React.createElement("div",{key:"confirm-overlay",className:"fixed inset-0 z-[60] flex items-center justify-center bg-black/50"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-lg shadow-2xl p-5 max-w-sm w-full text-slate-200"},/*#__PURE__*/React.createElement("h4",{className:"text-sm font-bold text-rose-400 mb-2"},confirmModal.title),/*#__PURE__*/React.createElement("p",{className:"text-xs text-slate-300 mb-4"},confirmModal.message),/*#__PURE__*/React.createElement("div",{className:"flex justify-end gap-2"},/*#__PURE__*/React.createElement("button",{onClick:()=>setConfirmModal(null),className:"px-3 py-1.5 bg-zinc-700 hover:bg-zinc-600 text-slate-300 rounded text-xs font-semibold"},"Hủy"),/*#__PURE__*/React.createElement("button",{onClick:()=>{const fn=confirmModal.onConfirm;setConfirmModal(null);fn();},className:"px-3 py-1.5 bg-rose-700 hover:bg-rose-600 text-white rounded text-xs font-semibold"},"Xác nhận xóa")))),/*#__PURE__*/React.createElement("div",{key:"dialog",className:"fixed z-50 bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-2xl p-6 text-slate-200 flex flex-col max-h-[85vh]",style:modalStyle},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-3 border-b border-[#383838] shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:handleDragStart},/*#__PURE__*/React.createElement("h3",{className:"text-md font-bold text-teal-400 flex items-center gap-1.5"},"👤 Hồ Sơ Cá Nhân & Quản Lý Dự Án"),/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),/*#__PURE__*/React.createElement("div",{className:"flex gap-2 border-b border-[#383838] py-2 shrink-0 text-xs font-semibold"},[/*#__PURE__*/React.createElement("button",{key:"tab-acc",onClick:()=>setActiveTab('account'),className:`px-3 py-1.5 rounded transition ${activeTab==='account'?'bg-teal-950/60 text-teal-300 border border-teal-800':'text-slate-400 hover:text-slate-200'}`},"Tài Khoản"),/*#__PURE__*/React.createElement("button",{key:"tab-proj",onClick:()=>setActiveTab('projects'),className:`px-3 py-1.5 rounded transition ${activeTab==='projects'?'bg-teal-950/60 text-teal-300 border border-teal-800':'text-slate-400 hover:text-slate-200'}`},"Dự Án Cloud"),/*#__PURE__*/React.createElement("button",{key:"tab-files",onClick:()=>setActiveTab('files'),className:`px-3 py-1.5 rounded transition ${activeTab==='files'?'bg-teal-950/60 text-teal-300 border border-teal-800':'text-slate-400 hover:text-slate-200'}`},"Tập Tin Của Tôi")]),/*#__PURE__*/React.createElement("div",{className:"flex-1 overflow-y-auto pt-4 space-y-4 pr-1 min-h-[300px]"},activeTab==='account'&&profile?[/*#__PURE__*/React.createElement("div",{key:"quota-info",className:"bg-[#1e1e1e] p-4 rounded-lg border border-[#333] grid grid-cols-2 gap-4 text-xs"},[/*#__PURE__*/React.createElement("div",{key:"username"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-500 block"},"Tên người dùng"),/*#__PURE__*/React.createElement("span",{className:"font-bold text-teal-300 text-sm"},profile.username)]),/*#__PURE__*/React.createElement("div",{key:"role"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-500 block"},"Vai trò"),/*#__PURE__*/React.createElement("span",{className:"uppercase font-semibold text-amber-400"},profile.role)]),/*#__PURE__*/React.createElement("div",{key:"email"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-500 block"},"Email"),/*#__PURE__*/React.createElement("span",null,profile.email)]),/*#__PURE__*/React.createElement("div",{key:"quota"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-500 block"},"Dung lượng Quota"),/*#__PURE__*/React.createElement("span",{className:"font-semibold text-slate-200"},`${profile.quota.used_mb} MB / ${profile.quota.storage_limit_mb} MB`)])]),/*#__PURE__*/React.createElement("div",{key:"progress"},[/*#__PURE__*/React.createElement("div",{className:"flex justify-between text-xs mb-1"},[/*#__PURE__*/React.createElement("span",{className:"text-slate-400"},"Tiến trình sử dụng bộ nhớ Server"),/*#__PURE__*/React.createElement("span",{className:"font-bold text-teal-400"},`${(profile.quota.used_mb/profile.quota.storage_limit_mb*100).toFixed(1)}%`)]),/*#__PURE__*/React.createElement("div",{className:"w-full h-2 bg-slate-800 rounded-full overflow-hidden"},[/*#__PURE__*/React.createElement("div",{className:"h-full bg-teal-500 rounded-full transition-all duration-300",style:{width:`${Math.min(100,profile.quota.used_mb/profile.quota.storage_limit_mb*100)}%`}})])]),/*#__PURE__*/React.createElement("form",{key:"pwd-form",onSubmit:handleChangePassword,className:"pt-4 border-t border-[#383838] space-y-3"},[/*#__PURE__*/React.createElement("h4",{className:"text-xs font-bold text-slate-300 uppercase"},"Thay Đổi Mật Khẩu"),msg&&/*#__PURE__*/React.createElement("div",{className:"p-2 bg-emerald-950/60 border border-emerald-700 text-emerald-300 rounded text-xs"},msg),error&&/*#__PURE__*/React.createElement("div",{className:"p-2 bg-red-950/60 border border-red-700 text-red-300 rounded text-xs"},error),/*#__PURE__*/React.createElement("div",{key:"old"},[/*#__PURE__*/React.createElement("label",{className:"block text-xs text-slate-400 mb-1"},"Mật khẩu cũ"),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:"current-password",required:true,value:oldPassword,onChange:e=>setOldPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs focus:outline-none focus:border-teal-500"})]),/*#__PURE__*/React.createElement("div",{key:"new"},[/*#__PURE__*/React.createElement("label",{className:"block text-xs text-slate-400 mb-1"},"Mật khẩu mới"),/*#__PURE__*/React.createElement("input",{type:"password",autoComplete:"new-password",required:true,value:newPassword,onChange:e=>setNewPassword(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs focus:outline-none focus:border-teal-500"})]),/*#__PURE__*/React.createElement("button",{type:"submit",disabled:loading,className:"w-full py-1.5 bg-teal-600 hover:bg-teal-500 text-white font-semibold text-xs rounded transition"},loading?'Đang cập nhật...':'Cập Nhật Mật Khẩu')])]:activeTab==='projects'?[loadingProjects?/*#__PURE__*/React.createElement("div",{key:"loading",className:"text-center py-8 text-xs text-zinc-500"},"Đang tải danh sách dự án..."):projectsList.length===0?/*#__PURE__*/React.createElement("div",{key:"empty",className:"text-center py-8 text-xs text-zinc-500"},"Bạn chưa có dự án nào lưu trên Cloud."):/*#__PURE__*/React.createElement("div",{key:"list",className:"space-y-1.5"},[projectsList.map(proj=>/*#__PURE__*/React.createElement("div",{key:proj.id,onClick:()=>handleOpenProject(proj.id),className:"flex items-center justify-between p-3 bg-[#1e1e1e] hover:bg-zinc-800 rounded border border-zinc-800 transition cursor-pointer text-xs group"},[/*#__PURE__*/React.createElement("div",{key:"meta"},[/*#__PURE__*/React.createElement("div",{className:"font-bold text-slate-200 group-hover:text-teal-400"},proj.name),/*#__PURE__*/React.createElement("div",{className:"text-[10px] text-zinc-500 mt-0.5"},`Dung lượng: ${proj.size_mb} MB | Cập nhật: ${new Date(proj.updated_at*1000).toLocaleString()}`)]),/*#__PURE__*/React.createElement("div",{key:"actions",className:"flex items-center gap-1.5"},[/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();handleOpenProject(proj.id);},className:"px-2.5 py-1 bg-teal-800/80 hover:bg-teal-700 text-teal-200 rounded font-semibold text-[10px]"},"MỞ"),/*#__PURE__*/React.createElement("button",{onClick:e=>handleDeleteProject(proj.id,e),className:"px-2 py-1 bg-rose-950/60 hover:bg-rose-900/80 text-rose-300 rounded font-semibold text-[10px]"},"XÓA")])]))])]:activeTab==='files'?[/*#__PURE__*/React.createElement("div",{key:"cleanup-header",className:"flex items-center justify-between bg-zinc-900/60 p-2.5 rounded border border-zinc-800 text-xs shrink-0 mb-3"},[/*#__PURE__*/React.createElement("span",{className:"text-zinc-400 text-[10px]"},"💡 Các tập tin không dùng trong dự án nào sẽ được đánh dấu 'Không dùng' và có thể xóa để giải phóng dung lượng."),/*#__PURE__*/React.createElement("button",{onClick:handleCleanUnusedFiles,className:"px-2.5 py-1 bg-rose-700 hover:bg-rose-600 text-white rounded font-bold text-[10px] uppercase flex items-center gap-1"},"🧹 Dọn dẹp tệp rác")]),loadingFiles?/*#__PURE__*/React.createElement("div",{key:"loading",className:"text-center py-8 text-xs text-zinc-500"},"Đang tải danh sách tập tin..."):filesList.length===0?/*#__PURE__*/React.createElement("div",{key:"empty",className:"text-center py-8 text-xs text-zinc-500"},"Chưa có tập tin nào tải lên hoặc tạo ra."):/*#__PURE__*/React.createElement("div",{key:"list",className:"space-y-1.5"},[filesList.map(file=>/*#__PURE__*/React.createElement("div",{key:file.file_id,className:"flex items-center justify-between p-3 bg-[#1e1e1e] rounded border border-zinc-800 text-xs"},[/*#__PURE__*/React.createElement("div",{key:"meta",className:"max-w-[70%]"},[/*#__PURE__*/React.createElement("div",{className:"font-semibold text-slate-300 truncate"},file.original_name||file.file_id),/*#__PURE__*/React.createElement("div",{className:"text-[10px] text-zinc-500 mt-0.5"},`Loại: ${file.type} | Dung lượng: ${file.size_mb} MB | Tạo lúc: ${new Date(file.created_at*1000).toLocaleString()}`)]),/*#__PURE__*/React.createElement("div",{key:"actions",className:"flex items-center gap-2"},[file.is_in_use?/*#__PURE__*/React.createElement("span",{className:"px-2 py-0.5 bg-emerald-950 text-emerald-400 border border-emerald-900 rounded text-[9px] uppercase font-bold font-mono"},"Đang dùng"):/*#__PURE__*/React.createElement("span",{className:"px-2 py-0.5 bg-zinc-850 text-zinc-400 border border-zinc-700 rounded text-[9px] uppercase font-bold font-mono"},"Không dùng"),!file.is_in_use&&/*#__PURE__*/React.createElement("button",{onClick:()=>handleDeleteFile(file.file_id),className:"px-2 py-0.5 bg-rose-950 hover:bg-rose-900 text-rose-300 rounded font-semibold text-[10px] border border-rose-900"},"Xóa")])]))])]:null)));};const SaveProjectModal=({isOpen,onClose,onSave})=>{if(!isOpen)return null;const[name,setName]=useState('');const handleSubmit=e=>{e.preventDefault();if(!name.trim())return;onSave(name.trim());onClose();};return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-md p-6 text-slate-200"},/*#__PURE__*/React.createElement("h3",{className:"text-sm font-bold text-teal-400 mb-4 uppercase"},"Đặt tên dự án"),/*#__PURE__*/React.createElement("form",{onSubmit:handleSubmit,className:"space-y-4"},[/*#__PURE__*/React.createElement("input",{key:"name-input",type:"text",placeholder:"Nhập tên dự án...",required:true,value:name,onChange:e=>setName(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-teal-500 font-bold",autoFocus:true}),/*#__PURE__*/React.createElement("div",{key:"actions",className:"flex justify-end gap-2 text-xs"},[/*#__PURE__*/React.createElement("button",{key:"cancel",type:"button",onClick:onClose,className:"px-3 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded"},"Hủy"),/*#__PURE__*/React.createElement("button",{key:"save",type:"submit",className:"px-3 py-1.5 bg-teal-600 hover:bg-teal-500 text-white rounded font-semibold"},"Lưu")])])));};const SaveAsModal=({isOpen,onClose,projectName,onSaveCloud,onSaveLocal})=>{if(!isOpen)return null;const[name,setName]=useState(projectName||'');const[saveType,setSaveType]=useState('cloud');const handleSubmit=e=>{e.preventDefault();if(!name.trim())return;if(saveType==='cloud'){onSaveCloud(name.trim());}else{onSaveLocal(name.trim());}onClose();};return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-md p-6 text-slate-200"},/*#__PURE__*/React.createElement("h3",{className:"text-sm font-bold text-teal-400 mb-4 uppercase"},"Lưu dưới tên khác (Save As...)"),/*#__PURE__*/React.createElement("form",{onSubmit:handleSubmit,className:"space-y-4"},[/*#__PURE__*/React.createElement("div",{key:"name-block"},[/*#__PURE__*/React.createElement("label",{className:"block text-[10px] text-zinc-400 uppercase font-bold mb-1"},"Tên dự án mới"),/*#__PURE__*/React.createElement("input",{type:"text",placeholder:"Nhập tên mới...",required:true,value:name,onChange:e=>setName(e.target.value),className:"w-full bg-[#1e1e1e] border border-[#383838] rounded px-3 py-1.5 text-xs text-slate-200 focus:outline-none focus:border-teal-500 font-bold",autoFocus:true})]),/*#__PURE__*/React.createElement("div",{key:"type-block"},[/*#__PURE__*/React.createElement("label",{className:"block text-[10px] text-zinc-400 uppercase font-bold mb-1.5"},"Phương thức lưu trữ"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-2 text-xs"},[/*#__PURE__*/React.createElement("button",{key:"btn-cloud",type:"button",onClick:()=>setSaveType('cloud'),className:`py-2 rounded border flex flex-col items-center gap-1 font-semibold transition ${saveType==='cloud'?'bg-teal-950/60 border-teal-500 text-teal-300':'bg-zinc-800 border-zinc-700 hover:bg-zinc-750 text-zinc-400'}`},[/*#__PURE__*/React.createElement("span",{key:"title"},"☁️ Lưu Cloud"),/*#__PURE__*/React.createElement("span",{key:"desc",className:"text-[9px] font-normal text-zinc-500"},"Lưu lên server cá nhân")]),/*#__PURE__*/React.createElement("button",{key:"btn-local",type:"button",onClick:()=>setSaveType('local'),className:`py-2 rounded border flex flex-col items-center gap-1 font-semibold transition ${saveType==='local'?'bg-teal-950/60 border-teal-500 text-teal-300':'bg-zinc-800 border-zinc-700 hover:bg-zinc-750 text-zinc-400'}`},[/*#__PURE__*/React.createElement("span",{key:"title"},"💾 Tải về máy (.sfs)"),/*#__PURE__*/React.createElement("span",{key:"desc",className:"text-[9px] font-normal text-zinc-500"},"Tải tệp JSON dự án về máy")])])]),/*#__PURE__*/React.createElement("div",{key:"actions",className:"flex justify-end gap-2 text-xs pt-2"},[/*#__PURE__*/React.createElement("button",{key:"cancel",type:"button",onClick:onClose,className:"px-3 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded"},"Hủy"),/*#__PURE__*/React.createElement("button",{key:"save",type:"submit",className:"px-3 py-1.5 bg-teal-600 hover:bg-teal-500 text-white rounded font-semibold"},"Thực hiện lưu")])])));};const SystemManagerModal=({isOpen,onClose})=>{if(!isOpen)return null;const[users,setUsers]=useState([]);const[loading,setLoading]=useState(true);const[msg,setMsg]=useState('');const[error,setError]=useState('');const[editingQuotaUser,setEditingQuotaUser]=useState(null);const[newQuotaMb,setNewQuotaMb]=useState(500);useEffect(()=>{if(isOpen)loadUsers();},[isOpen]);const loadUsers=async()=>{setLoading(true);setError('');try{const data=await window.SonicAPI.listUsers();setUsers(data);}catch(err){setError(err.message||'Không thể tải danh sách người dùng hệ thống');}finally{setLoading(false);}};const handleSaveQuota=async userId=>{try{await window.SonicAPI.updateUserQuota(userId,parseInt(newQuotaMb));setMsg('Đã cập nhật hạn mức Quota thành công!');setEditingQuotaUser(null);loadUsers();}catch(err){setError(err.message||'Lỗi cập nhật Quota');}};const handleToggleRole=async user=>{const nextRole=user.role==='admin'?'standard':'admin';try{await window.SonicAPI.updateUserRole(user.id,nextRole,user.is_active);setMsg(`Đã đổi vai trò người dùng ${user.username} thành ${nextRole}`);loadUsers();}catch(err){setError(err.message||'Lỗi cập nhật vai trò');}};const handleDeleteUser=async userId=>{if(!confirm('Bạn có chắc chắn muốn xóa người dùng này khỏi hệ thống?'))return;try{await window.SonicAPI.deleteUser(userId);setMsg('Đã xóa người dùng thành công');loadUsers();}catch(err){setError(err.message||'Lỗi khi xóa người dùng');}};return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#262626] border border-[#383838] rounded-xl shadow-2xl w-full max-w-4xl p-6 text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex justify-between items-center pb-4 border-b border-[#383838]"},/*#__PURE__*/React.createElement("h3",{className:"text-lg font-bold text-amber-400"},"⚙️ Quản Lý Hệ Thống & Phân Quyền Admin"),/*#__PURE__*/React.createElement("button",{onClick:onClose,className:"text-slate-400 hover:text-slate-200"},"✕")),msg&&/*#__PURE__*/React.createElement("div",{className:"mt-3 p-2 bg-emerald-950/60 border border-emerald-700 text-emerald-300 rounded text-xs"},msg),error&&/*#__PURE__*/React.createElement("div",{className:"mt-3 p-2 bg-red-950/60 border border-red-700 text-red-300 rounded text-xs"},error),/*#__PURE__*/React.createElement("div",{className:"mt-4 overflow-x-auto max-h-96 no-scrollbar"},loading?/*#__PURE__*/React.createElement("div",{className:"py-8 text-center text-slate-400 text-xs"},"Đang tải thông tin hệ thống..."):/*#__PURE__*/React.createElement("table",{className:"w-full text-left text-xs border-collapse"},/*#__PURE__*/React.createElement("thead",null,/*#__PURE__*/React.createElement("tr",{className:"border-b border-[#383838] text-slate-400 bg-[#1e1e1e]"},/*#__PURE__*/React.createElement("th",{className:"p-3"},"Tên Người Dùng"),/*#__PURE__*/React.createElement("th",{className:"p-3"},"Email"),/*#__PURE__*/React.createElement("th",{className:"p-3"},"Vai Trò"),/*#__PURE__*/React.createElement("th",{className:"p-3"},"Dung Lượng Sử Dụng"),/*#__PURE__*/React.createElement("th",{className:"p-3"},"Hạn Mức Quota"),/*#__PURE__*/React.createElement("th",{className:"p-3 text-right"},"Thao Tác"))),/*#__PURE__*/React.createElement("tbody",{className:"divide-y divide-[#333]"},users.map(u=>/*#__PURE__*/React.createElement("tr",{key:u.id,className:"hover:bg-[#2e2e2e]"},/*#__PURE__*/React.createElement("td",{className:"p-3 font-semibold text-teal-300"},u.username,u.must_change_password&&/*#__PURE__*/React.createElement("span",{className:"ml-2 text-xs bg-amber-900/60 text-amber-300 px-1.5 py-0.5 rounded"},"Mật khẩu gốc")),/*#__PURE__*/React.createElement("td",{className:"p-3 text-slate-300"},u.email),/*#__PURE__*/React.createElement("td",{className:"p-3 uppercase font-bold text-amber-400"},u.role),/*#__PURE__*/React.createElement("td",{className:"p-3"},u.used_mb," MB"),/*#__PURE__*/React.createElement("td",{className:"p-3"},editingQuotaUser===u.id?/*#__PURE__*/React.createElement("div",{className:"flex items-center space-x-1"},/*#__PURE__*/React.createElement("input",{type:"number",value:newQuotaMb,onChange:e=>setNewQuotaMb(e.target.value),className:"w-16 bg-[#1e1e1e] border border-[#444] rounded px-1 py-0.5 text-xs text-slate-200"}),/*#__PURE__*/React.createElement("span",null,"MB"),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSaveQuota(u.id),className:"px-2 py-0.5 bg-teal-600 rounded text-xs"},"Lưu")):/*#__PURE__*/React.createElement("span",{className:"font-semibold"},u.quota_mb," MB")),/*#__PURE__*/React.createElement("td",{className:"p-3 text-right space-x-2"},/*#__PURE__*/React.createElement("button",{onClick:()=>{setEditingQuotaUser(u.id);setNewQuotaMb(u.quota_mb);},className:"px-2 py-1 bg-slate-700 hover:bg-slate-600 rounded text-xs"},"Sửa Quota"),/*#__PURE__*/React.createElement("button",{onClick:()=>handleToggleRole(u),className:"px-2 py-1 bg-amber-700/60 hover:bg-amber-600 rounded text-xs"},"Đổi Role"),u.role!=='admin'&&/*#__PURE__*/React.createElement("button",{onClick:()=>handleDeleteUser(u.id),className:"px-2 py-1 bg-red-700/60 hover:bg-red-600 rounded text-xs"},"Xóa")))))))));};const DEFAULT_PRESETS=[{id:"preset_epic_orchestra_intro",name:"Epic Orchestra Intro (8 Bars)",keywords:["epic orchestra","epic orchestral","hoành tráng","nhạc phim epic"],category:"Orchestral / Film Score",default_bars:8,default_bpm:130,default_scale:"C Minor",system_instruction_template:"You are a professional Epic Orchestral film composer. Create a powerful, dramatic 8-bar intro composition.\nThe required structure to return via the `generate_multitrack_midi` tool consists of 5 tracks:\n1. Strings Ensemble: Plays staccato 16th notes in the low register (C2, G2) driving the rhythm (Ostinato).\n2. Brass Section: Plays the main swelling melodic theme (Horn/Trumpet swells) in the C3-C5 range.\n3. Epic Percussion / Taiko: Hits heavily on beats 1 and 3, featuring a snare roll accent at bars 4 and 8.\n4. Synth Bass/Pad: Holds smooth octave foundation layers (Legato).\n5. Orchestral Drums/Cymbals: Crashes on bar 1 and bar 5.\nEnsure the duration of each track is precisely 8 bars (32 beats).",is_user_defined:false,created_at:"2026-07-23T16:00:00Z"},{id:"preset_pop_piano_chords",name:"Pop Piano Chords (4 Bars)",keywords:["pop piano","piano chords","ballad piano","hợp âm piano"],category:"Pop / Ballad",default_bars:4,default_bpm:90,default_scale:"C Major",system_instruction_template:"You are a professional Pop Piano player. Generate a beautiful 4-bar piano chord progression (e.g. C - G - Am - F) with pleasant chord voicing and simple accompaniment. Return the MIDI notes via `generate_multitrack_midi` function on a track named 'Pop Piano'. Ensure the duration of the track is precisely 4 bars (16 beats).",is_user_defined:false,created_at:"2026-07-23T16:00:00Z"},{id:"preset_cyberpunk_synth",name:"Cyberpunk Synthwave (8 Bars)",keywords:["cyberpunk synth","synthwave","cyberpunk","futuristic synth"],category:"Electronic / Synthwave",default_bars:8,default_bpm:120,default_scale:"A Minor",system_instruction_template:"You are a Synthwave producer. Generate a driving 8-bar cyberpunk synth bassline and lead melody. Return MIDI notes via `generate_multitrack_midi` containing:\n1. Synth Bass: driving eighth notes on pitch A1, C2, G1.\n2. Synth Lead: arpeggiated melodic line in high register C4-E5.\nEnsure the duration of each track is precisely 8 bars (32 beats).",is_user_defined:false,created_at:"2026-07-23T16:00:00Z"}];const AIPresetModal=({isOpen,onClose})=>{if(!isOpen)return null;const[presets,setPresets]=React.useState(()=>{const local=localStorage.getItem('daw_ai_prompt_presets');return local?JSON.parse(local):DEFAULT_PRESETS;});const[search,setSearch]=React.useState('');const[filterCategory,setFilterCategory]=React.useState('ALL');const[editingPreset,setEditingPreset]=React.useState(null);// preset object or 'new' +// Form states +const[formName,setFormName]=React.useState('');const[formKeywords,setFormKeywords]=React.useState('');const[formCategory,setFormCategory]=React.useState('Orchestral / Film Score');const[formBars,setFormBars]=React.useState(8);const[formBpm,setFormBpm]=React.useState(120);const[formScale,setFormScale]=React.useState('C Minor');const[formTemplate,setFormTemplate]=React.useState('');const savePresets=newPresets=>{setPresets(newPresets);localStorage.setItem('daw_ai_prompt_presets',JSON.stringify(newPresets));};const handleEdit=p=>{setEditingPreset(p);setFormName(p.name);setFormKeywords(p.keywords.join(', '));setFormCategory(p.category);setFormBars(p.default_bars);setFormBpm(p.default_bpm);setFormScale(p.default_scale);setFormTemplate(p.system_instruction_template);};const handleNew=()=>{setEditingPreset('new');setFormName('');setFormKeywords('');setFormCategory('Orchestral / Film Score');setFormBars(8);setFormBpm(120);setFormScale('C Minor');setFormTemplate('');};const handleDelete=id=>{const updated=presets.filter(p=>p.id!==id);savePresets(updated);showToast('Đã xóa preset.','info');};const handleSaveForm=e=>{e.preventDefault();if(!formName.trim()||!formTemplate.trim()){showToast('Vui lòng điền đầy đủ tên và mẫu gợi ý.','warning');return;}const keywordsArray=formKeywords.split(',').map(k=>k.trim()).filter(Boolean);const presetObj={id:editingPreset==='new'?'preset_'+Date.now():editingPreset.id,name:formName.trim(),keywords:keywordsArray,category:formCategory,default_bars:parseInt(formBars)||8,default_bpm:parseInt(formBpm)||120,default_scale:formScale,system_instruction_template:formTemplate.trim(),is_user_defined:true,created_at:editingPreset==='new'?new Date().toISOString():editingPreset.created_at};let updated;if(editingPreset==='new'){updated=[...presets,presetObj];}else{updated=presets.map(p=>p.id===presetObj.id?presetObj:p);}savePresets(updated);setEditingPreset(null);showToast('Đã lưu preset thành công!','success');};const categories=['ALL',...new Set(presets.map(p=>p.category))];const filtered=presets.filter(p=>{const matchesSearch=p.name.toLowerCase().includes(search.toLowerCase())||p.keywords.some(k=>k.toLowerCase().includes(search.toLowerCase()));const matchesCategory=filterCategory==='ALL'||p.category===filterCategory;return matchesSearch&&matchesCategory;});return/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-50 flex items-center justify-center bg-black/75 backdrop-blur-sm p-4 animate-fade-in"},/*#__PURE__*/React.createElement("div",{className:"bg-[#18181b] border border-zinc-800 rounded-xl shadow-2xl w-full max-w-4xl max-h-[85vh] flex flex-col overflow-hidden text-zinc-100"},/*#__PURE__*/React.createElement("div",{className:"p-4 border-b border-zinc-800 flex items-center justify-between shrink-0 bg-[#202024]"},/*#__PURE__*/React.createElement("h2",{className:"text-sm font-bold tracking-wider uppercase text-purple-400 flex items-center gap-1.5"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-4 h-4"}),"AI Prompt Preset Manager"),/*#__PURE__*/React.createElement("button",{onClick:()=>{setEditingPreset(null);onClose();},className:"text-zinc-400 hover:text-zinc-200 transition"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-4 h-4"}))),/*#__PURE__*/React.createElement("div",{className:"flex-1 overflow-y-auto p-4 flex gap-4 min-h-0"},!editingPreset?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col min-w-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 mb-3 shrink-0"},/*#__PURE__*/React.createElement("input",{type:"text",placeholder:"Tìm kiếm preset hoặc từ khóa...",value:search,onChange:e=>setSearch(e.target.value),className:"flex-1 bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600"}),/*#__PURE__*/React.createElement("select",{value:filterCategory,onChange:e=>setFilterCategory(e.target.value),className:"bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600"},categories.map(c=>/*#__PURE__*/React.createElement("option",{key:c,value:c},c==='ALL'?'Tất cả danh mục':c))),/*#__PURE__*/React.createElement("button",{onClick:handleNew,className:"px-3 py-1 bg-purple-700 hover:bg-purple-600 text-white rounded text-xs font-bold flex items-center gap-1.5 shadow transition shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"}),"Tạo mới")),/*#__PURE__*/React.createElement("div",{className:"flex-1 border border-zinc-800 rounded bg-[#0f0f12] overflow-y-auto"},filtered.length===0?/*#__PURE__*/React.createElement("div",{className:"p-8 text-center text-zinc-500 text-xs italic"},"Không tìm thấy preset nào."):/*#__PURE__*/React.createElement("table",{className:"w-full text-left text-xs border-collapse"},/*#__PURE__*/React.createElement("thead",{className:"bg-[#1f1f23] text-zinc-400 font-bold border-b border-zinc-800"},/*#__PURE__*/React.createElement("tr",null,/*#__PURE__*/React.createElement("th",{className:"p-2.5 w-1/4"},"Tên Preset"),/*#__PURE__*/React.createElement("th",{className:"p-2.5 w-1/4"},"Từ khóa kích hoạt"),/*#__PURE__*/React.createElement("th",{className:"p-2.5 w-1/6"},"Số Bar"),/*#__PURE__*/React.createElement("th",{className:"p-2.5 w-1/6"},"BPM"),/*#__PURE__*/React.createElement("th",{className:"p-2.5 w-1/6 text-right"},"Hành động"))),/*#__PURE__*/React.createElement("tbody",null,filtered.map(p=>/*#__PURE__*/React.createElement("tr",{key:p.id,className:"border-b border-zinc-800/50 hover:bg-zinc-850"},/*#__PURE__*/React.createElement("td",{className:"p-2.5 font-semibold text-purple-300"},p.name),/*#__PURE__*/React.createElement("td",{className:"p-2.5 text-zinc-400 font-mono text-[11px] truncate max-w-[150px]"},p.keywords.join(', ')),/*#__PURE__*/React.createElement("td",{className:"p-2.5 text-zinc-400"},p.default_bars," Bars"),/*#__PURE__*/React.createElement("td",{className:"p-2.5 text-zinc-400"},p.default_bpm," BPM"),/*#__PURE__*/React.createElement("td",{className:"p-2.5 text-right flex items-center justify-end gap-1.5 h-full"},/*#__PURE__*/React.createElement("button",{type:"button",onClick:()=>handleEdit(p),className:"px-2 py-0.5 bg-zinc-850 hover:bg-zinc-700 text-zinc-300 rounded border border-zinc-700 text-[10px]"},"Sửa"),/*#__PURE__*/React.createElement("button",{type:"button",onClick:()=>handleDelete(p.id),className:"px-2 py-0.5 bg-red-950/40 hover:bg-red-800 text-red-400 rounded border border-red-900 text-[10px]"},"Xóa"))))))))):/*#__PURE__*/React.createElement("form",{onSubmit:handleSaveForm,className:"flex-1 flex flex-col gap-3 min-w-0"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-zinc-400 shrink-0 border-b border-zinc-800 pb-1"},editingPreset==='new'?"TẠO PRESET MỚI":`SỬA PRESET: ${editingPreset.name}`),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-3"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("label",{className:"text-[10px] uppercase font-bold text-zinc-500"},"Tên Preset"),/*#__PURE__*/React.createElement("input",{type:"text",value:formName,onChange:e=>setFormName(e.target.value),className:"bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("label",{className:"text-[10px] uppercase font-bold text-zinc-500"},"Danh mục"),/*#__PURE__*/React.createElement("input",{type:"text",value:formCategory,onChange:e=>setFormCategory(e.target.value),className:"bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200"}))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("label",{className:"text-[10px] uppercase font-bold text-zinc-500"},"Từ khóa kích hoạt (ngăn cách bằng dấu phẩy)"),/*#__PURE__*/React.createElement("input",{type:"text",value:formKeywords,onChange:e=>setFormKeywords(e.target.value),placeholder:"Ví dụ: epic orchestra, hoành tráng, nhạc phim epic",className:"bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200"})),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-3"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("label",{className:"text-[10px] uppercase font-bold text-zinc-500"},"Số Bars mặc định"),/*#__PURE__*/React.createElement("input",{type:"number",value:formBars,onChange:e=>setFormBars(e.target.value),className:"bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("label",{className:"text-[10px] uppercase font-bold text-zinc-500"},"BPM mặc định"),/*#__PURE__*/React.createElement("input",{type:"number",value:formBpm,onChange:e=>setFormBpm(e.target.value),className:"bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("label",{className:"text-[10px] uppercase font-bold text-zinc-500"},"Âm giai (Scale) mặc định"),/*#__PURE__*/React.createElement("input",{type:"text",value:formScale,onChange:e=>setFormScale(e.target.value),className:"bg-zinc-900 border border-zinc-700 rounded px-2.5 py-1 text-xs outline-none focus:border-purple-600 text-zinc-200"}))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1 flex-1 min-h-0"},/*#__PURE__*/React.createElement("label",{className:"text-[10px] uppercase font-bold text-zinc-500"},"System Prompt Template / Luật soạn nhạc"),/*#__PURE__*/React.createElement("textarea",{value:formTemplate,onChange:e=>setFormTemplate(e.target.value),rows:6,className:"flex-1 bg-zinc-900 border border-zinc-700 rounded p-2.5 text-xs outline-none focus:border-purple-600 text-zinc-200 font-mono resize-none"})),/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-end gap-2 shrink-0 pt-2 border-t border-zinc-800"},/*#__PURE__*/React.createElement("button",{type:"button",onClick:()=>setEditingPreset(null),className:"px-3 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-400 border border-zinc-700 rounded text-xs transition"},"Quay lại"),/*#__PURE__*/React.createElement("button",{type:"submit",className:"px-3 py-1.5 bg-purple-700 hover:bg-purple-600 text-white rounded text-xs font-bold shadow transition"},"Lưu Preset")))),/*#__PURE__*/React.createElement("div",{className:"p-4 border-t border-zinc-800 flex justify-end shrink-0 bg-[#202024]"},/*#__PURE__*/React.createElement("button",{onClick:()=>{setEditingPreset(null);onClose();},className:"px-4 py-1.5 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 border border-zinc-700 rounded text-xs font-bold shadow transition"},"Đóng"))));};const PianoRollTabEditor=({st,zoom,bpm,viewportWidth,onClose,onUpdateNotes,onSaveNotes,setSubTabs})=>{const[activeRollTool,setActiveRollTool]=React.useState('select');const[snapVal,setSnapVal]=React.useState('1/16');const[ccMode,setCcMode]=React.useState('velocity');const[rollZoom,setRollZoom]=React.useState(60);// local horizontal zoom factor const canvasRef=React.useRef(null);const ccCanvasRef=React.useRef(null);const gridScrollRef=React.useRef(null);const keybedRef=React.useRef(null);const rulerScrollRef=React.useRef(null);const NoteHeight=18;const pixelsPerBeat=rollZoom;const timeSigNum=4;const totalBeats=(st.duration||4)*timeSigNum;const drawWidth=totalBeats*pixelsPerBeat;const[notes,setNotes]=React.useState(st.notes||[]);const[selectedNoteIds,setSelectedNoteIds]=React.useState([]);const[selectionMarquee,setSelectionMarquee]=React.useState(null);// { startBeat, startPitch, currentBeat, currentPitch } const[draggedNote,setDraggedNote]=React.useState(null);// { mode: 'move'|'resize', idx, startOffsetBeat, originalStart } const[hoveredResizeIdx,setHoveredResizeIdx]=React.useState(-1);React.useEffect(()=>{onUpdateNotes(st.id,notes);},[notes]);const getSnapBeat=(beat,mode)=>{let q=0.25;if(mode==='free')return beat;if(mode==='1')q=4.0;else if(mode==='1/2')q=2.0;else if(mode==='1/4')q=1.0;else if(mode==='1/8')q=0.5;else if(mode==='1/16')q=0.25;else if(mode==='1/32')q=0.125;return Math.round(beat/q)*q;};const getSnapDuration=mode=>{if(mode==='free')return 0.25;if(mode==='1')return 4.0;if(mode==='1/2')return 2.0;if(mode==='1/4')return 1.0;if(mode==='1/8')return 0.5;if(mode==='1/16')return 0.25;if(mode==='1/32')return 0.125;return 0.25;};// Local Zoom Wheel Event handler to block browser page zoom @@ -152,7 +155,7 @@ const activeTracks=useMemo(()=>{const st=sessionTabs.find(s=>s.id===activeTab);r 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[currentUser,setCurrentUser]=useState(null);const[authModalOpen,setAuthModalOpen]=useState(false);const[authMode,setAuthMode]=useState('login');// 'login' | 'register' | 'force_change' -const[isMandatoryLogin,setIsMandatoryLogin]=useState(false);const[profileModalOpen,setProfileModalOpen]=useState(false);const[systemManagerModalOpen,setSystemManagerModalOpen]=useState(false);const[aiConfigModalOpen,setAiConfigModalOpen]=useState(false);useEffect(()=>{const checkAuthStatus=async()=>{const savedToken=localStorage.getItem('sonic_token');if(!savedToken){setIsMandatoryLogin(true);setAuthMode('login');setAuthModalOpen(true);return;}try{const profile=await window.SonicAPI.getProfile();setCurrentUser(profile);localStorage.setItem('sonic_user',JSON.stringify(profile));if(profile.must_change_password){setIsMandatoryLogin(true);setAuthMode('force_change');setAuthModalOpen(true);}else{setIsMandatoryLogin(false);setAuthModalOpen(false);}}catch(err){const cached=localStorage.getItem('sonic_user');if(cached){try{setCurrentUser(JSON.parse(cached));}catch(_){}setIsMandatoryLogin(false);setAuthModalOpen(false);}else{localStorage.removeItem('sonic_token');localStorage.removeItem('sonic_user');setCurrentUser(null);setIsMandatoryLogin(true);setAuthMode('login');setAuthModalOpen(true);}}};checkAuthStatus();},[]);const loadPendingSfsProject=()=>{const proj=window.__pendingSfsProject;if(!proj)return;try{let restoredTracks=[];let restoredBpm=bpm;let restoredSessionTabs=[];if(proj.main_session){const result=deserializeProjectFromSchema(proj);restoredTracks=result.tracks;restoredBpm=result.bpm;restoredSessionTabs=result.sessionTabs;}else{restoredTracks=(proj.tracks||[]).map(t=>{const{height:_h,...rest}=t;return{...rest,buffer:null,channelInfo:t.channelInfo||null,clips:t.clips||[],serverFileId:t.serverFileId||null};});}if(restoredTracks.length>0){setTracks(restoredTracks);setBpm(restoredBpm.toString());if(restoredSessionTabs.length>0){setSessionTabs(restoredSessionTabs);}showToast(`Đã tải dự án "${proj.metadata?.title||proj.name||'Dự án mới'}" từ liên kết .sfs thành công!`,"success");}}catch(e){showToast("Lỗi tải dự án từ .sfs","error");}finally{window.__pendingSfsProject=null;}};const handleAuthSuccess=user=>{setCurrentUser(user);if(user.must_change_password){setIsMandatoryLogin(true);setAuthMode('force_change');setAuthModalOpen(true);}else{setIsMandatoryLogin(false);setAuthModalOpen(false);loadPendingSfsProject();const loadPrefs=p=>{if(!p)return;if(p.showAIPanel!==undefined)setShowAIPanel(p.showAIPanel);if(p.showExportPanel!==undefined)setShowExportPanel(p.showExportPanel);if(p.showSelectionPanel!==undefined)setShowSelectionPanel(p.showSelectionPanel);if(p.showPythonToolsPanel!==undefined)setShowPythonToolsPanel(p.showPythonToolsPanel);if(p.showMediaExplorer!==undefined)setShowMediaExplorer(p.showMediaExplorer);if(p.showFxRack!==undefined)setShowFxRack(p.showFxRack);if(p.showMidiEvents!==undefined)setShowMidiEvents(p.showMidiEvents);if(p.panelPositions)setPanelPositions(p.panelPositions);if(p.rightSidebarWidth)setRightSidebarWidth(p.rightSidebarWidth);if(p.mediaExplorerHeight)setMediaExplorerHeight(p.mediaExplorerHeight);if(p.selectedProviderId)setSelectedProviderId(p.selectedProviderId);};(async()=>{try{const data=await window.SonicAPI.getPreferences();if(data&&data.preferences)loadPrefs(data.preferences);else{const cached=localStorage.getItem('sonic_preferences');if(cached)loadPrefs(JSON.parse(cached));}}catch(e){const cached=localStorage.getItem('sonic_preferences');if(cached)loadPrefs(JSON.parse(cached));}try{const data=await window.SonicAPI.getAIConfigs();if(data&&data.providers){setAiProviders(data.providers);const active=data.providers.find(p=>p.is_active)||data.providers[0];if(active)setSelectedProviderId(active.id);}}catch(e){}})();}};const handleLogout=()=>{localStorage.removeItem('sonic_token');localStorage.removeItem('sonic_user');setCurrentUser(null);setIsMandatoryLogin(true);setAuthMode('login');setAuthModalOpen(true);};// ── Temp project auto-save (local + server) ── +const[isMandatoryLogin,setIsMandatoryLogin]=useState(false);const[profileModalOpen,setProfileModalOpen]=useState(false);const[systemManagerModalOpen,setSystemManagerModalOpen]=useState(false);const[aiConfigModalOpen,setAiConfigModalOpen]=useState(false);const[aiPresetModalOpen,setAiPresetModalOpen]=useState(false);const[pluginManagerModalOpen,setPluginManagerModalOpen]=useState(false);const[pluginsData,setPluginsData]=useState(null);useEffect(()=>{const checkAuthStatus=async()=>{const savedToken=localStorage.getItem('sonic_token');if(!savedToken){setIsMandatoryLogin(true);setAuthMode('login');setAuthModalOpen(true);return;}try{const profile=await window.SonicAPI.getProfile();setCurrentUser(profile);localStorage.setItem('sonic_user',JSON.stringify(profile));if(profile.must_change_password){setIsMandatoryLogin(true);setAuthMode('force_change');setAuthModalOpen(true);}else{setIsMandatoryLogin(false);setAuthModalOpen(false);}}catch(err){const cached=localStorage.getItem('sonic_user');if(cached){try{setCurrentUser(JSON.parse(cached));}catch(_){}setIsMandatoryLogin(false);setAuthModalOpen(false);}else{localStorage.removeItem('sonic_token');localStorage.removeItem('sonic_user');setCurrentUser(null);setIsMandatoryLogin(true);setAuthMode('login');setAuthModalOpen(true);}}};checkAuthStatus();},[]);const loadPendingSfsProject=()=>{const proj=window.__pendingSfsProject;if(!proj)return;try{let restoredTracks=[];let restoredBpm=bpm;let restoredSessionTabs=[];if(proj.main_session){const result=deserializeProjectFromSchema(proj);restoredTracks=result.tracks;restoredBpm=result.bpm;restoredSessionTabs=result.sessionTabs;}else{restoredTracks=(proj.tracks||[]).map(t=>{const{height:_h,...rest}=t;return{...rest,buffer:null,channelInfo:t.channelInfo||null,clips:t.clips||[],serverFileId:t.serverFileId||null};});}if(restoredTracks.length>0){setTracks(restoredTracks);setBpm(restoredBpm.toString());if(restoredSessionTabs.length>0){setSessionTabs(restoredSessionTabs);}showToast(`Đã tải dự án "${proj.metadata?.title||proj.name||'Dự án mới'}" từ liên kết .sfs thành công!`,"success");}}catch(e){showToast("Lỗi tải dự án từ .sfs","error");}finally{window.__pendingSfsProject=null;}};const handleAuthSuccess=user=>{setCurrentUser(user);if(user.must_change_password){setIsMandatoryLogin(true);setAuthMode('force_change');setAuthModalOpen(true);}else{setIsMandatoryLogin(false);setAuthModalOpen(false);loadPendingSfsProject();const loadPrefs=p=>{if(!p)return;if(p.showAIPanel!==undefined)setShowAIPanel(p.showAIPanel);if(p.showExportPanel!==undefined)setShowExportPanel(p.showExportPanel);if(p.showSelectionPanel!==undefined)setShowSelectionPanel(p.showSelectionPanel);if(p.showPythonToolsPanel!==undefined)setShowPythonToolsPanel(p.showPythonToolsPanel);if(p.showMediaExplorer!==undefined)setShowMediaExplorer(p.showMediaExplorer);if(p.showFxRack!==undefined)setShowFxRack(p.showFxRack);if(p.showMidiEvents!==undefined)setShowMidiEvents(p.showMidiEvents);if(p.panelPositions)setPanelPositions(p.panelPositions);if(p.rightSidebarWidth)setRightSidebarWidth(p.rightSidebarWidth);if(p.mediaExplorerHeight)setMediaExplorerHeight(p.mediaExplorerHeight);if(p.selectedProviderId)setSelectedProviderId(p.selectedProviderId);};(async()=>{try{const data=await window.SonicAPI.getPreferences();if(data&&data.preferences)loadPrefs(data.preferences);else{const cached=localStorage.getItem('sonic_preferences');if(cached)loadPrefs(JSON.parse(cached));}}catch(e){const cached=localStorage.getItem('sonic_preferences');if(cached)loadPrefs(JSON.parse(cached));}try{const data=await window.SonicAPI.getAIConfigs();if(data&&data.providers){setAiProviders(data.providers);const active=data.providers.find(p=>p.is_active)||data.providers[0];if(active)setSelectedProviderId(active.id);}}catch(e){}})();}};const handleLogout=()=>{localStorage.removeItem('sonic_token');localStorage.removeItem('sonic_user');setCurrentUser(null);setIsMandatoryLogin(true);setAuthMode('login');setAuthModalOpen(true);};// ── Temp project auto-save (local + server) ── useEffect(()=>{const serializeSafe=arr=>(arr||[]).map(t=>({id:t.id,name:t.name,startTime:t.startTime,height:t.height,volumeDb:t.volumeDb,pan:t.pan,muted:t.muted,solo:t.solo,color:t.color,markers:t.markers||[],serverFileId:t.serverFileId||null,channelInfo:t.channelInfo?{channels:t.channelInfo.channels,isStereo:t.channelInfo.isStereo,label:t.channelInfo.label}:null}));window.SonicStorage.scheduleTempAutoSave(()=>{return serializeProjectToSchema(currentProjectId||'temp_project',projectName||'Dự án tạm chưa lưu',bpm,tracks,subTabs,sessionTabs);});},[tracks,subTabs,sessionTabs]);// Lucide icons initialization useEffect(()=>{setTimeout(()=>{if(window.lucide){window.lucide.createIcons();}},50);},[activeTool,activeTab]);const timelineWrapperRef=useRef(null);const[timelineWrapperNode,setTimelineWrapperNode]=useState(null);const handleTimelineWrapperRef=useCallback(node=>{timelineWrapperRef.current=node;setTimelineWrapperNode(node);},[]);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){timelineWrapperRef.current.scrollTop=e.currentTarget.scrollTop;}};const panelDropZoneRef=useRef(null);const startPanelDrag=(panelId,e)=>{panelDragRef.current={panelId,startX:e.clientX,startY:e.clientY};setPanelDropZone(null);setDragGhostPanel(panelId);setDragGhostPos({x:e.clientX-120,y:e.clientY-20});const onMove=ev=>{if(!panelDragRef.current||!workspaceRef.current)return;const rect=workspaceRef.current.getBoundingClientRect();const x=ev.clientX-rect.left;const y=ev.clientY-rect.top;const w=rect.width;const h=rect.height;const margin=60;let zone=null;if(x10)zone='left';else if(x>w-margin&&x10)zone='top';else if(y>h-margin&&y{if(panelDragRef.current){const pid=panelDragRef.current.panelId;const targetZone=panelDropZoneRef.current;if(targetZone&&targetZone!==panelPositions[pid]){setPanelPositions(prev=>({...prev,[pid]:targetZone}));}panelDragRef.current=null;panelDropZoneRef.current=null;setPanelDropZone(null);setDragGhostPos(null);setDragGhostPanel(null);}document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);};// ── Right Sidebar Column Resizer ── const startColResize=e=>{e.preventDefault();const startX=e.clientX;const startWidth=rightSidebarWidth;const onMove=ev=>{const deltaX=startX-ev.clientX;const newWidth=Math.max(200,Math.min(600,startWidth+deltaX));setRightSidebarWidth(newWidth);};const onUp=()=>{document.removeEventListener('mousemove',onMove);document.removeEventListener('mouseup',onUp);};document.addEventListener('mousemove',onMove);document.addEventListener('mouseup',onUp);};// ── Right Sidebar Row Resizer (Media Explorer / AI Panel) ── @@ -293,10 +296,10 @@ const barsFromStart=rawEnd/barDuration;const nearestBarEnd=Math.round(barsFromSt let loopEnd=Math.max(loopStart+barDuration,nearestBarEnd);if(loopEnd>rawEnd+beatDuration)loopEnd=loopStart+Math.ceil(selDuration/barDuration)*barDuration;// Snap to zero-crossing for click-free loop const snapLoopStart=findZeroCrossing(buffer,loopStart);const snapLoopEnd=findZeroCrossing(buffer,loopEnd);// Place markers for the loop points setTracks(prev=>prev.map(t=>{if(t.id!==activeTrack.id)return t;const existingMarkers=t.markers||[];const filtered=existingMarkers.filter(m=>!m.id.startsWith('ai_loop_'));return{...t,markers:[...filtered,{id:'ai_loop_start_'+Date.now(),time:snapLoopStart,label:'Loop Start (Bar '+(Math.floor(snapLoopStart/barDuration)+1)+')',color:'#06b6d4'},{id:'ai_loop_end_'+Date.now(),time:snapLoopEnd,label:'Loop End (Beat 4)',color:'#a855f7'}]};}));setSelectionStart(snapLoopStart);setSelectionEnd(snapLoopEnd);const startSample=Math.max(0,Math.min(dataLen-1,Math.floor(snapLoopStart*sampleRate)));const endSample=Math.max(0,Math.min(dataLen,Math.floor(snapLoopEnd*sampleRate)));const sliceLength=endSample-startSample;if(sliceLength<=0){showToast("Dải cắt không hợp lệ hoặc khoảng thời gian quá ngắn.","error");setAnalysisState({status:'Thất bại',data:null,isRunning:false});return;}const context=getAudioContext();const numChannels=buffer.numberOfChannels||1;const slicedBuffer=context.createBuffer(numChannels,sliceLength,sampleRate);for(let c=0;c{const idx=prev.findIndex(t=>t.id===selectedTrackId);const updated=[...prev];if(idx!==-1){updated.splice(idx+1,0,newTrack);}else{updated.push(newTrack);}return updated;});setSelectedTrackId(newId);setAnalysisState({status:`AI Cut: ${detectedBPM} BPM, ${barsCount} bars loop (Zero-Crossing aligned)`,data:{bpm:detectedBPM,bars:barsCount,timeSig:'4/4'},isRunning:false});showToast(`AI Cut: ${barsCount} bars loop at ${snapLoopStart.toFixed(3)}s - ${snapLoopEnd.toFixed(3)}s [${detectedBPM} BPM]`,"success");setTimeout(()=>lucide.createIcons(),200);}catch(err){showToast("Lỗi khi AI Cut: "+err.message,"error");setAnalysisState({status:'Lỗi AI Cut',data:null,isRunning:false});}},800);};// ── AI Prompt Send to Active Provider ── -const handleAISend=async()=>{const prompt=aiPrompt.trim();if(!prompt){showToast('Vui lòng nhập nội dung prompt.','warning');return;}if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentSelectedTrackId=selectedTrackId;window.DAWCommandDispatcher.currentTracks=tracks;window.DAWCommandDispatcher.lastCutSourceTrackId=null;window.DAWCommandDispatcher.lastCutNewTrackId=null;}setAiProcessing(true);setAiActionLog(prev=>[...prev,{type:'status',text:` ⏳ Đang gửi prompt đến AI...`,time:Date.now()}]);try{if(aiProviders.length===0||!selectedProviderId){try{const data=await window.SonicAPI.getAIConfigs();if(data&&data.providers&&data.providers.length>0){setAiProviders(data.providers);const active=data.providers.find(p=>p.is_active)||data.providers[0];if(active)setSelectedProviderId(active.id);}}catch(e){}}const prv=aiProviders.find(p=>p.id===selectedProviderId)||(aiProviders.length>0?aiProviders[0]:null);const provider=prv||aiConfig;const baseUrl=provider.api_base_url||provider.baseUrl||`${API_BASE_URL}`;const apiKey=provider.api_key||provider.apiKey||'';const model=provider.model_name||provider.model||'deepseek-chat';setAiActionLog(prev=>[...prev,{type:'info',text:` Provider: ${provider.name||'default'} | Model: ${model} | URL: ${baseUrl.slice(0,40)}`,time:Date.now()}]);const dawContext=window.AIGateway.buildAIPromptContext({tracks,bpm,selectedTrackId,currentTime,selLeft,selRight});const result=await window.AIGateway.executeAIPrompt({prompt:prompt,provider:provider.name||'default',model:model,apiKey:apiKey,baseUrl:baseUrl.replace(/\/chat\/completions$/,'').replace(/\/$/,''),dawContext,tools:window.AIGateway.DEFAULT_TOOLS});const hasText=!!result.textResponse;const hasCalls=result.functionCalls&&result.functionCalls.length>0;if(hasText){setAiActionLog(prev=>[...prev,{type:'status',text:` AI: ${result.textResponse.slice(0,500)}`,time:Date.now()}]);}if(hasCalls){setAiActionLog(prev=>[...prev,{type:'info',text:` Gọi ${result.functionCalls.length} lệnh...`,time:Date.now()}]);if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.isExecutingAI=true;}try{for(const fc of result.functionCalls){setAiActionLog(prev=>[...prev,{type:'info',text:` Gọi lệnh: ${fc.name}(${JSON.stringify(fc.arguments)})`,time:Date.now()}]);const cmdName=fc.name.toUpperCase();if(window.DAWCommandDispatcher){try{let cmdResult=window.DAWCommandDispatcher.execute(cmdName,fc.arguments);if(cmdResult&&typeof cmdResult.then==='function')cmdResult=await cmdResult;setAiActionLog(prev=>[...prev,{type:'status',text:` ✅ ${fc.name}: ${cmdResult&&cmdResult.success?'thành công':'thất bại: '+(cmdResult&&cmdResult.error||'unknown')}`,time:Date.now()}]);}catch(cmdErr){setAiActionLog(prev=>[...prev,{type:'error',text:` ❌ ${fc.name}: ${cmdErr.message}`,time:Date.now()}]);}}else{setAiActionLog(prev=>[...prev,{type:'error',text:` ❌ ${fc.name}: DAWCommandDispatcher not available`,time:Date.now()}]);}}}finally{if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.isExecutingAI=false;}}}if(!hasText&&!hasCalls){const rawKeys=result.raw?Object.keys(result.raw).join(', '):'null';const errDetail=result.raw&&result.raw.error?` (${result.raw.error.message||result.raw.error})`:'';setAiActionLog(prev=>[...prev,{type:'error',text:` AI không trả về lệnh hoặc text. Keys: [${rawKeys}]${errDetail}`,time:Date.now()}]);}if(prompt){promptHistRef.current=[...promptHistRef.current.slice(-49),prompt];setPromptHistory(promptHistRef.current);}setPromptHistIdx(-1);setAiActionLog(prev=>[...prev,{type:'status',text:` Hoàn tất.`,time:Date.now()}]);setAiPrompt('');setTimeout(()=>lucide.createIcons(),200);}catch(err){setAiActionLog(prev=>[...prev,{type:'error',text:` Lỗi: ${err.message}`,time:Date.now()}]);showToast(`AI Error: ${err.message}`,'error');}finally{setAiProcessing(false);}};// ── Split Track at Playhead ── +const handleAISend=async()=>{const prompt=aiPrompt.trim();if(!prompt){showToast('Vui lòng nhập nội dung prompt.','warning');return;}if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentSelectedTrackId=selectedTrackId;window.DAWCommandDispatcher.currentTracks=tracks;window.DAWCommandDispatcher.lastCutSourceTrackId=null;window.DAWCommandDispatcher.lastCutNewTrackId=null;}setAiProcessing(true);setAiActionLog(prev=>[...prev,{type:'status',text:` ⏳ Đang gửi prompt đến AI...`,time:Date.now()}]);try{if(aiProviders.length===0||!selectedProviderId){try{const data=await window.SonicAPI.getAIConfigs();if(data&&data.providers&&data.providers.length>0){setAiProviders(data.providers);const active=data.providers.find(p=>p.is_active)||data.providers[0];if(active)setSelectedProviderId(active.id);}}catch(e){}}const prv=aiProviders.find(p=>p.id===selectedProviderId)||(aiProviders.length>0?aiProviders[0]:null);const provider=prv||aiConfig;const baseUrl=provider.api_base_url||provider.baseUrl||`${API_BASE_URL}`;const apiKey=provider.api_key||provider.apiKey||'';const model=provider.model_name||provider.model||'deepseek-chat';setAiActionLog(prev=>[...prev,{type:'info',text:` Provider: ${provider.name||'default'} | Model: ${model} | URL: ${baseUrl.slice(0,40)}`,time:Date.now()}]);const dawContext=window.AIGateway.buildAIPromptContext({tracks,bpm,selectedTrackId,currentTime,selLeft,selRight});let matchedInstruction='';try{const localPresets=localStorage.getItem('daw_ai_prompt_presets');const presets=localPresets?JSON.parse(localPresets):DEFAULT_PRESETS;const matched=presets.find(p=>p.keywords.some(kw=>prompt.toLowerCase().includes(kw.toLowerCase())));if(matched){matchedInstruction=matched.system_instruction_template;setAiActionLog(prev=>[...prev,{type:'status',text:` 🎯 Khớp Preset: "${matched.name}". Tự động tối ưu gợi ý...`,time:Date.now()}]);}}catch(e){console.error("Lỗi khi tìm preset:",e);}const result=await window.AIGateway.executeAIPrompt({prompt:prompt,provider:provider.name||'default',model:model,apiKey:apiKey,baseUrl:baseUrl.replace(/\/chat\/completions$/,'').replace(/\/$/,''),dawContext,tools:window.AIGateway.DEFAULT_TOOLS,systemInstruction:matchedInstruction});const hasText=!!result.textResponse;const hasCalls=result.functionCalls&&result.functionCalls.length>0;if(hasText){setAiActionLog(prev=>[...prev,{type:'status',text:` AI: ${result.textResponse.slice(0,500)}`,time:Date.now()}]);}if(hasCalls){setAiActionLog(prev=>[...prev,{type:'info',text:` Gọi ${result.functionCalls.length} lệnh...`,time:Date.now()}]);if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.isExecutingAI=true;}try{for(const fc of result.functionCalls){setAiActionLog(prev=>[...prev,{type:'info',text:` Gọi lệnh: ${fc.name}(${JSON.stringify(fc.arguments)})`,time:Date.now()}]);const cmdName=fc.name.toUpperCase();if(window.DAWCommandDispatcher){try{let cmdResult=window.DAWCommandDispatcher.execute(cmdName,fc.arguments);if(cmdResult&&typeof cmdResult.then==='function')cmdResult=await cmdResult;setAiActionLog(prev=>[...prev,{type:'status',text:` ✅ ${fc.name}: ${cmdResult&&cmdResult.success?'thành công':'thất bại: '+(cmdResult&&cmdResult.error||'unknown')}`,time:Date.now()}]);}catch(cmdErr){setAiActionLog(prev=>[...prev,{type:'error',text:` ❌ ${fc.name}: ${cmdErr.message}`,time:Date.now()}]);}}else{setAiActionLog(prev=>[...prev,{type:'error',text:` ❌ ${fc.name}: DAWCommandDispatcher not available`,time:Date.now()}]);}}}finally{if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.isExecutingAI=false;}}}if(!hasText&&!hasCalls){const rawKeys=result.raw?Object.keys(result.raw).join(', '):'null';const errDetail=result.raw&&result.raw.error?` (${result.raw.error.message||result.raw.error})`:'';setAiActionLog(prev=>[...prev,{type:'error',text:` AI không trả về lệnh hoặc text. Keys: [${rawKeys}]${errDetail}`,time:Date.now()}]);}if(prompt){promptHistRef.current=[...promptHistRef.current.slice(-49),prompt];setPromptHistory(promptHistRef.current);}setPromptHistIdx(-1);setAiActionLog(prev=>[...prev,{type:'status',text:` Hoàn tất.`,time:Date.now()}]);setAiPrompt('');setTimeout(()=>lucide.createIcons(),200);}catch(err){setAiActionLog(prev=>[...prev,{type:'error',text:` Lỗi: ${err.message}`,time:Date.now()}]);showToast(`AI Error: ${err.message}`,'error');}finally{setAiProcessing(false);}};// ── Split Track at Playhead ── const handleSplitTrackAtTime=(trackId,clipId,time)=>{const track=tracks.find(t=>t.id===trackId);if(!track)return;const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default',buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];const targetClipId=clipId||clips.find(c=>time>=c.startTime&&timec.id===targetClipId);if(!clip||!clip.buffer)return;const relTime=Math.max(0,time-clip.startTime);const sr=clip.buffer.sampleRate;const cutSample=Math.floor(relTime*sr);const originalData=clip.buffer.getChannelData(0);if(cutSample<=0||cutSample>=originalData.length){showToast("Vị trí cắt nằm ngoài dải âm thanh của clip.","warning");return;}const beforeSnap=captureTrackSnapshot(trackId);const ctx=getAudioContext();const b1=ctx.createBuffer(1,cutSample,sr);b1.copyToChannel(originalData.subarray(0,cutSample),0);const b2=ctx.createBuffer(1,originalData.length-cutSample,sr);b2.copyToChannel(originalData.subarray(cutSample),0);const clip1={id:'clip_'+Date.now()+'_p1',name:`${clip.name.replace(' (Part 1)','').replace(' (Part 2)','')} (Part 1)`,buffer:b1,startTime:clip.startTime};const clip2={id:'clip_'+Date.now()+'_p2',name:`${clip.name.replace(' (Part 1)','').replace(' (Part 2)','')} (Part 2)`,buffer:b2,startTime:clip.startTime+cutSample/sr};setTracks(prev=>prev.map(t=>{if(t.id===trackId){const remainingClips=clips.filter(c=>c.id!==targetClipId);const updatedClips=[...remainingClips,clip1,clip2];return{...t,clips:updatedClips,buffer:updatedClips[0]?.buffer||null,startTime:updatedClips[0]?.startTime||0,name:updatedClips[0]?.name||t.name};}return t;}));setTimeout(()=>{const afterSnap=captureTrackSnapshot(trackId);pushAction('SPLIT_CLIP',trackId,beforeSnap,afterSnap);},50);showToast(`Đã chia nhỏ clip tại ${formatTime(time)}.`,"info");};const handleSplitTrack=trackId=>{handleSplitTrackAtTime(trackId,null,currentTime);};// ── Glue (Merge) Clips on Selected Track ── const handleGlueTracks=()=>{const track=tracks.find(t=>t.id===selectedTrackId);if(!track){showToast('Vui lòng chọn một track để thực hiện gộp (glue).','warning');return;}const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default',buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length<2){showToast('Cần ít nhất 2 clip trên track này để gộp (glue).','warning');return;}const beforeSnap=captureTrackSnapshot(track.id);const ctx=getAudioContext();const sr=clips[0].buffer.sampleRate;let minStart=Infinity;let maxEnd=-Infinity;clips.forEach(c=>{const start=c.startTime||0;const end=start+c.buffer.duration;minStart=Math.min(minStart,start);maxEnd=Math.max(maxEnd,end);});const newDur=maxEnd-minStart;const newBuffer=ctx.createBuffer(1,Math.ceil(newDur*sr),sr);const newData=newBuffer.getChannelData(0);clips.forEach(c=>{const data=c.buffer.getChannelData(0);const offset=Math.floor(((c.startTime||0)-minStart)*sr);for(let i=0;imaxPeak)maxPeak=abs;}if(maxPeak>1.0){for(let i=0;iprev.map(t=>{if(t.id===track.id){return{...t,clips:[mergedClip],buffer:newBuffer,startTime:minStart,name:mergedClip.name};}return t;}));setTimeout(()=>{const afterSnap=captureTrackSnapshot(track.id);pushAction('GLUE',track.id,beforeSnap,afterSnap);},50);showToast(`Đã gộp ${clips.length} clips thành công.`,'success');};// ── DAW Command Registration for AI (28_AI_PANEL.md §1 & §2) ── -useEffect(()=>{if(typeof window.DAWCommandDispatcher==='undefined')return;const api={createTrack:args=>{const name=args.name||`AI_Track_${Date.now()}`;const type=args.type||'audio';const newId=addNewTrack();if(name&&name!==`AI_Track_${Date.now()}`){updateTrackName(newId,name);}return{success:true,trackId:newId,name};},deleteTrack:args=>{const tid=args.track_id||selectedTrackId;if(!tid)return{success:false,error:'No track_id provided'};deleteTrack(tid);return{success:true,trackId:tid};},addClip:args=>{const trackId=args.track_id||selectedTrackId;const barDur=60/parseInt(bpm||120)*4;let startTime;if(args.start_time!==undefined&&args.start_time!==null)startTime=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)startTime=args.start_bar*barDur;else startTime=currentTime;const track=tracks.find(t=>t.id===trackId);if(!track)return{success:false,error:'Track not found'};const ctx=getAudioContext();const sr=44100;let duration;if(args.duration_seconds!==undefined&&args.duration_seconds!==null)duration=args.duration_seconds;else if(args.length_bars!==undefined&&args.length_bars!==null)duration=args.length_bars*barDur;else duration=2;const buffer=ctx.createBuffer(1,Math.floor(sr*duration),sr);const data=buffer.getChannelData(0);for(let i=0;iprev.map(t=>{if(t.id!==trackId)return t;const clips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];return{...t,clips:[...clips,{id:clipId,buffer,startTime,name:args.name||'AI Clip'}],buffer:clips.length>0?clips[0].buffer:buffer,startTime:clips.length>0?clips[0].startTime:startTime,name:clips.length>0?clips[0].name:args.name||t.name};}));return{success:true,clipId,trackId};},removeClip:args=>{const trackId=args.track_id||selectedTrackId;const clipId=args.clip_id;setTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;const updatedClips=(t.clips||[]).filter(c=>c.id!==clipId);return{...t,clips:updatedClips,buffer:updatedClips[0]?.buffer||null,startTime:updatedClips[0]?.startTime||0,name:updatedClips[0]?.name||t.name};}));return{success:true};},setTrackVolume:args=>{const trackId=args.track_id||selectedTrackId;const vol=args.volume_db??args.volume??0;updateTrackVolumeDb(trackId,parseFloat(vol));return{success:true,trackId,volumeDb:vol};},setTrackPan:args=>{const trackId=args.track_id||selectedTrackId;const pan=args.pan??0;updateTrackPan(trackId,parseInt(pan));return{success:true,trackId,pan};},toggleMute:args=>{const trackId=args.track_id||selectedTrackId;toggleTrackMute(trackId);const track=tracks.find(t=>t.id===trackId);return{success:true,trackId,muted:track?track.muted:null};},toggleSolo:args=>{const trackId=args.track_id||selectedTrackId;toggleTrackSoloEvaluate(trackId);const track=tracks.find(t=>t.id===trackId);return{success:true,trackId,solo:track?track.solo:null};},processAudioDsp:args=>{const trackId=args.track_id||selectedTrackId;const action=args.action;const params=args.params||{};const track=tracks.find(t=>t.id===trackId);if(!track||!track.buffer)return{success:false,error:'Track has no audio buffer'};if(action==='normalize'){const channelData=track.buffer.getChannelData(0);let maxVal=0;for(let i=0;i0){const gain=1.0/maxVal;for(let i=0;i{const newLen=Math.round(data.length*r);const out=new Float32Array(newLen);for(let i=0;iprev.map(t=>t.id===trackId?{...t,buffer:newBuffer}:t));return{success:true,action:'pitch_shift',semitones};}return{success:false,error:`Unknown action: ${action}`};},renameTrack:args=>{const tid=args.track_id||selectedTrackId;const name=args.name;if(!tid)return{success:false,error:'No track_id provided'};if(!name)return{success:false,error:'No name provided'};updateTrackName(tid,name);return{success:true,trackId:tid,name};},setSelection:args=>{const barDur=60/parseInt(bpm||120)*4;let start,end;if(args.start_time!==undefined&&args.start_time!==null)start=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)start=args.start_bar*barDur;else start=currentTime;if(args.end_time!==undefined&&args.end_time!==null)end=args.end_time;else if(args.length_bars!==undefined&&args.length_bars!==null)end=start+args.length_bars*barDur;else if(args.end_bar!==undefined&&args.end_bar!==null)end=args.end_bar*barDur;else end=start+barDur;clearLocalSelection();setSelectionMode('global');setSelectionStart(start);setSelectionEnd(end);selectionRef.current={start,end};return{success:true,start:parseFloat(start.toFixed(3)),end:parseFloat(end.toFixed(3)),length:parseFloat((end-start).toFixed(3))};},cutAudio:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;const tid=args.track_id||currentSelTrackId;const track=currentTracks.find(t=>t.id===String(tid));if(!track)return{success:false,error:'Track not found'};if(!track.buffer)return{success:false,error:'Track has no audio buffer'};const barDur=60/parseInt(bpm||120)*4;const sel=selectionRef.current;let rawStart,rawEnd;if(args.start_time!==undefined&&args.start_time!==null)rawStart=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)rawStart=args.start_bar*barDur;else if(sel.start!==null)rawStart=sel.start;else rawStart=currentTime;if(args.end_time!==undefined&&args.end_time!==null)rawEnd=args.end_time;else if(args.end_bar!==undefined&&args.end_bar!==null)rawEnd=args.end_bar*barDur;else if(args.length_bars!==undefined&&args.length_bars!==null)rawEnd=rawStart+args.length_bars*barDur;else if(sel.end!==null&&sel.end>rawStart)rawEnd=sel.end;else return{success:false,error:'No end position provided. Provide end_time, end_bar, or length_bars.'};if(rawEnd<=rawStart)return{success:false,error:'End position must be after start position.'};const buffer=track.buffer;const ctx=getAudioContext();const snap=args.snap_silence!==false;const loopStart=snap?findZeroCrossing(buffer,rawStart):rawStart;const loopEnd=snap?findZeroCrossing(buffer,rawEnd):rawEnd;const sampleRate=buffer.sampleRate;const startSample=Math.max(0,Math.min(buffer.length-1,Math.floor(loopStart*sampleRate)));const endSample=Math.max(0,Math.min(buffer.length,Math.floor(loopEnd*sampleRate)));const sliceLength=endSample-startSample;if(sliceLength<=100)return{success:false,error:'Selection too short or invalid'};const numChannels=buffer.numberOfChannels||1;const slicedBuffer=ctx.createBuffer(numChannels,sliceLength,sampleRate);for(let c=0;ct.id===tid);const nextTracks=[...currentTracks];if(idx!==-1){nextTracks.splice(idx+1,0,newTrack);}else{nextTracks.push(newTrack);}if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;window.DAWCommandDispatcher.currentSelectedTrackId=newId;window.DAWCommandDispatcher.lastCutSourceTrackId=tid;window.DAWCommandDispatcher.lastCutNewTrackId=newId;}setTracks(nextTracks);setSelectedTrackId(newId);selectionRef.current={start:0,end:slicedBuffer.duration};clearLocalSelection();setSelectionMode('global');setSelectionStart(0);setSelectionEnd(slicedBuffer.duration);setTimeout(()=>lucide.createIcons(),200);return{success:true,trackId:newId,trackName:cutName,cutStart:parseFloat(loopStart.toFixed(3)),cutEnd:parseFloat(loopEnd.toFixed(3)),duration:parseFloat(slicedBuffer.duration.toFixed(3))};},scanTrack:args=>{const tid=args.track_id||selectedTrackId;const track=tracks.find(t=>t.id===tid);if(!track)return{success:false,error:'Track not found'};if(!track.buffer)return{success:false,error:'Track has no audio buffer. Load audio first.'};const buffer=track.buffer;const data=buffer.getChannelData(0);const sr=buffer.sampleRate;const channels=buffer.numberOfChannels;const duration=buffer.duration;const totalSamples=buffer.length;const windowSize=Math.min(sr*3,data.length);let detectedBPM=0;if(windowSize>sr){let maxCorr=0;for(let lag=Math.floor(sr*0.3);lag<=Math.floor(sr*2.0);lag++){let corr=0;const step=4;for(let i=0;imaxCorr){maxCorr=corr;detectedBPM=60/(lag/sr);}}}detectedBPM=Math.round(Math.min(300,Math.max(30,detectedBPM)));if(args.set_tempo!==false&&detectedBPM>0){setBpm(String(detectedBPM));}const bitDepth=16;const bitrate=Math.round(sr*channels*bitDepth/1000);return{success:true,trackId:tid,trackName:track.name,bpm:detectedBPM,sampleRate:sr,channels,duration:parseFloat(duration.toFixed(3)),totalSamples,bitDepth,bitrateKbps:bitrate,hasAudio:true};},setBpm:args=>{const bpmVal=args.bpm||args.tempo||120;setBpm(String(bpmVal));return{success:true,bpm:bpmVal};},setPlayhead:args=>{const barDur=60/parseInt(bpm||120)*4;let time;if(args.time!==undefined&&args.time!==null)time=args.time;else if(args.bar!==undefined&&args.bar!==null)time=args.bar*barDur;else time=0;handlePlayheadSet(time);return{success:true,time:parseFloat(time.toFixed(3))};},exportAudio:async args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let tid=args.track_id;if(tid&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(tid)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+tid===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){tid=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!tid)tid=currentSelTrackId;const track=tid&¤tTracks.find(t=>t.id===String(tid)||t.id==='track_'+tid);if(!track)return{success:false,error:'No track found'};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0)return{success:false,error:'Track has no audio clips'};const totalDuration=Math.max(...clips.map(c=>(c.startTime||0)+(c.buffer?c.buffer.duration/(c.speed||1.0):0)));const barDur=60/parseInt(bpm||120)*4;const sel=selectionRef.current;let rawStart,rawEnd;if(args.start_time!==undefined)rawStart=args.start_time;else if(args.start_bar!==undefined)rawStart=args.start_bar*barDur;else if(sel.start!==null)rawStart=sel.start;else rawStart=0;if(args.end_time!==undefined)rawEnd=args.end_time;else if(args.length_bars!==undefined)rawEnd=(rawStart||0)+args.length_bars*barDur;else if(args.end_bar!==undefined)rawEnd=args.end_bar*barDur;else if(sel.end!==null&&sel.end>rawStart)rawEnd=sel.end;else rawEnd=totalDuration;if(rawEnd<=rawStart)return{success:false,error:'Export range is empty or invalid.'};const ctx=getAudioContext();const sr=parseInt(args.sample_rate||'44100');const firstBuffer=clips.find(c=>c.buffer)?.buffer;const numCh=args.channels==='mono'?1:firstBuffer?firstBuffer.numberOfChannels:2;const bd=parseInt(args.bit_depth||'16');const fmt=args.format||'wav';const renderLength=rawEnd-rawStart;const offlineCtx=new OfflineAudioContext(numCh,Math.ceil(sr*renderLength),sr);clips.forEach(clip=>{if(!clip.buffer)return;const clipStart=clip.startTime||0;const clipDuration=clip.buffer.duration/(clip.speed||1.0);const clipEnd=clipStart+clipDuration;if(clipEnd<=rawStart||clipStart>=rawEnd)return;const source=offlineCtx.createBufferSource();source.buffer=clip.buffer;source.playbackRate.value=clip.speed||1.0;source.connect(offlineCtx.destination);if(rawStart{for(let i=0;i>8&0xFF);vw.setUint8(ofs+2,v24>>16&0xFF);}ofs+=bps;}}const blob=new Blob([fileBuf],{type:'audio/wav'});const localUrl=URL.createObjectURL(blob);const targetFilename=`export_${Date.now()}.${fmt}`;const triggerDownload=(downloadUrl,finalFilename)=>{if(window.DAWCommandDispatcher?.isExecutingAI){showToast(`Xuất nhạc thành công (${fmt.toUpperCase()})!`,"success","Tải về",()=>{const a=document.createElement('a');a.href=downloadUrl;a.download=finalFilename;a.click();if(downloadUrl.startsWith('blob:')){URL.revokeObjectURL(downloadUrl);}});}else{const a=document.createElement('a');a.href=downloadUrl;a.download=finalFilename;a.click();showToast("Xuất bản âm thanh hoàn tất!","success");if(downloadUrl.startsWith('blob:')){URL.revokeObjectURL(downloadUrl);}}};if((fmt==='mp3'||fmt==='ogg')&&serverStatus==='connected'){try{const file=new File([blob],`export_ai.wav`,{type:'audio/wav'});const formData=new FormData();formData.append('file',file);const uploadResp=await fetch(`${API_AUDIO}/upload`,{method:'POST',body:formData});if(!uploadResp.ok)throw new Error("Upload failed");const uploadData=await uploadResp.json();const uploadId=uploadData.file_id;const exportResp=await fetch(`${API_AUDIO}/export`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({file_id:uploadId,format:fmt,sample_rate:sr,bit_depth:bd})});if(!exportResp.ok)throw new Error("Export failed");const exportData=await exportResp.json();const result=await pollTaskResult(exportData.task_id,20);if(result.success){const downloadUrl=`${API_AUDIO}/download/${result.output_file_id}`;triggerDownload(downloadUrl,targetFilename);}else{throw new Error(result.error||'Server encoding failed');}}catch(transcodeErr){showToast(`Lỗi chuyển đổi: ${transcodeErr.message}. Tải về dạng WAV thay thế.`,"warning");triggerDownload(localUrl,`export_${Date.now()}.wav`);}}else{const finalFilename=fmt==='wav'?`export_${Date.now()}.wav`:`export_${Date.now()}.wav`;if(fmt!=='wav'){showToast("Đang ngoại tuyến. Tải về định dạng WAV thay thế.","warning");}triggerDownload(localUrl,finalFilename);}return{success:true,trackId:tid,range:parseFloat((rawEnd-rawStart).toFixed(3))+'s',format:fmt,channels:numCh===1?'mono':'stereo'};},selectItem:args=>{if(args.select_all){setSelectedTrackId(null);clearLocalSelection();setSelectionMode('global');setSelectionStart(0);const maxDur=tracks.reduce((max,t)=>{const dur=t.buffer?t.buffer.duration:0;const clips=t.clips||[];const clipMax=clips.reduce((m,c)=>Math.max(m,(c.startTime||0)+(c.buffer?c.buffer.duration:0)),0);return Math.max(max,dur,clipMax);},0);setSelectionEnd(Math.max(maxDur,currentTime+10));return{success:true,selection:'all',duration:parseFloat(Math.max(maxDur,currentTime+10).toFixed(3))};}const tid=args.track_id||selectedTrackId;const track=tracks.find(t=>t.id===tid);if(!track)return{success:false,error:`Track ${tid} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,name:track.name,buffer:track.buffer,startTime:track.startTime||0}]:[];if(args.item_name){const match=clips.find(c=>c.name&&c.name.toLowerCase().includes(args.item_name.toLowerCase()));if(!match)return{success:false,error:`No clip matching "${args.item_name}" on track ${track.name}`};setSelectedTrackId(tid);clearLocalSelection();setSelectionMode('global');const start=match.startTime||0;const end=start+(match.buffer?match.buffer.duration:2);setSelectionStart(start);setSelectionEnd(end);return{success:true,trackId:tid,trackName:track.name,clipId:match.id,clipName:match.name,start:parseFloat(start.toFixed(3)),end:parseFloat(end.toFixed(3))};}setSelectedTrackId(tid);clearLocalSelection();setSelectionMode('global');const trackEnd=track.buffer?track.buffer.duration:clips.length>0?Math.max(...clips.map(c=>(c.startTime||0)+(c.buffer?c.buffer.duration:0))):4;setSelectionStart(0);setSelectionEnd(trackEnd);return{success:true,trackId:tid,trackName:track.name,duration:parseFloat(trackEnd.toFixed(3))};},addMarker:args=>{const trackId=args.track_id||selectedTrackId;const time=args.time??currentTime;const track=tracks.find(t=>t.id===trackId);if(!track)return{success:false,error:'Track not found'};setTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;return{...t,markers:[...(t.markers||[]),{id:'ai_marker_'+Date.now(),time,label:args.label||'AI Marker'}]};}));return{success:true,trackId,time};},fadeIn:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let trackIdRaw=args.track_id;if(trackIdRaw&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(trackIdRaw)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+trackIdRaw===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){trackIdRaw=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!trackIdRaw)trackIdRaw=currentSelTrackId;const track=currentTracks.find(t=>t.id===String(trackIdRaw)||t.id==='track_'+trackIdRaw);if(!track)return{success:false,error:`Track ${trackIdRaw} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0)return{success:false,error:'No clips on track'};let clip=null;if(args.clip_id){clip=clips.find(c=>c.id===args.clip_id);}else if(args.clip_index!==undefined){const idx=parseInt(args.clip_index);const realIdx=idx>0?idx-1:0;clip=clips[realIdx]||clips[0];}else{clip=clips[0];}if(!clip||!clip.buffer)return{success:false,error:'Clip has no audio buffer'};const duration=parseFloat(args.duration_seconds||3);const buffer=clip.buffer;const sr=buffer.sampleRate;const numChannels=buffer.numberOfChannels;const length=buffer.length;const ctx=getAudioContext();const newBuffer=ctx.createBuffer(numChannels,length,sr);for(let c=0;c{if(t.id!==track.id)return t;const existingClips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];const updatedClips=existingClips.map(c=>{if(c.id===clip.id||clip.id.startsWith('default_')&&c.id==='default'){return{...c,buffer:newBuffer};}return c;});const mainBuffer=updatedClips[0]?.buffer||t.buffer;return{...t,clips:updatedClips,buffer:mainBuffer};});if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;}setTracks(nextTracks);setTimeout(()=>{const afterSnap=captureTrackSnapshot(track.id);pushAction('AI_FADE_IN',track.id,beforeSnap,afterSnap);},50);return{success:true,trackId:track.id,clipId:clip.id,duration_seconds:duration};},fadeOut:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let trackIdRaw=args.track_id;if(trackIdRaw&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(trackIdRaw)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+trackIdRaw===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){trackIdRaw=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!trackIdRaw)trackIdRaw=currentSelTrackId;const track=currentTracks.find(t=>t.id===String(trackIdRaw)||t.id==='track_'+trackIdRaw);if(!track)return{success:false,error:`Track ${trackIdRaw} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0)return{success:false,error:'No clips on track'};let clip=null;if(args.clip_id){clip=clips.find(c=>c.id===args.clip_id);}else if(args.clip_index!==undefined){const idx=parseInt(args.clip_index);const realIdx=idx>0?idx-1:0;clip=clips[realIdx]||clips[0];}else{clip=clips[0];}if(!clip||!clip.buffer)return{success:false,error:'Clip has no audio buffer'};const duration=parseFloat(args.duration_seconds||3);const buffer=clip.buffer;const sr=buffer.sampleRate;const numChannels=buffer.numberOfChannels;const length=buffer.length;const ctx=getAudioContext();const newBuffer=ctx.createBuffer(numChannels,length,sr);for(let c=0;c{if(t.id!==track.id)return t;const existingClips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];const updatedClips=existingClips.map(c=>{if(c.id===clip.id||clip.id.startsWith('default_')&&c.id==='default'){return{...c,buffer:newBuffer};}return c;});const mainBuffer=updatedClips[0]?.buffer||t.buffer;return{...t,clips:updatedClips,buffer:mainBuffer};});if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;}setTracks(nextTracks);setTimeout(()=>{const afterSnap=captureTrackSnapshot(track.id);pushAction('AI_FADE_OUT',track.id,beforeSnap,afterSnap);},50);return{success:true,trackId:track.id,clipId:clip.id,duration_seconds:duration};}};window.DAWCommandDispatcher.registerDAWCommands(api);},[tracks,selectedTrackId,currentTime,bpm]);// ── Save AI config to localStorage ── +useEffect(()=>{if(typeof window.DAWCommandDispatcher==='undefined')return;const api={createTrack:args=>{const name=args.name||`AI_Track_${Date.now()}`;const type=args.type||'audio';const newId=addNewTrack();if(name&&name!==`AI_Track_${Date.now()}`){updateTrackName(newId,name);}return{success:true,trackId:newId,name};},deleteTrack:args=>{const tid=args.track_id||selectedTrackId;if(!tid)return{success:false,error:'No track_id provided'};deleteTrack(tid);return{success:true,trackId:tid};},addClip:args=>{const trackId=args.track_id||selectedTrackId;const barDur=60/parseInt(bpm||120)*4;let startTime;if(args.start_time!==undefined&&args.start_time!==null)startTime=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)startTime=args.start_bar*barDur;else startTime=currentTime;const track=tracks.find(t=>t.id===trackId);if(!track)return{success:false,error:'Track not found'};const ctx=getAudioContext();const sr=44100;let duration;if(args.duration_seconds!==undefined&&args.duration_seconds!==null)duration=args.duration_seconds;else if(args.length_bars!==undefined&&args.length_bars!==null)duration=args.length_bars*barDur;else duration=2;const buffer=ctx.createBuffer(1,Math.floor(sr*duration),sr);const data=buffer.getChannelData(0);for(let i=0;iprev.map(t=>{if(t.id!==trackId)return t;const clips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];return{...t,clips:[...clips,{id:clipId,buffer,startTime,name:args.name||'AI Clip'}],buffer:clips.length>0?clips[0].buffer:buffer,startTime:clips.length>0?clips[0].startTime:startTime,name:clips.length>0?clips[0].name:args.name||t.name};}));return{success:true,clipId,trackId};},removeClip:args=>{const trackId=args.track_id||selectedTrackId;const clipId=args.clip_id;setTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;const updatedClips=(t.clips||[]).filter(c=>c.id!==clipId);return{...t,clips:updatedClips,buffer:updatedClips[0]?.buffer||null,startTime:updatedClips[0]?.startTime||0,name:updatedClips[0]?.name||t.name};}));return{success:true};},setTrackVolume:args=>{const trackId=args.track_id||selectedTrackId;const vol=args.volume_db??args.volume??0;updateTrackVolumeDb(trackId,parseFloat(vol));return{success:true,trackId,volumeDb:vol};},setTrackPan:args=>{const trackId=args.track_id||selectedTrackId;const pan=args.pan??0;updateTrackPan(trackId,parseInt(pan));return{success:true,trackId,pan};},toggleMute:args=>{const trackId=args.track_id||selectedTrackId;toggleTrackMute(trackId);const track=tracks.find(t=>t.id===trackId);return{success:true,trackId,muted:track?track.muted:null};},toggleSolo:args=>{const trackId=args.track_id||selectedTrackId;toggleTrackSoloEvaluate(trackId);const track=tracks.find(t=>t.id===trackId);return{success:true,trackId,solo:track?track.solo:null};},processAudioDsp:args=>{const trackId=args.track_id||selectedTrackId;const action=args.action;const params=args.params||{};const track=tracks.find(t=>t.id===trackId);if(!track||!track.buffer)return{success:false,error:'Track has no audio buffer'};if(action==='normalize'){const channelData=track.buffer.getChannelData(0);let maxVal=0;for(let i=0;i0){const gain=1.0/maxVal;for(let i=0;i{const newLen=Math.round(data.length*r);const out=new Float32Array(newLen);for(let i=0;iprev.map(t=>t.id===trackId?{...t,buffer:newBuffer}:t));return{success:true,action:'pitch_shift',semitones};}return{success:false,error:`Unknown action: ${action}`};},renameTrack:args=>{const tid=args.track_id||selectedTrackId;const name=args.name;if(!tid)return{success:false,error:'No track_id provided'};if(!name)return{success:false,error:'No name provided'};updateTrackName(tid,name);return{success:true,trackId:tid,name};},setSelection:args=>{const barDur=60/parseInt(bpm||120)*4;let start,end;if(args.start_time!==undefined&&args.start_time!==null)start=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)start=args.start_bar*barDur;else start=currentTime;if(args.end_time!==undefined&&args.end_time!==null)end=args.end_time;else if(args.length_bars!==undefined&&args.length_bars!==null)end=start+args.length_bars*barDur;else if(args.end_bar!==undefined&&args.end_bar!==null)end=args.end_bar*barDur;else end=start+barDur;clearLocalSelection();setSelectionMode('global');setSelectionStart(start);setSelectionEnd(end);selectionRef.current={start,end};return{success:true,start:parseFloat(start.toFixed(3)),end:parseFloat(end.toFixed(3)),length:parseFloat((end-start).toFixed(3))};},cutAudio:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;const tid=args.track_id||currentSelTrackId;const track=currentTracks.find(t=>t.id===String(tid));if(!track)return{success:false,error:'Track not found'};if(!track.buffer)return{success:false,error:'Track has no audio buffer'};const barDur=60/parseInt(bpm||120)*4;const sel=selectionRef.current;let rawStart,rawEnd;if(args.start_time!==undefined&&args.start_time!==null)rawStart=args.start_time;else if(args.start_bar!==undefined&&args.start_bar!==null)rawStart=args.start_bar*barDur;else if(sel.start!==null)rawStart=sel.start;else rawStart=currentTime;if(args.end_time!==undefined&&args.end_time!==null)rawEnd=args.end_time;else if(args.end_bar!==undefined&&args.end_bar!==null)rawEnd=args.end_bar*barDur;else if(args.length_bars!==undefined&&args.length_bars!==null)rawEnd=rawStart+args.length_bars*barDur;else if(sel.end!==null&&sel.end>rawStart)rawEnd=sel.end;else return{success:false,error:'No end position provided. Provide end_time, end_bar, or length_bars.'};if(rawEnd<=rawStart)return{success:false,error:'End position must be after start position.'};const buffer=track.buffer;const ctx=getAudioContext();const snap=args.snap_silence!==false;const loopStart=snap?findZeroCrossing(buffer,rawStart):rawStart;const loopEnd=snap?findZeroCrossing(buffer,rawEnd):rawEnd;const sampleRate=buffer.sampleRate;const startSample=Math.max(0,Math.min(buffer.length-1,Math.floor(loopStart*sampleRate)));const endSample=Math.max(0,Math.min(buffer.length,Math.floor(loopEnd*sampleRate)));const sliceLength=endSample-startSample;if(sliceLength<=100)return{success:false,error:'Selection too short or invalid'};const numChannels=buffer.numberOfChannels||1;const slicedBuffer=ctx.createBuffer(numChannels,sliceLength,sampleRate);for(let c=0;ct.id===tid);const nextTracks=[...currentTracks];if(idx!==-1){nextTracks.splice(idx+1,0,newTrack);}else{nextTracks.push(newTrack);}if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;window.DAWCommandDispatcher.currentSelectedTrackId=newId;window.DAWCommandDispatcher.lastCutSourceTrackId=tid;window.DAWCommandDispatcher.lastCutNewTrackId=newId;}setTracks(nextTracks);setSelectedTrackId(newId);selectionRef.current={start:0,end:slicedBuffer.duration};clearLocalSelection();setSelectionMode('global');setSelectionStart(0);setSelectionEnd(slicedBuffer.duration);setTimeout(()=>lucide.createIcons(),200);return{success:true,trackId:newId,trackName:cutName,cutStart:parseFloat(loopStart.toFixed(3)),cutEnd:parseFloat(loopEnd.toFixed(3)),duration:parseFloat(slicedBuffer.duration.toFixed(3))};},scanTrack:args=>{const tid=args.track_id||selectedTrackId;const track=tracks.find(t=>t.id===tid);if(!track)return{success:false,error:'Track not found'};if(!track.buffer)return{success:false,error:'Track has no audio buffer. Load audio first.'};const buffer=track.buffer;const data=buffer.getChannelData(0);const sr=buffer.sampleRate;const channels=buffer.numberOfChannels;const duration=buffer.duration;const totalSamples=buffer.length;const windowSize=Math.min(sr*3,data.length);let detectedBPM=0;if(windowSize>sr){let maxCorr=0;for(let lag=Math.floor(sr*0.3);lag<=Math.floor(sr*2.0);lag++){let corr=0;const step=4;for(let i=0;imaxCorr){maxCorr=corr;detectedBPM=60/(lag/sr);}}}detectedBPM=Math.round(Math.min(300,Math.max(30,detectedBPM)));if(args.set_tempo!==false&&detectedBPM>0){setBpm(String(detectedBPM));}const bitDepth=16;const bitrate=Math.round(sr*channels*bitDepth/1000);return{success:true,trackId:tid,trackName:track.name,bpm:detectedBPM,sampleRate:sr,channels,duration:parseFloat(duration.toFixed(3)),totalSamples,bitDepth,bitrateKbps:bitrate,hasAudio:true};},setBpm:args=>{const bpmVal=args.bpm||args.tempo||120;setBpm(String(bpmVal));return{success:true,bpm:bpmVal};},setPlayhead:args=>{const barDur=60/parseInt(bpm||120)*4;let time;if(args.time!==undefined&&args.time!==null)time=args.time;else if(args.bar!==undefined&&args.bar!==null)time=args.bar*barDur;else time=0;handlePlayheadSet(time);return{success:true,time:parseFloat(time.toFixed(3))};},exportAudio:async args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let tid=args.track_id;if(tid&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(tid)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+tid===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){tid=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!tid)tid=currentSelTrackId;const track=tid&¤tTracks.find(t=>t.id===String(tid)||t.id==='track_'+tid);if(!track)return{success:false,error:'No track found'};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0)return{success:false,error:'Track has no audio clips'};const totalDuration=Math.max(...clips.map(c=>(c.startTime||0)+(c.buffer?c.buffer.duration/(c.speed||1.0):0)));const barDur=60/parseInt(bpm||120)*4;const sel=selectionRef.current;let rawStart,rawEnd;if(args.start_time!==undefined)rawStart=args.start_time;else if(args.start_bar!==undefined)rawStart=args.start_bar*barDur;else if(sel.start!==null)rawStart=sel.start;else rawStart=0;if(args.end_time!==undefined)rawEnd=args.end_time;else if(args.length_bars!==undefined)rawEnd=(rawStart||0)+args.length_bars*barDur;else if(args.end_bar!==undefined)rawEnd=args.end_bar*barDur;else if(sel.end!==null&&sel.end>rawStart)rawEnd=sel.end;else rawEnd=totalDuration;if(rawEnd<=rawStart)return{success:false,error:'Export range is empty or invalid.'};const ctx=getAudioContext();const sr=parseInt(args.sample_rate||'44100');const firstBuffer=clips.find(c=>c.buffer)?.buffer;const numCh=args.channels==='mono'?1:firstBuffer?firstBuffer.numberOfChannels:2;const bd=parseInt(args.bit_depth||'16');const fmt=args.format||'wav';const renderLength=rawEnd-rawStart;const offlineCtx=new OfflineAudioContext(numCh,Math.ceil(sr*renderLength),sr);clips.forEach(clip=>{if(!clip.buffer)return;const clipStart=clip.startTime||0;const clipDuration=clip.buffer.duration/(clip.speed||1.0);const clipEnd=clipStart+clipDuration;if(clipEnd<=rawStart||clipStart>=rawEnd)return;const source=offlineCtx.createBufferSource();source.buffer=clip.buffer;source.playbackRate.value=clip.speed||1.0;source.connect(offlineCtx.destination);if(rawStart{for(let i=0;i>8&0xFF);vw.setUint8(ofs+2,v24>>16&0xFF);}ofs+=bps;}}const blob=new Blob([fileBuf],{type:'audio/wav'});const localUrl=URL.createObjectURL(blob);const targetFilename=`export_${Date.now()}.${fmt}`;const triggerDownload=(downloadUrl,finalFilename)=>{if(window.DAWCommandDispatcher?.isExecutingAI){showToast(`Xuất nhạc thành công (${fmt.toUpperCase()})!`,"success","Tải về",()=>{const a=document.createElement('a');a.href=downloadUrl;a.download=finalFilename;a.click();if(downloadUrl.startsWith('blob:')){URL.revokeObjectURL(downloadUrl);}});}else{const a=document.createElement('a');a.href=downloadUrl;a.download=finalFilename;a.click();showToast("Xuất bản âm thanh hoàn tất!","success");if(downloadUrl.startsWith('blob:')){URL.revokeObjectURL(downloadUrl);}}};if((fmt==='mp3'||fmt==='ogg')&&serverStatus==='connected'){try{const file=new File([blob],`export_ai.wav`,{type:'audio/wav'});const formData=new FormData();formData.append('file',file);const uploadResp=await fetch(`${API_AUDIO}/upload`,{method:'POST',body:formData});if(!uploadResp.ok)throw new Error("Upload failed");const uploadData=await uploadResp.json();const uploadId=uploadData.file_id;const exportResp=await fetch(`${API_AUDIO}/export`,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({file_id:uploadId,format:fmt,sample_rate:sr,bit_depth:bd})});if(!exportResp.ok)throw new Error("Export failed");const exportData=await exportResp.json();const result=await pollTaskResult(exportData.task_id,20);if(result.success){const downloadUrl=`${API_AUDIO}/download/${result.output_file_id}`;triggerDownload(downloadUrl,targetFilename);}else{throw new Error(result.error||'Server encoding failed');}}catch(transcodeErr){showToast(`Lỗi chuyển đổi: ${transcodeErr.message}. Tải về dạng WAV thay thế.`,"warning");triggerDownload(localUrl,`export_${Date.now()}.wav`);}}else{const finalFilename=fmt==='wav'?`export_${Date.now()}.wav`:`export_${Date.now()}.wav`;if(fmt!=='wav'){showToast("Đang ngoại tuyến. Tải về định dạng WAV thay thế.","warning");}triggerDownload(localUrl,finalFilename);}return{success:true,trackId:tid,range:parseFloat((rawEnd-rawStart).toFixed(3))+'s',format:fmt,channels:numCh===1?'mono':'stereo'};},selectItem:args=>{if(args.select_all){setSelectedTrackId(null);clearLocalSelection();setSelectionMode('global');setSelectionStart(0);const maxDur=tracks.reduce((max,t)=>{const dur=t.buffer?t.buffer.duration:0;const clips=t.clips||[];const clipMax=clips.reduce((m,c)=>Math.max(m,(c.startTime||0)+(c.buffer?c.buffer.duration:0)),0);return Math.max(max,dur,clipMax);},0);setSelectionEnd(Math.max(maxDur,currentTime+10));return{success:true,selection:'all',duration:parseFloat(Math.max(maxDur,currentTime+10).toFixed(3))};}const tid=args.track_id||selectedTrackId;const track=tracks.find(t=>t.id===tid);if(!track)return{success:false,error:`Track ${tid} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,name:track.name,buffer:track.buffer,startTime:track.startTime||0}]:[];if(args.item_name){const match=clips.find(c=>c.name&&c.name.toLowerCase().includes(args.item_name.toLowerCase()));if(!match)return{success:false,error:`No clip matching "${args.item_name}" on track ${track.name}`};setSelectedTrackId(tid);clearLocalSelection();setSelectionMode('global');const start=match.startTime||0;const end=start+(match.buffer?match.buffer.duration:2);setSelectionStart(start);setSelectionEnd(end);return{success:true,trackId:tid,trackName:track.name,clipId:match.id,clipName:match.name,start:parseFloat(start.toFixed(3)),end:parseFloat(end.toFixed(3))};}setSelectedTrackId(tid);clearLocalSelection();setSelectionMode('global');const trackEnd=track.buffer?track.buffer.duration:clips.length>0?Math.max(...clips.map(c=>(c.startTime||0)+(c.buffer?c.buffer.duration:0))):4;setSelectionStart(0);setSelectionEnd(trackEnd);return{success:true,trackId:tid,trackName:track.name,duration:parseFloat(trackEnd.toFixed(3))};},addMarker:args=>{const trackId=args.track_id||selectedTrackId;const time=args.time??currentTime;const track=tracks.find(t=>t.id===trackId);if(!track)return{success:false,error:'Track not found'};setTracks(prev=>prev.map(t=>{if(t.id!==trackId)return t;return{...t,markers:[...(t.markers||[]),{id:'ai_marker_'+Date.now(),time,label:args.label||'AI Marker'}]};}));return{success:true,trackId,time};},fadeIn:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let trackIdRaw=args.track_id;if(trackIdRaw&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(trackIdRaw)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+trackIdRaw===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){trackIdRaw=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!trackIdRaw)trackIdRaw=currentSelTrackId;const track=currentTracks.find(t=>t.id===String(trackIdRaw)||t.id==='track_'+trackIdRaw);if(!track)return{success:false,error:`Track ${trackIdRaw} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0)return{success:false,error:'No clips on track'};let clip=null;if(args.clip_id){clip=clips.find(c=>c.id===args.clip_id);}else if(args.clip_index!==undefined){const idx=parseInt(args.clip_index);const realIdx=idx>0?idx-1:0;clip=clips[realIdx]||clips[0];}else{clip=clips[0];}if(!clip||!clip.buffer)return{success:false,error:'Clip has no audio buffer'};const duration=parseFloat(args.duration_seconds||3);const buffer=clip.buffer;const sr=buffer.sampleRate;const numChannels=buffer.numberOfChannels;const length=buffer.length;const ctx=getAudioContext();const newBuffer=ctx.createBuffer(numChannels,length,sr);for(let c=0;c{if(t.id!==track.id)return t;const existingClips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];const updatedClips=existingClips.map(c=>{if(c.id===clip.id||clip.id.startsWith('default_')&&c.id==='default'){return{...c,buffer:newBuffer};}return c;});const mainBuffer=updatedClips[0]?.buffer||t.buffer;return{...t,clips:updatedClips,buffer:mainBuffer};});if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;}setTracks(nextTracks);setTimeout(()=>{const afterSnap=captureTrackSnapshot(track.id);pushAction('AI_FADE_IN',track.id,beforeSnap,afterSnap);},50);return{success:true,trackId:track.id,clipId:clip.id,duration_seconds:duration};},fadeOut:args=>{const currentTracks=window.DAWCommandDispatcher?.currentTracks||tracks;const currentSelTrackId=window.DAWCommandDispatcher?.currentSelectedTrackId||selectedTrackId;let trackIdRaw=args.track_id;if(trackIdRaw&&window.DAWCommandDispatcher?.lastCutSourceTrackId&&(String(trackIdRaw)===String(window.DAWCommandDispatcher.lastCutSourceTrackId)||'track_'+trackIdRaw===String(window.DAWCommandDispatcher.lastCutSourceTrackId))){trackIdRaw=window.DAWCommandDispatcher.lastCutNewTrackId;}if(!trackIdRaw)trackIdRaw=currentSelTrackId;const track=currentTracks.find(t=>t.id===String(trackIdRaw)||t.id==='track_'+trackIdRaw);if(!track)return{success:false,error:`Track ${trackIdRaw} not found`};const clips=track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default_'+track.id,buffer:track.buffer,startTime:track.startTime||0,name:track.name}]:[];if(clips.length===0)return{success:false,error:'No clips on track'};let clip=null;if(args.clip_id){clip=clips.find(c=>c.id===args.clip_id);}else if(args.clip_index!==undefined){const idx=parseInt(args.clip_index);const realIdx=idx>0?idx-1:0;clip=clips[realIdx]||clips[0];}else{clip=clips[0];}if(!clip||!clip.buffer)return{success:false,error:'Clip has no audio buffer'};const duration=parseFloat(args.duration_seconds||3);const buffer=clip.buffer;const sr=buffer.sampleRate;const numChannels=buffer.numberOfChannels;const length=buffer.length;const ctx=getAudioContext();const newBuffer=ctx.createBuffer(numChannels,length,sr);for(let c=0;c{if(t.id!==track.id)return t;const existingClips=t.clips&&t.clips.length>0?t.clips:t.buffer?[{id:'default_'+t.id,buffer:t.buffer,startTime:t.startTime||0,name:t.name}]:[];const updatedClips=existingClips.map(c=>{if(c.id===clip.id||clip.id.startsWith('default_')&&c.id==='default'){return{...c,buffer:newBuffer};}return c;});const mainBuffer=updatedClips[0]?.buffer||t.buffer;return{...t,clips:updatedClips,buffer:mainBuffer};});if(window.DAWCommandDispatcher){window.DAWCommandDispatcher.currentTracks=nextTracks;}setTracks(nextTracks);setTimeout(()=>{const afterSnap=captureTrackSnapshot(track.id);pushAction('AI_FADE_OUT',track.id,beforeSnap,afterSnap);},50);return{success:true,trackId:track.id,clipId:clip.id,duration_seconds:duration};},generateMultitrackMidi:args=>{const{composition_title,bpm:aiBpm,total_bars,tracks:aiTracks}=args;if(aiBpm){setBpm(aiBpm.toString());}const bpmVal=aiBpm||parseInt(bpm)||120;const secondsPerBeat=60.0/bpmVal;const secondsPerBar=secondsPerBeat*4;const durationSec=total_bars*secondsPerBar;updateActiveTracks(prev=>{let updatedTracks=[...prev];aiTracks.forEach(aiTrack=>{let targetTrack=updatedTracks.find(t=>t.name.toLowerCase()===aiTrack.track_name.toLowerCase());if(!targetTrack){const newId=(updatedTracks.length+1).toString();const colors=['#0f766e','#1d4ed8','#701a75','#a21caf','#b45309'];const selectColor=colors[updatedTracks.length%colors.length];targetTrack={id:newId,name:aiTrack.track_name,type:'MIDI',volumeDb:0,pan:0,muted:false,solo:false,color:selectColor,markers:[],serverFileId:null,clips:[],sections:[],midiItems:[],isArmed:false,monitoringEnabled:true,inputSource:{deviceType:'NONE',deviceId:''}};updatedTracks.push(targetTrack);}const itemStartTimeSec=currentTime;const newMidiItem={id:'item_ai_'+Date.now()+'_'+Math.random().toString(36).substr(2,5),name:`${composition_title||'AI Theme'} - ${aiTrack.track_name}`,startTime:itemStartTimeSec,duration:durationSec,notes:aiTrack.notes.map((note,index)=>({id:`note_ai_${Date.now()}_${index}`,pitch:note.pitch,start_beat:note.start_beat,duration_beats:note.duration_beats,velocity:note.velocity||0.8,pan:0.0}))};targetTrack.midiItems=[...(targetTrack.midiItems||[]),newMidiItem];});return updatedTracks;});showToast(`Đã nạp ${aiTracks.length} tracks MIDI thế hệ AI!`,'success');return{success:true};}};window.DAWCommandDispatcher.registerDAWCommands(api);},[tracks,selectedTrackId,currentTime,bpm]);// ── Save AI config to localStorage ── useEffect(()=>{localStorage.setItem('ai_base_url',aiConfig.baseUrl);localStorage.setItem('ai_api_key',aiConfig.apiKey);localStorage.setItem('ai_model',aiConfig.model);},[aiConfig]);// ── Auto-save user preferences (panel state, provider) ── -const prefsRef=useRef({});prefsRef.current={showAIPanel,showExportPanel,showSelectionPanel,showPythonToolsPanel,showMediaExplorer,showFxRack,showMidiEvents,panelPositions,rightSidebarWidth,mediaExplorerHeight,selectedProviderId};useEffect(()=>{const prefs=prefsRef.current;localStorage.setItem('sonic_preferences',JSON.stringify(prefs));if(!currentUser||currentUser==='cached')return;const timer=setTimeout(async()=>{try{await window.SonicAPI.savePreferences(prefs);}catch(e){}},2000);return()=>clearTimeout(timer);},[showAIPanel,showExportPanel,showSelectionPanel,showPythonToolsPanel,showMediaExplorer,showFxRack,showMidiEvents,panelPositions,rightSidebarWidth,mediaExplorerHeight,selectedProviderId,currentUser]);return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"h-full w-full flex flex-col bg-[#1e1e1e]"},/*#__PURE__*/React.createElement("header",{className:"h-9 bg-[#2e2e2e] border-b border-[#181818] flex items-center px-1 shrink-0 select-none"},[{label:'File',items:[{label:'New Project',icon:'file-plus',shortcut:'Ctrl+N',action:()=>{setTracks([{id:'1',name:'Track 01',buffer:null,startTime:0,volumeDb:0,pan:0,muted:false,solo:false,color:'#0f766e',markers:[],serverFileId:null,clips:[],sections:[],midiItems:[]},{id:'2',name:'Track 02',buffer:null,startTime:0,volumeDb:0,pan:0,muted:false,solo:false,color:'#1d4ed8',markers:[],serverFileId:null,clips:[],sections:[],midiItems:[]}]);setSelectedTrackId('1');setProjectName('');setCurrentProjectId(null);localStorage.removeItem('sonic_project_name');localStorage.removeItem('sonic_project_id');showToast('New project created','info');}},{label:'Open Project...',icon:'folder-open',shortcut:'Ctrl+O',action:()=>handleImportSFS()},{label:'Save Project',icon:'upload-cloud',shortcut:'Ctrl+S',action:()=>handleSaveProject()},{label:'Save As...',icon:'download',shortcut:'Ctrl+Alt+S',action:()=>setSaveAsModalOpen(true)},{sep:true},{label:'Config AI Providers...',icon:'settings',action:()=>setAiConfigModalOpen(true)},{label:'Import Audio...',icon:'file-input',shortcut:'Ctrl+Alt+I',action:()=>{const input=document.createElement('input');input.type='file';input.accept='audio/*';input.onchange=async e=>{if(e.target.files[0]){addNewTrack();const newId=(tracks.length+1).toString();setTimeout(()=>loadFileOnTrack(newId,e.target.files[0]),100);}};input.click();showToast('Import audio','info');}},{label:'Export Mix...',icon:'file-output',action:()=>triggerWavExport()},{sep:true},...(currentUser?[{label:'Profile',icon:'user',action:()=>setProfileModalOpen(true)}]:[]),...(currentUser&¤tUser.role==='admin'?[{label:'System Manager',icon:'settings',action:()=>setSystemManagerModalOpen(true)}]:[]),{label:'Logout',icon:'log-out',action:()=>handleLogout()}]},{label:'Edit',items:[{label:'Insert New Track',icon:'plus',shortcut:'Ctrl+I',action:addNewTrack},{label:'Insert Music to Track',icon:'music',shortcut:'Ctrl+Alt+I',action:()=>showToast('Select music file to insert','info')},{sep:true},{label:'Edit in New Tab',icon:'file-edit',shortcut:'Ctrl+E',action:()=>openTempTab()},{label:'Split at Playhead',icon:'scissors',shortcut:'S',action:()=>handleSplitTrack(selectedTrackId)},{label:'Merge Tracks',icon:'combine',shortcut:'Ctrl+M',action:()=>{handleMergeTracks();}},{sep:true},{label:'Undo',icon:'undo',shortcut:'Ctrl+Z',action:()=>{handleUndo();}},{label:'Redo',icon:'redo',shortcut:'Ctrl+Y',action:()=>{handleRedo();}},{sep:true},{label:'Copy',icon:'copy',shortcut:'Ctrl+C',action:()=>{handleCopyTrack();}},{label:'Cut',icon:'scissors',shortcut:'Ctrl+X',action:()=>{handleCutTrack();}},{label:'Paste',icon:'clipboard',shortcut:'Ctrl+V',action:handlePasteTrack},{sep:true},{label:'Delete Track',icon:'trash-2',shortcut:'Del',action:()=>{handleDeleteTrack();}}]},{label:'Insert',items:[...(!sessionTabs.some(s=>s.id===activeTab)?[{label:'Insert Section',icon:'folder-plus',action:insertSectionAtPlayhead}]:[]),{label:'Insert MIDI item',icon:'music',action:insertMidiItemAtPlayhead},{label:'Insert sound clip',icon:'file-input',action:insertSoundClipAtCursor},{label:'Insert track',icon:'plus',action:insertTrackBelow}]},{label:'View',items:[{label:'Master Track',icon:'disc',action:()=>showToast('Master track view','info')},{label:'Maker View',icon:'layout',action:()=>showToast('Maker view','info')},{label:'Mixer',icon:'sliders',action:()=>showToast('Mixer panel','info')},{label:'Tempo Track',icon:'timer',action:()=>showToast('Tempo track','info')},{label:'Video',icon:'film',action:()=>showToast('Video panel','info')},{label:'Media Explorer',icon:'folder-search',action:()=>showToast('Media explorer','info')}]},{label:'Tools',items:[{label:'Config AI Providers...',icon:'settings',action:()=>setAiConfigModalOpen(true)},{label:'DSP Tools Panel',icon:'wrench',action:()=>openPanel('python_tools')}]},{label:'Help',items:[{label:'About SonicForge',icon:'info',action:()=>showToast('SonicForge Studio v1.0 - Professional DAW','info')}]}].map(menu=>/*#__PURE__*/React.createElement("div",{key:menu.label,className:"relative"},/*#__PURE__*/React.createElement("button",{onClick:()=>setMenuOpen(menuOpen===menu.label?null:menu.label),className:`px-3 py-1 text-xs font-medium transition rounded ${menuOpen===menu.label?'bg-zinc-700 text-zinc-100':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`},menu.label),menuOpen===menu.label&&/*#__PURE__*/React.createElement("div",{className:`absolute top-full left-0 mt-0.5 bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 z-50 ${menu.label==='Edit'?'w-72':'w-64'}`,onClick:()=>setMenuOpen(null)},menu.items.map((item,i)=>item.sep?/*#__PURE__*/React.createElement("div",{key:i,className:"h-px bg-zinc-700 my-1"}):/*#__PURE__*/React.createElement("button",{key:item.label,onClick:e=>{e.stopPropagation();item.action();setMenuOpen(null);},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":item.icon,className:"w-3.5 h-3.5 text-zinc-500 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},item.label),item.shortcut&&/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},item.shortcut)))))),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 px-2"},/*#__PURE__*/React.createElement("span",{className:`text-xs font-bold uppercase px-1.5 py-0.5 rounded ${serverStatus==='connected'?'bg-emerald-950 text-emerald-400':serverStatus==='checking'?'bg-amber-950 text-amber-400':'bg-red-950 text-red-400'}`},"Server: ",serverStatus),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowAIConfig(!showAIConfig),className:`px-1.5 py-0.5 rounded text-xs border transition ${showAIConfig?'bg-purple-900 text-purple-200 border-purple-700':'bg-zinc-800 text-zinc-400 border-zinc-700 hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3"}))))),menuOpen&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-40",onClick:()=>setMenuOpen(null)}),/*#__PURE__*/React.createElement("div",{className:"h-7 bg-[#222] border-b border-zinc-800 flex items-stretch px-2 gap-0.5 shrink-0 overflow-x-auto"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab('main'),className:`px-3 text-xs font-bold uppercase tracking-wider border-b-2 transition flex items-center gap-1 ${activeTab==='main'?'text-cyan-400 border-cyan-500 bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"layout-dashboard",className:"w-3 h-3"}))," Main Session"),sessionTabs.map(st=>/*#__PURE__*/React.createElement("div",{key:st.id,className:"flex items-stretch"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab(st.id),className:`px-2 text-xs font-medium border-b-2 transition flex items-center gap-1 ${activeTab===st.id?'text-cyan-400 border-cyan-500 bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"layout-dashboard",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"max-w-[120px] truncate"},st.name)),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSessionTab(st.id),className:"px-1 text-zinc-600 hover:text-red-400 transition text-xs",title:"Close tab"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))))),subTabs.map(st=>/*#__PURE__*/React.createElement("div",{key:st.id,className:"flex items-stretch"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab(st.id),className:`px-2 text-xs font-medium border-b-2 transition flex items-center gap-1 ${activeTab===st.id?'text-amber-400 border-amber-500 bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-edit",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"max-w-[100px] truncate"},st.label)),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSubTab(st.id),className:"px-1 text-zinc-600 hover:text-red-400 transition text-xs",title:"Close tab"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))))),showAIConfig&&/*#__PURE__*/React.createElement("div",{className:"bg-zinc-900 border-b border-purple-900 p-3 flex flex-col gap-2 transition-all"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-purple-400 uppercase tracking-wider flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-4 h-4"}))," Cấu hình cổng kết nối API"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-2 text-xs"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Endpoint Base URL"),/*#__PURE__*/React.createElement("input",{type:"text",value:aiConfig.baseUrl,onChange:e=>setAiConfig(prev=>({...prev,baseUrl:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"https://api.openai.com/v1"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"API Token Key"),/*#__PURE__*/React.createElement("input",{type:"password",value:aiConfig.apiKey,onChange:e=>setAiConfig(prev=>({...prev,apiKey:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"sk-..."})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Model Name"),/*#__PURE__*/React.createElement("input",{type:"text",value:aiConfig.model,onChange:e=>setAiConfig(prev=>({...prev,model:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"gpt-4o-mini"})))),/*#__PURE__*/React.createElement("div",{className:"h-9 bg-[#222] border-b border-zinc-800 flex items-center px-3 gap-2 shrink-0 select-none"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 shadow-lg",title:"Kéo để di chuyển toolbar",style:{cursor:'grab'}},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-0.5 mr-1 text-zinc-600"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('select');showToast('Select Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='select'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Select Tool (V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"mouse-pointer",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('grab');showToast('Grab Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='grab'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Grab Tool (H)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"hand",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-0.5 border border-zinc-700 rounded bg-zinc-850 px-0.5"},/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('razor');showToast('Razor Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='razor'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Razor Tool (C)"},/*#__PURE__*/React.createElement("svg",{className:"w-3.5 h-3.5 text-orange-400",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"},/*#__PURE__*/React.createElement("path",{d:"M6 3h12a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}),/*#__PURE__*/React.createElement("path",{d:"M4 9h16l-3 9H7z"}),/*#__PURE__*/React.createElement("circle",{cx:"12",cy:"6",r:"1"}))),/*#__PURE__*/React.createElement("button",{onClick:handleGlueTracks,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-purple-400 hover:bg-zinc-800",title:"Glue Clips"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"link",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('pen');showToast('Pen Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='pen'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Pen Tool (P)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"pen-tool",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:handleCutTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-red-400 hover:bg-zinc-800",title:"Cut (Ctrl+X)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handleCopyTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-blue-400 hover:bg-zinc-800",title:"Copy (Ctrl+C)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handlePasteTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-emerald-400 hover:bg-zinc-800",title:"Paste (Ctrl+V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-2 py-1 bg-cyan-600 hover:bg-cyan-500 text-white font-semibold rounded text-xs flex items-center gap-1 shadow transition",title:"Thêm Track Mới (Ctrl+I)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"})),/*#__PURE__*/React.createElement("span",null,"Track")),sessionTabs.some(s=>s.id===activeTab)&&/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSaveSectionTab(activeTab),className:"px-2 py-1 bg-emerald-600 hover:bg-emerald-500 text-white font-semibold rounded text-xs flex items-center gap-1 shadow transition",title:"Lưu Section vào Main Session"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3.5 h-3.5"})),/*#__PURE__*/React.createElement("span",null,"Lưu Section"))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:handleUndo,disabled:undoStack.length===0,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 disabled:opacity-30",title:"Undo (Ctrl+Z)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"undo",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handleRedo,disabled:redoStack.length===0,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 disabled:opacity-30",title:"Redo (Ctrl+Y)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"redo",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>s.id===activeTab?{...s,currentTime:0}:s));}else{setCurrentTime(0);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Quay lại đầu"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-back",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const left=s.selectionStart!==null&&s.selectionEnd!==null?Math.min(s.selectionStart,s.selectionEnd):null;return left!==null?{...s,currentTime:left}:s;}));}else{if(selLeft!==null)setCurrentTime(selLeft);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Đầu vùng chọn"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"step-back",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handlePlayPause,className:`w-7 h-7 flex items-center justify-center rounded border transition ${isPlaying?'bg-emerald-600 text-black border-emerald-500 hover:bg-emerald-500':'bg-cyan-600 text-white border-cyan-500 hover:bg-cyan-500'}`,title:isPlaying?"Tạm dừng":"Play"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":isPlaying?"pause":"play",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:handleStop,className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Stop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"square",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:handleRecordClick,className:`w-7 h-7 flex items-center justify-center rounded border transition ${recordingState==='RECORDING'?'bg-red-600 text-white border-red-500 hover:bg-red-500 animate-pulse':recordingState==='COUNT_IN'?'bg-amber-500 text-black border-amber-400 hover:bg-amber-400 animate-pulse':'bg-zinc-800 text-red-500 border-zinc-700 hover:bg-zinc-700 hover:text-red-400'}`,title:recordingState==='RECORDING'?"Đang ghi âm...":recordingState==='COUNT_IN'?"Chuẩn bị ghi âm...":"Ghi âm (Record)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const right=s.selectionStart!==null&&s.selectionEnd!==null?Math.max(s.selectionStart,s.selectionEnd):null;return right!==null?{...s,currentTime:right}:s;}));}else{if(selRight!==null)setCurrentTime(selRight);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Cuối vùng chọn"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"step-forward",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const duration=s.buffer?s.buffer.duration/(s.speed||1.0):0;return{...s,currentTime:duration};}));}else{setCurrentTime(maxDuration);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Đến cuối"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-forward",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>setIsLoopingSelection(prev=>!prev),className:`w-7 h-7 flex items-center justify-center rounded border transition ${isLoopingSelection?'bg-amber-600 text-black border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-200 border-zinc-700 hover:bg-zinc-700'}`,title:isLoopingSelection?selLeft!==null&&selRight!==null?"Loop vùng chọn":"Loop timeline":"Bật loop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500 font-bold uppercase ml-2"},"Snap"),/*#__PURE__*/React.createElement("select",{value:snapValue,onChange:e=>setSnapValue(e.target.value),className:"bg-black text-white text-[14px] px-1.5 py-0.5 rounded border border-zinc-700 focus:outline-none focus:border-cyan-500 font-mono cursor-pointer"},/*#__PURE__*/React.createElement("option",{value:"free"},"Free"),/*#__PURE__*/React.createElement("option",{value:"1"},"1"),/*#__PURE__*/React.createElement("option",{value:"1/2"},"1/2"),/*#__PURE__*/React.createElement("option",{value:"1/4"},"1/4"),/*#__PURE__*/React.createElement("option",{value:"1/8"},"1/8"),/*#__PURE__*/React.createElement("option",{value:"1/16"},"1/16"),/*#__PURE__*/React.createElement("option",{value:"1/32"},"1/32")),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-6 bg-zinc-800 mx-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500 font-bold"},"Bars:"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:beginBar,onChange:e=>{const b=parseInt(e.target.value)||1;setBeginBar(b);const beatDuration=60/parseInt(bpm||120);const t=(b-1)*beatDuration*4;clearLocalSelection();setSelectionMode('global');setSelectionStart(t);setSelectionEnd(t+beatDuration*4);},className:"w-14 bg-black text-white text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"-"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:endBar,onChange:e=>{const b=parseInt(e.target.value)||1;setEndBar(b);const beatDuration=60/parseInt(bpm||120);const t=(b-1)*beatDuration*4;setSelectionEnd(t+beatDuration*4);setNumberBar(b-beginBar+1);},className:"w-14 bg-black text-white text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"#"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:numberBar,readOnly:true,className:"w-14 bg-black text-zinc-400 text-[14px] px-1 py-0.5 rounded border border-zinc-800 text-center font-mono"}),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-6 bg-zinc-800 mx-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"Start:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selLeft!==null?formatTime(selLeft):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));clearLocalSelection();setSelectionMode('global');setSelectionStart(secs);}},className:"w-20 bg-black text-zinc-200 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"End:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selRight!==null?formatTime(selRight):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));setSelectionEnd(secs);}},className:"w-20 bg-black text-zinc-200 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"Len:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selLeft!==null&&selRight!==null?formatTime(Math.abs(selRight-selLeft)):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3&&selLeft!==null){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));setSelectionEnd(selLeft+secs);}},className:"w-20 bg-black text-amber-300 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold font-mono text-zinc-100"},formatTime(currentTime))),(()=>{const dockPanels={top:[],right:[],bottom:[],left:[]};const addPanel=(id,pos,visible)=>{if(visible)dockPanels[pos].push(id);};addPanel('export',panelPositions.export,showExportPanel);addPanel('ai',panelPositions.ai,showAIPanel);addPanel('python_tools',panelPositions.python_tools||'bottom',showPythonToolsPanel);addPanel('selection',panelPositions.selection,showSelectionPanel);addPanel('media_explorer','bottom',showMediaExplorer);addPanel('fx_rack',panelPositions.fx_rack||'bottom',showFxRack);addPanel('midi_events',panelPositions.midi_events||'bottom',showMidiEvents);const closePanel=id=>{if(id==='export')setShowExportPanel(false);else if(id==='ai')setShowAIPanel(false);else if(id==='python_tools')setShowPythonToolsPanel(false);else if(id==='selection')setShowSelectionPanel(false);else if(id==='media_explorer')setShowMediaExplorer(false);else if(id==='fx_rack')setShowFxRack(false);else if(id==='midi_events')setShowMidiEvents(false);};const renderPanelContent=panelId=>{const h=id=>e=>{startPanelDrag(id,e);};if(panelId==='export')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('export',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-zinc-200 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3.5 h-3.5 text-cyan-400"}))," Export"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('export'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Ngu\u1ed3n"),/*#__PURE__*/React.createElement("select",{value:exportSettings.source,onChange:e=>setExportSettings(p=>({...p,source:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"project"},"Project (Mix)"),/*#__PURE__*/React.createElement("option",{value:"track_mix"},"Track Selection"),/*#__PURE__*/React.createElement("option",{value:"active_clip"},"Active Clip"),/*#__PURE__*/React.createElement("option",{value:"clip_selection"},"Clip Selection"))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"\u0110\u1ecbnh d\u1ea1ng"),/*#__PURE__*/React.createElement("select",{value:exportSettings.format,onChange:e=>setExportSettings(p=>({...p,format:e.target.value,sampleRate:e.target.value==='wav'?'44100':e.target.value==='mp3'?'44100':'44100',bitDepth:e.target.value==='wav'?'16':'16',quality:'44khz'})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"wav"},"WAV"),/*#__PURE__*/React.createElement("option",{value:"mp3"},"MP3"),/*#__PURE__*/React.createElement("option",{value:"ogg"},"OGG")))),exportSettings.format==='wav'?/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"SR (Hz)"),/*#__PURE__*/React.createElement("select",{value:exportSettings.sampleRate,onChange:e=>setExportSettings(p=>({...p,sampleRate:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"22500"},"22500"),/*#__PURE__*/React.createElement("option",{value:"44100"},"44100"))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Bit"),/*#__PURE__*/React.createElement("select",{value:exportSettings.bitDepth,onChange:e=>setExportSettings(p=>({...p,bitDepth:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"8"},"8"),/*#__PURE__*/React.createElement("option",{value:"16"},"16"),/*#__PURE__*/React.createElement("option",{value:"24"},"24")))):/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Ch\u1ea5t l\u01b0\u1ee3ng"),/*#__PURE__*/React.createElement("select",{value:exportSettings.quality,onChange:e=>setExportSettings(p=>({...p,quality:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"44khz"},"44kHz"),/*#__PURE__*/React.createElement("option",{value:"lossless"},"Lossless"))),/*#__PURE__*/React.createElement("div",null)),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Kênh"),/*#__PURE__*/React.createElement("select",{value:exportSettings.channels,onChange:e=>setExportSettings(p=>({...p,channels:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"mono"},"Mono"),/*#__PURE__*/React.createElement("option",{value:"stereo"},"Stereo"))),/*#__PURE__*/React.createElement("div",null)),/*#__PURE__*/React.createElement("button",{onClick:triggerWavExport,disabled:isExporting,className:"w-full py-1 bg-cyan-700 hover:bg-cyan-600 text-zinc-100 font-bold rounded text-xs flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"download-cloud",className:"w-3 h-3"})),isExporting?'...':'Export'));if(panelId==='ai')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1.5 flex-1 min-h-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('ai',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-zinc-200 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3.5 h-3.5 text-purple-400"}))," AI Copilot"),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:()=>{setAiActionLog([]);showToast('Đã xoá nhật ký AI.','info');},className:"text-zinc-600 hover:text-zinc-300",title:"Clear log"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('ai'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 w-full min-w-0 pb-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3 text-purple-400"})),/*#__PURE__*/React.createElement("select",{value:selectedProviderId,onChange:e=>setSelectedProviderId(e.target.value),className:"flex-1 min-w-0 max-w-full bg-[#141414] text-zinc-200 border border-zinc-700 rounded px-1 py-0.5 text-xs font-mono focus:outline-none focus:border-purple-600 truncate"},aiProviders.length===0?/*#__PURE__*/React.createElement("option",{value:""},"Chưa có provider"):aiProviders.map(p=>/*#__PURE__*/React.createElement("option",{key:p.id,value:p.id},p.name,p.is_active?'':' (inactive)')))),/*#__PURE__*/React.createElement("div",{className:"border-t border-zinc-800 pt-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement("button",{onClick:()=>{if(window.DAWCommandDispatcher&&window.DAWCommandDispatcher.undo){const entry=window.DAWCommandDispatcher.undo();if(entry){setAiActionLog(prev=>[...prev,{type:'undo',text:`Undo: ${entry.name}`,time:Date.now()}]);showToast(`Undo AI: ${entry.name}`,'info');}}else{handleUndo();setAiActionLog(prev=>[...prev,{type:'undo',text:'Undo (Ctrl+Z)',time:Date.now()}]);}},className:"w-full text-[10px] text-amber-400 hover:text-amber-300 border border-amber-800 rounded py-0.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("i",{"data-lucide":"rotate-ccw",className:"w-3 h-3"}),"Undo"))),/*#__PURE__*/React.createElement("div",{className:"flex-1 min-h-0 flex flex-col overflow-hidden mt-1"},/*#__PURE__*/React.createElement("div",{className:"text-[10px] font-bold text-zinc-400 uppercase shrink-0 pb-0.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center gap-1"},/*#__PURE__*/React.createElement("i",{"data-lucide":"list",className:"w-3 h-3"})," Action Log")),/*#__PURE__*/React.createElement("div",{ref:actionLogContainerRef,className:"flex-1 overflow-y-auto no-scrollbar bg-[#0f0f0f] rounded border border-zinc-800 select-text"},aiActionLog.length===0?/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-600 italic select-text"},"Chưa có hành động nào."):aiActionLog.map((entry,i)=>/*#__PURE__*/React.createElement("div",{key:i,className:`text-xs font-mono py-0.5 border-b border-zinc-900 last:border-0 ${entry.type==='error'?'text-red-400':entry.type==='status'?'text-zinc-400 italic':entry.type==='undo'?'text-amber-400':'text-zinc-300'}`},new Date(entry.time).toLocaleTimeString(),entry.text)))),/*#__PURE__*/React.createElement("div",{className:"border-t border-zinc-800 pt-1.5 mt-1 shrink-0"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-zinc-400 uppercase mb-1 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"message-square",className:"w-3 h-3"}))," Copilot Prompt"),/*#__PURE__*/React.createElement("textarea",{value:aiPrompt,onChange:e=>setAiPrompt(e.target.value),placeholder:"Nhập lệnh điều khiển DAW... (VD: Tạo track mới tên Beat, đặt BPM 128)",className:"w-full bg-[#1e1e1e] text-zinc-200 p-1.5 rounded border border-zinc-700 focus:outline-none focus:border-purple-600 font-mono text-xs resize-none",rows:2,onKeyDown:e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();handleAISend();}else if(e.key==='ArrowUp'&&promptHistRef.current.length>0){e.preventDefault();const idx=promptHistIdx===-1?promptHistRef.current.length-1:Math.max(0,promptHistIdx-1);setPromptHistIdx(idx);setAiPrompt(promptHistRef.current[idx]);}else if(e.key==='ArrowDown'){e.preventDefault();if(promptHistIdx===-1)return;const idx=promptHistIdx+1;if(idx>=promptHistRef.current.length){setPromptHistIdx(-1);setAiPrompt('');}else{setPromptHistIdx(idx);setAiPrompt(promptHistRef.current[idx]);}}}})),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement("button",{onClick:handleAISend,disabled:aiProcessing,className:"flex-1 py-1 bg-purple-700 hover:bg-purple-600 text-white font-bold rounded text-xs border border-purple-500 flex items-center justify-center gap-1"},aiProcessing?'Đang suy luận...':/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"send",className:"w-3 h-3"}))," Gửi")),/*#__PURE__*/React.createElement("button",{onClick:()=>{setAiPrompt('');setAiActionLog([]);},className:"px-2 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-400 rounded text-xs border border-zinc-700"},"Clear")),/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-600 shrink-0"},"Enter để gửi nhanh"));if(panelId==='python_tools')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('python_tools',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-amber-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"wrench",className:"w-3.5 h-3.5 text-amber-400"}))," DSP Tools"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('python_tools'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"p-1.5 bg-[#141414] rounded border border-zinc-800 text-[10px] font-mono text-zinc-400 space-y-0.5 leading-relaxed"},dspSelectionStats?[/*#__PURE__*/React.createElement("div",{key:"track"},`Track: ${dspSelectionStats.trackName}`),/*#__PURE__*/React.createElement("div",{key:"range"},`Range: ${dspSelectionStats.timeRange}`),/*#__PURE__*/React.createElement("div",{key:"ch"},`Channels: ${dspSelectionStats.channels}`),/*#__PURE__*/React.createElement("div",{key:"peak"},`Peak Vol: ${dspSelectionStats.peakVolume}`)]:"Chưa chọn track"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1 text-xs"},/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('normalize'),className:"py-1 bg-amber-950/80 hover:bg-amber-900 text-amber-300 border border-amber-800/80 rounded font-bold flex items-center justify-center gap-1"},"⚡ Peak Norm (0dB)"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('invert_phase'),className:"py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-200 border border-zinc-700 rounded font-bold flex items-center justify-center gap-1"},"🔄 Phase Invert"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('swap_channels'),className:"py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-200 border border-zinc-700 rounded font-bold flex items-center justify-center gap-1"},"🔀 Swap L/R"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('synth_wave'),className:"py-1 bg-teal-950/80 hover:bg-teal-900 text-teal-300 border border-teal-800/80 rounded font-bold flex items-center justify-center gap-1"},"🎹 Gen Synth Tone")));if(panelId==='selection')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('selection',e)},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"}))," Selection"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('selection'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-1 bg-[#141414] p-1.5 rounded border border-zinc-800"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Start"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.01",value:selectionStats.start,onChange:e=>handleSelectionInputChange('start',e.target.value),className:"w-full bg-[#242424] text-amber-400 text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"End"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.01",value:selectionStats.end,onChange:e=>handleSelectionInputChange('end',e.target.value),className:"w-full bg-[#242424] text-amber-400 text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col justify-center"},/*#__PURE__*/React.createElement("span",{className:"text-[7px] text-zinc-500 font-bold uppercase"},"Len"),/*#__PURE__*/React.createElement("span",{className:"text-zinc-200 font-mono text-xs font-semibold mt-0.5"},selectionStats.length,"s"))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-1 bg-[#141414] p-1.5 rounded border border-zinc-800 mt-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Begin Bar"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:beginBar,onChange:e=>{const b=parseInt(e.target.value)||1;setBeginBar(b);const beatDuration=60/parseInt(bpm||120);const t=(b-1)*beatDuration*4;clearLocalSelection();setSelectionMode('global');setSelectionStart(t);setSelectionEnd(t+beatDuration*4);},className:"w-full bg-[#242424] text-white text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"End Bar"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:endBar,onChange:e=>{const b=parseInt(e.target.value)||1;setEndBar(b);const beatDuration=60/parseInt(bpm||120);const t=(b-1)*beatDuration*4;setSelectionEnd(t+beatDuration*4);setNumberBar(b-beginBar+1);},className:"w-full bg-[#242424] text-white text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col justify-center"},/*#__PURE__*/React.createElement("span",{className:"text-[7px] text-zinc-500 font-bold uppercase"},"# Bars"),/*#__PURE__*/React.createElement("span",{className:"text-zinc-200 font-mono text-xs font-semibold mt-0.5"},numberBar))));if(panelId==='media_explorer')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('media_explorer',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-emerald-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"folder-open",className:"w-3.5 h-3.5 text-emerald-400"}))," Media Explorer"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('media_explorer'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 overflow-y-auto text-xs text-zinc-400 font-mono p-2"},"// Placeholder: Media files browser"));if(panelId==='fx_rack')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('fx_rack',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-rose-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3.5 h-3.5 text-rose-400"}))," Plugin FX Rack"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('fx_rack'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 text-xs text-zinc-500 italic flex items-center justify-center"},"No FX plugins loaded"));if(panelId==='midi_events')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('midi_events',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-sky-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3.5 h-3.5 text-sky-400"}))," MIDI Event List"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('midi_events'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 text-xs text-zinc-500 italic flex items-center justify-center"},"No MIDI events selected"));return null;};const renderDock=(pos,title)=>{const panels=dockPanels[pos];if(panels.length===0)return null;const isSide=pos==='left'||pos==='right';const borderClass=pos==='left'?'border-r':pos==='right'?'border-l':pos==='top'?'border-b':'border-t';const bgClass='bg-[#1e1e1e]';const highlight=panelDragRef.current&&panelDropZone===pos;if(pos==='right')return/*#__PURE__*/React.createElement("div",{id:"right-sidebar",className:`${borderClass} ${bgClass} flex flex-col overflow-hidden select-none h-full`,style:{width:`${rightSidebarWidth}px`,minWidth:'200px',maxWidth:'600px',flexShrink:0}},/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col gap-2 p-2 overflow-hidden h-full"},panels.map((p,idx)=>/*#__PURE__*/React.createElement(React.Fragment,{key:p},/*#__PURE__*/React.createElement("div",{className:'flex flex-col flex-1 min-h-0 border border-zinc-700 rounded-lg bg-[#262626] shadow-sm p-3'},renderPanelContent(p)),idx/*#__PURE__*/React.createElement("div",{key:p,className:`${isSide?'w-full':'flex-none w-[320px]'} border border-zinc-700 rounded-lg bg-[#262626] shadow-sm p-2`},renderPanelContent(p))));};return/*#__PURE__*/React.createElement("div",{ref:workspaceRef,className:"flex-1 flex flex-col overflow-hidden select-none daw-bg relative"},panelDragRef.current&&panelDropZone&&/*#__PURE__*/React.createElement("div",{className:"absolute inset-0 z-50 pointer-events-none"},panelDropZone==='top'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 left-0 right-0 h-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='bottom'&&/*#__PURE__*/React.createElement("div",{className:"absolute bottom-0 left-0 right-0 h-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='left'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 left-0 w-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='right'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 right-0 w-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"})),dragGhostPanel&&dragGhostPos&&/*#__PURE__*/React.createElement("div",{className:"fixed z-[100] pointer-events-none opacity-80 border border-cyan-500 rounded-lg bg-[#262626] shadow-2xl p-3 w-56",style:{left:dragGhostPos.x,top:dragGhostPos.y}},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 text-xs text-zinc-200 font-bold"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"move",className:"w-3.5 h-3.5 text-cyan-400"})),dragGhostPanel==='export'?'Export Panel':dragGhostPanel==='ai'?'AI Panel':dragGhostPanel==='python_tools'?'Audio Processing Panel':'Selection Panel'),/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-500 mt-1"},"Drop at edge to dock")),renderDock('top','Top'),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex overflow-hidden"},renderDock('left','Left'),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col overflow-hidden min-w-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 flex overflow-hidden"},activeTab==='main'||sessionTabs.some(s=>s.id===activeTab)?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{ref:tcpContainerRef,onScroll:handleTCPScroll,className:"w-[320px] shrink-0 z-20 bg-[#262626] overflow-y-auto flex flex-col border-r border-zinc-900 no-scrollbar",style:{scrollbarWidth:'none',msOverflowStyle:'none'}},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-50 flex items-center justify-between h-10 border-b border-zinc-900 bg-[#242424] px-2 shrink-0"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-300 flex items-center gap-1.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3.5 h-3.5 text-cyan-400"})),"TRACKS (",activeTracks.length,")"),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-2.5 py-1 bg-cyan-600 hover:bg-cyan-500 text-white rounded text-xs font-semibold flex items-center gap-1 shadow transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3 h-3"}))," Add Track")),/*#__PURE__*/React.createElement("div",{className:"sticky top-10 z-40 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] p-2 border-l-4 border-purple-500 shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between w-full"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-purple-400 font-mono"},"TM"),/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300"},"Tempo")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("input",{type:"number",value:bpm,onChange:e=>setBpm(e.target.value),onBlur:()=>localStorage.setItem('studio_bpm',bpm),className:"w-12 bg-zinc-800 border border-zinc-700 rounded text-xs text-zinc-300 text-center font-mono focus:outline-none focus:border-purple-500",min:"40",max:"300"}),/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500"},"BPM")))),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col divide-y divide-[#141414] bg-[#262626]"},activeTracks.length===0?/*#__PURE__*/React.createElement("div",{className:"p-6 text-center text-zinc-400 flex flex-col items-center justify-center space-y-3"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-circle",className:"w-8 h-8 text-cyan-400 opacity-80"})),/*#__PURE__*/React.createElement("p",{className:"text-xs font-medium"},"Chưa có Track nào trong dự án."),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-3 py-1.5 bg-cyan-600 hover:bg-cyan-500 text-white rounded text-xs font-semibold flex items-center gap-1.5 shadow"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-circle",className:"w-3.5 h-3.5"}))," Thêm Track Mới")):activeTracks.map((track,idx)=>{const isSelected=selectedTrackId===track.id;const autoHeight=track.height||(track.isArmed?164:140);return/*#__PURE__*/React.createElement("div",{key:track.id,style:{height:`${autoHeight}px`},className:`shrink-0 relative flex flex-col justify-between p-2.5 bg-[#1e1e1e] border-r border-zinc-900 cursor-pointer border-l-4 border-b border-[#141414] overflow-hidden ${isSelected?'border-cyan-500 bg-[#252525]':'border-transparent hover:bg-zinc-800/20'}`,onClick:()=>setSelectedTrackId(track.id)},/*#__PURE__*/React.createElement("div",{className:"flex items-start justify-between"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-500 font-mono"},(idx+1).toString().padStart(2,'0')),/*#__PURE__*/React.createElement("label",{onClick:e=>{e.stopPropagation();const el=e.currentTarget.querySelector('input');if(el)el.click();},className:"cursor-pointer"},/*#__PURE__*/React.createElement("input",{type:"color",value:track.color||'#0f766e',onChange:e=>{e.stopPropagation();updateTrackColor(track.id,e.target.value);},className:"w-0 h-0 opacity-0 absolute pointer-events-none"}),/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 rounded-full border border-zinc-600 hover:scale-110 transition-transform",style:{backgroundColor:track.color}})),editingTrackName===track.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{updateTrackName(track.id,editNameInput||track.name);setEditingTrackName(null);},onKeyDown:e=>{if(e.key==='Enter'){updateTrackName(track.id,editNameInput||track.name);setEditingTrackName(null);}if(e.key==='Escape')setEditingTrackName(null);},onClick:e=>e.stopPropagation(),className:"text-xs font-semibold bg-black text-zinc-200 border border-cyan-500 rounded px-1 py-0 w-24 outline-none"}):/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300 truncate max-w-[80px] cursor-text hover:text-cyan-300 transition-colors",title:"Click to rename",onClick:e=>{e.stopPropagation();setEditingTrackName(track.id);setEditNameInput(track.name);}},track.name)),/*#__PURE__*/React.createElement("div",{className:"flex flex-wrap gap-0.5 max-w-[100px] mb-0.5"},(track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default',name:track.name,startTime:track.startTime}]:[]).slice(0,3).map(c=>/*#__PURE__*/React.createElement("span",{key:c.id,className:"text-[9px] font-mono text-zinc-500 bg-zinc-800/60 rounded px-0.5 truncate max-w-[90px] cursor-pointer hover:text-cyan-400 hover:bg-zinc-700",title:c.name||track.name,onClick:e=>{e.stopPropagation();setSelectedTrackId(track.id);clearLocalSelection();setSelectionMode('global');const start=c.startTime||0;const end=start+(c.buffer?c.buffer.duration:2);setSelectionStart(start);setSelectionEnd(end);showToast(`Selected: ${c.name||track.name}`,'info');}},c.name||track.name),editingClipName&&editingClipName.trackId===track.id&&editingClipName.clipId===c.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{if(editNameInput.trim())updateClipName(track.id,c.id,editNameInput.trim());setEditingClipName(null);},onKeyDown:e=>{if(e.key==='Enter'){if(editNameInput.trim())updateClipName(track.id,c.id,editNameInput.trim());setEditingClipName(null);}if(e.key==='Escape')setEditingClipName(null);},onClick:e=>e.stopPropagation(),className:"w-20 text-[9px] font-mono bg-black text-cyan-300 border border-cyan-500 rounded px-0.5 py-0 outline-none"}):/*#__PURE__*/React.createElement("button",{className:"text-[9px] text-zinc-600 hover:text-cyan-400 ml-0.5 shrink-0",title:"Sửa tên clip",onClick:e=>{e.stopPropagation();setEditingClipName({trackId:track.id,clipId:c.id});setEditNameInput(c.name||track.name);}},/*#__PURE__*/React.createElement("i",{"data-lucide":"pencil",className:"w-2.5 h-2.5"})))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMute(track.id);},title:"Mute",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.muted?'bg-red-950 text-red-400 border-red-700':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":track.muted?"volume-x":"volume-2",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackSoloEvaluate(track.id);},title:"Solo",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${soloedTrackId===track.id||track.solo?'bg-amber-950 text-amber-400 border-amber-600':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":soloedTrackId===track.id||track.solo?"headphones":"headphone-off",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackArm(track.id);},title:"ARM (Record)",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.isArmed?'bg-red-600 text-white border-red-500 hover:bg-red-500':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:`w-2.5 h-2.5 ${track.isArmed?'fill-white':''}`})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMonitor(track.id);},title:"Input Monitor",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.monitoringEnabled?'bg-amber-600 text-white border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-500 border-transparent hover:text-zinc-305'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":track.monitoringEnabled?"mic":"mic-off",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();deleteTrack(track.id);},className:"p-0.5 rounded text-red-500 hover:bg-red-950/40 hover:text-red-400 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3 h-3"}))))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-0.5 text-xs",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Vol:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-50",max:"7",step:"0.5",value:track.volumeDb??0,onChange:e=>updateTrackVolumeDb(track.id,parseFloat(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-12 text-right font-mono text-zinc-300 text-xs"},track.volumeDb??0,"dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Pan:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-100",max:"100",step:"1",value:track.pan??0,onChange:e=>updateTrackPan(track.id,parseInt(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-12 text-right font-mono text-zinc-300 text-xs"},track.pan>0?'R'+track.pan:track.pan<0?'L'+Math.abs(track.pan):'C')),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-0.5"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-[10px]"},"In:"),/*#__PURE__*/React.createElement("select",{value:`${track.inputSource?.deviceType||'NONE'}:${track.inputSource?.deviceId||''}`,onChange:e=>{const val=e.target.value;const parts=val.split(':');const type=parts[0];const id=parts.slice(1).join(':');updateTrackInputSource(track.id,type,id);},className:"flex-1 bg-[#18181b] text-zinc-300 text-[10px] rounded border border-zinc-700 focus:outline-none py-0.5 px-1 truncate max-w-[120px]"},/*#__PURE__*/React.createElement("option",{value:"NONE:"},"No Input"),/*#__PURE__*/React.createElement("optgroup",{label:"Microphones"},audioDevices.map(d=>/*#__PURE__*/React.createElement("option",{key:d.deviceId,value:`MICROPHONE:${d.deviceId}`},d.label||`Microphone ${d.deviceId.slice(0,5)}`))),/*#__PURE__*/React.createElement("optgroup",{label:"MIDI Keyboards"},/*#__PURE__*/React.createElement("option",{value:"MIDI_KEYBOARD:ALL"},"Any MIDI Keyboard"),midiDevices.map(d=>/*#__PURE__*/React.createElement("option",{key:d.id,value:`MIDI_KEYBOARD:${d.id}`},d.name||`MIDI Input ${d.id.slice(0,5)}`)))),track.isArmed&&lastMidiNote&&(lastMidiNote.length===0||Date.now()-lastMidiNote.time<3000)&&/*#__PURE__*/React.createElement("span",{className:"text-[9px] font-mono text-emerald-400 ml-0.5 truncate max-w-[60px] shrink-0",title:"MIDI Note:velocity:length"},`${midiPitchToName(lastMidiNote.pitch)}:${lastMidiNote.velocity}:${lastMidiNote.length>0?lastMidiNote.length.toFixed(2)+'s':'...'}`)),track.isArmed&&/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-0.5"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-[9px]"},"VU:"),/*#__PURE__*/React.createElement("canvas",{ref:el=>{if(el)trackVuRefs.current[track.id]=el;else delete trackVuRefs.current[track.id];},width:100,height:4,className:"flex-1 bg-[#18181b] rounded h-1"}))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 mt-1",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("input",{type:"file",id:`upload-${track.id}`,accept:"audio/*",className:"hidden",onChange:e=>loadFileOnTrack(track.id,e.target.files[0])}),/*#__PURE__*/React.createElement("label",{htmlFor:`upload-${track.id}`,className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded text-xs flex items-center gap-1 cursor-pointer border border-zinc-700 font-medium"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"upload",className:"w-3 h-3"}))," File"),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();showToast('FX panel for track '+track.id,'info');},className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-purple-400 border border-purple-900 rounded text-xs font-bold flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"wand-2",className:"w-3 h-3"}))," FX: ",/*#__PURE__*/React.createElement("span",{className:"text-zinc-500 font-normal"},"None")),/*#__PURE__*/React.createElement("button",{onClick:()=>generateSynthToTrack(track.id,'synth'),className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-amber-400 border border-amber-800 rounded text-xs font-bold flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3"}))," Synth: ",/*#__PURE__*/React.createElement("span",{className:"text-zinc-500 font-normal"},"None"))),/*#__PURE__*/React.createElement("div",{onMouseDown:e=>handleTrackResizeMouseDown(e,track.id),className:"absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",onClick:e=>e.stopPropagation()}));})),/*#__PURE__*/React.createElement("div",{className:"h-[48px] border-r border-zinc-900 bg-[#1e1e1e]/50 shrink-0"})),/*#__PURE__*/React.createElement("div",{ref:handleTimelineWrapperRef,onScroll:handleTimelineScroll,className:"flex-1 relative z-10 overflow-x-auto overflow-y-auto min-w-0"},/*#__PURE__*/React.createElement("div",{style:{width:`${timelineWidth}px`},className:"relative flex flex-col min-h-full"},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-45 flex h-10 border-b border-zinc-900 bg-[#242424] shrink-0"},/*#__PURE__*/React.createElement("div",{ref:rulerRef,className:"flex-1 relative h-full flex items-center select-none cursor-ew-resize overflow-hidden",onMouseDown:handleRulerMouseDown},Array.from({length:Math.ceil(maxDuration)}).map((_,i)=>{const sec=i;const x=sec*zoom;return/*#__PURE__*/React.createElement("div",{key:i,className:"absolute h-full border-l border-zinc-700 pl-1 pt-1 text-[14px] font-mono text-zinc-300 pointer-events-none",style:{left:`${x}px`}},formatTimeSimple(sec));}))),selectionMode==='global'&&selLeft!==null&&selRight!==null&&selRight>selLeft&&/*#__PURE__*/React.createElement("div",{className:"absolute inset-0 pointer-events-none z-20",style:{left:`${selLeft*zoom}px`,width:`${(selRight-selLeft)*zoom}px`,top:'40px'}},/*#__PURE__*/React.createElement("div",{className:"w-full h-full bg-amber-500/10",style:{borderLeft:'1px solid #f59e0b',borderRight:'1px solid #f59e0b'}})),/*#__PURE__*/React.createElement("div",{className:"sticky top-10 z-35 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 relative h-full overflow-hidden bg-[#1a1a2e]"},/*#__PURE__*/React.createElement(TempoTrackLane,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,onPlayheadSet:handlePlayheadSet,snapValue:snapValue,onRulerMouseDown:handleRulerMouseDown,scrollLeft:scrollLeft}))),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col divide-y divide-[#141414] relative bg-[#111111] min-h-full"},activeTracks.map((track,idx)=>{const isSelected=selectedTrackId===track.id;const autoHeight=track.height||(track.isArmed?164:140);return/*#__PURE__*/React.createElement("div",{key:track.id,style:{height:`${autoHeight}px`},className:`shrink-0 relative border-b border-[#141414] hover:bg-zinc-850/5 transition-colors ${isSelected?'bg-zinc-800/10':''}`,onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault();if(e.dataTransfer.files[0])loadFileOnTrack(track.id,e.dataTransfer.files[0]);},onMouseEnter:()=>setHoveredTrackId(track.id)},/*#__PURE__*/React.createElement(WaveformLane,{track:track,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,onSelectRange:handleSelectRange,onPlayheadSet:handlePlayheadSet,isSelected:isSelected,onSelectTrack:setSelectedTrackId,markers:track.markers,onTrackLaneMouseDown:handleTrackLaneMouseDown,onContextMenu:handleContextMenu,onClipDragStart:handleClipDragStart,onClipStretchStart:handleClipStretchStart,onSectionItemDragStart:handleSectionItemDragStart,onSectionItemResizeStart:handleSectionItemResizeStart,onSelectionEdgeDragStart:handleSelectionEdgeDragStart,setSelectedClipId:setSelectedClipId,selectedClipId:selectedClipId,activeTool:activeTool,onSplitTrackAtTime:handleSplitTrackAtTime,onEditClipInSubTab:handleEditClipInSubTab,onEditSectionInTab:handleEditSectionInTab,onEditMidiInTab:handleEditMidiInTab,snapValue:snapValue,bpm:bpm,selectionMode:selectionMode,localSelectionTrackId:localSelectionTrackId,localSelectionStart:localSelectionStart,currentTime:currentTime,getLocalAnchor:()=>localSelectionAnchorRef.current,onClearLocalSelection:clearLocalSelection,onSetSelectionMode:setSelectionMode,onSetSelectionStart:setSelectionStart,onSetSelectionEnd:setSelectionEnd,onSetCurrentTime:setCurrentTime,onSetLocalSelectionTrackId:setLocalSelectionTrackId,onSetLocalSelectionStart:setLocalSelectionStart,onSetLocalSelectionEnd:setLocalSelectionEnd,localSelLeft:localSelectionStart!==null&&localSelectionEnd!==null?Math.min(localSelectionStart,localSelectionEnd):null,localSelRight:localSelectionStart!==null&&localSelectionEnd!==null?Math.max(localSelectionStart,localSelectionEnd):null,scrollLeft:scrollLeft,recordingState:recordingState,recTempMidiNotes:recTempMidiNotes,recTempAudioBuffer:recTempAudioBuffer,recStartTimelineTime:recStartTimelineTime,canvasRedrawCount:canvasRedrawCount}),selectionMode==='local'&&localSelectionTrackId===track.id&&localSelectionStart!==null&&localSelectionEnd!==null&&Math.abs(localSelectionEnd-localSelectionStart)>0&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-400 bg-amber-500/20 z-20 pointer-events-none",style:{left:`${Math.min(localSelectionStart,localSelectionEnd)*zoom}px`,width:`${Math.abs(localSelectionEnd-localSelectionStart)*zoom}px`}},/*#__PURE__*/React.createElement("div",{className:"absolute -left-[1px] top-0 bottom-0 w-[2px] bg-amber-400 z-30 pointer-events-auto cursor-ew-resize",onMouseDown:e=>handleHandleDragStart(e,'left')}),/*#__PURE__*/React.createElement("div",{className:"absolute -right-[1px] top-0 bottom-0 w-[2px] bg-amber-400 z-30 pointer-events-auto cursor-ew-resize",onMouseDown:e=>handleHandleDragStart(e,'right')})),track.buffer&&/*#__PURE__*/React.createElement("div",{className:"absolute right-2 top-2 flex items-center gap-1 z-10 opacity-70 hover:opacity-100"},/*#__PURE__*/React.createElement("button",{onClick:()=>handleSplitTrack(track.id),className:"px-1.5 py-0.5 bg-zinc-900/95 text-zinc-300 rounded text-xs flex items-center gap-1 border border-zinc-700/50"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-2.5 h-2.5 text-cyan-400"}))," Cắt")),/*#__PURE__*/React.createElement("div",{onMouseDown:e=>handleTrackResizeMouseDown(e,track.id),className:"absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",onClick:e=>e.stopPropagation()}));}),/*#__PURE__*/React.createElement("div",{className:"h-[48px] flex items-center justify-center text-xs text-zinc-500 hover:bg-zinc-900/20 cursor-pointer select-none border-t border-dashed border-zinc-800",onMouseEnter:()=>{if(draggedClipRef.current||draggedSectionItemRef.current){setHoveredTrackId(addNewTrack());}},onClick:addNewTrack},/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1 text-zinc-400"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"}))," Kéo clip xuống hoặc Click tạo Track")),selectionMode==='global'&&selLeft!==null&&selRight!==null&&selRight>selLeft&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-500 bg-amber-500/10 z-20 selection-interactive-box cursor-grab active:cursor-grabbing",style:{left:`${selLeft*zoom}px`,width:`${(selRight-selLeft)*zoom}px`},onMouseDown:handleSelectionBodyDragStart},/*#__PURE__*/React.createElement("div",{className:"absolute -left-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30",onMouseDown:e=>handleHandleDragStart(e,'left')}),/*#__PURE__*/React.createElement("div",{className:"absolute -right-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30",onMouseDown:e=>handleHandleDragStart(e,'right')})),/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 w-[2px] bg-[#ef4444] z-20 pointer-events-none",style:{left:`${playheadLeftPos}px`}},/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 bg-[#ef4444] rotate-45 transform -translate-x-1/2 -translate-y-1/2 absolute top-0"})))))):(()=>{const st=subTabs.find(s=>s.id===activeTab);if(!st)return null;if(st.type==='PIANO_ROLL'){return/*#__PURE__*/React.createElement(PianoRollTabEditor,{st:st,zoom:zoom,bpm:bpm,viewportWidth:viewportWidth,onClose:()=>closeSubTab(st.id),onUpdateNotes:handleUpdateMidiNotes,onSaveNotes:handleSaveMidiNotes,setSubTabs:setSubTabs});}const subTrack=tracks.find(t=>t.id===st.trackId);const vTrack=subTrack?{...subTrack,buffer:st.buffer,isSubTab:true}:null;const subTabTimelineWidth=Math.max(zoom*(st.buffer?st.buffer.duration:0),viewportWidth);return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"w-[320px] shrink-0 z-30 bg-[#262626] overflow-y-scroll no-scrollbar flex flex-col border-r border-zinc-900",style:{scrollbarWidth:'none',msOverflowStyle:'none'}},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-50 flex items-center h-10 border-b border-zinc-900 bg-[#242424] px-2 justify-between shrink-0"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-500 uppercase"},"Sub-Tab"),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSubTab(st.id),className:"px-1.5 py-0.5 text-xs bg-zinc-800 hover:bg-zinc-700 text-zinc-400 rounded border border-zinc-700 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))," Close")),vTrack?/*#__PURE__*/React.createElement("div",{key:vTrack.id,className:"flex-1 flex flex-col p-2.5 bg-[#1e1e1e] border-r border-zinc-900 border-l-4 border-l-cyan-500"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between mb-2"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("label",{onClick:e=>{e.stopPropagation();const el=e.currentTarget.querySelector('input');if(el)el.click();},className:"cursor-pointer"},/*#__PURE__*/React.createElement("input",{type:"color",value:vTrack.color||'#0f766e',onChange:e=>{e.stopPropagation();updateTrackColor(vTrack.id,e.target.value);},className:"w-0 h-0 opacity-0 absolute pointer-events-none"}),/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 rounded-full border border-zinc-600 hover:scale-110 transition-transform",style:{backgroundColor:vTrack.color}})),editingTrackName===vTrack.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{updateTrackName(vTrack.id,editNameInput||vTrack.name);setEditingTrackName(null);},onKeyDown:e=>{if(e.key==='Enter'){updateTrackName(vTrack.id,editNameInput||vTrack.name);setEditingTrackName(null);}if(e.key==='Escape')setEditingTrackName(null);},onClick:e=>e.stopPropagation(),className:"text-xs font-semibold bg-black text-zinc-200 border border-cyan-500 rounded px-1 py-0 w-24 outline-none"}):/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300 truncate max-w-[80px] cursor-text hover:text-cyan-300 transition-colors",title:"Click to rename",onClick:e=>{e.stopPropagation();setEditingTrackName(vTrack.id);setEditNameInput(vTrack.name);}},vTrack.name)),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMute(vTrack.id);},className:`px-1.5 py-0.5 text-xs rounded font-mono font-bold border ${vTrack.muted?'bg-red-950 text-red-400 border-red-700':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},"M"),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackSoloEvaluate(vTrack.id);},className:`px-1.5 py-0.5 text-xs rounded font-mono font-bold border ${soloedTrackId===vTrack.id||vTrack.solo?'bg-amber-950 text-amber-400 border-amber-600':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},"S"))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-2.5 text-[14px] mb-3"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Vol:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-50",max:"7",step:"0.5",id:`tcp-vol-${st.id}`,value:vTrack.volumeDb??0,onChange:e=>updateTrackVolumeDb(vTrack.id,parseFloat(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-16 text-right font-mono text-zinc-300 text-[14px]",id:`tcp-vol-label-${st.id}`},vTrack.volumeDb??0,"dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Pan:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-100",max:"100",step:"1",id:`tcp-pan-${st.id}`,value:vTrack.pan??0,onChange:e=>updateTrackPan(vTrack.id,parseInt(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-16 text-right font-mono text-zinc-300 text-[14px]",id:`tcp-pan-label-detailed-${st.id}`},vTrack.pan>0?'R'+vTrack.pan:vTrack.pan<0?'L'+Math.abs(vTrack.pan):'C')),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 text-[14px]"},/*#__PURE__*/React.createElement("button",{onClick:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,isLooping:!s.isLooping}:s)),className:`px-2 py-0.5 text-[14px] rounded border font-bold ${st.isLooping?'bg-amber-700 text-white border-amber-500':'bg-zinc-800 text-zinc-400 border-zinc-700'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>updateSubTabEffects(st.id,{reverse:!(st.effects||{}).reverse}),className:`px-2 py-0.5 rounded border text-[14px] font-bold ${(st.effects||{}).reverse?'bg-zinc-600 text-white border-zinc-500':'bg-zinc-800 text-zinc-400 border-zinc-700'} flex items-center justify-center`,title:"Reverse"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"arrow-left-right",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Loop:"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",max:"999",value:st.loopCount||0,onChange:e=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,loopCount:Math.max(0,parseInt(e.target.value)||0)}:s)),className:"w-12 bg-black text-amber-300 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono",title:"Loop count"}))),/*#__PURE__*/React.createElement("div",{className:"flex gap-1 justify-between my-2.5"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Normalize"},"Norm"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"0",step:"0.1",value:subTabNormVal,onChange:e=>setSubTabNormVal(parseFloat(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabNormVal,"dB"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'normalize',subTabNormVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply")),/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Pitch Shift"},"Pitch"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"12",step:"0.5",value:subTabPitchVal,onChange:e=>setSubTabPitchVal(parseFloat(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabPitchVal>0?'+':'',subTabPitchVal,"st"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'pitch',subTabPitchVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply")),/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Gain Multiplier"},"Gain"),/*#__PURE__*/React.createElement("input",{type:"range",min:"0",max:"150",step:"1",value:subTabGainVal,onChange:e=>setSubTabGainVal(parseInt(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabGainVal,"%"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'gain',subTabGainVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply"))),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"mt-auto pt-2.5 border-t border-zinc-800"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between text-[14px] text-zinc-500 mb-1 font-semibold uppercase"},/*#__PURE__*/React.createElement("span",null,"Duration:"),/*#__PURE__*/React.createElement("span",{className:"font-mono text-zinc-300"},st.buffer?formatTime(st.buffer.duration):'0s')),/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between text-[14px] text-zinc-500 mb-2.5 font-semibold uppercase"},/*#__PURE__*/React.createElement("span",null,"SR:"),/*#__PURE__*/React.createElement("span",{className:"font-mono text-zinc-300"},st.buffer?st.buffer.sampleRate:0," Hz")),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1 mb-2"},/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;handleAIScan();},disabled:analysisState.isRunning,className:"py-1 bg-purple-900 hover:bg-purple-800 text-purple-100 font-bold rounded text-xs border border-purple-700 flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"map-pin",className:"w-3 h-3"}))," Scan"),/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;handleAICutToNewTrack();},disabled:analysisState.isRunning,className:"py-1 bg-fuchsia-800 hover:bg-fuchsia-700 text-white font-bold rounded text-xs flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3 h-3"}))," Cut"),/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;if(st.buffer){setSelectionRangeOnBuffer(st.buffer,st.selectionStart||0,st.selectionEnd||st.buffer.duration);}handleAIAnalysicLoop();},disabled:analysisState.isRunning,className:"py-1 bg-violet-800 hover:bg-violet-700 text-violet-100 font-bold rounded text-xs border border-violet-600 flex items-center justify-center gap-1 col-span-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sparkles",className:"w-3 h-3"}))," AI Analysic Loop")),/*#__PURE__*/React.createElement("button",{onClick:()=>exportSubTabBuffer(st.id),className:"w-full py-1.5 mb-1.5 bg-blue-700 hover:bg-blue-600 text-white font-bold rounded text-[14px] flex items-center justify-center gap-1 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"download",className:"w-4 h-4"}))," Export"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTab(st.id),className:"w-full py-1.5 bg-emerald-700 hover:bg-emerald-600 text-white font-bold rounded text-[14px] flex items-center justify-center gap-1 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-4 h-4"}))," Save"))):/*#__PURE__*/React.createElement("div",{className:"flex-1 flex items-center justify-center text-xs text-zinc-500"},"Track not found")),/*#__PURE__*/React.createElement("div",{ref:handleTimelineWrapperRef,className:"flex-1 relative z-10 overflow-x-auto overflow-y-auto min-w-0"},/*#__PURE__*/React.createElement("div",{style:{width:`${subTabTimelineWidth}px`},className:"relative flex flex-col min-h-full"},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-45 flex h-10 border-b border-zinc-900 bg-[#242424] shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 relative h-full flex items-center select-none cursor-ew-resize overflow-hidden",onMouseDown:handleRulerMouseDown},Array.from({length:Math.ceil(st.buffer?st.buffer.duration:0)}).map((_,i)=>{const sec=i;const x=sec*zoom;return/*#__PURE__*/React.createElement("div",{key:i,className:"absolute h-full border-l border-zinc-700 pl-1 pt-1 text-[14px] font-mono text-zinc-300 pointer-events-none",style:{left:`${x}px`}},formatTimeSimple(sec));}))),/*#__PURE__*/React.createElement("div",{className:"sticky top-10 z-35 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 relative h-full overflow-hidden bg-[#1a1a2e]"},/*#__PURE__*/React.createElement(TempoTrackLane,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:subTabTimelineWidth,onPlayheadSet:setCurrentTime,snapValue:snapValue}))),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col relative bg-[#111111] min-h-full"},vTrack&&/*#__PURE__*/React.createElement("div",{style:{height:`${subTabHeight}px`},className:"relative overflow-hidden border-2 border-purple-500/40 rounded bg-[#151515] mx-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement(SubTabWaveform,{buffer:st.buffer,subTabId:st.id,activeTab:activeTab,activeTool:activeTool,currentTime:st.currentTime,selectionStart:st.selectionStart,selectionEnd:st.selectionEnd,onSelectRange:(start,end)=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:start,selectionEnd:end}:s)),onPlayheadSet:time=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:time}:s)),onContextMenu:(e,clickTime)=>setContextMenu({x:e.clientX,y:e.clientY,isSubTab:true,subTabId:st.id,time:clickTime}),zoom:zoom,timelineWidth:subTabTimelineWidth,color:vTrack.color,name:vTrack.name,speed:st.speed||1.0,volumeNodes:st.volumeNodes||[],panningNodes:st.panningNodes||[],fadeInLen:st.fadeInLen||0,fadeOutLen:st.fadeOutLen||0,graphMode:st.graphMode,channelInfo:st.channelInfo,selectedNodeTime:subTabSelectedNodeTime,setSelectedNodeTime:setSubTabSelectedNodeTime,onUpdateNodes:nodes=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,[s.graphMode==='pan'?'panningNodes':'volumeNodes']:nodes}:s)),onUpdateFade:fade=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,fadeInLen:fade.fadeInLen??s.fadeInLen,fadeOutLen:fade.fadeOutLen??s.fadeOutLen}:s)),onModeToggle:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,graphMode:s.graphMode==='pan'?null:'pan'}:s)),onSpeedChange:newSpeed=>{setSubTabs(prev=>prev.map(s=>{if(s.id!==st.id)return s;const oldSpeed=s.speed||1.0;const ratio=oldSpeed/newSpeed;const newVolumeNodes=(s.volumeNodes||[]).map(n=>({...n,time:n.time*ratio}));const newPanningNodes=(s.panningNodes||[]).map(n=>({...n,time:n.time*ratio}));return{...s,speed:newSpeed,volumeNodes:newVolumeNodes,panningNodes:newPanningNodes,fadeInLen:(s.fadeInLen||0)*ratio,fadeOutLen:(s.fadeOutLen||0)*ratio,currentTime:(s.currentTime||0)*ratio,label:s.label.replace(/\s\(\d+%\)$/,'')+` (${Math.round(newSpeed*100)}%)`};}));const n=activeTrackNodesRef.current[st.trackId];if(n&&n.source)n.source.playbackRate.value=newSpeed;// Reset time refs to prevent playhead jump when speed changes mid-playback -const ctx=getAudioContext();const elapsed=ctx.currentTime-startAudioTimeRef.current;const oldSpeed=activePlaybackSpeedRef.current;const ratio=oldSpeed/newSpeed;startBufferOffsetRef.current=startBufferOffsetRef.current+elapsed*oldSpeed;startOffsetTimeRef.current=(startOffsetTimeRef.current+elapsed)*ratio;startAudioTimeRef.current=ctx.currentTime;activePlaybackSpeedRef.current=newSpeed;}}),/*#__PURE__*/React.createElement("div",{onMouseDown:handleSubTabResizeMouseDown,className:"absolute bottom-0 left-0 right-0 h-1.5 cursor-ns-resize z-30 hover:bg-purple-500/50 transition-colors"})),st.selectionStart!==null&&st.selectionEnd!==null&&st.selectionEnd>st.selectionStart&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-500 bg-amber-500/10 z-20 pointer-events-none",style:{left:`${Math.min(st.selectionStart,st.selectionEnd)*zoom}px`,width:`${Math.abs(st.selectionEnd-st.selectionStart)*zoom}px`}})))));})())),/*#__PURE__*/React.createElement("div",{className:"w-1 cursor-ew-resize hover:bg-cyan-500/50 active:bg-cyan-400 transition-colors shrink-0 z-10",onMouseDown:startColResize}),renderDock('right','Right')),renderDock('bottom','Bottom'));})(),/*#__PURE__*/React.createElement("div",{className:"h-6 bg-[#141414] border-t border-zinc-900 px-4 flex items-center justify-between text-xs text-zinc-500 select-none shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-4"},/*#__PURE__*/React.createElement("span",null,"Status: ",isPlaying?'Playing':'Stopped'),activeTab!=='main'&&/*#__PURE__*/React.createElement("span",{className:"text-amber-400 font-semibold uppercase"},"Sub-Tab"),activeTab==='main'&&/*#__PURE__*/React.createElement("span",{className:"text-cyan-400 font-semibold uppercase"},"Track: ID ",selectedTrackId),selectionMode==='local'&&/*#__PURE__*/React.createElement("span",{className:"text-amber-400 font-semibold uppercase text-xs"},"Local Sel"),selectionMode==='global'&&/*#__PURE__*/React.createElement("span",{className:"text-purple-400 font-semibold uppercase text-xs"},"Global Sel"),soloedTrackId&&/*#__PURE__*/React.createElement("span",{className:"text-amber-500 font-semibold"},"Solo: ID ",soloedTrackId),isLoopingSelection&&selectionMode==='local'&&/*#__PURE__*/React.createElement("span",{className:"text-emerald-400 font-semibold uppercase text-xs"},"Solo Loop"),isLoopingSelection&&selectionMode!=='local'&&/*#__PURE__*/React.createElement("span",{className:"text-cyan-400 font-semibold uppercase text-xs"},"Master Loop")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("button",{onClick:()=>setShowExportPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showExportPanel?'bg-cyan-900 text-cyan-300':'text-zinc-500 hover:text-zinc-300'}`,title:`Export Panel (${panelPositions.export})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showExportPanel?panelPositions.export[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowSelectionPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showSelectionPanel?'bg-amber-900 text-amber-300':'text-zinc-500 hover:text-zinc-300'}`,title:`Selection Panel (${panelPositions.selection})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showSelectionPanel?panelPositions.selection[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowAIPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showAIPanel?'bg-purple-900 text-purple-300':'text-zinc-500 hover:text-zinc-300'}`,title:`AI Panel (${panelPositions.ai})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showAIPanel?panelPositions.ai[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowFxRack(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showFxRack?'bg-rose-900 text-rose-300':'text-zinc-500 hover:text-zinc-300'}`,title:`FX Rack Panel (${panelPositions.fx_rack||'bottom'})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showFxRack?(panelPositions.fx_rack||'bottom')[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowMidiEvents(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showMidiEvents?'bg-sky-900 text-sky-300':'text-zinc-500 hover:text-zinc-300'}`,title:`MIDI Events Panel (${panelPositions.midi_events||'bottom'})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showMidiEvents?(panelPositions.midi_events||'bottom')[0].toUpperCase():'')),/*#__PURE__*/React.createElement("span",{className:"w-[1px] h-3 bg-zinc-800 mx-1"}),/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"info",className:"w-3 h-3 text-zinc-600"}))," Scroll: Zoom"),/*#__PURE__*/React.createElement("span",null,"|"),/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"keyboard",className:"w-3 h-3 text-zinc-600"}))," Ctrl+Scroll: Playhead"))),contextMenu&&(contextMenu.isSubTab?/*#__PURE__*/React.createElement("div",{className:"fixed z-[60] bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 w-64",style:{left:contextMenu.x,top:contextMenu.y},onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("div",{className:"px-3 py-1 text-xs text-zinc-500 font-bold uppercase border-b border-zinc-800 pb-1 mb-1"},"Selection: ",formatTime(subTabs.find(s=>s.id===contextMenu.subTabId)?.selectionStart||0)," - ",formatTime(subTabs.find(s=>s.id===contextMenu.subTabId)?.selectionEnd||0)),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabCut(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-rose-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Cut"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+X")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabCopy(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5 text-zinc-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Copy"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+C")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabPaste(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5 text-emerald-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Paste"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+V")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabDelete(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3.5 h-3.5 text-red-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Delete Selected Segment"),/*#__PURE__*/React.createElement("span",{className:"text-amber-400 text-xs font-semibold font-mono ml-auto"},"Del")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabLoop(contextMenu.subTabId,4);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5 text-cyan-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Loop Selection 4 times"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+L"))):/*#__PURE__*/React.createElement("div",{className:"fixed z-[60] bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 w-64",style:{left:contextMenu.x,top:contextMenu.y},onClick:e=>e.stopPropagation()},contextMenu.sectionId?/*#__PURE__*/React.createElement("button",{onClick:contextMenuEditSection,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-edit",className:"w-3.5 h-3.5 text-amber-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Edit Section"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+E")):/*#__PURE__*/React.createElement("button",{onClick:contextMenuEdit,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-edit",className:"w-3.5 h-3.5 text-amber-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Edit"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+E")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuSplit,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-cyan-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Split"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"S")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuMerge,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"combine",className:"w-3.5 h-3.5 text-purple-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Merge"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+M")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:contextMenuCopy,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5 text-zinc-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Copy"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+C")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuCut,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-rose-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Cut"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+X")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuPaste,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5 text-emerald-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Paste"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+V")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:contextMenuDelete,className:"w-full px-3 py-1.5 text-xs text-red-300 hover:bg-red-950 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3.5 h-3.5 text-red-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Delete"),/*#__PURE__*/React.createElement("span",{className:"text-amber-400 text-xs font-semibold font-mono ml-auto pl-8"},"Del")))),toastMessage&&/*#__PURE__*/React.createElement("div",{className:"absolute top-14 right-4 z-50 px-4 py-2.5 rounded shadow-lg text-xs font-semibold flex items-center gap-2 border bg-zinc-900 text-zinc-100 border-zinc-800"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"bell",className:`w-4 h-4 ${toastMessage.type==='success'?'text-emerald-400':toastMessage.type==='error'?'text-rose-400':toastMessage.type==='warning'?'text-amber-400':'text-cyan-400'}`})),toastMessage.text,toastMessage.onActionClick&&/*#__PURE__*/React.createElement("button",{onClick:()=>{toastMessage.onActionClick();setToastMessage(null);},className:"ml-2 px-2 py-0.5 bg-purple-700 hover:bg-purple-600 text-white rounded text-[10px] uppercase font-bold"},toastMessage.actionText||'Tải về'))),appWarningModal&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#222222] border border-zinc-800 rounded-lg shadow-2xl p-6 max-w-md w-full text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 mb-3 text-cyan-400 font-bold"},/*#__PURE__*/React.createElement("h3",{className:"text-base font-bold"},appWarningModal.title)),/*#__PURE__*/React.createElement("div",{className:"text-xs text-slate-300 mb-5 leading-relaxed whitespace-pre-line"},appWarningModal.message),/*#__PURE__*/React.createElement("div",{className:"flex justify-end gap-2"},appWarningModal.isAlert?/*#__PURE__*/React.createElement("button",{onClick:()=>setAppWarningModal(null),className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 active:bg-cyan-700 text-white rounded text-xs font-semibold transition"},"Đóng"):/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("button",{onClick:()=>setAppWarningModal(null),className:"px-4 py-2 bg-zinc-700 hover:bg-zinc-600 active:bg-zinc-800 text-slate-300 rounded text-xs font-semibold transition"},"Hủy"),/*#__PURE__*/React.createElement("button",{onClick:()=>{const fn=appWarningModal.onConfirm;setAppWarningModal(null);if(fn)fn();},className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 active:bg-cyan-700 text-white rounded text-xs font-semibold transition"},"Xác nhận"))))),/*#__PURE__*/React.createElement(AuthModal,{isOpen:authModalOpen,mode:authMode,forceMandatory:isMandatoryLogin,onClose:()=>setAuthModalOpen(false),onSuccess:handleAuthSuccess}),/*#__PURE__*/React.createElement(ProfileModal,{isOpen:profileModalOpen,onClose:()=>setProfileModalOpen(false),tracks:tracks,setTracks:setTracks,setSelectedTrackId:setSelectedTrackId,projectName:projectName,setProjectName:setProjectName,currentProjectId:currentProjectId,setCurrentProjectId:setCurrentProjectId,showToast:showToast}),/*#__PURE__*/React.createElement(SaveProjectModal,{isOpen:saveProjectModalOpen,onClose:()=>setSaveProjectModalOpen(false),onSave:newName=>{handleSaveProjectWithName(newName);}}),/*#__PURE__*/React.createElement(SaveAsModal,{isOpen:saveAsModalOpen,onClose:()=>setSaveAsModalOpen(false),projectName:projectName,onSaveCloud:newName=>{handleSaveAsCloud(newName);},onSaveLocal:newName=>{handleExportSFS(newName);setProjectName(newName);localStorage.setItem('sonic_project_name',newName);}}),/*#__PURE__*/React.createElement(AIConfigModal,{isOpen:aiConfigModalOpen,onClose:()=>setAiConfigModalOpen(false),onConfigSaved:providers=>{setAiProviders(providers);const active=providers.find(p=>p.is_active)||providers[0];if(active)setSelectedProviderId(active.id);}}),/*#__PURE__*/React.createElement(SystemManagerModal,{isOpen:systemManagerModalOpen,onClose:()=>setSystemManagerModalOpen(false)}));};const root=ReactDOM.createRoot(document.getElementById('root'));root.render(/*#__PURE__*/React.createElement(App,null));setTimeout(()=>lucide.createIcons(),300); +const prefsRef=useRef({});prefsRef.current={showAIPanel,showExportPanel,showSelectionPanel,showPythonToolsPanel,showMediaExplorer,showFxRack,showMidiEvents,panelPositions,rightSidebarWidth,mediaExplorerHeight,selectedProviderId};useEffect(()=>{const prefs=prefsRef.current;localStorage.setItem('sonic_preferences',JSON.stringify(prefs));if(!currentUser||currentUser==='cached')return;const timer=setTimeout(async()=>{try{await window.SonicAPI.savePreferences(prefs);}catch(e){}},2000);return()=>clearTimeout(timer);},[showAIPanel,showExportPanel,showSelectionPanel,showPythonToolsPanel,showMediaExplorer,showFxRack,showMidiEvents,panelPositions,rightSidebarWidth,mediaExplorerHeight,selectedProviderId,currentUser]);return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"h-full w-full flex flex-col bg-[#1e1e1e]"},/*#__PURE__*/React.createElement("header",{className:"h-9 bg-[#2e2e2e] border-b border-[#181818] flex items-center px-1 shrink-0 select-none"},[{label:'File',items:[{label:'New Project',icon:'file-plus',shortcut:'Ctrl+N',action:()=>{setTracks([{id:'1',name:'Track 01',buffer:null,startTime:0,volumeDb:0,pan:0,muted:false,solo:false,color:'#0f766e',markers:[],serverFileId:null,clips:[],sections:[],midiItems:[]},{id:'2',name:'Track 02',buffer:null,startTime:0,volumeDb:0,pan:0,muted:false,solo:false,color:'#1d4ed8',markers:[],serverFileId:null,clips:[],sections:[],midiItems:[]}]);setSelectedTrackId('1');setProjectName('');setCurrentProjectId(null);localStorage.removeItem('sonic_project_name');localStorage.removeItem('sonic_project_id');showToast('New project created','info');}},{label:'Open Project...',icon:'folder-open',shortcut:'Ctrl+O',action:()=>handleImportSFS()},{label:'Save Project',icon:'upload-cloud',shortcut:'Ctrl+S',action:()=>handleSaveProject()},{label:'Save As...',icon:'download',shortcut:'Ctrl+Alt+S',action:()=>setSaveAsModalOpen(true)},{sep:true},{label:'Config AI Providers...',icon:'settings',action:()=>setAiConfigModalOpen(true)},{label:'Import Audio...',icon:'file-input',shortcut:'Ctrl+Alt+I',action:()=>{const input=document.createElement('input');input.type='file';input.accept='audio/*';input.onchange=async e=>{if(e.target.files[0]){addNewTrack();const newId=(tracks.length+1).toString();setTimeout(()=>loadFileOnTrack(newId,e.target.files[0]),100);}};input.click();showToast('Import audio','info');}},{label:'Export Mix...',icon:'file-output',action:()=>triggerWavExport()},{sep:true},...(currentUser?[{label:'Profile',icon:'user',action:()=>setProfileModalOpen(true)}]:[]),...(currentUser&¤tUser.role==='admin'?[{label:'System Manager',icon:'settings',action:()=>setSystemManagerModalOpen(true)}]:[]),{label:'Logout',icon:'log-out',action:()=>handleLogout()}]},{label:'Edit',items:[{label:'Insert New Track',icon:'plus',shortcut:'Ctrl+I',action:addNewTrack},{label:'Insert Music to Track',icon:'music',shortcut:'Ctrl+Alt+I',action:()=>showToast('Select music file to insert','info')},{sep:true},{label:'Edit in New Tab',icon:'file-edit',shortcut:'Ctrl+E',action:()=>openTempTab()},{label:'Split at Playhead',icon:'scissors',shortcut:'S',action:()=>handleSplitTrack(selectedTrackId)},{label:'Merge Tracks',icon:'combine',shortcut:'Ctrl+M',action:()=>{handleMergeTracks();}},{sep:true},{label:'Undo',icon:'undo',shortcut:'Ctrl+Z',action:()=>{handleUndo();}},{label:'Redo',icon:'redo',shortcut:'Ctrl+Y',action:()=>{handleRedo();}},{sep:true},{label:'Copy',icon:'copy',shortcut:'Ctrl+C',action:()=>{handleCopyTrack();}},{label:'Cut',icon:'scissors',shortcut:'Ctrl+X',action:()=>{handleCutTrack();}},{label:'Paste',icon:'clipboard',shortcut:'Ctrl+V',action:handlePasteTrack},{sep:true},{label:'Delete Track',icon:'trash-2',shortcut:'Del',action:()=>{handleDeleteTrack();}}]},{label:'Insert',items:[...(!sessionTabs.some(s=>s.id===activeTab)?[{label:'Insert Section',icon:'folder-plus',action:insertSectionAtPlayhead}]:[]),{label:'Insert MIDI item',icon:'music',action:insertMidiItemAtPlayhead},{label:'Insert sound clip',icon:'file-input',action:insertSoundClipAtCursor},{label:'Insert track',icon:'plus',action:insertTrackBelow}]},{label:'View',items:[{label:'Master Track',icon:'disc',action:()=>showToast('Master track view','info')},{label:'Maker View',icon:'layout',action:()=>showToast('Maker view','info')},{label:'Mixer',icon:'sliders',action:()=>showToast('Mixer panel','info')},{label:'Tempo Track',icon:'timer',action:()=>showToast('Tempo track','info')},{label:'Video',icon:'film',action:()=>showToast('Video panel','info')},{label:'Media Explorer',icon:'folder-search',action:()=>showToast('Media explorer','info')}]},{label:'Tools',items:[{label:'Config AI Providers...',icon:'settings',action:()=>setAiConfigModalOpen(true)},{label:'AI MIDI Preset Manager...',icon:'sliders',action:()=>setAiPresetModalOpen(true)},{label:'DSP Tools Panel',icon:'wrench',action:()=>openPanel('python_tools')},{sep:true},{label:'Plugin Manager (SoundFont/VSTi)',icon:'zap',action:()=>{setPluginManagerModalOpen(true);window.SonicAPI.listPlugins().then(data=>setPluginsData(data)).catch(()=>{});}}]},{label:'Help',items:[{label:'About SonicForge',icon:'info',action:()=>showToast('SonicForge Studio v1.0 - Professional DAW','info')}]}].map(menu=>/*#__PURE__*/React.createElement("div",{key:menu.label,className:"relative"},/*#__PURE__*/React.createElement("button",{onClick:()=>setMenuOpen(menuOpen===menu.label?null:menu.label),className:`px-3 py-1 text-xs font-medium transition rounded ${menuOpen===menu.label?'bg-zinc-700 text-zinc-100':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`},menu.label),menuOpen===menu.label&&/*#__PURE__*/React.createElement("div",{className:`absolute top-full left-0 mt-0.5 bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 z-50 ${menu.label==='Edit'?'w-72':'w-64'}`,onClick:()=>setMenuOpen(null)},menu.items.map((item,i)=>item.sep?/*#__PURE__*/React.createElement("div",{key:i,className:"h-px bg-zinc-700 my-1"}):/*#__PURE__*/React.createElement("button",{key:item.label,onClick:e=>{e.stopPropagation();item.action();setMenuOpen(null);},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":item.icon,className:"w-3.5 h-3.5 text-zinc-500 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},item.label),item.shortcut&&/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},item.shortcut)))))),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 px-2"},/*#__PURE__*/React.createElement("span",{className:`text-xs font-bold uppercase px-1.5 py-0.5 rounded ${serverStatus==='connected'?'bg-emerald-950 text-emerald-400':serverStatus==='checking'?'bg-amber-950 text-amber-400':'bg-red-950 text-red-400'}`},"Server: ",serverStatus),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowAIConfig(!showAIConfig),className:`px-1.5 py-0.5 rounded text-xs border transition ${showAIConfig?'bg-purple-900 text-purple-200 border-purple-700':'bg-zinc-800 text-zinc-400 border-zinc-700 hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3"}))))),menuOpen&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-40",onClick:()=>setMenuOpen(null)}),/*#__PURE__*/React.createElement("div",{className:"h-7 bg-[#222] border-b border-zinc-800 flex items-stretch px-2 gap-0.5 shrink-0 overflow-x-auto"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab('main'),className:`px-3 text-xs font-bold uppercase tracking-wider border-b-2 transition flex items-center gap-1 ${activeTab==='main'?'text-cyan-400 border-cyan-500 bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"layout-dashboard",className:"w-3 h-3"}))," Main Session"),sessionTabs.map(st=>/*#__PURE__*/React.createElement("div",{key:st.id,className:"flex items-stretch"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab(st.id),className:`px-2 text-xs font-medium border-b-2 transition flex items-center gap-1 ${activeTab===st.id?'text-cyan-400 border-cyan-500 bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"layout-dashboard",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"max-w-[120px] truncate"},st.name)),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSessionTab(st.id),className:"px-1 text-zinc-600 hover:text-red-400 transition text-xs",title:"Close tab"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))))),subTabs.map(st=>/*#__PURE__*/React.createElement("div",{key:st.id,className:"flex items-stretch"},/*#__PURE__*/React.createElement("button",{onClick:()=>setActiveTab(st.id),className:`px-2 text-xs font-medium border-b-2 transition flex items-center gap-1 ${activeTab===st.id?'text-amber-400 border-amber-500 bg-zinc-800/50':'text-zinc-500 border-transparent hover:text-zinc-300 hover:bg-zinc-800/30'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-edit",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"max-w-[100px] truncate"},st.label)),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSubTab(st.id),className:"px-1 text-zinc-600 hover:text-red-400 transition text-xs",title:"Close tab"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))))),showAIConfig&&/*#__PURE__*/React.createElement("div",{className:"bg-zinc-900 border-b border-purple-900 p-3 flex flex-col gap-2 transition-all"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-purple-400 uppercase tracking-wider flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-4 h-4"}))," Cấu hình cổng kết nối API"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-1 md:grid-cols-3 gap-2 text-xs"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Endpoint Base URL"),/*#__PURE__*/React.createElement("input",{type:"text",value:aiConfig.baseUrl,onChange:e=>setAiConfig(prev=>({...prev,baseUrl:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"https://api.openai.com/v1"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"API Token Key"),/*#__PURE__*/React.createElement("input",{type:"password",value:aiConfig.apiKey,onChange:e=>setAiConfig(prev=>({...prev,apiKey:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"sk-..."})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1"},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase"},"Model Name"),/*#__PURE__*/React.createElement("input",{type:"text",value:aiConfig.model,onChange:e=>setAiConfig(prev=>({...prev,model:e.target.value})),className:"bg-zinc-850 text-zinc-200 p-1.5 rounded border border-zinc-800 focus:outline-none focus:border-purple-600 font-mono text-xs",placeholder:"gpt-4o-mini"})))),/*#__PURE__*/React.createElement("div",{className:"h-9 bg-[#222] border-b border-zinc-800 flex items-center px-3 gap-2 shrink-0 select-none"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 bg-zinc-900 border border-zinc-700 rounded px-1.5 py-0.5 shadow-lg",title:"Kéo để di chuyển toolbar",style:{cursor:'grab'}},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-0.5 mr-1 text-zinc-600"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('select');showToast('Select Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='select'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Select Tool (V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"mouse-pointer",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('grab');showToast('Grab Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='grab'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Grab Tool (H)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"hand",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-0.5 border border-zinc-700 rounded bg-zinc-850 px-0.5"},/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('razor');showToast('Razor Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='razor'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Razor Tool (C)"},/*#__PURE__*/React.createElement("svg",{className:"w-3.5 h-3.5 text-orange-400",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2.5",strokeLinecap:"round",strokeLinejoin:"round"},/*#__PURE__*/React.createElement("path",{d:"M6 3h12a2 2 0 0 1 2 2v2a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2z"}),/*#__PURE__*/React.createElement("path",{d:"M4 9h16l-3 9H7z"}),/*#__PURE__*/React.createElement("circle",{cx:"12",cy:"6",r:"1"}))),/*#__PURE__*/React.createElement("button",{onClick:handleGlueTracks,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-purple-400 hover:bg-zinc-800",title:"Glue Clips"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"link",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setActiveTool('pen');showToast('Pen Tool','info');},className:`w-7 h-7 flex items-center justify-center rounded ${activeTool==='pen'?'bg-cyan-700 text-white':'text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800'}`,title:"Pen Tool (P)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"pen-tool",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:handleCutTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-red-400 hover:bg-zinc-800",title:"Cut (Ctrl+X)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handleCopyTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-blue-400 hover:bg-zinc-800",title:"Copy (Ctrl+C)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handlePasteTrack,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-emerald-400 hover:bg-zinc-800",title:"Paste (Ctrl+V)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-2 py-1 bg-cyan-600 hover:bg-cyan-500 text-white font-semibold rounded text-xs flex items-center gap-1 shadow transition",title:"Thêm Track Mới (Ctrl+I)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"})),/*#__PURE__*/React.createElement("span",null,"Track")),sessionTabs.some(s=>s.id===activeTab)&&/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>handleSaveSectionTab(activeTab),className:"px-2 py-1 bg-emerald-600 hover:bg-emerald-500 text-white font-semibold rounded text-xs flex items-center gap-1 shadow transition",title:"Lưu Section vào Main Session"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3.5 h-3.5"})),/*#__PURE__*/React.createElement("span",null,"Lưu Section"))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-700 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:handleUndo,disabled:undoStack.length===0,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 disabled:opacity-30",title:"Undo (Ctrl+Z)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"undo",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handleRedo,disabled:redoStack.length===0,className:"w-7 h-7 flex items-center justify-center rounded text-zinc-400 hover:text-zinc-200 hover:bg-zinc-800 disabled:opacity-30",title:"Redo (Ctrl+Y)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"redo",className:"w-3.5 h-3.5"})))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>s.id===activeTab?{...s,currentTime:0}:s));}else{setCurrentTime(0);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Quay lại đầu"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-back",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const left=s.selectionStart!==null&&s.selectionEnd!==null?Math.min(s.selectionStart,s.selectionEnd):null;return left!==null?{...s,currentTime:left}:s;}));}else{if(selLeft!==null)setCurrentTime(selLeft);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Đầu vùng chọn"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"step-back",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:handlePlayPause,className:`w-7 h-7 flex items-center justify-center rounded border transition ${isPlaying?'bg-emerald-600 text-black border-emerald-500 hover:bg-emerald-500':'bg-cyan-600 text-white border-cyan-500 hover:bg-cyan-500'}`,title:isPlaying?"Tạm dừng":"Play"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":isPlaying?"pause":"play",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:handleStop,className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Stop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"square",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:handleRecordClick,className:`w-7 h-7 flex items-center justify-center rounded border transition ${recordingState==='RECORDING'?'bg-red-600 text-white border-red-500 hover:bg-red-500 animate-pulse':recordingState==='COUNT_IN'?'bg-amber-500 text-black border-amber-400 hover:bg-amber-400 animate-pulse':'bg-zinc-800 text-red-500 border-zinc-700 hover:bg-zinc-700 hover:text-red-400'}`,title:recordingState==='RECORDING'?"Đang ghi âm...":recordingState==='COUNT_IN'?"Chuẩn bị ghi âm...":"Ghi âm (Record)"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:"w-3.5 h-3.5 fill-current"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const right=s.selectionStart!==null&&s.selectionEnd!==null?Math.max(s.selectionStart,s.selectionEnd):null;return right!==null?{...s,currentTime:right}:s;}));}else{if(selRight!==null)setCurrentTime(selRight);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Cuối vùng chọn"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"step-forward",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{const isSubTab=subTabs.some(sub=>sub.id===activeTab);if(isSubTab){setSubTabs(prev=>prev.map(s=>{if(s.id!==activeTab)return s;const duration=s.buffer?s.buffer.duration/(s.speed||1.0):0;return{...s,currentTime:duration};}));}else{setCurrentTime(maxDuration);}},className:"w-7 h-7 flex items-center justify-center bg-zinc-800 hover:bg-zinc-700 text-zinc-200 rounded border border-zinc-700 transition",title:"Đến cuối"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"skip-forward",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-5 bg-zinc-800 mx-0.5"}),/*#__PURE__*/React.createElement("button",{onClick:()=>setIsLoopingSelection(prev=>!prev),className:`w-7 h-7 flex items-center justify-center rounded border transition ${isLoopingSelection?'bg-amber-600 text-black border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-200 border-zinc-700 hover:bg-zinc-700'}`,title:isLoopingSelection?selLeft!==null&&selRight!==null?"Loop vùng chọn":"Loop timeline":"Bật loop"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500 font-bold uppercase ml-2"},"Snap"),/*#__PURE__*/React.createElement("select",{value:snapValue,onChange:e=>setSnapValue(e.target.value),className:"bg-black text-white text-[14px] px-1.5 py-0.5 rounded border border-zinc-700 focus:outline-none focus:border-cyan-500 font-mono cursor-pointer"},/*#__PURE__*/React.createElement("option",{value:"free"},"Free"),/*#__PURE__*/React.createElement("option",{value:"1"},"1"),/*#__PURE__*/React.createElement("option",{value:"1/2"},"1/2"),/*#__PURE__*/React.createElement("option",{value:"1/4"},"1/4"),/*#__PURE__*/React.createElement("option",{value:"1/8"},"1/8"),/*#__PURE__*/React.createElement("option",{value:"1/16"},"1/16"),/*#__PURE__*/React.createElement("option",{value:"1/32"},"1/32")),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-6 bg-zinc-800 mx-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500 font-bold"},"Bars:"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:beginBar,onChange:e=>{const b=parseInt(e.target.value)||1;setBeginBar(b);const beatDuration=60/parseInt(bpm||120);const t=(b-1)*beatDuration*4;clearLocalSelection();setSelectionMode('global');setSelectionStart(t);setSelectionEnd(t+beatDuration*4);},className:"w-14 bg-black text-white text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"-"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:endBar,onChange:e=>{const b=parseInt(e.target.value)||1;setEndBar(b);const beatDuration=60/parseInt(bpm||120);const t=(b-1)*beatDuration*4;setSelectionEnd(t+beatDuration*4);setNumberBar(b-beginBar+1);},className:"w-14 bg-black text-white text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"#"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:numberBar,readOnly:true,className:"w-14 bg-black text-zinc-400 text-[14px] px-1 py-0.5 rounded border border-zinc-800 text-center font-mono"}),/*#__PURE__*/React.createElement("div",{className:"w-[1px] h-6 bg-zinc-800 mx-1.5"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"Start:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selLeft!==null?formatTime(selLeft):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));clearLocalSelection();setSelectionMode('global');setSelectionStart(secs);}},className:"w-20 bg-black text-zinc-200 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"End:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selRight!==null?formatTime(selRight):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));setSelectionEnd(secs);}},className:"w-20 bg-black text-zinc-200 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] text-zinc-500"},"Len:"),/*#__PURE__*/React.createElement("input",{type:"text",value:selLeft!==null&&selRight!==null?formatTime(Math.abs(selRight-selLeft)):'',onChange:e=>{const parts=e.target.value.split(/[:.]/);if(parts.length===3&&selLeft!==null){const secs=parseInt(parts[0])*60+parseInt(parts[1])+parseFloat('0.'+(parts[2]||'0'));setSelectionEnd(selLeft+secs);}},className:"w-20 bg-black text-amber-300 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono"}),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold font-mono text-zinc-100"},formatTime(currentTime))),(()=>{const dockPanels={top:[],right:[],bottom:[],left:[]};const addPanel=(id,pos,visible)=>{if(visible)dockPanels[pos].push(id);};addPanel('export',panelPositions.export,showExportPanel);addPanel('ai',panelPositions.ai,showAIPanel);addPanel('python_tools',panelPositions.python_tools||'bottom',showPythonToolsPanel);addPanel('selection',panelPositions.selection,showSelectionPanel);addPanel('media_explorer','bottom',showMediaExplorer);addPanel('fx_rack',panelPositions.fx_rack||'bottom',showFxRack);addPanel('midi_events',panelPositions.midi_events||'bottom',showMidiEvents);const closePanel=id=>{if(id==='export')setShowExportPanel(false);else if(id==='ai')setShowAIPanel(false);else if(id==='python_tools')setShowPythonToolsPanel(false);else if(id==='selection')setShowSelectionPanel(false);else if(id==='media_explorer')setShowMediaExplorer(false);else if(id==='fx_rack')setShowFxRack(false);else if(id==='midi_events')setShowMidiEvents(false);};const renderPanelContent=panelId=>{const h=id=>e=>{startPanelDrag(id,e);};if(panelId==='export')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('export',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-zinc-200 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3.5 h-3.5 text-cyan-400"}))," Export"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('export'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Ngu\u1ed3n"),/*#__PURE__*/React.createElement("select",{value:exportSettings.source,onChange:e=>setExportSettings(p=>({...p,source:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"project"},"Project (Mix)"),/*#__PURE__*/React.createElement("option",{value:"track_mix"},"Track Selection"),/*#__PURE__*/React.createElement("option",{value:"active_clip"},"Active Clip"),/*#__PURE__*/React.createElement("option",{value:"clip_selection"},"Clip Selection"))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"\u0110\u1ecbnh d\u1ea1ng"),/*#__PURE__*/React.createElement("select",{value:exportSettings.format,onChange:e=>setExportSettings(p=>({...p,format:e.target.value,sampleRate:e.target.value==='wav'?'44100':e.target.value==='mp3'?'44100':'44100',bitDepth:e.target.value==='wav'?'16':'16',quality:'44khz'})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"wav"},"WAV"),/*#__PURE__*/React.createElement("option",{value:"mp3"},"MP3"),/*#__PURE__*/React.createElement("option",{value:"ogg"},"OGG")))),exportSettings.format==='wav'?/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"SR (Hz)"),/*#__PURE__*/React.createElement("select",{value:exportSettings.sampleRate,onChange:e=>setExportSettings(p=>({...p,sampleRate:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"22500"},"22500"),/*#__PURE__*/React.createElement("option",{value:"44100"},"44100"))),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Bit"),/*#__PURE__*/React.createElement("select",{value:exportSettings.bitDepth,onChange:e=>setExportSettings(p=>({...p,bitDepth:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"8"},"8"),/*#__PURE__*/React.createElement("option",{value:"16"},"16"),/*#__PURE__*/React.createElement("option",{value:"24"},"24")))):/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Ch\u1ea5t l\u01b0\u1ee3ng"),/*#__PURE__*/React.createElement("select",{value:exportSettings.quality,onChange:e=>setExportSettings(p=>({...p,quality:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"44khz"},"44kHz"),/*#__PURE__*/React.createElement("option",{value:"lossless"},"Lossless"))),/*#__PURE__*/React.createElement("div",null)),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("label",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Kênh"),/*#__PURE__*/React.createElement("select",{value:exportSettings.channels,onChange:e=>setExportSettings(p=>({...p,channels:e.target.value})),className:"w-full bg-[#141414] border border-zinc-800 rounded px-1 py-0.5 text-xs text-zinc-300 focus:outline-none"},/*#__PURE__*/React.createElement("option",{value:"mono"},"Mono"),/*#__PURE__*/React.createElement("option",{value:"stereo"},"Stereo"))),/*#__PURE__*/React.createElement("div",null)),/*#__PURE__*/React.createElement("button",{onClick:triggerWavExport,disabled:isExporting,className:"w-full py-1 bg-cyan-700 hover:bg-cyan-600 text-zinc-100 font-bold rounded text-xs flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"download-cloud",className:"w-3 h-3"})),isExporting?'...':'Export'));if(panelId==='ai')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-1.5 flex-1 min-h-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('ai',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-zinc-200 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3.5 h-3.5 text-purple-400"}))," AI Copilot"),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:()=>setAiPresetModalOpen(true),className:"text-zinc-600 hover:text-zinc-300 mr-0.5",title:"Preset Manager"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>{setAiActionLog([]);showToast('Đã xoá nhật ký AI.','info');},className:"text-zinc-600 hover:text-zinc-300",title:"Clear log"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3 h-3"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('ai'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 w-full min-w-0 pb-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3 text-purple-400"})),/*#__PURE__*/React.createElement("select",{value:selectedProviderId,onChange:e=>setSelectedProviderId(e.target.value),className:"flex-1 min-w-0 max-w-full bg-[#141414] text-zinc-200 border border-zinc-700 rounded px-1 py-0.5 text-xs font-mono focus:outline-none focus:border-purple-600 truncate"},aiProviders.length===0?/*#__PURE__*/React.createElement("option",{value:""},"Chưa có provider"):aiProviders.map(p=>/*#__PURE__*/React.createElement("option",{key:p.id,value:p.id},p.name,p.is_active?'':' (inactive)')))),/*#__PURE__*/React.createElement("div",{className:"border-t border-zinc-800 pt-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement("button",{onClick:()=>{if(window.DAWCommandDispatcher&&window.DAWCommandDispatcher.undo){const entry=window.DAWCommandDispatcher.undo();if(entry){setAiActionLog(prev=>[...prev,{type:'undo',text:`Undo: ${entry.name}`,time:Date.now()}]);showToast(`Undo AI: ${entry.name}`,'info');}}else{handleUndo();setAiActionLog(prev=>[...prev,{type:'undo',text:'Undo (Ctrl+Z)',time:Date.now()}]);}},className:"w-full text-[10px] text-amber-400 hover:text-amber-300 border border-amber-800 rounded py-0.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("i",{"data-lucide":"rotate-ccw",className:"w-3 h-3"}),"Undo"))),/*#__PURE__*/React.createElement("div",{className:"flex-1 min-h-0 flex flex-col overflow-hidden mt-1"},/*#__PURE__*/React.createElement("div",{className:"text-[10px] font-bold text-zinc-400 uppercase shrink-0 pb-0.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center gap-1"},/*#__PURE__*/React.createElement("i",{"data-lucide":"list",className:"w-3 h-3"})," Action Log")),/*#__PURE__*/React.createElement("div",{ref:actionLogContainerRef,className:"flex-1 overflow-y-auto no-scrollbar bg-[#0f0f0f] rounded border border-zinc-800 select-text"},aiActionLog.length===0?/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-600 italic select-text"},"Chưa có hành động nào."):aiActionLog.map((entry,i)=>/*#__PURE__*/React.createElement("div",{key:i,className:`text-xs font-mono py-0.5 border-b border-zinc-900 last:border-0 ${entry.type==='error'?'text-red-400':entry.type==='status'?'text-zinc-400 italic':entry.type==='undo'?'text-amber-400':'text-zinc-300'}`},new Date(entry.time).toLocaleTimeString(),entry.text)))),/*#__PURE__*/React.createElement("div",{className:"border-t border-zinc-800 pt-1.5 mt-1 shrink-0"},/*#__PURE__*/React.createElement("div",{className:"text-xs font-bold text-zinc-400 uppercase mb-1 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"message-square",className:"w-3 h-3"}))," Copilot Prompt"),/*#__PURE__*/React.createElement("textarea",{value:aiPrompt,onChange:e=>setAiPrompt(e.target.value),placeholder:"Nhập lệnh điều khiển DAW... (VD: Tạo track mới tên Beat, đặt BPM 128)",className:"w-full bg-[#1e1e1e] text-zinc-200 p-1.5 rounded border border-zinc-700 focus:outline-none focus:border-purple-600 font-mono text-xs resize-none",rows:2,onKeyDown:e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();handleAISend();}else if(e.key==='ArrowUp'&&promptHistRef.current.length>0){e.preventDefault();const idx=promptHistIdx===-1?promptHistRef.current.length-1:Math.max(0,promptHistIdx-1);setPromptHistIdx(idx);setAiPrompt(promptHistRef.current[idx]);}else if(e.key==='ArrowDown'){e.preventDefault();if(promptHistIdx===-1)return;const idx=promptHistIdx+1;if(idx>=promptHistRef.current.length){setPromptHistIdx(-1);setAiPrompt('');}else{setPromptHistIdx(idx);setAiPrompt(promptHistRef.current[idx]);}}}})),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement("button",{onClick:handleAISend,disabled:aiProcessing,className:"flex-1 py-1 bg-purple-700 hover:bg-purple-600 text-white font-bold rounded text-xs border border-purple-500 flex items-center justify-center gap-1"},aiProcessing?'Đang suy luận...':/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"send",className:"w-3 h-3"}))," Gửi")),/*#__PURE__*/React.createElement("button",{onClick:()=>{setAiPrompt('');setAiActionLog([]);},className:"px-2 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-400 rounded text-xs border border-zinc-700"},"Clear")),/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-600 shrink-0"},"Enter để gửi nhanh"));if(panelId==='python_tools')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('python_tools',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-amber-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"wrench",className:"w-3.5 h-3.5 text-amber-400"}))," DSP Tools"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('python_tools'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"p-1.5 bg-[#141414] rounded border border-zinc-800 text-[10px] font-mono text-zinc-400 space-y-0.5 leading-relaxed"},dspSelectionStats?[/*#__PURE__*/React.createElement("div",{key:"track"},`Track: ${dspSelectionStats.trackName}`),/*#__PURE__*/React.createElement("div",{key:"range"},`Range: ${dspSelectionStats.timeRange}`),/*#__PURE__*/React.createElement("div",{key:"ch"},`Channels: ${dspSelectionStats.channels}`),/*#__PURE__*/React.createElement("div",{key:"peak"},`Peak Vol: ${dspSelectionStats.peakVolume}`)]:"Chưa chọn track"),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1 text-xs"},/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('normalize'),className:"py-1 bg-amber-950/80 hover:bg-amber-900 text-amber-300 border border-amber-800/80 rounded font-bold flex items-center justify-center gap-1"},"⚡ Peak Norm (0dB)"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('invert_phase'),className:"py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-200 border border-zinc-700 rounded font-bold flex items-center justify-center gap-1"},"🔄 Phase Invert"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('swap_channels'),className:"py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-200 border border-zinc-700 rounded font-bold flex items-center justify-center gap-1"},"🔀 Swap L/R"),/*#__PURE__*/React.createElement("button",{onClick:()=>runPythonTool('synth_wave'),className:"py-1 bg-teal-950/80 hover:bg-teal-900 text-teal-300 border border-teal-800/80 rounded font-bold flex items-center justify-center gap-1"},"🎹 Gen Synth Tone")));if(panelId==='selection')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('selection',e)},/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500 font-bold uppercase flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"}))," Selection"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('selection'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-1 bg-[#141414] p-1.5 rounded border border-zinc-800"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Start"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.01",value:selectionStats.start,onChange:e=>handleSelectionInputChange('start',e.target.value),className:"w-full bg-[#242424] text-amber-400 text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"End"),/*#__PURE__*/React.createElement("input",{type:"number",step:"0.01",value:selectionStats.end,onChange:e=>handleSelectionInputChange('end',e.target.value),className:"w-full bg-[#242424] text-amber-400 text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col justify-center"},/*#__PURE__*/React.createElement("span",{className:"text-[7px] text-zinc-500 font-bold uppercase"},"Len"),/*#__PURE__*/React.createElement("span",{className:"text-zinc-200 font-mono text-xs font-semibold mt-0.5"},selectionStats.length,"s"))),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-3 gap-1 bg-[#141414] p-1.5 rounded border border-zinc-800 mt-1"},/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"Begin Bar"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:beginBar,onChange:e=>{const b=parseInt(e.target.value)||1;setBeginBar(b);const beatDuration=60/parseInt(bpm||120);const t=(b-1)*beatDuration*4;clearLocalSelection();setSelectionMode('global');setSelectionStart(t);setSelectionEnd(t+beatDuration*4);},className:"w-full bg-[#242424] text-white text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",null,/*#__PURE__*/React.createElement("span",{className:"block text-[7px] text-zinc-500 font-bold uppercase mb-0.5"},"End Bar"),/*#__PURE__*/React.createElement("input",{type:"number",min:"1",value:endBar,onChange:e=>{const b=parseInt(e.target.value)||1;setEndBar(b);const beatDuration=60/parseInt(bpm||120);const t=(b-1)*beatDuration*4;setSelectionEnd(t+beatDuration*4);setNumberBar(b-beginBar+1);},className:"w-full bg-[#242424] text-white text-center font-mono text-xs rounded py-0.5 border border-zinc-700 focus:outline-none"})),/*#__PURE__*/React.createElement("div",{className:"flex flex-col justify-center"},/*#__PURE__*/React.createElement("span",{className:"text-[7px] text-zinc-500 font-bold uppercase"},"# Bars"),/*#__PURE__*/React.createElement("span",{className:"text-zinc-200 font-mono text-xs font-semibold mt-0.5"},numberBar))));if(panelId==='media_explorer')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('media_explorer',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-emerald-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"folder-open",className:"w-3.5 h-3.5 text-emerald-400"}))," Media Explorer"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('media_explorer'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 overflow-y-auto text-xs text-zinc-400 font-mono p-2"},"// Placeholder: Media files browser"));if(panelId==='fx_rack')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('fx_rack',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-rose-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3.5 h-3.5 text-rose-400"}))," Plugin FX Rack"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('fx_rack'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 text-xs text-zinc-500 italic flex items-center justify-center"},"No FX plugins loaded"));if(panelId==='midi_events')return/*#__PURE__*/React.createElement("div",{className:"flex flex-col h-full gap-1.5"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between shrink-0 cursor-grab active:cursor-grabbing select-none",onMouseDown:e=>startPanelDrag('midi_events',e)},/*#__PURE__*/React.createElement("h3",{className:"font-bold text-xs text-sky-300 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"grip-vertical",className:"w-3 h-3 text-zinc-500"})),/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3.5 h-3.5 text-sky-400"}))," MIDI Event List"),/*#__PURE__*/React.createElement("button",{onClick:()=>closePanel('midi_events'),className:"text-zinc-600 hover:text-zinc-300"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"})))),/*#__PURE__*/React.createElement("div",{className:"flex-1 text-xs text-zinc-500 italic flex items-center justify-center"},"No MIDI events selected"));return null;};const renderDock=(pos,title)=>{const panels=dockPanels[pos];if(panels.length===0)return null;const isSide=pos==='left'||pos==='right';const borderClass=pos==='left'?'border-r':pos==='right'?'border-l':pos==='top'?'border-b':'border-t';const bgClass='bg-[#1e1e1e]';const highlight=panelDragRef.current&&panelDropZone===pos;if(pos==='right')return/*#__PURE__*/React.createElement("div",{id:"right-sidebar",className:`${borderClass} ${bgClass} flex flex-col overflow-hidden select-none h-full`,style:{width:`${rightSidebarWidth}px`,minWidth:'200px',maxWidth:'600px',flexShrink:0}},/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col gap-2 p-2 overflow-hidden h-full"},panels.map((p,idx)=>/*#__PURE__*/React.createElement(React.Fragment,{key:p},/*#__PURE__*/React.createElement("div",{className:'flex flex-col flex-1 min-h-0 border border-zinc-700 rounded-lg bg-[#262626] shadow-sm p-3'},renderPanelContent(p)),idx/*#__PURE__*/React.createElement("div",{key:p,className:`${isSide?'w-full':'flex-none w-[320px]'} border border-zinc-700 rounded-lg bg-[#262626] shadow-sm p-2`},renderPanelContent(p))));};return/*#__PURE__*/React.createElement("div",{ref:workspaceRef,className:"flex-1 flex flex-col overflow-hidden select-none daw-bg relative"},panelDragRef.current&&panelDropZone&&/*#__PURE__*/React.createElement("div",{className:"absolute inset-0 z-50 pointer-events-none"},panelDropZone==='top'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 left-0 right-0 h-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='bottom'&&/*#__PURE__*/React.createElement("div",{className:"absolute bottom-0 left-0 right-0 h-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='left'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 left-0 w-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"}),panelDropZone==='right'&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 right-0 w-1 bg-cyan-400 shadow-[0_0_8px_#06b6d4]"})),dragGhostPanel&&dragGhostPos&&/*#__PURE__*/React.createElement("div",{className:"fixed z-[100] pointer-events-none opacity-80 border border-cyan-500 rounded-lg bg-[#262626] shadow-2xl p-3 w-56",style:{left:dragGhostPos.x,top:dragGhostPos.y}},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 text-xs text-zinc-200 font-bold"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"move",className:"w-3.5 h-3.5 text-cyan-400"})),dragGhostPanel==='export'?'Export Panel':dragGhostPanel==='ai'?'AI Panel':dragGhostPanel==='python_tools'?'Audio Processing Panel':'Selection Panel'),/*#__PURE__*/React.createElement("div",{className:"text-xs text-zinc-500 mt-1"},"Drop at edge to dock")),renderDock('top','Top'),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex overflow-hidden"},renderDock('left','Left'),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col overflow-hidden min-w-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 flex overflow-hidden"},activeTab==='main'||sessionTabs.some(s=>s.id===activeTab)?/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{ref:tcpContainerRef,onScroll:handleTCPScroll,className:"w-[320px] shrink-0 z-20 bg-[#262626] overflow-y-auto flex flex-col border-r border-zinc-900 no-scrollbar",style:{scrollbarWidth:'none',msOverflowStyle:'none'}},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-50 flex items-center justify-between h-10 border-b border-zinc-900 bg-[#242424] px-2 shrink-0"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-300 flex items-center gap-1.5"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3.5 h-3.5 text-cyan-400"})),"TRACKS (",activeTracks.length,")"),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-2.5 py-1 bg-cyan-600 hover:bg-cyan-500 text-white rounded text-xs font-semibold flex items-center gap-1 shadow transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3 h-3"}))," Add Track")),/*#__PURE__*/React.createElement("div",{className:"sticky top-10 z-40 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] p-2 border-l-4 border-purple-500 shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between w-full"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-purple-400 font-mono"},"TM"),/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300"},"Tempo")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("input",{type:"number",value:bpm,onChange:e=>setBpm(e.target.value),onBlur:()=>localStorage.setItem('studio_bpm',bpm),className:"w-12 bg-zinc-800 border border-zinc-700 rounded text-xs text-zinc-300 text-center font-mono focus:outline-none focus:border-purple-500",min:"40",max:"300"}),/*#__PURE__*/React.createElement("span",{className:"text-xs text-zinc-500"},"BPM")))),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col divide-y divide-[#141414] bg-[#262626]"},activeTracks.length===0?/*#__PURE__*/React.createElement("div",{className:"p-6 text-center text-zinc-400 flex flex-col items-center justify-center space-y-3"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-circle",className:"w-8 h-8 text-cyan-400 opacity-80"})),/*#__PURE__*/React.createElement("p",{className:"text-xs font-medium"},"Chưa có Track nào trong dự án."),/*#__PURE__*/React.createElement("button",{onClick:addNewTrack,className:"px-3 py-1.5 bg-cyan-600 hover:bg-cyan-500 text-white rounded text-xs font-semibold flex items-center gap-1.5 shadow"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus-circle",className:"w-3.5 h-3.5"}))," Thêm Track Mới")):activeTracks.map((track,idx)=>{const isSelected=selectedTrackId===track.id;const autoHeight=track.height||(track.isArmed?164:140);return/*#__PURE__*/React.createElement("div",{key:track.id,style:{height:`${autoHeight}px`},className:`shrink-0 relative flex flex-col justify-between p-2.5 bg-[#1e1e1e] border-r border-zinc-900 cursor-pointer border-l-4 border-b border-[#141414] overflow-hidden ${isSelected?'border-cyan-500 bg-[#252525]':'border-transparent hover:bg-zinc-800/20'}`,onClick:()=>setSelectedTrackId(track.id)},/*#__PURE__*/React.createElement("div",{className:"flex items-start justify-between"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-500 font-mono"},(idx+1).toString().padStart(2,'0')),/*#__PURE__*/React.createElement("label",{onClick:e=>{e.stopPropagation();const el=e.currentTarget.querySelector('input');if(el)el.click();},className:"cursor-pointer"},/*#__PURE__*/React.createElement("input",{type:"color",value:track.color||'#0f766e',onChange:e=>{e.stopPropagation();updateTrackColor(track.id,e.target.value);},className:"w-0 h-0 opacity-0 absolute pointer-events-none"}),/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 rounded-full border border-zinc-600 hover:scale-110 transition-transform",style:{backgroundColor:track.color}})),editingTrackName===track.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{updateTrackName(track.id,editNameInput||track.name);setEditingTrackName(null);},onKeyDown:e=>{if(e.key==='Enter'){updateTrackName(track.id,editNameInput||track.name);setEditingTrackName(null);}if(e.key==='Escape')setEditingTrackName(null);},onClick:e=>e.stopPropagation(),className:"text-xs font-semibold bg-black text-zinc-200 border border-cyan-500 rounded px-1 py-0 w-24 outline-none"}):/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300 truncate max-w-[80px] cursor-text hover:text-cyan-300 transition-colors",title:"Click to rename",onClick:e=>{e.stopPropagation();setEditingTrackName(track.id);setEditNameInput(track.name);}},track.name)),/*#__PURE__*/React.createElement("div",{className:"flex flex-wrap gap-0.5 max-w-[100px] mb-0.5"},(track.clips&&track.clips.length>0?track.clips:track.buffer?[{id:'default',name:track.name,startTime:track.startTime}]:[]).slice(0,3).map(c=>/*#__PURE__*/React.createElement("span",{key:c.id,className:"text-[9px] font-mono text-zinc-500 bg-zinc-800/60 rounded px-0.5 truncate max-w-[90px] cursor-pointer hover:text-cyan-400 hover:bg-zinc-700",title:c.name||track.name,onClick:e=>{e.stopPropagation();setSelectedTrackId(track.id);clearLocalSelection();setSelectionMode('global');const start=c.startTime||0;const end=start+(c.buffer?c.buffer.duration:2);setSelectionStart(start);setSelectionEnd(end);showToast(`Selected: ${c.name||track.name}`,'info');}},c.name||track.name),editingClipName&&editingClipName.trackId===track.id&&editingClipName.clipId===c.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{if(editNameInput.trim())updateClipName(track.id,c.id,editNameInput.trim());setEditingClipName(null);},onKeyDown:e=>{if(e.key==='Enter'){if(editNameInput.trim())updateClipName(track.id,c.id,editNameInput.trim());setEditingClipName(null);}if(e.key==='Escape')setEditingClipName(null);},onClick:e=>e.stopPropagation(),className:"w-20 text-[9px] font-mono bg-black text-cyan-300 border border-cyan-500 rounded px-0.5 py-0 outline-none"}):/*#__PURE__*/React.createElement("button",{className:"text-[9px] text-zinc-600 hover:text-cyan-400 ml-0.5 shrink-0",title:"Sửa tên clip",onClick:e=>{e.stopPropagation();setEditingClipName({trackId:track.id,clipId:c.id});setEditNameInput(c.name||track.name);}},/*#__PURE__*/React.createElement("i",{"data-lucide":"pencil",className:"w-2.5 h-2.5"})))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMute(track.id);},title:"Mute",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.muted?'bg-red-950 text-red-400 border-red-700':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":track.muted?"volume-x":"volume-2",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackSoloEvaluate(track.id);},title:"Solo",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${soloedTrackId===track.id||track.solo?'bg-amber-950 text-amber-400 border-amber-600':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":soloedTrackId===track.id||track.solo?"headphones":"headphone-off",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackArm(track.id);},title:"ARM (Record)",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.isArmed?'bg-red-600 text-white border-red-500 hover:bg-red-500':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":"circle",className:`w-2.5 h-2.5 ${track.isArmed?'fill-white':''}`})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMonitor(track.id);},title:"Input Monitor",className:`px-1.5 py-0.5 text-[10px] rounded font-mono font-bold border transition flex items-center gap-0.5 ${track.monitoringEnabled?'bg-amber-600 text-white border-amber-500 hover:bg-amber-500':'bg-zinc-800 text-zinc-500 border-transparent hover:text-zinc-305'}`},/*#__PURE__*/React.createElement("i",{"data-lucide":track.monitoringEnabled?"mic":"mic-off",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();deleteTrack(track.id);},className:"p-0.5 rounded text-red-500 hover:bg-red-950/40 hover:text-red-400 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3 h-3"}))))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-0.5 text-xs",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Vol:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-50",max:"7",step:"0.5",value:track.volumeDb??0,onChange:e=>updateTrackVolumeDb(track.id,parseFloat(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-12 text-right font-mono text-zinc-300 text-xs"},track.volumeDb??0,"dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-xs"},"Pan:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-100",max:"100",step:"1",value:track.pan??0,onChange:e=>updateTrackPan(track.id,parseInt(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-12 text-right font-mono text-zinc-300 text-xs"},track.pan>0?'R'+track.pan:track.pan<0?'L'+Math.abs(track.pan):'C')),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-0.5"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-[10px]"},"In:"),/*#__PURE__*/React.createElement("select",{value:`${track.inputSource?.deviceType||'NONE'}:${track.inputSource?.deviceId||''}`,onChange:e=>{const val=e.target.value;const parts=val.split(':');const type=parts[0];const id=parts.slice(1).join(':');updateTrackInputSource(track.id,type,id);},className:"flex-1 bg-[#18181b] text-zinc-300 text-[10px] rounded border border-zinc-700 focus:outline-none py-0.5 px-1 truncate max-w-[120px]"},/*#__PURE__*/React.createElement("option",{value:"NONE:"},"No Input"),/*#__PURE__*/React.createElement("optgroup",{label:"Microphones"},audioDevices.map(d=>/*#__PURE__*/React.createElement("option",{key:d.deviceId,value:`MICROPHONE:${d.deviceId}`},d.label||`Microphone ${d.deviceId.slice(0,5)}`))),/*#__PURE__*/React.createElement("optgroup",{label:"MIDI Keyboards"},/*#__PURE__*/React.createElement("option",{value:"MIDI_KEYBOARD:ALL"},"Any MIDI Keyboard"),midiDevices.map(d=>/*#__PURE__*/React.createElement("option",{key:d.id,value:`MIDI_KEYBOARD:${d.id}`},d.name||`MIDI Input ${d.id.slice(0,5)}`)))),track.isArmed&&lastMidiNote&&(lastMidiNote.length===0||Date.now()-lastMidiNote.time<3000)&&/*#__PURE__*/React.createElement("span",{className:"text-[9px] font-mono text-emerald-400 ml-0.5 truncate max-w-[60px] shrink-0",title:"MIDI Note:velocity:length"},`${midiPitchToName(lastMidiNote.pitch)}:${lastMidiNote.velocity}:${lastMidiNote.length>0?lastMidiNote.length.toFixed(2)+'s':'...'}`)),track.isArmed&&/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1 mt-0.5"},/*#__PURE__*/React.createElement("span",{className:"w-8 text-right text-zinc-500 text-[9px]"},"VU:"),/*#__PURE__*/React.createElement("canvas",{ref:el=>{if(el)trackVuRefs.current[track.id]=el;else delete trackVuRefs.current[track.id];},width:100,height:4,className:"flex-1 bg-[#18181b] rounded h-1"}))),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 mt-1",onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("input",{type:"file",id:`upload-${track.id}`,accept:"audio/*",className:"hidden",onChange:e=>loadFileOnTrack(track.id,e.target.files[0])}),/*#__PURE__*/React.createElement("label",{htmlFor:`upload-${track.id}`,className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-zinc-300 rounded text-xs flex items-center gap-1 cursor-pointer border border-zinc-700 font-medium"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"upload",className:"w-3 h-3"}))," File"),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();showToast('FX panel for track '+track.id,'info');},className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-purple-400 border border-purple-900 rounded text-xs font-bold flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"wand-2",className:"w-3 h-3"}))," FX: ",/*#__PURE__*/React.createElement("span",{className:"text-zinc-500 font-normal"},"None")),/*#__PURE__*/React.createElement("button",{onClick:()=>generateSynthToTrack(track.id,'synth'),className:"px-2.5 py-1 bg-zinc-800 hover:bg-zinc-700 text-amber-400 border border-amber-800 rounded text-xs font-bold flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3"}))," Synth: ",/*#__PURE__*/React.createElement("span",{className:"text-zinc-500 font-normal"},"None"))),/*#__PURE__*/React.createElement("div",{onMouseDown:e=>handleTrackResizeMouseDown(e,track.id),className:"absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",onClick:e=>e.stopPropagation()}));})),/*#__PURE__*/React.createElement("div",{className:"h-[48px] border-r border-zinc-900 bg-[#1e1e1e]/50 shrink-0"})),/*#__PURE__*/React.createElement("div",{ref:handleTimelineWrapperRef,onScroll:handleTimelineScroll,className:"flex-1 relative z-10 overflow-x-auto overflow-y-auto min-w-0"},/*#__PURE__*/React.createElement("div",{style:{width:`${timelineWidth}px`},className:"relative flex flex-col min-h-full"},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-45 flex h-10 border-b border-zinc-900 bg-[#242424] shrink-0"},/*#__PURE__*/React.createElement("div",{ref:rulerRef,className:"flex-1 relative h-full flex items-center select-none cursor-ew-resize overflow-hidden",onMouseDown:handleRulerMouseDown},Array.from({length:Math.ceil(maxDuration)}).map((_,i)=>{const sec=i;const x=sec*zoom;return/*#__PURE__*/React.createElement("div",{key:i,className:"absolute h-full border-l border-zinc-700 pl-1 pt-1 text-[14px] font-mono text-zinc-300 pointer-events-none",style:{left:`${x}px`}},formatTimeSimple(sec));}))),selectionMode==='global'&&selLeft!==null&&selRight!==null&&selRight>selLeft&&/*#__PURE__*/React.createElement("div",{className:"absolute inset-0 pointer-events-none z-20",style:{left:`${selLeft*zoom}px`,width:`${(selRight-selLeft)*zoom}px`,top:'40px'}},/*#__PURE__*/React.createElement("div",{className:"w-full h-full bg-amber-500/10",style:{borderLeft:'1px solid #f59e0b',borderRight:'1px solid #f59e0b'}})),/*#__PURE__*/React.createElement("div",{className:"sticky top-10 z-35 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 relative h-full overflow-hidden bg-[#1a1a2e]"},/*#__PURE__*/React.createElement(TempoTrackLane,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,onPlayheadSet:handlePlayheadSet,snapValue:snapValue,onRulerMouseDown:handleRulerMouseDown,scrollLeft:scrollLeft}))),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col divide-y divide-[#141414] relative bg-[#111111] min-h-full"},activeTracks.map((track,idx)=>{const isSelected=selectedTrackId===track.id;const autoHeight=track.height||(track.isArmed?164:140);return/*#__PURE__*/React.createElement("div",{key:track.id,style:{height:`${autoHeight}px`},className:`shrink-0 relative border-b border-[#141414] hover:bg-zinc-850/5 transition-colors ${isSelected?'bg-zinc-800/10':''}`,onDragOver:e=>e.preventDefault(),onDrop:e=>{e.preventDefault();if(e.dataTransfer.files[0])loadFileOnTrack(track.id,e.dataTransfer.files[0]);},onMouseEnter:()=>setHoveredTrackId(track.id)},/*#__PURE__*/React.createElement(WaveformLane,{track:track,zoom:zoom,timelineWidth:timelineWidth,viewportWidth:viewportWidth,onSelectRange:handleSelectRange,onPlayheadSet:handlePlayheadSet,isSelected:isSelected,onSelectTrack:setSelectedTrackId,markers:track.markers,onTrackLaneMouseDown:handleTrackLaneMouseDown,onContextMenu:handleContextMenu,onClipDragStart:handleClipDragStart,onClipStretchStart:handleClipStretchStart,onSectionItemDragStart:handleSectionItemDragStart,onSectionItemResizeStart:handleSectionItemResizeStart,onSelectionEdgeDragStart:handleSelectionEdgeDragStart,setSelectedClipId:setSelectedClipId,selectedClipId:selectedClipId,activeTool:activeTool,onSplitTrackAtTime:handleSplitTrackAtTime,onEditClipInSubTab:handleEditClipInSubTab,onEditSectionInTab:handleEditSectionInTab,onEditMidiInTab:handleEditMidiInTab,snapValue:snapValue,bpm:bpm,selectionMode:selectionMode,localSelectionTrackId:localSelectionTrackId,localSelectionStart:localSelectionStart,currentTime:currentTime,getLocalAnchor:()=>localSelectionAnchorRef.current,onClearLocalSelection:clearLocalSelection,onSetSelectionMode:setSelectionMode,onSetSelectionStart:setSelectionStart,onSetSelectionEnd:setSelectionEnd,onSetCurrentTime:setCurrentTime,onSetLocalSelectionTrackId:setLocalSelectionTrackId,onSetLocalSelectionStart:setLocalSelectionStart,onSetLocalSelectionEnd:setLocalSelectionEnd,localSelLeft:localSelectionStart!==null&&localSelectionEnd!==null?Math.min(localSelectionStart,localSelectionEnd):null,localSelRight:localSelectionStart!==null&&localSelectionEnd!==null?Math.max(localSelectionStart,localSelectionEnd):null,scrollLeft:scrollLeft,recordingState:recordingState,recTempMidiNotes:recTempMidiNotes,recTempAudioBuffer:recTempAudioBuffer,recStartTimelineTime:recStartTimelineTime,canvasRedrawCount:canvasRedrawCount}),selectionMode==='local'&&localSelectionTrackId===track.id&&localSelectionStart!==null&&localSelectionEnd!==null&&Math.abs(localSelectionEnd-localSelectionStart)>0&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-400 bg-amber-500/20 z-20 pointer-events-none",style:{left:`${Math.min(localSelectionStart,localSelectionEnd)*zoom}px`,width:`${Math.abs(localSelectionEnd-localSelectionStart)*zoom}px`}},/*#__PURE__*/React.createElement("div",{className:"absolute -left-[1px] top-0 bottom-0 w-[2px] bg-amber-400 z-30 pointer-events-auto cursor-ew-resize",onMouseDown:e=>handleHandleDragStart(e,'left')}),/*#__PURE__*/React.createElement("div",{className:"absolute -right-[1px] top-0 bottom-0 w-[2px] bg-amber-400 z-30 pointer-events-auto cursor-ew-resize",onMouseDown:e=>handleHandleDragStart(e,'right')})),track.buffer&&/*#__PURE__*/React.createElement("div",{className:"absolute right-2 top-2 flex items-center gap-1 z-10 opacity-70 hover:opacity-100"},/*#__PURE__*/React.createElement("button",{onClick:()=>handleSplitTrack(track.id),className:"px-1.5 py-0.5 bg-zinc-900/95 text-zinc-300 rounded text-xs flex items-center gap-1 border border-zinc-700/50"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-2.5 h-2.5 text-cyan-400"}))," Cắt")),/*#__PURE__*/React.createElement("div",{onMouseDown:e=>handleTrackResizeMouseDown(e,track.id),className:"absolute bottom-0 left-0 right-0 h-1 cursor-ns-resize z-30 hover:bg-cyan-500/50 transition-colors",onClick:e=>e.stopPropagation()}));}),/*#__PURE__*/React.createElement("div",{className:"h-[48px] flex items-center justify-center text-xs text-zinc-500 hover:bg-zinc-900/20 cursor-pointer select-none border-t border-dashed border-zinc-800",onMouseEnter:()=>{if(draggedClipRef.current||draggedSectionItemRef.current){setHoveredTrackId(addNewTrack());}},onClick:addNewTrack},/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1 text-zinc-400"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"plus",className:"w-3.5 h-3.5"}))," Kéo clip xuống hoặc Click tạo Track")),selectionMode==='global'&&selLeft!==null&&selRight!==null&&selRight>selLeft&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-500 bg-amber-500/10 z-20 selection-interactive-box cursor-grab active:cursor-grabbing",style:{left:`${selLeft*zoom}px`,width:`${(selRight-selLeft)*zoom}px`},onMouseDown:handleSelectionBodyDragStart},/*#__PURE__*/React.createElement("div",{className:"absolute -left-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30",onMouseDown:e=>handleHandleDragStart(e,'left')}),/*#__PURE__*/React.createElement("div",{className:"absolute -right-[1px] top-0 bottom-0 w-[1px] bg-amber-500 hover:bg-amber-400 cursor-ew-resize z-30",onMouseDown:e=>handleHandleDragStart(e,'right')})),/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 w-[2px] bg-[#ef4444] z-20 pointer-events-none",style:{left:`${playheadLeftPos}px`}},/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 bg-[#ef4444] rotate-45 transform -translate-x-1/2 -translate-y-1/2 absolute top-0"})))))):(()=>{const st=subTabs.find(s=>s.id===activeTab);if(!st)return null;if(st.type==='PIANO_ROLL'){return/*#__PURE__*/React.createElement(PianoRollTabEditor,{st:st,zoom:zoom,bpm:bpm,viewportWidth:viewportWidth,onClose:()=>closeSubTab(st.id),onUpdateNotes:handleUpdateMidiNotes,onSaveNotes:handleSaveMidiNotes,setSubTabs:setSubTabs});}const subTrack=tracks.find(t=>t.id===st.trackId);const vTrack=subTrack?{...subTrack,buffer:st.buffer,isSubTab:true}:null;const subTabTimelineWidth=Math.max(zoom*(st.buffer?st.buffer.duration:0),viewportWidth);return/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("div",{className:"w-[320px] shrink-0 z-30 bg-[#262626] overflow-y-scroll no-scrollbar flex flex-col border-r border-zinc-900",style:{scrollbarWidth:'none',msOverflowStyle:'none'}},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-50 flex items-center h-10 border-b border-zinc-900 bg-[#242424] px-2 justify-between shrink-0"},/*#__PURE__*/React.createElement("span",{className:"text-xs font-bold text-zinc-500 uppercase"},"Sub-Tab"),/*#__PURE__*/React.createElement("button",{onClick:()=>closeSubTab(st.id),className:"px-1.5 py-0.5 text-xs bg-zinc-800 hover:bg-zinc-700 text-zinc-400 rounded border border-zinc-700 flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"x",className:"w-3 h-3"}))," Close")),vTrack?/*#__PURE__*/React.createElement("div",{key:vTrack.id,className:"flex-1 flex flex-col p-2.5 bg-[#1e1e1e] border-r border-zinc-900 border-l-4 border-l-cyan-500"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between mb-2"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("label",{onClick:e=>{e.stopPropagation();const el=e.currentTarget.querySelector('input');if(el)el.click();},className:"cursor-pointer"},/*#__PURE__*/React.createElement("input",{type:"color",value:vTrack.color||'#0f766e',onChange:e=>{e.stopPropagation();updateTrackColor(vTrack.id,e.target.value);},className:"w-0 h-0 opacity-0 absolute pointer-events-none"}),/*#__PURE__*/React.createElement("div",{className:"w-3 h-3 rounded-full border border-zinc-600 hover:scale-110 transition-transform",style:{backgroundColor:vTrack.color}})),editingTrackName===vTrack.id?/*#__PURE__*/React.createElement("input",{type:"text",value:editNameInput,autoFocus:true,onChange:e=>setEditNameInput(e.target.value),onBlur:()=>{updateTrackName(vTrack.id,editNameInput||vTrack.name);setEditingTrackName(null);},onKeyDown:e=>{if(e.key==='Enter'){updateTrackName(vTrack.id,editNameInput||vTrack.name);setEditingTrackName(null);}if(e.key==='Escape')setEditingTrackName(null);},onClick:e=>e.stopPropagation(),className:"text-xs font-semibold bg-black text-zinc-200 border border-cyan-500 rounded px-1 py-0 w-24 outline-none"}):/*#__PURE__*/React.createElement("span",{className:"text-xs font-semibold text-zinc-300 truncate max-w-[80px] cursor-text hover:text-cyan-300 transition-colors",title:"Click to rename",onClick:e=>{e.stopPropagation();setEditingTrackName(vTrack.id);setEditNameInput(vTrack.name);}},vTrack.name)),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackMute(vTrack.id);},className:`px-1.5 py-0.5 text-xs rounded font-mono font-bold border ${vTrack.muted?'bg-red-950 text-red-400 border-red-700':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},"M"),/*#__PURE__*/React.createElement("button",{onClick:e=>{e.stopPropagation();toggleTrackSoloEvaluate(vTrack.id);},className:`px-1.5 py-0.5 text-xs rounded font-mono font-bold border ${soloedTrackId===vTrack.id||vTrack.solo?'bg-amber-950 text-amber-400 border-amber-600':'bg-zinc-800 text-zinc-400 border-transparent hover:text-zinc-200'}`},"S"))),/*#__PURE__*/React.createElement("div",{className:"flex flex-col gap-2.5 text-[14px] mb-3"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Vol:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-50",max:"7",step:"0.5",id:`tcp-vol-${st.id}`,value:vTrack.volumeDb??0,onChange:e=>updateTrackVolumeDb(vTrack.id,parseFloat(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-cyan-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-16 text-right font-mono text-zinc-300 text-[14px]",id:`tcp-vol-label-${st.id}`},vTrack.volumeDb??0,"dB")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Pan:"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-100",max:"100",step:"1",id:`tcp-pan-${st.id}`,value:vTrack.pan??0,onChange:e=>updateTrackPan(vTrack.id,parseInt(e.target.value)),className:"flex-1 h-1 bg-zinc-700 rounded-lg appearance-none cursor-pointer accent-purple-500",style:{height:'4px'}}),/*#__PURE__*/React.createElement("span",{className:"w-16 text-right font-mono text-zinc-300 text-[14px]",id:`tcp-pan-label-detailed-${st.id}`},vTrack.pan>0?'R'+vTrack.pan:vTrack.pan<0?'L'+Math.abs(vTrack.pan):'C')),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-1.5 text-[14px]"},/*#__PURE__*/React.createElement("button",{onClick:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,isLooping:!s.isLooping}:s)),className:`px-2 py-0.5 text-[14px] rounded border font-bold ${st.isLooping?'bg-amber-700 text-white border-amber-500':'bg-zinc-800 text-zinc-400 border-zinc-700'}`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("button",{onClick:()=>updateSubTabEffects(st.id,{reverse:!(st.effects||{}).reverse}),className:`px-2 py-0.5 rounded border text-[14px] font-bold ${(st.effects||{}).reverse?'bg-zinc-600 text-white border-zinc-500':'bg-zinc-800 text-zinc-400 border-zinc-700'} flex items-center justify-center`,title:"Reverse"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"arrow-left-right",className:"w-3.5 h-3.5"}))),/*#__PURE__*/React.createElement("span",{className:"w-10 text-right text-zinc-500 text-[14px]"},"Loop:"),/*#__PURE__*/React.createElement("input",{type:"number",min:"0",max:"999",value:st.loopCount||0,onChange:e=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,loopCount:Math.max(0,parseInt(e.target.value)||0)}:s)),className:"w-12 bg-black text-amber-300 text-[14px] px-1 py-0.5 rounded border border-zinc-700 text-center font-mono",title:"Loop count"}))),/*#__PURE__*/React.createElement("div",{className:"flex gap-1 justify-between my-2.5"},/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Normalize"},"Norm"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"0",step:"0.1",value:subTabNormVal,onChange:e=>setSubTabNormVal(parseFloat(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabNormVal,"dB"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'normalize',subTabNormVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply")),/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Pitch Shift"},"Pitch"),/*#__PURE__*/React.createElement("input",{type:"range",min:"-12",max:"12",step:"0.5",value:subTabPitchVal,onChange:e=>setSubTabPitchVal(parseFloat(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabPitchVal>0?'+':'',subTabPitchVal,"st"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'pitch',subTabPitchVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply")),/*#__PURE__*/React.createElement("div",{className:"flex flex-col items-center bg-zinc-900/60 p-1.5 rounded border border-zinc-800 flex-1"},/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-bold text-zinc-400 uppercase tracking-tighter",title:"Gain Multiplier"},"Gain"),/*#__PURE__*/React.createElement("input",{type:"range",min:"0",max:"150",step:"1",value:subTabGainVal,onChange:e=>setSubTabGainVal(parseInt(e.target.value)),style:{writingMode:'vertical-lr',direction:'rtl',height:'120px',width:'20px',accentColor:'#a1a1aa'},className:"my-2 cursor-pointer"}),/*#__PURE__*/React.createElement("span",{className:"text-[14px] font-mono text-zinc-300 font-bold"},subTabGainVal,"%"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTabEffect(st.id,'gain',subTabGainVal),className:"mt-1.5 px-1 py-1 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 rounded text-[14px] font-bold w-full uppercase border border-zinc-650"},"Apply"))),/*#__PURE__*/React.createElement("div",{className:"flex-1"}),/*#__PURE__*/React.createElement("div",{className:"mt-auto pt-2.5 border-t border-zinc-800"},/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between text-[14px] text-zinc-500 mb-1 font-semibold uppercase"},/*#__PURE__*/React.createElement("span",null,"Duration:"),/*#__PURE__*/React.createElement("span",{className:"font-mono text-zinc-300"},st.buffer?formatTime(st.buffer.duration):'0s')),/*#__PURE__*/React.createElement("div",{className:"flex items-center justify-between text-[14px] text-zinc-500 mb-2.5 font-semibold uppercase"},/*#__PURE__*/React.createElement("span",null,"SR:"),/*#__PURE__*/React.createElement("span",{className:"font-mono text-zinc-300"},st.buffer?st.buffer.sampleRate:0," Hz")),/*#__PURE__*/React.createElement("div",{className:"grid grid-cols-2 gap-1 mb-2"},/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;handleAIScan();},disabled:analysisState.isRunning,className:"py-1 bg-purple-900 hover:bg-purple-800 text-purple-100 font-bold rounded text-xs border border-purple-700 flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"map-pin",className:"w-3 h-3"}))," Scan"),/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;handleAICutToNewTrack();},disabled:analysisState.isRunning,className:"py-1 bg-fuchsia-800 hover:bg-fuchsia-700 text-white font-bold rounded text-xs flex items-center justify-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3 h-3"}))," Cut"),/*#__PURE__*/React.createElement("button",{onClick:async e=>{subTabAiTrackIdRef.current=st.trackId;if(st.buffer){setSelectionRangeOnBuffer(st.buffer,st.selectionStart||0,st.selectionEnd||st.buffer.duration);}handleAIAnalysicLoop();},disabled:analysisState.isRunning,className:"py-1 bg-violet-800 hover:bg-violet-700 text-violet-100 font-bold rounded text-xs border border-violet-600 flex items-center justify-center gap-1 col-span-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sparkles",className:"w-3 h-3"}))," AI Analysic Loop")),/*#__PURE__*/React.createElement("button",{onClick:()=>exportSubTabBuffer(st.id),className:"w-full py-1.5 mb-1.5 bg-blue-700 hover:bg-blue-600 text-white font-bold rounded text-[14px] flex items-center justify-center gap-1 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"download",className:"w-4 h-4"}))," Export"),/*#__PURE__*/React.createElement("button",{onClick:()=>applySubTab(st.id),className:"w-full py-1.5 bg-emerald-700 hover:bg-emerald-600 text-white font-bold rounded text-[14px] flex items-center justify-center gap-1 transition"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-4 h-4"}))," Save"))):/*#__PURE__*/React.createElement("div",{className:"flex-1 flex items-center justify-center text-xs text-zinc-500"},"Track not found")),/*#__PURE__*/React.createElement("div",{ref:handleTimelineWrapperRef,className:"flex-1 relative z-10 overflow-x-auto overflow-y-auto min-w-0"},/*#__PURE__*/React.createElement("div",{style:{width:`${subTabTimelineWidth}px`},className:"relative flex flex-col min-h-full"},/*#__PURE__*/React.createElement("div",{className:"sticky top-0 z-45 flex h-10 border-b border-zinc-900 bg-[#242424] shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 relative h-full flex items-center select-none cursor-ew-resize overflow-hidden",onMouseDown:handleRulerMouseDown},Array.from({length:Math.ceil(st.buffer?st.buffer.duration:0)}).map((_,i)=>{const sec=i;const x=sec*zoom;return/*#__PURE__*/React.createElement("div",{key:i,className:"absolute h-full border-l border-zinc-700 pl-1 pt-1 text-[14px] font-mono text-zinc-300 pointer-events-none",style:{left:`${x}px`}},formatTimeSimple(sec));}))),/*#__PURE__*/React.createElement("div",{className:"sticky top-10 z-35 flex h-[40px] border-b border-purple-500/30 bg-[#1a1a2e] shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex-1 relative h-full overflow-hidden bg-[#1a1a2e]"},/*#__PURE__*/React.createElement(TempoTrackLane,{bpm:parseInt(bpm)||120,zoom:zoom,timelineWidth:subTabTimelineWidth,onPlayheadSet:setCurrentTime,snapValue:snapValue}))),/*#__PURE__*/React.createElement("div",{className:"flex-1 flex flex-col relative bg-[#111111] min-h-full"},vTrack&&/*#__PURE__*/React.createElement("div",{style:{height:`${subTabHeight}px`},className:"relative overflow-hidden border-2 border-purple-500/40 rounded bg-[#151515] mx-1 mt-1 shrink-0"},/*#__PURE__*/React.createElement(SubTabWaveform,{buffer:st.buffer,subTabId:st.id,activeTab:activeTab,activeTool:activeTool,currentTime:st.currentTime,selectionStart:st.selectionStart,selectionEnd:st.selectionEnd,onSelectRange:(start,end)=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,selectionStart:start,selectionEnd:end}:s)),onPlayheadSet:time=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,currentTime:time}:s)),onContextMenu:(e,clickTime)=>setContextMenu({x:e.clientX,y:e.clientY,isSubTab:true,subTabId:st.id,time:clickTime}),zoom:zoom,timelineWidth:subTabTimelineWidth,color:vTrack.color,name:vTrack.name,speed:st.speed||1.0,volumeNodes:st.volumeNodes||[],panningNodes:st.panningNodes||[],fadeInLen:st.fadeInLen||0,fadeOutLen:st.fadeOutLen||0,graphMode:st.graphMode,channelInfo:st.channelInfo,selectedNodeTime:subTabSelectedNodeTime,setSelectedNodeTime:setSubTabSelectedNodeTime,onUpdateNodes:nodes=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,[s.graphMode==='pan'?'panningNodes':'volumeNodes']:nodes}:s)),onUpdateFade:fade=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,fadeInLen:fade.fadeInLen??s.fadeInLen,fadeOutLen:fade.fadeOutLen??s.fadeOutLen}:s)),onModeToggle:()=>setSubTabs(prev=>prev.map(s=>s.id===st.id?{...s,graphMode:s.graphMode==='pan'?null:'pan'}:s)),onSpeedChange:newSpeed=>{setSubTabs(prev=>prev.map(s=>{if(s.id!==st.id)return s;const oldSpeed=s.speed||1.0;const ratio=oldSpeed/newSpeed;const newVolumeNodes=(s.volumeNodes||[]).map(n=>({...n,time:n.time*ratio}));const newPanningNodes=(s.panningNodes||[]).map(n=>({...n,time:n.time*ratio}));return{...s,speed:newSpeed,volumeNodes:newVolumeNodes,panningNodes:newPanningNodes,fadeInLen:(s.fadeInLen||0)*ratio,fadeOutLen:(s.fadeOutLen||0)*ratio,currentTime:(s.currentTime||0)*ratio,label:s.label.replace(/\s\(\d+%\)$/,'')+` (${Math.round(newSpeed*100)}%)`};}));const n=activeTrackNodesRef.current[st.trackId];if(n&&n.source)n.source.playbackRate.value=newSpeed;// Reset time refs to prevent playhead jump when speed changes mid-playback +const ctx=getAudioContext();const elapsed=ctx.currentTime-startAudioTimeRef.current;const oldSpeed=activePlaybackSpeedRef.current;const ratio=oldSpeed/newSpeed;startBufferOffsetRef.current=startBufferOffsetRef.current+elapsed*oldSpeed;startOffsetTimeRef.current=(startOffsetTimeRef.current+elapsed)*ratio;startAudioTimeRef.current=ctx.currentTime;activePlaybackSpeedRef.current=newSpeed;}}),/*#__PURE__*/React.createElement("div",{onMouseDown:handleSubTabResizeMouseDown,className:"absolute bottom-0 left-0 right-0 h-1.5 cursor-ns-resize z-30 hover:bg-purple-500/50 transition-colors"})),st.selectionStart!==null&&st.selectionEnd!==null&&st.selectionEnd>st.selectionStart&&/*#__PURE__*/React.createElement("div",{className:"absolute top-0 bottom-0 border-l border-r border-amber-500 bg-amber-500/10 z-20 pointer-events-none",style:{left:`${Math.min(st.selectionStart,st.selectionEnd)*zoom}px`,width:`${Math.abs(st.selectionEnd-st.selectionStart)*zoom}px`}})))));})())),/*#__PURE__*/React.createElement("div",{className:"w-1 cursor-ew-resize hover:bg-cyan-500/50 active:bg-cyan-400 transition-colors shrink-0 z-10",onMouseDown:startColResize}),renderDock('right','Right')),renderDock('bottom','Bottom'));})(),/*#__PURE__*/React.createElement("div",{className:"h-6 bg-[#141414] border-t border-zinc-900 px-4 flex items-center justify-between text-xs text-zinc-500 select-none shrink-0"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-4"},/*#__PURE__*/React.createElement("span",null,"Status: ",isPlaying?'Playing':'Stopped'),activeTab!=='main'&&/*#__PURE__*/React.createElement("span",{className:"text-amber-400 font-semibold uppercase"},"Sub-Tab"),activeTab==='main'&&/*#__PURE__*/React.createElement("span",{className:"text-cyan-400 font-semibold uppercase"},"Track: ID ",selectedTrackId),selectionMode==='local'&&/*#__PURE__*/React.createElement("span",{className:"text-amber-400 font-semibold uppercase text-xs"},"Local Sel"),selectionMode==='global'&&/*#__PURE__*/React.createElement("span",{className:"text-purple-400 font-semibold uppercase text-xs"},"Global Sel"),soloedTrackId&&/*#__PURE__*/React.createElement("span",{className:"text-amber-500 font-semibold"},"Solo: ID ",soloedTrackId),isLoopingSelection&&selectionMode==='local'&&/*#__PURE__*/React.createElement("span",{className:"text-emerald-400 font-semibold uppercase text-xs"},"Solo Loop"),isLoopingSelection&&selectionMode!=='local'&&/*#__PURE__*/React.createElement("span",{className:"text-cyan-400 font-semibold uppercase text-xs"},"Master Loop")),/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2"},/*#__PURE__*/React.createElement("button",{onClick:()=>setShowExportPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showExportPanel?'bg-cyan-900 text-cyan-300':'text-zinc-500 hover:text-zinc-300'}`,title:`Export Panel (${panelPositions.export})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"save",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showExportPanel?panelPositions.export[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowSelectionPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showSelectionPanel?'bg-amber-900 text-amber-300':'text-zinc-500 hover:text-zinc-300'}`,title:`Selection Panel (${panelPositions.selection})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showSelectionPanel?panelPositions.selection[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowAIPanel(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showAIPanel?'bg-purple-900 text-purple-300':'text-zinc-500 hover:text-zinc-300'}`,title:`AI Panel (${panelPositions.ai})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"cpu",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showAIPanel?panelPositions.ai[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowFxRack(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showFxRack?'bg-rose-900 text-rose-300':'text-zinc-500 hover:text-zinc-300'}`,title:`FX Rack Panel (${panelPositions.fx_rack||'bottom'})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"sliders",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showFxRack?(panelPositions.fx_rack||'bottom')[0].toUpperCase():'')),/*#__PURE__*/React.createElement("button",{onClick:()=>setShowMidiEvents(p=>!p),className:`px-1.5 py-0.5 rounded text-xs font-semibold transition flex items-center gap-1 ${showMidiEvents?'bg-sky-900 text-sky-300':'text-zinc-500 hover:text-zinc-300'}`,title:`MIDI Events Panel (${panelPositions.midi_events||'bottom'})`},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"music",className:"w-3 h-3"})),/*#__PURE__*/React.createElement("span",{className:"text-[7px] opacity-60"},showMidiEvents?(panelPositions.midi_events||'bottom')[0].toUpperCase():'')),/*#__PURE__*/React.createElement("span",{className:"w-[1px] h-3 bg-zinc-800 mx-1"}),/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"info",className:"w-3 h-3 text-zinc-600"}))," Scroll: Zoom"),/*#__PURE__*/React.createElement("span",null,"|"),/*#__PURE__*/React.createElement("span",{className:"flex items-center gap-1"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"keyboard",className:"w-3 h-3 text-zinc-600"}))," Ctrl+Scroll: Playhead"))),contextMenu&&(contextMenu.isSubTab?/*#__PURE__*/React.createElement("div",{className:"fixed z-[60] bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 w-64",style:{left:contextMenu.x,top:contextMenu.y},onClick:e=>e.stopPropagation()},/*#__PURE__*/React.createElement("div",{className:"px-3 py-1 text-xs text-zinc-500 font-bold uppercase border-b border-zinc-800 pb-1 mb-1"},"Selection: ",formatTime(subTabs.find(s=>s.id===contextMenu.subTabId)?.selectionStart||0)," - ",formatTime(subTabs.find(s=>s.id===contextMenu.subTabId)?.selectionEnd||0)),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabCut(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-rose-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Cut"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+X")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabCopy(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5 text-zinc-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Copy"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+C")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabPaste(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5 text-emerald-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Paste"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+V")),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabDelete(contextMenu.subTabId);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3.5 h-3.5 text-red-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Delete Selected Segment"),/*#__PURE__*/React.createElement("span",{className:"text-amber-400 text-xs font-semibold font-mono ml-auto"},"Del")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:()=>{handleSubTabLoop(contextMenu.subTabId,4);closeContextMenu();},className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"repeat",className:"w-3.5 h-3.5 text-cyan-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Loop Selection 4 times"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto"},"Ctrl+L"))):/*#__PURE__*/React.createElement("div",{className:"fixed z-[60] bg-[#2a2a2a] border border-zinc-700 rounded-lg shadow-2xl py-1 w-64",style:{left:contextMenu.x,top:contextMenu.y},onClick:e=>e.stopPropagation()},contextMenu.sectionId?/*#__PURE__*/React.createElement("button",{onClick:contextMenuEditSection,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-edit",className:"w-3.5 h-3.5 text-amber-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Edit Section"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+E")):/*#__PURE__*/React.createElement("button",{onClick:contextMenuEdit,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"file-edit",className:"w-3.5 h-3.5 text-amber-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Edit"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+E")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuSplit,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-cyan-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Split"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"S")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuMerge,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"combine",className:"w-3.5 h-3.5 text-purple-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Merge"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+M")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:contextMenuCopy,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"copy",className:"w-3.5 h-3.5 text-zinc-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Copy"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+C")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuCut,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"scissors",className:"w-3.5 h-3.5 text-rose-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Cut"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+X")),/*#__PURE__*/React.createElement("button",{onClick:contextMenuPaste,className:"w-full px-3 py-1.5 text-xs text-zinc-200 hover:bg-zinc-700 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"clipboard",className:"w-3.5 h-3.5 text-emerald-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Paste"),/*#__PURE__*/React.createElement("span",{className:"text-purple-400 text-xs font-semibold font-mono ml-auto pl-8"},"Ctrl+V")),/*#__PURE__*/React.createElement("div",{className:"h-px bg-zinc-700 my-1"}),/*#__PURE__*/React.createElement("button",{onClick:contextMenuDelete,className:"w-full px-3 py-1.5 text-xs text-red-300 hover:bg-red-950 text-left flex items-center gap-2"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"trash-2",className:"w-3.5 h-3.5 text-red-400 shrink-0"})),/*#__PURE__*/React.createElement("span",{className:"flex-1"},"Delete"),/*#__PURE__*/React.createElement("span",{className:"text-amber-400 text-xs font-semibold font-mono ml-auto pl-8"},"Del")))),toastMessage&&/*#__PURE__*/React.createElement("div",{className:"absolute top-14 right-4 z-50 px-4 py-2.5 rounded shadow-lg text-xs font-semibold flex items-center gap-2 border bg-zinc-900 text-zinc-100 border-zinc-800"},/*#__PURE__*/React.createElement("span",{className:"inline-flex items-center shrink-0"},/*#__PURE__*/React.createElement("i",{"data-lucide":"bell",className:`w-4 h-4 ${toastMessage.type==='success'?'text-emerald-400':toastMessage.type==='error'?'text-rose-400':toastMessage.type==='warning'?'text-amber-400':'text-cyan-400'}`})),toastMessage.text,toastMessage.onActionClick&&/*#__PURE__*/React.createElement("button",{onClick:()=>{toastMessage.onActionClick();setToastMessage(null);},className:"ml-2 px-2 py-0.5 bg-purple-700 hover:bg-purple-600 text-white rounded text-[10px] uppercase font-bold"},toastMessage.actionText||'Tải về'))),appWarningModal&&/*#__PURE__*/React.createElement("div",{className:"fixed inset-0 z-[100] flex items-center justify-center bg-black/60 backdrop-blur-sm"},/*#__PURE__*/React.createElement("div",{className:"bg-[#222222] border border-zinc-800 rounded-lg shadow-2xl p-6 max-w-md w-full text-slate-200"},/*#__PURE__*/React.createElement("div",{className:"flex items-center gap-2 mb-3 text-cyan-400 font-bold"},/*#__PURE__*/React.createElement("h3",{className:"text-base font-bold"},appWarningModal.title)),/*#__PURE__*/React.createElement("div",{className:"text-xs text-slate-300 mb-5 leading-relaxed whitespace-pre-line"},appWarningModal.message),/*#__PURE__*/React.createElement("div",{className:"flex justify-end gap-2"},appWarningModal.isAlert?/*#__PURE__*/React.createElement("button",{onClick:()=>setAppWarningModal(null),className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 active:bg-cyan-700 text-white rounded text-xs font-semibold transition"},"Đóng"):/*#__PURE__*/React.createElement(React.Fragment,null,/*#__PURE__*/React.createElement("button",{onClick:()=>setAppWarningModal(null),className:"px-4 py-2 bg-zinc-700 hover:bg-zinc-600 active:bg-zinc-800 text-slate-300 rounded text-xs font-semibold transition"},"Hủy"),/*#__PURE__*/React.createElement("button",{onClick:()=>{const fn=appWarningModal.onConfirm;setAppWarningModal(null);if(fn)fn();},className:"px-4 py-2 bg-cyan-600 hover:bg-cyan-500 active:bg-cyan-700 text-white rounded text-xs font-semibold transition"},"Xác nhận"))))),/*#__PURE__*/React.createElement(AuthModal,{isOpen:authModalOpen,mode:authMode,forceMandatory:isMandatoryLogin,onClose:()=>setAuthModalOpen(false),onSuccess:handleAuthSuccess}),/*#__PURE__*/React.createElement(ProfileModal,{isOpen:profileModalOpen,onClose:()=>setProfileModalOpen(false),tracks:tracks,setTracks:setTracks,setSelectedTrackId:setSelectedTrackId,projectName:projectName,setProjectName:setProjectName,currentProjectId:currentProjectId,setCurrentProjectId:setCurrentProjectId,showToast:showToast}),/*#__PURE__*/React.createElement(SaveProjectModal,{isOpen:saveProjectModalOpen,onClose:()=>setSaveProjectModalOpen(false),onSave:newName=>{handleSaveProjectWithName(newName);}}),/*#__PURE__*/React.createElement(SaveAsModal,{isOpen:saveAsModalOpen,onClose:()=>setSaveAsModalOpen(false),projectName:projectName,onSaveCloud:newName=>{handleSaveAsCloud(newName);},onSaveLocal:newName=>{handleExportSFS(newName);setProjectName(newName);localStorage.setItem('sonic_project_name',newName);}}),/*#__PURE__*/React.createElement(AIConfigModal,{isOpen:aiConfigModalOpen,onClose:()=>setAiConfigModalOpen(false),onConfigSaved:providers=>{setAiProviders(providers);const active=providers.find(p=>p.is_active)||providers[0];if(active)setSelectedProviderId(active.id);}}),/*#__PURE__*/React.createElement(SystemManagerModal,{isOpen:systemManagerModalOpen,onClose:()=>setSystemManagerModalOpen(false)}),/*#__PURE__*/React.createElement(PluginManagerModal,{isOpen:pluginManagerModalOpen,onClose:()=>setPluginManagerModalOpen(false),pluginsData:pluginsData}),/*#__PURE__*/React.createElement(AIPresetModal,{isOpen:aiPresetModalOpen,onClose:()=>setAiPresetModalOpen(false)}));};const root=ReactDOM.createRoot(document.getElementById('root'));root.render(/*#__PURE__*/React.createElement(App,null));setTimeout(()=>lucide.createIcons(),300); diff --git a/app/storage/sonicforge.db b/app/storage/sonicforge.db index 13b8d005efc3b12bc8ba236034db67f00162e9a3..98bb9e7265d5a70470e548db3350dede0026086c 100644 GIT binary patch delta 424 zcmZp8z|`=7X~P9Mm83Mwq?9BRBVB`}R0~}bBcmkUL?aV(UE>r>Q`6*R1M@Uf!^vOd za?NU{o!_~iLz{y!5aMp uVoYTGBB0I463WC#j2AQ*9O&Wpf@D7CrAn@w)9R)&verzyQ1Eb3g8=~ai*t4W delta 424 zcmZp8z|`=7X~P9M6%!+4%OtZTGhJiDq(og4Gb3Z&BntyeT}uN?(^LcF6jM_Z^T}W2 za?L81ymi-T6ldfL6}N8W73XBqPSG_nFfajXwKUUBGBh_#GP5u- zH8V__JY7CTuwqG;%3m%91_mbn^$h&$`EP6%G+4|ZsKFe{NR0JN>dc`;S+>bwjeY_# tCNh2z&}L)_Wnv`83mOa#^l*DYG9R;S=Dp2nbyFExE0(-76