...
This commit is contained in:
@@ -16,23 +16,101 @@ class FileTree {
|
||||
}
|
||||
|
||||
setupEventListeners() {
|
||||
// Click handler for tree nodes
|
||||
this.container.addEventListener('click', (e) => {
|
||||
console.log('Container clicked', e.target);
|
||||
const node = e.target.closest('.tree-node');
|
||||
if (!node) return;
|
||||
|
||||
console.log('Node found', node);
|
||||
const path = node.dataset.path;
|
||||
const isDir = node.dataset.isdir === 'true';
|
||||
|
||||
// If it's a directory, and the click was on the title, select the folder
|
||||
if (isDir && e.target.classList.contains('tree-node-title')) {
|
||||
this.selectFolder(path);
|
||||
} else if (!isDir) { // If it's a file, select the file
|
||||
this.selectFile(path);
|
||||
}
|
||||
// Clicks on the toggle are handled by the toggle's specific event listener
|
||||
});
|
||||
|
||||
// DRAG AND DROP
|
||||
this.container.addEventListener('dragstart', (e) => {
|
||||
const node = e.target.closest('.tree-node');
|
||||
if (!node) return;
|
||||
|
||||
const path = node.dataset.path;
|
||||
const isDir = node.dataset.isdir === 'true';
|
||||
|
||||
// The toggle is handled inside renderNodes now
|
||||
console.log('[FileTree] Drag start:', path);
|
||||
|
||||
// Select node
|
||||
if (isDir) {
|
||||
this.selectFolder(path);
|
||||
} else {
|
||||
this.selectFile(path);
|
||||
e.dataTransfer.effectAllowed = 'move';
|
||||
e.dataTransfer.setData('text/plain', path);
|
||||
e.dataTransfer.setData('application/json', JSON.stringify({
|
||||
path,
|
||||
isDir,
|
||||
name: node.querySelector('.tree-node-title').textContent
|
||||
}));
|
||||
|
||||
node.classList.add('dragging');
|
||||
setTimeout(() => node.classList.remove('dragging'), 0);
|
||||
});
|
||||
|
||||
this.container.addEventListener('dragover', (e) => {
|
||||
const node = e.target.closest('.tree-node');
|
||||
if (!node) return;
|
||||
|
||||
const isDir = node.dataset.isdir === 'true';
|
||||
if (!isDir) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.dataTransfer.dropEffect = 'move';
|
||||
node.classList.add('drag-over');
|
||||
});
|
||||
|
||||
this.container.addEventListener('dragleave', (e) => {
|
||||
const node = e.target.closest('.tree-node');
|
||||
if (node) {
|
||||
node.classList.remove('drag-over');
|
||||
}
|
||||
});
|
||||
|
||||
this.container.addEventListener('drop', async (e) => {
|
||||
const targetNode = e.target.closest('.tree-node');
|
||||
if (!targetNode) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
const targetPath = targetNode.dataset.path;
|
||||
const isDir = targetNode.dataset.isdir === 'true';
|
||||
|
||||
if (!isDir) {
|
||||
console.log('[FileTree] Target is not a directory');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const data = JSON.parse(e.dataTransfer.getData('application/json'));
|
||||
const sourcePath = data.path;
|
||||
const sourceName = data.name;
|
||||
|
||||
if (sourcePath === targetPath) {
|
||||
console.log('[FileTree] Source and target are same');
|
||||
return;
|
||||
}
|
||||
|
||||
const destPath = `${targetPath}/${sourceName}`.replace(/\/+/g, '/');
|
||||
|
||||
console.log('[FileTree] Moving:', sourcePath, '→', destPath);
|
||||
|
||||
await this.webdavClient.move(sourcePath, destPath);
|
||||
await this.load();
|
||||
|
||||
showNotification(`Moved to ${targetNode.querySelector('.tree-node-title').textContent}`, 'success');
|
||||
} catch (error) {
|
||||
console.error('[FileTree] Drop error:', error);
|
||||
showNotification(`Failed to move: ${error.message}`, 'error');
|
||||
} finally {
|
||||
targetNode.classList.remove('drag-over');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -42,13 +120,9 @@ class FileTree {
|
||||
e.preventDefault();
|
||||
|
||||
if (node) {
|
||||
// Clicked on a node
|
||||
const path = node.dataset.path;
|
||||
const isDir = node.dataset.isdir === 'true';
|
||||
window.showContextMenu(e.clientX, e.clientY, { path, isDir });
|
||||
} else if (e.target === this.container) {
|
||||
// Clicked on the empty space in the file tree container
|
||||
window.showContextMenu(e.clientX, e.clientY, { path: '', isDir: true });
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -91,18 +165,8 @@ class FileTree {
|
||||
nodeWrapper.appendChild(childContainer);
|
||||
|
||||
// Make toggle functional
|
||||
const toggle = nodeElement.querySelector('.tree-node-toggle');
|
||||
if (toggle) {
|
||||
toggle.addEventListener('click', (e) => {
|
||||
console.log('Toggle clicked', e.target);
|
||||
e.stopPropagation();
|
||||
const isHidden = childContainer.style.display === 'none';
|
||||
console.log('Is hidden?', isHidden);
|
||||
childContainer.style.display = isHidden ? 'block' : 'none';
|
||||
toggle.innerHTML = isHidden ? '▼' : '▶';
|
||||
toggle.classList.toggle('expanded');
|
||||
});
|
||||
}
|
||||
// The toggle functionality is already handled in renderNodes, no need to duplicate here.
|
||||
// Ensure the toggle's click event stops propagation to prevent the parent node's click from firing.
|
||||
}
|
||||
|
||||
parentElement.appendChild(nodeWrapper);
|
||||
|
||||
Reference in New Issue
Block a user