feat: keyboard functionaliteit shift + / Shift - toegevoegd

This commit is contained in:
kodi
2026-03-11 12:56:02 +01:00
parent df47bd13b3
commit fa9dc00f61
5 changed files with 194 additions and 0 deletions
+132
View File
@@ -22,6 +22,7 @@ let state = {
lastTaskCount: 0,
};
const ROW_JUMP_STEP = 10;
let wildcardDialogMode = "select";
function paneState(pane) {
return state.panes[pane];
@@ -616,6 +617,104 @@ function shouldHandleShortcut(target) {
return false;
}
function wildcardPopupElements() {
return {
overlay: document.getElementById("wildcard-popup"),
title: document.getElementById("wildcard-popup-title"),
meta: document.getElementById("wildcard-popup-meta"),
input: document.getElementById("wildcard-pattern-input"),
error: document.getElementById("wildcard-popup-error"),
applyButton: document.getElementById("wildcard-apply-btn"),
cancelButton: document.getElementById("wildcard-cancel-btn"),
};
}
function isWildcardPopupOpen() {
return !wildcardPopupElements().overlay.classList.contains("hidden");
}
function escapeRegExp(text) {
return text.replace(/[|\\{}()[\]^$+?.]/g, "\\$&");
}
function globToRegExp(pattern) {
const escaped = pattern
.split("*")
.map((part) => escapeRegExp(part))
.join(".*");
return new RegExp(`^${escaped}$`, "i");
}
function applyWildcardSelection(mode, pattern) {
const pane = state.activePane;
const model = paneState(pane);
const matcher = globToRegExp(pattern);
const candidates = model.visibleItems.filter((entry) => !entry.isParent);
const matches = candidates.filter((entry) => matcher.test(entry.name));
const matchPaths = new Set(matches.map((entry) => entry.path));
let changed = 0;
if (mode === "select") {
const existing = new Set(model.selectedItems.map((item) => item.path));
for (const entry of matches) {
if (existing.has(entry.path)) {
continue;
}
model.selectedItems.push({ path: entry.path, name: entry.name, kind: entry.kind });
changed += 1;
}
if (matches.length > 0) {
const last = matches[matches.length - 1];
model.selectedItem = { path: last.path, name: last.name, kind: last.kind };
}
} else {
const before = model.selectedItems.length;
model.selectedItems = model.selectedItems.filter((item) => !matchPaths.has(item.path));
changed = before - model.selectedItems.length;
if (!model.selectedItem || matchPaths.has(model.selectedItem.path)) {
model.selectedItem = model.selectedItems.length > 0 ? model.selectedItems[model.selectedItems.length - 1] : null;
}
}
renderPaneItems(pane);
setStatus(`Wildcard ${mode}: ${matches.length} matched, ${changed} changed`);
}
function closeWildcardPopup() {
const elements = wildcardPopupElements();
elements.overlay.classList.add("hidden");
elements.error.textContent = "";
elements.input.value = "";
}
function submitWildcardPopup() {
const elements = wildcardPopupElements();
const pattern = elements.input.value.trim();
if (!pattern) {
elements.error.textContent = "Pattern is required";
return;
}
try {
applyWildcardSelection(wildcardDialogMode, pattern);
closeWildcardPopup();
} catch (err) {
elements.error.textContent = `Wildcard: ${err.message}`;
}
}
function openWildcardPopup(mode) {
wildcardDialogMode = mode;
const pane = state.activePane;
const elements = wildcardPopupElements();
elements.title.textContent = mode === "select" ? "Wildcard Select" : "Wildcard Deselect";
elements.meta.textContent = `Active pane: ${pane} (visible items only, case-insensitive)`;
elements.applyButton.textContent = mode === "select" ? "Select" : "Deselect";
elements.error.textContent = "";
elements.input.value = "";
elements.overlay.classList.remove("hidden");
elements.input.focus();
}
function moveCurrentRow(delta) {
const pane = state.activePane;
const model = paneState(pane);
@@ -671,10 +770,23 @@ function clearSelectionForActivePane() {
}
function handleKeyboardShortcuts(event) {
if (isWildcardPopupOpen()) {
return;
}
if (!shouldHandleShortcut(event.target)) {
return;
}
if (event.shiftKey && event.key === "+") {
event.preventDefault();
openWildcardPopup("select");
return;
}
if (event.shiftKey && event.key === "_") {
event.preventDefault();
openWildcardPopup("deselect");
return;
}
if (event.metaKey && event.key === "ArrowUp") {
event.preventDefault();
jumpCurrentRow("start");
@@ -745,6 +857,26 @@ function setupEvents() {
document.getElementById("move-btn").onclick = startMoveSelected;
document.getElementById("mkdir-btn").onclick = createFolderForActivePane;
document.getElementById("add-bookmark-btn").onclick = addBookmark;
const wildcard = wildcardPopupElements();
wildcard.cancelButton.onclick = closeWildcardPopup;
wildcard.applyButton.onclick = submitWildcardPopup;
wildcard.input.onkeydown = (event) => {
if (event.key === "Enter") {
event.preventDefault();
submitWildcardPopup();
return;
}
if (event.key === "Escape") {
event.preventDefault();
closeWildcardPopup();
}
};
wildcard.overlay.onclick = (event) => {
if (event.target === wildcard.overlay) {
closeWildcardPopup();
}
};
}
async function init() {