LỖI: màn hình đen khi load

This commit is contained in:
2026-08-08 16:21:00 +07:00
parent 24051a2794
commit 4789f73ae7
12 changed files with 33873 additions and 64 deletions
+69 -21
View File
@@ -4899,7 +4899,6 @@ const AuthModal = ({
onClose,
onSuccess
}) => {
if (!isOpen) return null;
const [activeTab, setActiveTab] = useState(mode || 'login');
const [username, setUsername] = useState('admin');
const [email, setEmail] = useState('');
@@ -4965,6 +4964,10 @@ const AuthModal = ({
};
const isForceMode = activeTab === 'force_change';
const canClose = !forceMandatory && !isForceMode;
// return null SAU tt c hooks (Rules of Hooks bug 10:05: if !isOpen return
// null TRƯC hooks m login ln đu (falsetrue) hook order đi React
// crash unmount MÀN ĐEN)
if (!isOpen) return null;
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", {
@@ -5065,7 +5068,6 @@ const AIConfigModal = ({
onClose,
onConfigSaved
}) => {
if (!isOpen) return null;
const defaultProvidersList = [{
id: 'openai_default',
name: 'OpenAI Official',
@@ -5148,6 +5150,8 @@ const AIConfigModal = ({
} : p));
};
const activeProvider = providers.find(p => p.id === selectedId) || providers[0];
// return null SAU hooks (Rules of Hooks bug 10:05)
if (!isOpen) return null;
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", {
@@ -5280,7 +5284,6 @@ const AIConfigModal = ({
};
const PluginManagerModal = ({ isOpen, onClose, pluginsData }) => {
if (!isOpen) return null;
const [localData, setLocalData] = React.useState(pluginsData);
const [sfUploadStatus, setSfUploadStatus] = React.useState('');
const [sfToDelete, setSfToDelete] = React.useState(null);
@@ -5311,6 +5314,8 @@ const PluginManagerModal = ({ isOpen, onClose, pluginsData }) => {
}
};
const [pmTab, setPmTab] = React.useState('soundfont');
// return null SAU hooks (Rules of Hooks bug 10:05)
if (!isOpen) return null;
return React.createElement('div', {
className: 'fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm',
onClick: onClose
@@ -5548,7 +5553,6 @@ const ProfileModal = ({
setSubTabs,
trackMidiChannelsRef
}) => {
if (!isOpen) return null;
const [activeTab, setActiveTab] = useState('account');
const [profile, setProfile] = useState(null);
const [oldPassword, setOldPassword] = useState('');
@@ -5838,6 +5842,8 @@ const ProfileModal = ({
top: `calc(50% + ${dragOfs.y}px)`,
transform: 'translate(-50%, -50%)'
};
// return null SAU hooks (Rules of Hooks bug 10:05)
if (!isOpen) return null;
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",
@@ -6079,7 +6085,6 @@ const SaveProjectModal = ({
onSaveLocal,
projectName
}) => {
if (!isOpen) return null;
const [name, setName] = useState(projectName || '');
const [saveType, setSaveType] = useState(localStorage.getItem('sonic_token') ? 'cloud' : 'local');
const [cloudProjects, setCloudProjects] = useState([]);
@@ -6105,6 +6110,8 @@ const SaveProjectModal = ({
else { onSaveLocal(name.trim()); onClose(); }
}
};
// return null SAU hooks (Rules of Hooks bug 10:05)
if (!isOpen) return null;
if (confirmOverwriteProject) {
return React.createElement("div", {
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"
@@ -6182,7 +6189,6 @@ const SaveProjectModal = ({
};
const OpenProjectModal = ({ isOpen, onClose, onOpenCloud, onOpenLocal }) => {
if (!isOpen) return null;
const [tab, setTab] = useState('cloud');
const [projects, setProjects] = useState([]);
const [loading, setLoading] = useState(false);
@@ -6196,6 +6202,8 @@ const OpenProjectModal = ({ isOpen, onClose, onOpenCloud, onOpenLocal }) => {
} else { setLoading(false); }
}
}, [isOpen, tab]);
// return null SAU hooks (Rules of Hooks bug 10:05)
if (!isOpen) return null;
return React.createElement("div", {
className: "fixed inset-0 z-50 flex items-center justify-center bg-black/70 backdrop-blur-sm"
}, React.createElement("div", {
@@ -6256,7 +6264,6 @@ const SaveAsModal = ({
onSaveCloud,
onSaveLocal
}) => {
if (!isOpen) return null;
const [name, setName] = useState(projectName || '');
const [saveType, setSaveType] = useState('cloud');
const handleSubmit = (e) => {
@@ -6269,6 +6276,8 @@ const SaveAsModal = ({
}
onClose();
};
// return null SAU hooks (Rules of Hooks bug 10:05)
if (!isOpen) return null;
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", {
@@ -6336,7 +6345,6 @@ const SystemManagerModal = ({
isOpen,
onClose
}) => {
if (!isOpen) return null;
const [users, setUsers] = useState([]);
const [loading, setLoading] = useState(true);
const [msg, setMsg] = useState('');
@@ -6388,6 +6396,8 @@ const SystemManagerModal = ({
setError(err.message || 'Lỗi khi xóa người dùng');
}
};
// return null SAU hooks (Rules of Hooks bug 10:05)
if (!isOpen) return null;
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", {
@@ -6470,7 +6480,6 @@ const SystemManagerModal = ({
};
const AIPresetModal = ({ isOpen, onClose }) => {
if (!isOpen) return null;
const mgrRef = React.useRef(null);
if (!mgrRef.current) mgrRef.current = new window.PromptTemplateManager();
@@ -6688,6 +6697,8 @@ const AIPresetModal = ({ isOpen, onClose }) => {
if (showFavoritesOnly) matchesCategory = matchesCategory && p.is_favorite;
return matchesSearch && matchesCategory;
});
// return null SAU hooks (Rules of Hooks bug 10:05)
if (!isOpen) return null;
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__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"
@@ -10419,12 +10430,10 @@ const FXRackModal = ({ track, onUpdateTrack, onClose }) => {
const eqCurveRef = React.useRef(null);
const scopeStateRef = React.useRef({ L: null, R: null, head: 0, len: 0, tmpL: null, tmpR: null, freq: null });
if (!track) return null;
const chain = track.fxChain || [];
const chain = track ? (track.fxChain || []) : [];
const setChain = (next) => {
if (onUpdateTrack) onUpdateTrack(track.id, { fxChain: next });
if (window.__rebuildTrackFxGraph) window.__rebuildTrackFxGraph(track.id);
if (onUpdateTrack && track) onUpdateTrack(track.id, { fxChain: next });
if (track && window.__rebuildTrackFxGraph) window.__rebuildTrackFxGraph(track.id);
};
const paramsOf = (m) => ({ ...(TRACK_FX_DEFAULTS[m.type] || {}), ...(m.params || {}) });
const setParams = (idx, patch) => {
@@ -10645,6 +10654,8 @@ const FXRackModal = ({ track, onUpdateTrack, onClose }) => {
ctx.fillText('20kHz', w - 38, h - 2);
}, [ap.g1, ap.g2, ap.g3, ap.g4, activeMod]);
if (!track) return null;
return (
<div className="fixed inset-0 z-[115] bg-black/80 backdrop-blur-sm flex items-center justify-center p-4" onClick={onClose}>
<div className="w-full max-w-4xl bg-slate-900 border border-slate-700 rounded-2xl p-5 space-y-4 shadow-2xl flex flex-col max-h-[90vh] text-slate-200" onClick={e => e.stopPropagation()}>
@@ -15546,6 +15557,7 @@ const App = () => {
// 401 bt k m màn login (bug 09:45 màn đen khi token hng/hết hn)
React.useEffect(() => {
window.__onAuthFail = () => {
console.log('[AUTH] __onAuthFail — mở login');
setCurrentUser(null);
setIsMandatoryLogin(true);
setAuthMode('login');
@@ -15553,6 +15565,14 @@ const App = () => {
};
return () => { delete window.__onAuthFail; };
}, []);
// Chn đoán: sau mount root có ni dung không (bug màn đen 10:20)
React.useEffect(() => {
try {
const rootEl = document.getElementById('root');
console.log('[APP] mounted — root children:', rootEl ? rootEl.children.length : -1,
'| authModalOpen:', authModalOpen, '| currentUser:', currentUser ? currentUser.username : null);
} catch (e) { console.log('[APP] diag err', e.message); }
});
const [authMode, setAuthMode] = useState('login'); // 'login' | 'register' | 'force_change'
const [isMandatoryLogin, setIsMandatoryLogin] = useState(false);
const [profileModalOpen, setProfileModalOpen] = useState(false);
@@ -15836,8 +15856,10 @@ const App = () => {
useEffect(() => {
const checkAuthStatus = async () => {
console.log('[AUTH] checkAuthStatus bắt đầu, token=', (localStorage.getItem('sonic_token') || '(rỗng)').slice(0, 12));
const savedToken = localStorage.getItem('sonic_token');
if (!savedToken) {
console.log('[AUTH] không có token → mở login');
setIsMandatoryLogin(true);
setAuthMode('login');
setAuthModalOpen(true);
@@ -15845,6 +15867,7 @@ const App = () => {
}
try {
const profile = await window.SonicAPI.getProfile();
console.log('[AUTH] profile OK:', profile && profile.username);
setCurrentUser(profile);
localStorage.setItem('sonic_user', JSON.stringify(profile));
if (profile.must_change_password) {
@@ -15857,11 +15880,13 @@ const App = () => {
restoreLastSessionProject();
}
} catch (err) {
console.log('[AUTH] profile lỗi:', String((err && err.message) || err).slice(0, 80));
// 401 (token hng/đi SECRET_KEY bug 09:45: dùng cached user vào app
// nhưng mi API 401 màn đen không login) B qua cached m LOGIN.
// detail server: "Thiếu Token xác thc..." / "Token đã hết hn..." (auth.py)
const errMsg = String((err && err.message) || err || '');
const isAuthErr = errMsg.includes('Token') || errMsg.includes('401') || errMsg.includes('Unauthorized') || errMsg.includes('unauthorized') || errMsg.includes('Không xác thực');
console.log('[AUTH] isAuthErr=', isAuthErr, 'errMsg=', errMsg.slice(0, 60));
if (!isAuthErr) {
const cached = localStorage.getItem('sonic_user');
if (cached) {
@@ -25978,6 +26003,7 @@ STRICT CONSTRAINTS:
});
};
console.log('[APP] return UI — bắt đầu render');
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", {
@@ -26854,6 +26880,7 @@ STRICT CONSTRAINTS:
else if (id === 'midi_events') setShowMidiEvents(false);
};
const renderPanelContent = panelId => {
console.log('[FN] renderPanelContent bắt đầu, panel=', panelId);
const h = id => e => {
startPanelDrag(id, e);
};
@@ -27424,6 +27451,7 @@ STRICT CONSTRAINTS:
return null;
};
const renderDock = (pos, title) => {
console.log('[FN] renderDock bắt đầu, pos=', pos);
const panels = dockPanels[pos];
if (panels.length === 0) return null;
const isSide = pos === 'left' || pos === 'right';
@@ -27486,7 +27514,7 @@ STRICT CONSTRAINTS:
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", {
}, "Drop at edge to dock")), renderDock('top', 'Top'), console.log('[SEQ] dock-top xong'), /*#__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"
@@ -28615,7 +28643,7 @@ STRICT CONSTRAINTS:
})())), /*#__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'), showMixer && /*#__PURE__*/React.createElement("div", {
}), renderDock('right', 'Right')), renderDock('bottom', 'Bottom'), console.log('[SEQ] dock-bottom xong'), showMixer && /*#__PURE__*/React.createElement("div", {
className: "flex flex-col border-t border-zinc-700 bg-slate-900 shrink-0 select-none",
style: { height: mixerHeight + 'px' }
}, /*#__PURE__*/React.createElement("div", {
@@ -29123,7 +29151,7 @@ STRICT CONSTRAINTS:
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", {
}, "Del")))), console.log('[SEQ] trước toastMessage'), 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"
@@ -29185,7 +29213,7 @@ STRICT CONSTRAINTS:
handleSetTabColor(tabContextMenu.tabId, tabContextMenu.tabType, color);
setTabContextMenu(null);
}
})))), /*#__PURE__*/React.createElement(AuthModal, {
})))), console.log('[SEQ] trước AuthModal'), /*#__PURE__*/React.createElement(AuthModal, {
isOpen: authModalOpen,
mode: authMode,
forceMandatory: isMandatoryLogin,
@@ -29469,10 +29497,30 @@ STRICT CONSTRAINTS:
}, vstScanning ? "Scanning..." : "Scan")
),
vstScanError && /*#__PURE__*/React.createElement("p", { className: "text-[10px] text-red-400" }, vstScanError),
/*#__PURE__*/React.createElement("p", { className: "text-[10px] text-zinc-600" }, "Windows: C:\\Program Files\\Common Files\\VST3 \u00B7 macOS: /Library/Audio/Plug-Ins/Components \u00B7 Linux: /opt/daw_engine/vst3, ~/.vst3")
/*#__PURE__*/React.createElement("p", { className: "text-[10px] text-zinc-600" }, "Windows: C:\\Program Files\\Common Files\\VST3 · macOS: /Library/Audio/Plug-Ins/Components · Linux: /opt/daw_engine/vst3, ~/.vst3"),
console.log('[SEQ] cuối children — evaluate xong')
)
))
};
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(/*#__PURE__*/React.createElement(App, null));
// Legacy render ĐNG B COMMIT (createRoot/concurrent có vn đ commit trên
// môi trưng này root children 0 dù render chy bug màn đen 10:35)
window.addEventListener('error', function(ev) {
console.log('[GLOBAL-ERR]', ev.message, ev.filename, ev.lineno);
});
window.addEventListener('unhandledrejection', function(ev) {
console.log('[GLOBAL-REJECT]', String(ev.reason && ev.reason.message || ev.reason).slice(0, 200));
});
class ErrorBoundary extends React.Component {
constructor(props) { super(props); this.state = { err: null }; }
static getDerivedStateFromError(err) { return { err: err }; }
componentDidCatch(err, info) { console.log('[BOUNDARY-ERR]', err && err.message, info && info.componentStack ? info.componentStack.slice(0, 300) : ''); }
render() {
if (this.state.err) {
return React.createElement('div', { style: { padding: 20, color: '#fbb', fontFamily: 'monospace', fontSize: 12, whiteSpace: 'pre-wrap' } },
'⚠️ LỖI RENDER: ' + (this.state.err && this.state.err.message) + '\n' + (this.state.err && this.state.err.stack || '').slice(0, 600));
}
return this.props.children;
}
}
ReactDOM.render(React.createElement(ErrorBoundary, null, React.createElement(App, null)), document.getElementById('root'));
setTimeout(() => lucide.createIcons(), 300);