fix: Window Explorer liệt kê ổ đĩa thật + xử lý lỗi API

This commit is contained in:
2026-08-02 14:27:03 +07:00
parent d1995307f5
commit 1989bfb105
5 changed files with 79 additions and 27 deletions
+27 -14
View File
@@ -9045,7 +9045,8 @@ const MediaExplorerPanel = ({ height }) => {
const fileDuration = f => {
if (!f) return 0;
if (isMidiFile(f)) return (f.lengthQn || 16) * 60 / (f.bpm || 120);
return f.duration || (audioBuffer && selected && (selected.file_id || selected.fileId) === (f.file_id || f.fileId) ? audioBuffer.duration : 0) || 0;
const matches = selected && ((f.path && f.path === selected.path) || (!f.path && (f.file_id || f.fileId) === (selected.file_id || selected.fileId)));
return f.duration || (audioBuffer && matches ? audioBuffer.duration : 0) || 0;
};
const folderFiles = React.useMemo(() => {
@@ -9097,18 +9098,26 @@ const MediaExplorerPanel = ({ height }) => {
const openMyComputer = async () => {
setFolder('computer');
if (!computerRoots) {
try {
const resp = await fetch(`${API_BASE_URL}/api/v1/media/computer`);
const data = await resp.json();
setComputerRoots(data.roots || []);
} catch (e) { setComputerRoots([]); }
if (computerRoots) return;
setComputerRoots(null);
try {
const resp = await fetch(`${API_BASE_URL}/api/v1/media/computer`);
if (!resp.ok) throw new Error('HTTP ' + resp.status);
const data = await resp.json();
const roots = data.roots || [];
setComputerRoots(roots.length ? roots : [{ path: '/', name: 'Root (/)', is_dir: true }]);
if (!roots.length) window.showToast && window.showToast('Không tìm thấy ổ đĩa nào', 'warning');
} catch (e) {
setComputerRoots([{ path: '/', name: 'Root (/)', is_dir: true }]);
window.showToast && window.showToast('Không thể truy cập My Computer: ' + e.message, 'error');
}
};
const browseComputerDir = async (path) => {
if (!path) return;
try {
const resp = await fetch(`${API_BASE_URL}/api/v1/media/browse?path=${encodeURIComponent(path)}`);
if (!resp.ok) throw new Error('HTTP ' + resp.status);
const data = await resp.json();
setComputerPath(data.path);
setComputerFiles(data.files || []);
@@ -9117,8 +9126,7 @@ const MediaExplorerPanel = ({ height }) => {
stopMediaPlayback();
setComputerTree(prev => ({ ...prev, [path]: { dirs: data.dirs || [], expanded: true } }));
} catch (e) {
setComputerPath(path);
setComputerFiles([]);
window.showToast && window.showToast('Không thể mở thư mục: ' + e.message, 'error');
}
};
@@ -9133,10 +9141,15 @@ const MediaExplorerPanel = ({ height }) => {
const goComputerParent = () => {
if (!computerPath) return;
const parent = computerPath.split(/[\\/]/).filter(Boolean);
parent.pop();
const parentPath = (parent.length === 0 ? (computerPath.startsWith('/') ? '/' : '') : (computerPath.startsWith('/') ? '/' + parent.join('/') : parent.join('\\')));
browseComputerDir(parentPath);
const isUnix = computerPath.startsWith('/');
const parts = computerPath.split(/[\\/]/).filter(Boolean);
parts.pop();
if (isUnix) {
browseComputerDir(parts.length ? '/' + parts.join('/') : '/');
} else {
// Windows: quay v root đĩa nếu đã lên ti đnh
browseComputerDir(parts.length ? parts.join('\\') : computerPath.split(/[\\/]/)[0] + '\\');
}
};
const filePreviewUrl = (f) => {
@@ -9416,7 +9429,7 @@ const MediaExplorerPanel = ({ height }) => {
return (
<tr key={(f.file_id || f.name) + i} className={`cursor-pointer hover:bg-blue-100 ${isSel ? 'file-row-selected' : ''}`} onClick={() => handleSelect(f)}>
<td className="py-1 px-2"><i className={`fa-solid ${isMidi ? 'fa-music text-purple-600' : 'fa-file-audio text-emerald-600'} mr-2`}></i>{f.name || f.original_name}</td>
{viewMode === 'details' && <td className="py-1 px-2">{f.size_mb != null ? f.size_mb.toFixed(2) + ' MB' : (isMidi ? f.tpqn + ' TPQN' : '-')}</td>}
{viewMode === 'details' && <td className="py-1 px-2">{f.size_mb != null ? f.size_mb.toFixed(2) + ' MB' : (isMidi ? (f.tpqn || 'MIDI') + ' TPQN' : '-')}</td>}
</tr>
);
})}
File diff suppressed because one or more lines are too long