fix: sửa copilot không gửi AI provider 2

This commit is contained in:
2026-07-22 17:01:41 +07:00
parent 8a85dd2dfc
commit d6fe1326c5
5 changed files with 205 additions and 329 deletions
+67 -48
View File
@@ -3031,6 +3031,7 @@ const App = () => {
const [numberBar, setNumberBar] = useState(1);
const [subTabHeight, setSubTabHeight] = useState(96);
const [isExporting, setIsExporting] = useState(false);
const [projectName, setProjectName] = useState(() => localStorage.getItem('sonic_project_name') || '');
const [soloedTrackId, setSoloedTrackId] = useState(null);
const [toastMessage, setToastMessage] = useState(null);
const [showAIConfig, setShowAIConfig] = useState(false);
@@ -3048,7 +3049,7 @@ const App = () => {
ai: 'right',
python_tools: 'bottom',
selection: 'bottom',
media_explorer: 'right',
media_explorer: 'bottom',
fx_rack: 'bottom',
midi_events: 'bottom'
});
@@ -3952,6 +3953,11 @@ const App = () => {
return;
}
}
if (ctrl && !alt && e.key === 's') {
e.preventDefault();
handleSaveProject();
return;
}
if (!ctrl && !alt && e.key === 's') {
e.preventDefault();
handleSplitTrack(selectedTrackId);
@@ -6338,6 +6344,19 @@ const App = () => {
clientSideExport(exportTracks);
}
};
const handleSaveProject = async () => {
if (!currentUser) { setIsMandatoryLogin(false); setAuthMode('login'); setAuthModalOpen(true); return; }
let name = projectName;
if (!name) { name = prompt("Nhập tên dự án:", "Dự án SonicForge"); if (!name) return; }
setProjectName(name);
localStorage.setItem('sonic_project_name', name);
const ss = 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 }));
try {
const dataJson = JSON.stringify({ id: 'project_' + Date.now(), name, tracks: ss(tracks) });
await window.SonicAPI.saveCloudProject(name, dataJson);
showToast(`Đã lưu "${name}" lên server!`, "success");
} catch (err) { showToast(err.message || "Lỗi lưu server", "error"); }
};
const handleSaveCloud = async () => {
if (!currentUser) {
setIsMandatoryLogin(false);
@@ -7788,18 +7807,14 @@ const App = () => {
action: () => handleImportSFS()
}, {
label: 'Save Project',
icon: 'save',
icon: 'upload-cloud',
shortcut: 'Ctrl+S',
action: () => handleExportSFS()
action: () => handleSaveProject()
}, {
label: 'Save As...',
icon: 'save',
icon: 'download',
shortcut: 'Ctrl+Alt+S',
action: () => handleExportSFS()
}, {
label: 'Save to Cloud',
icon: 'upload-cloud',
action: () => handleSaveCloud()
}, {
sep: true
}, {
@@ -8479,7 +8494,7 @@ const App = () => {
addPanel('ai', panelPositions.ai, showAIPanel);
addPanel('python_tools', panelPositions.python_tools || 'bottom', showPythonToolsPanel);
addPanel('selection', panelPositions.selection, showSelectionPanel);
addPanel('media_explorer', panelPositions.media_explorer || 'right', showMediaExplorer);
addPanel('media_explorer', 'bottom', showMediaExplorer);
addPanel('fx_rack', panelPositions.fx_rack || 'bottom', showFxRack);
addPanel('midi_events', panelPositions.midi_events || 'bottom', showMidiEvents);
const closePanel = id => {
@@ -8575,7 +8590,7 @@ const App = () => {
className: "w-3 h-3"
})), isExporting ? '...' : 'Export'));
if (panelId === 'ai') return /*#__PURE__*/React.createElement("div", {
className: "flex flex-col h-full gap-1.5"
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)
@@ -8630,6 +8645,43 @@ const App = () => {
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", {
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"
@@ -8666,8 +8718,8 @@ const App = () => {
}
}
}
}), /*#__PURE__*/React.createElement("div", {
className: "flex items-center gap-1 mt-1"
})), /*#__PURE__*/React.createElement("div", {
className: "flex items-center gap-1 mt-1 shrink-0"
}, /*#__PURE__*/React.createElement("button", {
onClick: handleAISend,
disabled: aiProcessing,
@@ -8684,38 +8736,8 @@ const App = () => {
},
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 mt-0.5"
}, "Enter để gửi nhanh")), /*#__PURE__*/React.createElement("div", {
className: "border-t border-zinc-800 pt-1 mt-1 flex-1 min-h-0 flex flex-col overflow-hidden"
}, /*#__PURE__*/React.createElement("div", {
className: "text-[10px] font-bold text-zinc-400 uppercase flex items-center justify-between 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"), aiActionLog.length > 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: "text-[10px] text-amber-400 hover:text-amber-300 border border-amber-800 rounded px-1 py-0"
}, "Undo"))), /*#__PURE__*/React.createElement("div", {
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))));
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", {
@@ -8950,10 +8972,7 @@ const App = () => {
}, panels.map((p, idx) => /*#__PURE__*/React.createElement(React.Fragment, {
key: p
}, /*#__PURE__*/React.createElement("div", {
className: `${p === 'media_explorer' ? 'flex-shrink-0' : 'flex-1 min-h-0'} border border-zinc-700 rounded-lg bg-[#262626] shadow-sm`,
style: p === 'media_explorer' ? {
height: `${mediaExplorerHeight}%`
} : {}
className: 'flex flex-col flex-1 min-h-0 border border-zinc-700 rounded-lg bg-[#262626] shadow-sm'
}, renderPanelContent(p)), idx < panels.length - 1 && /*#__PURE__*/React.createElement("div", {
className: "h-1.5 cursor-ns-resize hover:bg-cyan-500/50 transition-colors rounded shrink-0",
onMouseDown: startRowResize