feat(export): modal tien trinh export rieng (khong dung statusbar) - dong modal settings ngay khi bam Export + bao loi that khi khong ghi duoc file
This commit is contained in:
+48
-11
@@ -12628,16 +12628,6 @@ const ExportModal = ({ open, onClose, exportSettings, setExportSettings, isExpor
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="p-4 pt-3 border-t border-slate-700 space-y-2">
|
<div className="p-4 pt-3 border-t border-slate-700 space-y-2">
|
||||||
{isExporting && (
|
|
||||||
<div className="bg-[#141414] border border-zinc-800 rounded px-2 py-1.5">
|
|
||||||
<div className="h-1.5 bg-zinc-800 rounded-full overflow-hidden">
|
|
||||||
<div className="h-full bg-cyan-500 transition-all duration-200" style={{ width: (exportProgress >= 0 ? exportProgress : 25) + '%' }} />
|
|
||||||
</div>
|
|
||||||
<div className="text-[8px] text-zinc-500 mt-1">
|
|
||||||
{exportProgress >= 0 ? 'Đang xuất... ' + Math.round(exportProgress) + '%' : 'Đang xử lý...'}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
<div className="grid grid-cols-2 gap-2">
|
<div className="grid grid-cols-2 gap-2">
|
||||||
<button onClick={onExport} disabled={isExporting}
|
<button onClick={onExport} 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">
|
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">
|
||||||
@@ -12654,6 +12644,38 @@ const ExportModal = ({ open, onClose, exportSettings, setExportSettings, isExpor
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// ── Export progress modal (RIÊNG, không dùng statusbar — vị trí đó cho tools) ──
|
||||||
|
// Settings modal đóng ngay khi bấm Export; modal này hiện tiến trình render +
|
||||||
|
// encode + ghi file, tự đóng khi xong (success/error qua toast).
|
||||||
|
const ExportProgressModal = ({ open, exportProgress, isExporting, onClose }) => {
|
||||||
|
if (!open) return null;
|
||||||
|
return (
|
||||||
|
<div className="fixed inset-0 z-[310] bg-black/70 backdrop-blur-sm flex items-center justify-center p-6">
|
||||||
|
<div className="w-full max-w-md bg-slate-900 border border-slate-700 rounded-2xl shadow-2xl overflow-hidden">
|
||||||
|
<div className="h-9 bg-slate-800/80 border-b border-slate-700 flex items-center justify-between px-3 select-none">
|
||||||
|
<span className="text-xs font-bold text-cyan-300 font-mono flex items-center gap-1.5">
|
||||||
|
<span className="w-3 h-3 border-2 border-cyan-300 border-t-transparent rounded-full animate-spin" />
|
||||||
|
ĐANG XUẤT ÂM THANH
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="p-5 space-y-3">
|
||||||
|
<div className="h-2.5 bg-zinc-800 rounded-full overflow-hidden">
|
||||||
|
<div className="h-full bg-cyan-500 transition-all duration-200" style={{ width: (exportProgress >= 0 ? exportProgress : 25) + '%' }} />
|
||||||
|
</div>
|
||||||
|
<div className="text-xs text-zinc-400 text-center">
|
||||||
|
{exportProgress >= 0 ? 'Đang xuất... ' + Math.round(exportProgress) + '%' : 'Đang xử lý...'}
|
||||||
|
</div>
|
||||||
|
{!isExporting && (
|
||||||
|
<button onClick={onClose} className="w-full py-1.5 bg-zinc-700 hover:bg-zinc-600 text-zinc-100 font-bold rounded text-xs">
|
||||||
|
Đóng
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
// --- Embedded VST GUI (PLAN_MASTERBUS_VST_GUI_EMBED.md) --------------------
|
// --- Embedded VST GUI (PLAN_MASTERBUS_VST_GUI_EMBED.md) --------------------
|
||||||
// Frame-capture + input relay: hiển thị native GUI qua HTTP /frame (~10fps),
|
// Frame-capture + input relay: hiển thị native GUI qua HTTP /frame (~10fps),
|
||||||
// gửi pointer/key về bridge qua /input. Dùng chung MasteringModal + FXRackModal.
|
// gửi pointer/key về bridge qua /input. Dùng chung MasteringModal + FXRackModal.
|
||||||
@@ -18100,6 +18122,7 @@ const App = () => {
|
|||||||
const lastTempCompileTimeRef = useRef(0);
|
const lastTempCompileTimeRef = useRef(0);
|
||||||
const nextMetronomeBeatRef = useRef(0);
|
const nextMetronomeBeatRef = useRef(0);
|
||||||
const [showExportPanel, setShowExportPanel] = useState(false);
|
const [showExportPanel, setShowExportPanel] = useState(false);
|
||||||
|
const [showExportProgress, setShowExportProgress] = useState(false); // modal tiến trình export RIÊNG
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (showExportPanel) setTimeout(() => { try { window.lucide && window.lucide.createIcons(); } catch (e) { } }, 80);
|
if (showExportPanel) setTimeout(() => { try { window.lucide && window.lucide.createIcons(); } catch (e) { } }, 80);
|
||||||
}, [showExportPanel]);
|
}, [showExportPanel]);
|
||||||
@@ -28041,6 +28064,8 @@ const App = () => {
|
|||||||
if (!exportSettings.loop && allOnServer && serverStatus === 'connected') {
|
if (!exportSettings.loop && allOnServer && serverStatus === 'connected') {
|
||||||
// Use server-side export
|
// Use server-side export
|
||||||
setIsExporting(true);
|
setIsExporting(true);
|
||||||
|
setShowExportPanel(false);
|
||||||
|
setShowExportProgress(true);
|
||||||
setExportProgress(-1);
|
setExportProgress(-1);
|
||||||
showToast("Đang gửi yêu cầu xuất âm thanh đến máy chủ...", "info");
|
showToast("Đang gửi yêu cầu xuất âm thanh đến máy chủ...", "info");
|
||||||
try {
|
try {
|
||||||
@@ -28113,6 +28138,7 @@ const App = () => {
|
|||||||
clientSideExport(exportTracks);
|
clientSideExport(exportTracks);
|
||||||
} finally {
|
} finally {
|
||||||
setIsExporting(false);
|
setIsExporting(false);
|
||||||
|
setShowExportProgress(false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Client-side export (existing working code)
|
// Client-side export (existing working code)
|
||||||
@@ -28177,6 +28203,8 @@ const App = () => {
|
|||||||
if (!masterBus) { showToast("Hãy phát thử một lần để khởi tạo audio engine trước.", "warning"); return; }
|
if (!masterBus) { showToast("Hãy phát thử một lần để khởi tạo audio engine trước.", "warning"); return; }
|
||||||
if (isExporting) return;
|
if (isExporting) return;
|
||||||
setIsExporting(true);
|
setIsExporting(true);
|
||||||
|
setShowExportPanel(false);
|
||||||
|
setShowExportProgress(true);
|
||||||
const audioCtx = getAudioContext();
|
const audioCtx = getAudioContext();
|
||||||
try {
|
try {
|
||||||
const allTracks = (activeTracksRef.current && activeTracksRef.current.length) ? activeTracksRef.current : tracks;
|
const allTracks = (activeTracksRef.current && activeTracksRef.current.length) ? activeTracksRef.current : tracks;
|
||||||
@@ -28275,6 +28303,7 @@ const App = () => {
|
|||||||
showToast("Lỗi bounce: " + err.message, "error");
|
showToast("Lỗi bounce: " + err.message, "error");
|
||||||
} finally {
|
} finally {
|
||||||
setIsExporting(false);
|
setIsExporting(false);
|
||||||
|
setShowExportProgress(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
const handleSaveLocalProject = (name) => {
|
const handleSaveLocalProject = (name) => {
|
||||||
@@ -28483,6 +28512,8 @@ const App = () => {
|
|||||||
};
|
};
|
||||||
const clientSideExport = async (activeTracks, loopInfo) => {
|
const clientSideExport = async (activeTracks, loopInfo) => {
|
||||||
setIsExporting(true);
|
setIsExporting(true);
|
||||||
|
setShowExportPanel(false);
|
||||||
|
setShowExportProgress(true);
|
||||||
setExportProgress(5);
|
setExportProgress(5);
|
||||||
showToast("Đang trộn âm thanh đa kênh (Offline Mixdown)...", "info");
|
showToast("Đang trộn âm thanh đa kênh (Offline Mixdown)...", "info");
|
||||||
// Yield 1 frame → React vẽ thanh "Đang xử lý..." trước khi graph build +
|
// Yield 1 frame → React vẽ thanh "Đang xử lý..." trước khi graph build +
|
||||||
@@ -28789,7 +28820,7 @@ const App = () => {
|
|||||||
if (dres && dres.saved_path) {
|
if (dres && dres.saved_path) {
|
||||||
showToast(`Xuất bản âm thanh hoàn tất → ${dres.saved_path}`, "success");
|
showToast(`Xuất bản âm thanh hoàn tất → ${dres.saved_path}`, "success");
|
||||||
} else {
|
} else {
|
||||||
showToast("Xuất bản âm thanh hoàn tất!", "success");
|
showToast("Không thể ghi file export — engine không lưu được file. Kiểm tra kết nối engine và thư mục export.", "error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Export hoàn tất → tự đóng modal.
|
// Export hoàn tất → tự đóng modal.
|
||||||
@@ -28822,6 +28853,7 @@ const App = () => {
|
|||||||
} finally {
|
} finally {
|
||||||
setExportProgress(-1);
|
setExportProgress(-1);
|
||||||
setIsExporting(false);
|
setIsExporting(false);
|
||||||
|
setShowExportProgress(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -34613,6 +34645,11 @@ STRICT CONSTRAINTS:
|
|||||||
onNoteOn: vkbNoteOn,
|
onNoteOn: vkbNoteOn,
|
||||||
onNoteOff: vkbNoteOff,
|
onNoteOff: vkbNoteOff,
|
||||||
bpm: bpm
|
bpm: bpm
|
||||||
|
}), /*#__PURE__*/React.createElement(ExportProgressModal, {
|
||||||
|
open: showExportProgress,
|
||||||
|
exportProgress: exportProgress,
|
||||||
|
isExporting: isExporting,
|
||||||
|
onClose: () => setShowExportProgress(false)
|
||||||
}), /*#__PURE__*/React.createElement(ExportModal, {
|
}), /*#__PURE__*/React.createElement(ExportModal, {
|
||||||
open: showExportPanel,
|
open: showExportPanel,
|
||||||
onClose: () => setShowExportPanel(false),
|
onClose: () => setShowExportPanel(false),
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -51,7 +51,7 @@
|
|||||||
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
|
<script src="/static/js/services/promptTemplateManager.js?v=202607281039"></script>
|
||||||
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
|
<script src="/static/js/services/undoRedoEngine.js?v=202607290941"></script>
|
||||||
<script src="/static/js/services/chordTheory.js?v=202608211300"></script>
|
<script src="/static/js/services/chordTheory.js?v=202608211300"></script>
|
||||||
<script src="/static/js/app.precompiled.js?v=202608240110" defer></script>
|
<script src="/static/js/app.precompiled.js?v=202608231800" defer></script>
|
||||||
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
|
<link rel="stylesheet" href="/static/css/styles.css?v=202607271016">
|
||||||
<style>
|
<style>
|
||||||
:root {
|
:root {
|
||||||
|
|||||||
Reference in New Issue
Block a user