From 5752b6db4889f94f82c6fb352798234eef5d93f3 Mon Sep 17 00:00:00 2001 From: ed Date: Wed, 26 May 2021 00:47:43 +0200 Subject: [PATCH] hook up the multiselect ui --- README.md | 19 ++++++++++++++-- copyparty/ico.py | 3 ++- copyparty/web/browser.css | 21 +++++++++++++++-- copyparty/web/browser.js | 47 ++++++++++++++++++++++++++++++++++----- 4 files changed, 79 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index ae53219b..17fa8669 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ turn your phone or raspi into a portable file server with resumable uploads/down * *resumable* uploads need `firefox 34+` / `chrome 41+` / `safari 7+` for full speed * code standard: `black` -📷 screenshots: [browser](#the-browser) // [upload](#uploading) // [md-viewer](#markdown-viewer) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [ie4](#browser-support) +📷 **screenshots:** [browser](#the-browser) // [upload](#uploading) // [thumbnails](#thumbnails) // [md-viewer](#markdown-viewer) // [search](#searching) // [fsearch](#file-search) // [zip-DL](#zip-downloads) // [ie4](#browser-support) ## readme toc @@ -29,6 +29,7 @@ turn your phone or raspi into a portable file server with resumable uploads/down * [tabs](#tabs) * [hotkeys](#hotkeys) * [tree-mode](#tree-mode) + * [thumbnails](#thumbnails) * [zip downloads](#zip-downloads) * [uploading](#uploading) * [file-search](#file-search) @@ -43,6 +44,8 @@ turn your phone or raspi into a portable file server with resumable uploads/down * [client examples](#client-examples) * [up2k](#up2k) * [dependencies](#dependencies) + * [optional dependencies](#optional-dependencies) + * [install recommended deps](#install-recommended-deps) * [optional gpl stuff](#optional-gpl-stuff) * [sfx](#sfx) * [sfx repack](#sfx-repack) @@ -148,11 +151,16 @@ summary: it works! the browser has the following hotkeys * `I/K` prev/next folder * `P` parent folder +* `G` toggle list / grid view +* `T` toggle thumbnails / icons * when playing audio: * `0..9` jump to 10%..90% * `U/O` skip 10sec back/forward * `J/L` prev/next song * `J` also starts playing the folder +* in the grid view: + * `S` toggle multiselect + * `A/D` zoom ## tree-mode @@ -162,6 +170,13 @@ by default there's a breadcrumbs path; you can replace this with a tree-browser click `[-]` and `[+]` to adjust the size, and the `[a]` toggles if the tree should widen dynamically as you go deeper or stay fixed-size +## thumbnails + +![copyparty-thumbs-fs8](https://user-images.githubusercontent.com/241032/119577189-6d490200-bdba-11eb-81a6-7b2ef7bc1128.png) + +it does static images with Pillow and uses FFmpeg for video files, so you may want to `--no-thumb` or maybe just `--no-vthumb` depending on how destructive your users are + + ## zip downloads the `zip` link next to folders can produce various types of zip/tar files using these alternatives in the browser settings tab: @@ -421,7 +436,7 @@ enable reading HEIF pictures: * `pyheif-pillow-opener` (requires Linux or a C compiler) -## install recommended dependencies +## install recommended deps ``` python -m pip install --user -U jinja2 mutagen Pillow ``` diff --git a/copyparty/ico.py b/copyparty/ico.py index eb03c7c2..450d9f23 100644 --- a/copyparty/ico.py +++ b/copyparty/ico.py @@ -25,7 +25,8 @@ class Ico(object): -{} +{} """ svg = svg.format(c[:6], c[6:], ext).encode("utf-8") diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css index cb58e71c..c2bc271d 100644 --- a/copyparty/web/browser.css +++ b/copyparty/web/browser.css @@ -67,6 +67,11 @@ a, #files tbody div a:last-child { background: #161616; text-decoration: underline; } +#files thead { + background: #333; + position: sticky; + top: 0; +} #files thead a { color: #999; font-weight: normal; @@ -183,11 +188,21 @@ a, #files tbody div a:last-child { color: #840; text-shadow: 0 0 .3em #b80; } -#files tbody tr.sel td { +#files tbody tr.sel td, +#ggrid a.sel { color: #fff; background: #925; border-color: #c37; } +#files tbody tr.sel:hover td, +#ggrid a.sel:hover { + color: #fff; + background: #a36; + border-color: #d48; +} +#ggrid a.sel { + box-shadow: 0 .1em .7em #b36; +} #files tr.sel a { color: #fff; } @@ -719,7 +734,9 @@ input[type="checkbox"]:checked+label { border: 1px solid #444; border-radius: .3em; padding: .5em; - margin: 0 1.5em 0 .4em; + margin: 0 1.5em 1em .4em; + position: sticky; + top: 0; } #ghead .btn { position: relative; diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index 6f6b37b6..e06d71c0 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -745,7 +745,7 @@ var thegrid = (function () { } }; - var click = function (e) { + var btnclick = function (e) { ev(e); var s = this.getAttribute('s'), z = this.getAttribute('z'); @@ -765,12 +765,13 @@ var thegrid = (function () { var links = QSA('#ghead>a'); for (var a = 0; a < links.length; a++) - links[a].onclick = click; + links[a].onclick = btnclick; ebi('gridsel').onclick = function (e) { ev(e); r.sel = !r.sel; bcfg_set('gridsel', r.sel); + r.loadsel(); }; r.setvis = function (vis) { @@ -793,15 +794,34 @@ var thegrid = (function () { } setsz(); + function seltgl(e) { + ev(e); + var oth = ebi(this.getAttribute('ref')), + td = oth.parentNode.nextSibling, + tr = td.parentNode; + + td.click(); + this.setAttribute('class', tr.getAttribute('class')); + } + + r.loadsel = function () { + var ths = QSA('#ggrid>a'); + for (var a = 0, aa = ths.length; a < aa; a++) { + ths[a].onclick = r.sel ? seltgl : null; + ths[a].setAttribute('class', ebi(ths[a].getAttribute('ref')).parentNode.parentNode.getAttribute('class')); + } + } + function loadgrid() { if (!r.dirty) - return; + return r.loadsel(); var html = []; var tr = lfiles.tBodies[0].rows; for (var a = 0; a < tr.length; a++) { var ao = tr[a].cells[1].firstChild, href = esc(ao.getAttribute('href')), + ref = ao.getAttribute('id'), isdir = href.split('?')[0].slice(-1)[0] == '/', ihref = href; @@ -830,13 +850,13 @@ var thegrid = (function () { ihref = '/.cpr/ico/' + ihref.slice(0, -1); } - html.push('' + - ao.innerHTML + ''); + html.push('' + ao.innerHTML + ''); } lfiles.style.display = 'none'; gfiles.style.display = 'block'; ebi('ggrid').innerHTML = html.join('\n'); + r.loadsel(); } if (r.en) { @@ -920,6 +940,19 @@ document.onkeydown = function (e) { if (k == 'KeyT') return ebi('thumbs').click(); + + if (window['thegrid'] && thegrid.en) { + if (k == 'KeyS') + return ebi('gridsel').click(); + + if (k == 'KeyA') + return QSA('#ghead>a[z]')[0].click(); + + if (k == 'KeyD') + return QSA('#ghead>a[z]')[1].click(); + } + + }; @@ -1943,6 +1976,8 @@ var msel = (function () { } function selui() { clmod(ebi('wtoggle'), 'sel', getsel().length); + if (window['thegrid']) + thegrid.loadsel(); } function seltgl(e) { ev(e);