From 061532460722e86140a0673618c7a4db34cd4408 Mon Sep 17 00:00:00 2001 From: kodi Date: Sat, 14 Mar 2026 09:22:24 +0100 Subject: [PATCH] feat: contextmenu deel 1 --- webui/backend/data/tasks.db | Bin 172032 -> 172032 bytes .../test_ui_smoke_golden.cpython-313.pyc | Bin 29454 -> 29750 bytes .../tests/golden/test_ui_smoke_golden.py | 5 +- webui/html/app.js | 47 ++++++++++++- webui/html/base.css | 66 ++++++++++++++++++ 5 files changed, 114 insertions(+), 4 deletions(-) diff --git a/webui/backend/data/tasks.db b/webui/backend/data/tasks.db index 8df5d3f74eef95ff4896577f70b61096108a7c6f..29245548218a7dab2da9b7a83ff8c8bb8face8b4 100644 GIT binary patch delta 885 zcma))PiPZC6vlUEYj-C}YpfUuX{|!3Xc?WI+1c66siJrg3)-fjEw$ZEb}xbo1|ou( zIaRR-HHY;ef+&a})KJUnt%6X!2>o*v>qUyE>dk{-w*G0+f;rCn9^Y@?_g-}_QJqWN z%7KpCoku{2oS2;ek3N8baN7znVC&V;S^?*xhby2*1uyGz79QBI4nsqj0b?G;zC~?p zdIrG`FZq}eN*u%Siw?7urReb|ForUNpsxkp08iAf2~B;Y-cL-oyhbx&W)0klp00sm z4cx5DNl=K5x#Jd1!7VI=%du$&Hg*`Xut$g&G!Q{a1j=&UX>sbC%%Cy7)ac|swyDRl z;J#11B6CZWD+|&4Z(!fC)OB!FLGRFWw3>jC-VYIovWMX{4RqIK4uqY@VfwV4r$*l7 zBg%4C<&Y9;VZyLs7RVoE>2F2knaEQ%qAYHykcP4lHQZOZ%Cz}VtHRNgHm`ryU+H)C z3wo|D&uHs`2A=B*vna65Ob44>2<&m+!NMsy)b{MaVve#HeVK$i^<4= zdQ(%$7s;N)6*RLq{S28B%R*{6+pQ=vt0gZOmpI@7YXL2{qTm4~0|Dc) zf!_kRr{)1&2@+5ND+B?l1M&(71IPoO3aJKMq(9iVktN7(oJn2LXq%fr9~;L_q=&w=7Bm*fj$(2l1B& zfC5_z2Ppz diff --git a/webui/backend/tests/golden/__pycache__/test_ui_smoke_golden.cpython-313.pyc b/webui/backend/tests/golden/__pycache__/test_ui_smoke_golden.cpython-313.pyc index d4d5be5f157b480f75e8f9eb84f17e64004023fb..85b4696d051a3fe927720ee702090313677bcadc 100644 GIT binary patch delta 515 zcmeBs#<=YTBj0CUUM>b8@Riz{*%G#qFHxJZV{?JFlfYy>eUZs0g(37?2)&ul<{aB( z9epvzIg{n}m6_*;GEZ)FQQmyPsf%&*F_#cVuqHh>HAa@niu#Jot3z2Pe>7BNUIU~- z{I#L1lMlKnGqQqt>qFVV^oCG&FugI9V{)LoG9xFLw>gvxOm7M02Gd(Zc|bJdw#n1o zby>Fu?+D&G`J}rl=l0-T!8FnY=+zfhCkbcrS<{6e8oyS(Pw~P)UAzdQNJU6NH8v=vd+jG5~5OM0=`S ziYv%)x1#)9&yv(!4X{C)FuSZbZwxQzVZ66lGvyN7>~u5cJl-jgXY*)l_5 zvtV{T8>7eOiG|*bMk%a}u8cD{u1jcMl+gUb0Oo%1<7Qyt>8QHQEO~>4r`@;7x7Ggx MGXslMkr*%>0OsDP?*IS* delta 334 zcmdn?g0b%zBj0CUUM>b8c*L+Cnau^-P6Ctv8H!9kDJ(EqPhVv6TL`_G z&*mK4W)J5&M&>!8ERz-W6`AKk>3I-(^D&nYMzB^rH#J69u#(lG5PD508<@W~lzs9+ zH)Tc+FmHV*Cz#$4$_1u3hH_61bXR8N0r40&PiFSe<=hgyHF%pPQy$-Beh)>~Ey3G^ zw@r@sPz8$b0E-Ju-smCD%on_K@&-W#mQeoST_A=~s6g;;Qznq_7#I{7(it@OZ2s#Z z#LvfDoSKuGT%wzsSd^Vww0TWLIS=E;%_^yv*m$pVNL=KQm?6JH?FxtCWXBAN%^o=g lY>cj(cNTdwiY2l#x-!n-xGtf2Q9| { + 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(); diff --git a/webui/html/base.css b/webui/html/base.css index cfee420..60dce9a 100644 --- a/webui/html/base.css +++ b/webui/html/base.css @@ -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;