feat: contextmenu deel 2

This commit is contained in:
kodi
2026-03-14 09:31:01 +01:00
parent 0615324607
commit 7bb59a2b65
5 changed files with 155 additions and 1 deletions
+96 -1
View File
@@ -52,6 +52,12 @@ let deleteConfirmState = {
items: [],
recursivePaths: [],
};
let contextMenuState = {
open: false,
pane: "left",
items: [],
anchorPath: null,
};
let batchMoveState = {
destinationBase: "",
count: 0,
@@ -315,6 +321,62 @@ function feedbackElements() {
};
}
function contextMenuElements() {
return {
menu: document.getElementById("context-menu"),
scope: document.getElementById("context-menu-scope"),
target: document.getElementById("context-menu-target"),
placeholder: document.getElementById("context-menu-open-placeholder"),
};
}
function isContextMenuOpen() {
return contextMenuState.open && !contextMenuElements().menu.classList.contains("hidden");
}
function closeContextMenu() {
const elements = contextMenuElements();
contextMenuState.open = false;
contextMenuState.pane = "left";
contextMenuState.items = [];
contextMenuState.anchorPath = null;
if (!elements.menu) {
return;
}
elements.menu.classList.add("hidden");
elements.scope.textContent = "";
elements.target.textContent = "";
}
function openContextMenu(pane, entry, event) {
if (!entry || entry.isParent) {
return;
}
const elements = contextMenuElements();
const selectedItems = paneState(pane).selectedItems || [];
const selectedPathsSet = new Set(selectedItems.map((item) => item.path));
const items = selectedPathsSet.has(entry.path)
? selectedItems.map((item) => ({ ...item }))
: [selectedEntryFromItem(entry)];
contextMenuState.open = true;
contextMenuState.pane = pane;
contextMenuState.items = items;
contextMenuState.anchorPath = entry.path;
const isMulti = items.length > 1;
elements.scope.textContent = isMulti ? "Multi-selection" : "Single item";
elements.target.textContent = isMulti ? `${items.length} selected items` : entry.name;
const menuWidth = 220;
const menuHeight = 120;
const x = Math.min(event.clientX, window.innerWidth - menuWidth - 12);
const y = Math.min(event.clientY, window.innerHeight - menuHeight - 12);
elements.menu.style.left = `${Math.max(8, x)}px`;
elements.menu.style.top = `${Math.max(8, y)}px`;
elements.menu.classList.remove("hidden");
}
function settingsElements() {
return {
overlay: document.getElementById("settings-modal"),
@@ -1689,6 +1751,7 @@ function updatePaneFocusLine(pane) {
}
function renderPaneItems(pane) {
closeContextMenu();
const model = paneState(pane);
const items = document.getElementById(`${pane}-items`);
items.innerHTML = "";
@@ -1718,6 +1781,9 @@ function renderPaneItems(pane) {
clearSelectionAnchor(pane);
renderPaneItems(pane);
};
up.oncontextmenu = (event) => {
event.preventDefault();
};
const upNameCell = document.createElement("span");
upNameCell.className = "entry-name entry-dir";
upNameCell.append(createSelectionSlot(pane, { ...entry, isParent: true }, index));
@@ -1789,6 +1855,12 @@ function renderPaneItems(pane) {
}
renderPaneItems(pane);
};
row.oncontextmenu = (event) => {
event.preventDefault();
event.stopPropagation();
setActivePane(pane);
openContextMenu(pane, entry, event);
};
if (entry.kind === "file" && isImageSelection({ path: entry.path, name: entry.name, kind: entry.kind })) {
row.ondblclick = (ev) => {
ev.stopPropagation();
@@ -1873,6 +1945,7 @@ async function loadBrowsePane(pane) {
}
function navigateTo(pane, path) {
closeContextMenu();
const model = paneState(pane);
model.currentPath = path;
model.currentRowIndex = 0;
@@ -3335,6 +3408,13 @@ function clearSelectionForActivePane() {
}
function handleKeyboardShortcuts(event) {
if (isContextMenuOpen()) {
if (event.key === "Escape") {
event.preventDefault();
closeContextMenu();
}
return;
}
if (event.key === "Escape" && !uploadElements().menuPopup.classList.contains("hidden")) {
event.preventDefault();
closeUploadMenu();
@@ -3617,9 +3697,24 @@ function setupEvents() {
document.addEventListener("click", (event) => {
const elements = uploadElements();
if (!elements.menu || elements.menu.contains(event.target)) {
} else {
closeUploadMenu();
}
const contextMenu = contextMenuElements().menu;
if (contextMenu && !contextMenu.contains(event.target)) {
closeContextMenu();
}
});
document.addEventListener("contextmenu", (event) => {
const contextMenu = contextMenuElements().menu;
if (contextMenu && contextMenu.contains(event.target)) {
event.preventDefault();
return;
}
closeUploadMenu();
const row = event.target instanceof Element ? event.target.closest("li[data-row-index]") : null;
if (!row) {
closeContextMenu();
}
});
const rename = renameElements();