Merge commit '47e4220c70787a80ab79e518d5b77e544e608c7e' into hovudstraum

This commit is contained in:
Til Schmitter 2026-05-02 15:31:23 +02:00
commit ffb69a38fb
2 changed files with 72 additions and 70 deletions

View file

@ -659,11 +659,15 @@ the main tabs in the ui
* `[🔎]` [search](#searching) by size, date, path/name, mp3-tags ... * `[🔎]` [search](#searching) by size, date, path/name, mp3-tags ...
* `[🧯]` [unpost](#unpost): undo/delete accidental uploads * `[🧯]` [unpost](#unpost): undo/delete accidental uploads
* `[🚀]` and `[🎈]` are the [uploaders](#uploading) * `[🚀]` and `[🎈]` are the [uploaders](#uploading)
* `[📟]` send-msg: either to server-log or into textfiles if `--urlform save`
* `[⚙️]` client config options
## quick actions (+)
* `[📂]` mkdir: create directories * `[📂]` mkdir: create directories
* `[📝]` new-file: create a new textfile * `[📝]` new-file: create a new textfile
* `[📟]` send-msg: either to server-log or into textfiles if `--urlform save` * `[🚀]` upload: quick way to pick files for upload
* `[🎺]` audio-player config options
* `[⚙️]` general client config options
## hotkeys ## hotkeys
@ -732,9 +736,9 @@ the browser has the following hotkeys (always qwerty)
## navpane ## navpane
switching between breadcrumbs or navpane opening the navpane
click the `🌲` or pressing the `B` hotkey to toggle between breadcrumbs path (default), or a navpane (tree-browser sidebar thing) clicking the `≡` or pressing the `B` hotkey toggles the navpane (tree-browser sidebar thing)
* `[+]` and `[-]` (or hotkeys `A`/`D`) adjust the size * `[+]` and `[-]` (or hotkeys `A`/`D`) adjust the size
* `[🎯]` jumps to the currently open folder * `[🎯]` jumps to the currently open folder
@ -747,7 +751,7 @@ click the `🌲` or pressing the `B` hotkey to toggle between breadcrumbs path (
## thumbnails ## thumbnails
press `g` or `田` to toggle grid-view instead of the file listing and `t` toggles icons / thumbnails press `g` or use the view mode buttons in the top left to toggle grid-view instead of the file listing and `t` toggles icons / thumbnails
* can be made default globally with `--grid` or per-volume with volflag `grid` * can be made default globally with `--grid` or per-volume with volflag `grid`
* enable by adding `?imgs` to a link, or disable with `?imgs=0` * enable by adding `?imgs` to a link, or disable with `?imgs=0`
@ -910,9 +914,7 @@ dropping files into the browser also lets you see if they exist on the server
![copyparty-fsearch-fs8](https://user-images.githubusercontent.com/241032/129635361-c79286f0-b8f1-440e-aaf4-6e929428fac9.png) ![copyparty-fsearch-fs8](https://user-images.githubusercontent.com/241032/129635361-c79286f0-b8f1-440e-aaf4-6e929428fac9.png)
when you drag/drop files into the browser, you will see two dropzones: `Upload` and `Search` toggle the `[🔎]` switch in the upload options to search for files instead of uploading
> on a phone? toggle the `[🔎]` switch green before tapping the big yellow Search button to select your files
the files will be hashed on the client-side, and each hash is sent to the server, which checks if that file exists somewhere the files will be hashed on the client-side, and each hash is sent to the server, which checks if that file exists somewhere
@ -982,6 +984,8 @@ file selection: click somewhere on the line (not the link itself), then:
you can copy/move files across browser tabs (cut/copy in one tab, paste in another) you can copy/move files across browser tabs (cut/copy in one tab, paste in another)
you can drag/drop selected files into other folders
## shares ## shares
@ -1158,7 +1162,7 @@ some highlights:
click the `play` link next to an audio file, or copy the link target to [share it](https://a.ocv.me/pub/demo/music/Ubiktune%20-%20SOUNDSHOCK%202%20-%20FM%20FUNK%20TERRROR!!/#af-1fbfba61&t=18) (optionally with a timestamp to start playing from, like that example does) click the `play` link next to an audio file, or copy the link target to [share it](https://a.ocv.me/pub/demo/music/Ubiktune%20-%20SOUNDSHOCK%202%20-%20FM%20FUNK%20TERRROR!!/#af-1fbfba61&t=18) (optionally with a timestamp to start playing from, like that example does)
open the `[🎺]` media-player-settings tab to configure it, open the `[⚙]` configuration options and go to the `[🎵]` media player section to configure it,
* "switches": * "switches":
* `[🔁]` repeats one single song forever * `[🔁]` repeats one single song forever
* `[🔀]` shuffles the files inside each folder * `[🔀]` shuffles the files inside each folder
@ -1210,7 +1214,7 @@ you can use foobar2000, deadbeef, just about any standalone player should work -
alternatively, you can create the playlist using copyparty itself: alternatively, you can create the playlist using copyparty itself:
* open the `[🎺]` media-player-settings tab and enable the `[📻]` create-playlist feature -- this adds two new buttons in the bottom-right tray, `[📻add]` and `[📻copy]` which appear when you listen to music, or when you select a few audiofiles * open the `[⚙]` configuration options, go to the `[🎵]` media player section and enable the `[📻]` create-playlist feature -- this adds two new buttons in the bottom-right tray, `[📻add]` and `[📻copy]` which appear when you listen to music, or when you select a few audiofiles
* click the `📻add` button while a song is playing (or when you've selected some songs) and they'll be added to "the list" (you can't see it yet) * click the `📻add` button while a song is playing (or when you've selected some songs) and they'll be added to "the list" (you can't see it yet)
@ -1299,6 +1303,12 @@ see [./srv/expand/](./srv/expand/) for usage and examples
search by size, date, path/name, mp3-tags, ... search by size, date, path/name, mp3-tags, ...
by default, the `[🔍]` search button shows the folder search bar.
search for files within a folder and optionally its subfolders.
for extended search options, use the dropdown arrow to open the full search UI
![copyparty-search-fs8](https://user-images.githubusercontent.com/241032/129635365-c0ff2a9f-0ee5-4fc3-8bb6-006033cf67b8.png) ![copyparty-search-fs8](https://user-images.githubusercontent.com/241032/129635365-c0ff2a9f-0ee5-4fc3-8bb6-006033cf67b8.png)
when started with `-e2dsa` copyparty will scan/index all your files. This avoids duplicates on upload, and also makes the volumes searchable through the web-ui: when started with `-e2dsa` copyparty will scan/index all your files. This avoids duplicates on upload, and also makes the volumes searchable through the web-ui:

View file

@ -2,6 +2,7 @@
var J_BRW = 1; var J_BRW = 1;
// disables emojis
var fun_tgl = sread('fun_tgl'); var fun_tgl = sread('fun_tgl');
if( fun_tgl == null) if( fun_tgl == null)
swrite('fun_tgl', 1); swrite('fun_tgl', 1);
@ -1350,7 +1351,6 @@ ebi('op_cfg').innerHTML = (
var s = subSettings.children[ii]; var s = subSettings.children[ii];
var info = tt.parse(s.getAttribute('tt')); var info = tt.parse(s.getAttribute('tt'));
s.removeAttribute('tt'); s.removeAttribute('tt');
//s.href = '#' + sId;
section += '<div id="' + subSettings.id + '" class="setting">' + section += '<div id="' + subSettings.id + '" class="setting">' +
s.outerHTML + s.outerHTML +
((info != null && info.length > 0) ? '<p class="s_desc">' + info + '</p>' : '') + ((info != null && info.length > 0) ? '<p class="s_desc">' + info + '</p>' : '') +
@ -1528,9 +1528,6 @@ function goto(dest) {
clmod(obj[a], 'vis'); clmod(obj[a], 'vis');
if (dest) { if (dest) {
if(dest == 'mkdir' || dest == 'new_md')
return;
var lnk = QS('#ops>a[data-dest=' + dest + ']'), var lnk = QS('#ops>a[data-dest=' + dest + ']'),
nps = lnk.getAttribute('data-perm'); nps = lnk.getAttribute('data-perm');
@ -1569,6 +1566,7 @@ function goto(dest) {
ebi('srchfolder_div').style.display = dest == 'search' ? 'block' : 'none'; ebi('srchfolder_div').style.display = dest == 'search' ? 'block' : 'none';
clmod(document.documentElement, 'op_open', dest); clmod(document.documentElement, 'op_open', dest);
// enables the use of keyboard page nav on modals
clmod(document.documentElement, 'noscroll', QS('.modal.vis')); clmod(document.documentElement, 'noscroll', QS('.modal.vis'));
if (treectl) if (treectl)
@ -2471,6 +2469,7 @@ function auto_grad(can, color, color2) {
return g; return g;
} }
// buffer/position bar // buffer/position bar
var pbar = (function () { var pbar = (function () {
var r = {}, var r = {},
@ -2586,22 +2585,21 @@ var pbar = (function () {
} }
var step = sm > 1 ? 1 : sm > 0.4 ? 3 : sm > 0.05 ? 30 : 720; var step = sm > 1 ? 1 : sm > 0.4 ? 3 : sm > 0.05 ? 30 : 720;
if(false){
bctx.fillStyle = light && !dy ? 'rgba(0,0,0,0.15)' : 'rgba(255, 255, 255, 0.15)';
for (var p = step, mins = adur / 10; p <= mins; p += step)
bctx.fillRect(Math.floor(sm * p * 10), 0, 2, pc.h);
step = sm > 0.15 ? 1 : sm > 0.05 ? 10 : 360; //bctx.fillStyle = light && !dy ? 'rgba(0,0,0,0.15)' : 'rgba(255, 255, 255, 0.15)';
bctx.fillStyle = light && !dy ? 'rgba(0, 0, 0, 0.5)' : 'rgba(255, 255, 255, 0.5)'; //for (var p = step, mins = adur / 10; p <= mins; p += step)
for (var p = step, mins = adur / 60; p <= mins; p += step) // bctx.fillRect(Math.floor(sm * p * 10), 0, 2, pc.h);
bctx.fillRect(Math.floor(sm * p * 60), 0, 2, pc.h);
step = sm > 0.33 ? 1 : sm > 0.15 ? 5 : sm > 0.05 ? 10 : sm > 0.01 ? 60 : 720; //step = sm > 0.15 ? 1 : sm > 0.05 ? 10 : 360;
bctx.fillStyle = dz ? '#0f0' : dy ? '#999' : light ? 'rgba(0, 0, 0, 0.9)' : 'rgb(255, 255, 255)'; //bctx.fillStyle = light && !dy ? 'rgba(0, 0, 0, 0.5)' : 'rgba(255, 255, 255, 0.5)';
for (var p = step, mins = adur / 60; p <= mins; p += step) { //for (var p = step, mins = adur / 60; p <= mins; p += step)
bctx.fillText(p, Math.floor(sm * p * 60 + 3), pc.h / 3); // bctx.fillRect(Math.floor(sm * p * 60), 0, 2, pc.h);
}
} //step = sm > 0.33 ? 1 : sm > 0.15 ? 5 : sm > 0.05 ? 10 : sm > 0.01 ? 60 : 720;
//bctx.fillStyle = dz ? '#0f0' : dy ? '#999' : light ? 'rgba(0, 0, 0, 0.9)' : 'rgb(255, 255, 255)';
//for (var p = step, mins = adur / 60; p <= mins; p += step) {
// bctx.fillText(p, Math.floor(sm * p * 60 + 3), pc.h / 3);
//}
step = sm > 0.2 ? 10 : sm > 0.1 ? 30 : sm > 0.01 ? 60 : sm > 0.005 ? 720 : 1440; step = sm > 0.2 ? 10 : sm > 0.1 ? 30 : sm > 0.01 ? 60 : sm > 0.005 ? 720 : 1440;
bctx.fillStyle = light ? 'rgba(0,0,0,1)' : 'rgba(255,255,255,1)'; bctx.fillStyle = light ? 'rgba(0,0,0,1)' : 'rgba(255,255,255,1)';
@ -5994,6 +5992,8 @@ var thegrid = (function () {
var ico2 = ebi('listicon_template').cloneNode(true); var ico2 = ebi('listicon_template').cloneNode(true);
clmod(ico1, 'on', 't'); clmod(ico1, 'on', 't');
clmod(ico2, 'on', 't'); clmod(ico2, 'on', 't');
// file list header
ebi('wtc').innerHTML = ( ebi('wtc').innerHTML = (
ico1.outerHTML + ico1.outerHTML +
ico2.outerHTML + ico2.outerHTML +
@ -6026,10 +6026,8 @@ var thegrid = (function () {
l = this.getAttribute('l'), l = this.getAttribute('l'),
grdbtn = clgot(this, 'grdbtn'); grdbtn = clgot(this, 'grdbtn');
if(grdbtn) { if(grdbtn)
ebi('griden').click();
return; return;
}
if (z) if (z)
return setsz(z > 0 ? r.sz * z : r.sz / (-z)); return setsz(z > 0 ? r.sz * z : r.sz / (-z));
@ -6135,11 +6133,8 @@ var thegrid = (function () {
function gselclick(e) { function gselclick(e) {
var oth = ebi(this.closest('a').getAttribute('ref')), var oth = ebi(this.closest('a').getAttribute('ref')),
td = oth.closest('td').nextSibling, td = oth.closest('td').nextSibling;
tr = td.parentNode;
//this.checked = !this.checked;
td.onclick.call(td, e); td.onclick.call(td, e);
// clmod(this, 'sel', clgot(tr, 'sel'));
} }
function gclick2(e) { function gclick2(e) {
@ -6171,9 +6166,6 @@ var thegrid = (function () {
if (e.shiftKey) if (e.shiftKey)
return r.loadsel(); return r.loadsel();
clmod(this, 'sel', clgot(tr, 'sel')); clmod(this, 'sel', clgot(tr, 'sel'));
var chk = this.getElementsByTagName('input')[0];
if(chk) chk.checked = clgot(tr, 'sel');
} }
else if (in_tree && !have_sel) else if (in_tree && !have_sel)
in_tree.click(); in_tree.click();
@ -6513,7 +6505,6 @@ var thegrid = (function () {
pbar.onresize(); pbar.onresize();
vbar.onresize(); vbar.onresize();
}); });
bcfg_bind(r, 'gaen', 'gauto', !!dgauto, function (v) { bcfg_bind(r, 'gaen', 'gauto', !!dgauto, function (v) {
if (r.en && sread("griden") != 1) { if (r.en && sread("griden") != 1) {
r.en = false; r.en = false;
@ -7075,7 +7066,6 @@ var search_ui = (function () {
is_txt = id.slice(-1) == 'v', is_txt = id.slice(-1) == 'v',
is_chk = id.slice(-1) == 'c'; is_chk = id.slice(-1) == 'c';
console.log(id);
if (is_txt) { if (is_txt) {
var chk = ebi(id.slice(0, -1) + 'c'); var chk = ebi(id.slice(0, -1) + 'c');
chk.checked = ((v + '').length > 0); chk.checked = ((v + '').length > 0);
@ -7619,7 +7609,7 @@ var treectl = (function () {
get_tree("", get_evpath(), true); get_tree("", get_evpath(), true);
r.show(); r.show();
ebi('treeToggleBtn').classList.add('on'); clmod(ebi('treeToggleBtn'), 'on', true)
} }
r.show = function () { r.show = function () {
@ -7634,6 +7624,7 @@ var treectl = (function () {
clmod(ebi('wfp'), 'shifted', false); clmod(ebi('wfp'), 'shifted', false);
window.addEventListener('scroll', onscroll); window.addEventListener('scroll', onscroll);
window.addEventListener('resize', onresize); window.addEventListener('resize', onresize);
// accounts for animation delay
setTimeout(function () { setTimeout(function () {
onresize(); onresize();
aligngriditems(); aligngriditems();
@ -7650,7 +7641,7 @@ var treectl = (function () {
if (!nonav) if (!nonav)
ebi('path').style.display = ''; ebi('path').style.display = '';
ebi('treeToggleBtn').classList.remove('on'); clmod(ebi('treeToggleBtn'), 'on', false)
}; };
r.toggleTree = function (e, nostore) { r.toggleTree = function (e, nostore) {
@ -9151,7 +9142,7 @@ var settheme = (function () {
var html = [], var html = [],
cb = ebi('themes'), cb = ebi('themes'),
itheme = ax.indexOf(theme[0]) * 2 + (light ? 1 : 0), itheme = ax.indexOf(theme[0]) * 2 + (light ? 1 : 0),
names = ['classic dark', 'classic light', 'flat dark', 'flat light', 'vice', 'hotdog stand', 'hacker', 'hi-con', 'phi95 dark', 'phi95', 'evil blue']; names = ['classic dark', 'classic light', 'flat dark', 'flat light', 'vice', 'hotdog stand', 'hacker', 'hi-con', 'phi95 dark', 'phi95'];
for (var a = 0; a < themes; a++) for (var a = 0; a < themes; a++)
html.push('<option value="{0}">{0} ┃ {1}</option>'.format(a, names[a] || 'custom')); html.push('<option value="{0}">{0} ┃ {1}</option>'.format(a, names[a] || 'custom'));
@ -10356,7 +10347,8 @@ ebi('files').onclick = ebi('docul').onclick = function (e) {
fun(); fun();
else else
modal.confirm(L.f_bigtxt.format(f2f(sz / 1024 / 1024, 1)), fun, function () { modal.confirm(L.f_bigtxt.format(f2f(sz / 1024 / 1024, 1)), fun, function () {
modal.confirm(L.f_bigtxt2, tfun, null)}); modal.confirm(L.f_bigtxt2, tfun, null)
});
return ev(e); return ev(e);
} }