feat: contextmenu deel 1
This commit is contained in:
+44
-3
@@ -1237,6 +1237,45 @@ function createMediaSlot(entry) {
|
||||
return slot;
|
||||
}
|
||||
|
||||
function createSelectionSlot(pane, entry, index) {
|
||||
const slot = document.createElement("span");
|
||||
slot.className = "entry-select-slot";
|
||||
|
||||
if (entry.isParent) {
|
||||
const placeholder = document.createElement("span");
|
||||
placeholder.className = "entry-select-toggle is-disabled";
|
||||
placeholder.setAttribute("aria-hidden", "true");
|
||||
const indicator = document.createElement("span");
|
||||
indicator.className = "entry-select-indicator";
|
||||
placeholder.append(indicator);
|
||||
slot.append(placeholder);
|
||||
return slot;
|
||||
}
|
||||
|
||||
const button = document.createElement("button");
|
||||
button.type = "button";
|
||||
button.className = "entry-select-toggle";
|
||||
const selected = selectedPaths(pane).includes(entry.path);
|
||||
if (selected) {
|
||||
button.classList.add("is-selected");
|
||||
}
|
||||
button.setAttribute("aria-label", `${selected ? "Deselect" : "Select"} ${entry.name}`);
|
||||
button.setAttribute("aria-pressed", selected ? "true" : "false");
|
||||
const indicator = document.createElement("span");
|
||||
indicator.className = "entry-select-indicator";
|
||||
button.append(indicator);
|
||||
button.onclick = (event) => {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
setActivePane(pane);
|
||||
paneState(pane).currentRowIndex = index;
|
||||
toggleSelectionAtIndex(pane, selectedEntryFromItem(entry), index);
|
||||
renderPaneItems(pane);
|
||||
};
|
||||
slot.append(button);
|
||||
return slot;
|
||||
}
|
||||
|
||||
async function loadSettings() {
|
||||
const data = await apiRequest("GET", "/api/settings");
|
||||
settingsState.showThumbnails = !!data.show_thumbnails;
|
||||
@@ -1546,7 +1585,7 @@ function formatFileSize(bytes) {
|
||||
return `${(bytes / (1024 ** 4)).toFixed(1)} TB`;
|
||||
}
|
||||
|
||||
function createBrowseItem(pane, entry, kind) {
|
||||
function createBrowseItem(pane, entry, kind, index) {
|
||||
const li = document.createElement("li");
|
||||
li.className = "selectable";
|
||||
li.dataset.path = entry.path;
|
||||
@@ -1567,6 +1606,7 @@ function createBrowseItem(pane, entry, kind) {
|
||||
|
||||
const name = document.createElement("span");
|
||||
name.className = `entry-name ${kind === "directory" ? "entry-dir" : "entry-file"}`;
|
||||
name.append(createSelectionSlot(pane, { ...entry, kind }, index));
|
||||
name.append(createMediaSlot({ ...entry, kind }));
|
||||
|
||||
if (kind === "directory") {
|
||||
@@ -1680,6 +1720,7 @@ function renderPaneItems(pane) {
|
||||
};
|
||||
const upNameCell = document.createElement("span");
|
||||
upNameCell.className = "entry-name entry-dir";
|
||||
upNameCell.append(createSelectionSlot(pane, { ...entry, isParent: true }, index));
|
||||
upNameCell.append(createMediaSlot({ name: "..", path: entry.path, kind: "directory" }));
|
||||
const upName = document.createElement("button");
|
||||
upName.type = "button";
|
||||
@@ -1705,7 +1746,7 @@ function renderPaneItems(pane) {
|
||||
return;
|
||||
}
|
||||
|
||||
const row = createBrowseItem(pane, entry, entry.kind);
|
||||
const row = createBrowseItem(pane, entry, entry.kind, index);
|
||||
row.dataset.rowIndex = String(index);
|
||||
if (index === model.currentRowIndex) {
|
||||
row.classList.add("is-current-row");
|
||||
@@ -1724,7 +1765,7 @@ function renderPaneItems(pane) {
|
||||
navigateTo(pane, entry.path);
|
||||
};
|
||||
}
|
||||
const fileName = row.querySelector(".entry-file span");
|
||||
const fileName = row.querySelector(".entry-file .entry-label");
|
||||
if (fileName) {
|
||||
fileName.onclick = (ev) => {
|
||||
ev.stopPropagation();
|
||||
|
||||
@@ -346,6 +346,72 @@ button:disabled {
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.entry-select-slot {
|
||||
width: 18px;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.entry-select-toggle {
|
||||
width: 18px;
|
||||
min-width: 18px;
|
||||
height: 18px;
|
||||
padding: 0;
|
||||
border: none;
|
||||
border-radius: 999px;
|
||||
background: transparent;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.entry-select-toggle:hover {
|
||||
background: transparent;
|
||||
border-color: transparent;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.entry-select-toggle.is-disabled {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.entry-select-indicator {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 999px;
|
||||
border: 1.5px solid color-mix(in srgb, var(--color-text-muted) 80%, transparent);
|
||||
opacity: 0;
|
||||
transition: opacity 100ms ease, border-color 100ms ease, background 100ms ease;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.list li:hover .entry-select-indicator,
|
||||
.entry-select-toggle:focus-visible .entry-select-indicator,
|
||||
.entry-select-toggle.is-selected .entry-select-indicator {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.entry-select-toggle.is-selected .entry-select-indicator {
|
||||
border-color: var(--color-accent);
|
||||
background: var(--color-accent);
|
||||
}
|
||||
|
||||
.entry-select-toggle.is-selected .entry-select-indicator::after {
|
||||
content: "✓";
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 11px;
|
||||
line-height: 1;
|
||||
color: var(--color-surface);
|
||||
}
|
||||
|
||||
.entry-media-slot {
|
||||
width: 28px;
|
||||
min-width: 28px;
|
||||
|
||||
Reference in New Issue
Block a user