continue work
This commit is contained in:
+160
-44
@@ -1134,14 +1134,28 @@ let currentFileBrowserVolumeId = null;
|
||||
let currentFileBrowserPath = '/';
|
||||
|
||||
function openFileBrowser(volumeId) {
|
||||
console.log('[DEBUG] Opening file browser for volume ID:', volumeId);
|
||||
currentFileBrowserVolumeId = volumeId;
|
||||
currentFileBrowserPath = '/';
|
||||
|
||||
const fileBrowserModal = document.getElementById('fileBrowserModal');
|
||||
if (fileBrowserModal && typeof bootstrap !== 'undefined') {
|
||||
if (!fileBrowserModal) {
|
||||
console.error('[ERROR] File browser modal element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
if (typeof bootstrap === 'undefined') {
|
||||
console.error('[ERROR] Bootstrap is not available');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const modal = new bootstrap.Modal(fileBrowserModal);
|
||||
modal.show();
|
||||
console.log('[DEBUG] File browser modal opened, loading root directory');
|
||||
loadDirectoryContents('/');
|
||||
} catch (error) {
|
||||
console.error('[ERROR] Failed to open file browser modal:', error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1150,7 +1164,12 @@ async function loadDirectoryContents(path) {
|
||||
const fileBrowserContent = document.getElementById('fileBrowserContent');
|
||||
const fileBrowserBreadcrumb = document.getElementById('fileBrowserBreadcrumb');
|
||||
|
||||
if (!fileBrowserContent) return;
|
||||
if (!fileBrowserContent) {
|
||||
console.error('[ERROR] File browser content element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[DEBUG] Loading directory contents for path:', path);
|
||||
|
||||
// Show loading
|
||||
fileBrowserContent.innerHTML = '<div class="text-center p-4"><i class="fas fa-spinner fa-spin"></i> Loading...</div>';
|
||||
@@ -1178,55 +1197,119 @@ async function loadDirectoryContents(path) {
|
||||
}
|
||||
|
||||
try {
|
||||
if (typeof window.sendCommand === 'function') {
|
||||
// Store original handler
|
||||
const originalHandler = window.handlePeerResponse;
|
||||
let directoryReceived = false;
|
||||
if (typeof window.sendCommand !== 'function') {
|
||||
console.error('[ERROR] sendCommand function not available');
|
||||
fileBrowserContent.innerHTML = '<div class="alert alert-danger">Error: Cannot communicate with server</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
// Store original handler
|
||||
const originalHandler = window.handlePeerResponse;
|
||||
let directoryReceived = false;
|
||||
const requestId = `browseDir_${Date.now()}_${Math.random()}`;
|
||||
|
||||
console.log('[DEBUG] Setting up directory handler with request ID:', requestId);
|
||||
|
||||
const directoryHandler = (response) => {
|
||||
console.log('[DEBUG] Directory handler received response:', response);
|
||||
|
||||
const directoryHandler = (response) => {
|
||||
if (directoryReceived) {
|
||||
// Check if this is a directory browser response
|
||||
// Look for: success + contents, or error related to directory browsing
|
||||
const isDirectoryResponse =
|
||||
(response.success === true && Array.isArray(response.contents)) ||
|
||||
(response.error && (response.error.includes('directory') || response.error.includes('browse'))) ||
|
||||
(response.path && response.contents !== undefined);
|
||||
|
||||
if (!isDirectoryResponse) {
|
||||
// Not a directory response, pass to original handler
|
||||
if (typeof originalHandler === 'function') {
|
||||
originalHandler(response);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (directoryReceived) {
|
||||
// Already processed, pass to original handler
|
||||
if (typeof originalHandler === 'function') {
|
||||
originalHandler(response);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
console.log('[DEBUG] Processing directory response');
|
||||
|
||||
// Handle success response
|
||||
if (response.success === true && Array.isArray(response.contents)) {
|
||||
directoryReceived = true;
|
||||
window.handlePeerResponse = originalHandler;
|
||||
currentFileBrowserPath = response.path || path;
|
||||
console.log('[DEBUG] Displaying directory contents, count:', response.contents.length);
|
||||
displayDirectoryContents(response.contents, currentFileBrowserPath);
|
||||
}
|
||||
// Handle error response
|
||||
else if (response.error) {
|
||||
directoryReceived = true;
|
||||
window.handlePeerResponse = originalHandler;
|
||||
console.error('[ERROR] Directory browse error:', response.error);
|
||||
fileBrowserContent.innerHTML = `<div class="alert alert-danger"><i class="fas fa-exclamation-triangle"></i> Error: ${response.error}</div>`;
|
||||
}
|
||||
// Handle unexpected format
|
||||
else {
|
||||
console.warn('[WARN] Unexpected response format:', response);
|
||||
// Still try to process if it has contents
|
||||
if (response.contents !== undefined) {
|
||||
directoryReceived = true;
|
||||
window.handlePeerResponse = originalHandler;
|
||||
currentFileBrowserPath = response.path || path;
|
||||
displayDirectoryContents(response.contents || [], currentFileBrowserPath);
|
||||
} else {
|
||||
// Pass to original handler if we can't process it
|
||||
if (typeof originalHandler === 'function') {
|
||||
originalHandler(response);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (response.success && response.contents) {
|
||||
directoryReceived = true;
|
||||
window.handlePeerResponse = originalHandler;
|
||||
currentFileBrowserPath = path;
|
||||
displayDirectoryContents(response.contents, path);
|
||||
} else if (response.error) {
|
||||
directoryReceived = true;
|
||||
window.handlePeerResponse = originalHandler;
|
||||
fileBrowserContent.innerHTML = `<div class="alert alert-danger">Error: ${response.error}</div>`;
|
||||
}
|
||||
};
|
||||
|
||||
window.handlePeerResponse = directoryHandler;
|
||||
window.sendCommand('browseDirectory', { path: path });
|
||||
|
||||
// Timeout after 10 seconds
|
||||
setTimeout(() => {
|
||||
if (!directoryReceived) {
|
||||
window.handlePeerResponse = originalHandler;
|
||||
fileBrowserContent.innerHTML = '<div class="alert alert-warning">Request timed out</div>';
|
||||
}
|
||||
}, 10000);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// Set the handler
|
||||
window.handlePeerResponse = directoryHandler;
|
||||
|
||||
// Send the command
|
||||
console.log('[DEBUG] Sending browseDirectory command for path:', path);
|
||||
window.sendCommand('browseDirectory', { path: path });
|
||||
|
||||
// Timeout after 10 seconds
|
||||
const timeoutId = setTimeout(() => {
|
||||
if (!directoryReceived) {
|
||||
console.warn('[WARN] Directory browse request timed out');
|
||||
window.handlePeerResponse = originalHandler;
|
||||
directoryReceived = true; // Mark as received to prevent double handling
|
||||
fileBrowserContent.innerHTML = '<div class="alert alert-warning"><i class="fas fa-clock"></i> Request timed out. Please try again.</div>';
|
||||
}
|
||||
}, 10000);
|
||||
|
||||
// Store timeout ID for potential cleanup (though we don't need it after timeout)
|
||||
// This is just for reference
|
||||
|
||||
} catch (error) {
|
||||
console.error('[ERROR] Failed to load directory:', error);
|
||||
fileBrowserContent.innerHTML = `<div class="alert alert-danger">Error: ${error.message}</div>`;
|
||||
fileBrowserContent.innerHTML = `<div class="alert alert-danger"><i class="fas fa-exclamation-triangle"></i> Error: ${error.message}</div>`;
|
||||
}
|
||||
}
|
||||
|
||||
// Display directory contents
|
||||
function displayDirectoryContents(contents, currentPath) {
|
||||
console.log('[DEBUG] Displaying directory contents for path:', currentPath, 'Items:', contents.length);
|
||||
|
||||
const fileBrowserContent = document.getElementById('fileBrowserContent');
|
||||
if (!fileBrowserContent) return;
|
||||
if (!fileBrowserContent) {
|
||||
console.error('[ERROR] File browser content element not found');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!contents || contents.length === 0) {
|
||||
fileBrowserContent.innerHTML = '<div class="text-center p-4 text-muted">Directory is empty</div>';
|
||||
console.log('[DEBUG] Directory is empty');
|
||||
fileBrowserContent.innerHTML = '<div class="text-center p-4 text-muted"><i class="fas fa-folder-open"></i> Directory is empty</div>';
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1237,25 +1320,33 @@ function displayDirectoryContents(contents, currentPath) {
|
||||
return (a.name || '').localeCompare(b.name || '');
|
||||
});
|
||||
|
||||
console.log('[DEBUG] Sorted contents:', sorted.length, 'items');
|
||||
|
||||
let html = '<div class="file-browser-list">';
|
||||
sorted.forEach(item => {
|
||||
const icon = item.type === 'directory' ? 'fa-folder' : 'fa-file';
|
||||
const iconColor = item.type === 'directory' ? 'text-warning' : 'text-secondary';
|
||||
const path = currentPath === '/' ? `/${item.name}` : `${currentPath}/${item.name}`;
|
||||
// Escape path for onclick to prevent XSS
|
||||
const escapedPath = (currentPath === '/' ? `/${item.name}` : `${currentPath}/${item.name}`)
|
||||
.replace(/'/g, "\\'")
|
||||
.replace(/"/g, '"');
|
||||
const escapedName = (item.name || '').replace(/</g, '<').replace(/>/g, '>');
|
||||
|
||||
if (item.type === 'directory') {
|
||||
html += `
|
||||
<div class="file-browser-item" onclick="loadDirectoryContents('${path}')">
|
||||
<div class="file-browser-item" onclick="loadDirectoryContents('${escapedPath}')" title="Click to open">
|
||||
<i class="fas ${icon} ${iconColor}"></i>
|
||||
<span>${item.name}</span>
|
||||
<span>${escapedName}</span>
|
||||
<i class="fas fa-chevron-right text-muted"></i>
|
||||
</div>
|
||||
`;
|
||||
} else {
|
||||
const size = item.size ? formatFileSize(item.size) : '';
|
||||
html += `
|
||||
<div class="file-browser-item">
|
||||
<div class="file-browser-item" title="File${size ? ': ' + size : ''}">
|
||||
<i class="fas ${icon} ${iconColor}"></i>
|
||||
<span>${item.name}</span>
|
||||
<span>${escapedName}</span>
|
||||
${size ? `<small class="text-muted ms-2">${size}</small>` : ''}
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
@@ -1263,24 +1354,49 @@ function displayDirectoryContents(contents, currentPath) {
|
||||
html += '</div>';
|
||||
|
||||
fileBrowserContent.innerHTML = html;
|
||||
console.log('[DEBUG] Directory contents displayed successfully');
|
||||
}
|
||||
|
||||
// Helper function to format file size
|
||||
function formatFileSize(bytes) {
|
||||
if (!bytes || bytes === 0) return '';
|
||||
const k = 1024;
|
||||
const sizes = ['B', 'KB', 'MB', 'GB'];
|
||||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||||
return Math.round(bytes / Math.pow(k, i) * 100) / 100 + ' ' + sizes[i];
|
||||
}
|
||||
|
||||
// Select directory for volume mount
|
||||
function selectDirectoryForVolume() {
|
||||
if (!currentFileBrowserVolumeId) return;
|
||||
console.log('[DEBUG] Selecting directory for volume mount:', currentFileBrowserPath);
|
||||
|
||||
if (!currentFileBrowserVolumeId) {
|
||||
console.warn('[WARN] No volume ID set for directory selection');
|
||||
return;
|
||||
}
|
||||
|
||||
const hostInput = document.querySelector(`[data-volume-host="${currentFileBrowserVolumeId}"]`);
|
||||
if (hostInput) {
|
||||
hostInput.value = currentFileBrowserPath;
|
||||
console.log('[DEBUG] Set host path to:', currentFileBrowserPath);
|
||||
validateVolumeMount(currentFileBrowserVolumeId);
|
||||
updatePreview();
|
||||
} else {
|
||||
console.error('[ERROR] Host input not found for volume ID:', currentFileBrowserVolumeId);
|
||||
}
|
||||
|
||||
// Close modal
|
||||
const fileBrowserModal = document.getElementById('fileBrowserModal');
|
||||
if (fileBrowserModal && typeof bootstrap !== 'undefined') {
|
||||
const modal = bootstrap.Modal.getInstance(fileBrowserModal);
|
||||
if (modal) modal.hide();
|
||||
try {
|
||||
const modal = bootstrap.Modal.getInstance(fileBrowserModal);
|
||||
if (modal) {
|
||||
modal.hide();
|
||||
console.log('[DEBUG] File browser modal closed');
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('[ERROR] Failed to close file browser modal:', error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user