- Extract UI components into separate JS files - Centralize configuration values in config.js - Introduce a dedicated logger module - Improve file tree drag-and-drop and undo functionality - Refactor modal handling to a single manager - Add URL routing support for SPA navigation - Implement view mode for read-only access
90 lines
2.6 KiB
JavaScript
90 lines
2.6 KiB
JavaScript
/**
|
|
* Context Menu Module
|
|
* Handles the right-click context menu for file tree items
|
|
*/
|
|
|
|
/**
|
|
* Show context menu at specified position
|
|
* @param {number} x - X coordinate
|
|
* @param {number} y - Y coordinate
|
|
* @param {Object} target - Target object with path and isDir properties
|
|
*/
|
|
function showContextMenu(x, y, target) {
|
|
const menu = document.getElementById('contextMenu');
|
|
if (!menu) return;
|
|
|
|
// Store target data
|
|
menu.dataset.targetPath = target.path;
|
|
menu.dataset.targetIsDir = target.isDir;
|
|
|
|
// Show/hide menu items based on target type
|
|
const items = {
|
|
'new-file': target.isDir,
|
|
'new-folder': target.isDir,
|
|
'upload': target.isDir,
|
|
'download': true,
|
|
'paste': target.isDir && window.fileTreeActions?.clipboard,
|
|
'open': !target.isDir
|
|
};
|
|
|
|
Object.entries(items).forEach(([action, show]) => {
|
|
const item = menu.querySelector(`[data-action="${action}"]`);
|
|
if (item) {
|
|
item.style.display = show ? 'flex' : 'none';
|
|
}
|
|
});
|
|
|
|
// Position menu
|
|
menu.style.display = 'block';
|
|
menu.style.left = x + 'px';
|
|
menu.style.top = y + 'px';
|
|
|
|
// Adjust if off-screen
|
|
setTimeout(() => {
|
|
const rect = menu.getBoundingClientRect();
|
|
if (rect.right > window.innerWidth) {
|
|
menu.style.left = (window.innerWidth - rect.width - 10) + 'px';
|
|
}
|
|
if (rect.bottom > window.innerHeight) {
|
|
menu.style.top = (window.innerHeight - rect.height - 10) + 'px';
|
|
}
|
|
}, 0);
|
|
}
|
|
|
|
/**
|
|
* Hide the context menu
|
|
*/
|
|
function hideContextMenu() {
|
|
const menu = document.getElementById('contextMenu');
|
|
if (menu) {
|
|
menu.style.display = 'none';
|
|
}
|
|
}
|
|
|
|
// Combined click handler for context menu and outside clicks
|
|
document.addEventListener('click', async (e) => {
|
|
const menuItem = e.target.closest('.context-menu-item');
|
|
|
|
if (menuItem) {
|
|
// Handle context menu item click
|
|
const action = menuItem.dataset.action;
|
|
const menu = document.getElementById('contextMenu');
|
|
const targetPath = menu.dataset.targetPath;
|
|
const isDir = menu.dataset.targetIsDir === 'true';
|
|
|
|
hideContextMenu();
|
|
|
|
if (window.fileTreeActions) {
|
|
await window.fileTreeActions.execute(action, targetPath, isDir);
|
|
}
|
|
} else if (!e.target.closest('#contextMenu') && !e.target.closest('.tree-node')) {
|
|
// Hide on outside click
|
|
hideContextMenu();
|
|
}
|
|
});
|
|
|
|
// Make functions globally available
|
|
window.showContextMenu = showContextMenu;
|
|
window.hideContextMenu = hideContextMenu;
|
|
|