continue work

This commit is contained in:
Raven Scott
2025-11-24 19:16:23 -05:00
parent 9ed79d5209
commit fc91f4c6bb
2 changed files with 171 additions and 47 deletions
+160 -44
View File
@@ -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, '&quot;');
const escapedName = (item.name || '').replace(/</g, '&lt;').replace(/>/g, '&gt;');
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);
}
}
}