diff --git a/copyparty/__main__.py b/copyparty/__main__.py
index e68bde0c..38fb9d10 100644
--- a/copyparty/__main__.py
+++ b/copyparty/__main__.py
@@ -483,6 +483,7 @@ def run_argparse(argv: list[str], formatter: Any, retry: bool) -> argparse.Names
ap2.add_argument("--no-dedup", action="store_true", help="disable symlink/hardlink creation; copy file contents instead")
ap2.add_argument("--sparse", metavar="MiB", type=int, default=4, help="windows-only: minimum size of incoming uploads through up2k before they are made into sparse files")
ap2.add_argument("--turbo", metavar="LVL", type=int, default=0, help="configure turbo-mode in up2k client; 0 = off and warn if enabled, 1 = off, 2 = on, 3 = on and disable datecheck")
+ ap2.add_argument("--u2sort", metavar="TXT", type=u, default="s", help="upload order; s=smallest-first, n=alphabetical, fs=force-s, fn=force-n -- alphabetical is a bit slower on fiber/LAN but makes it easier to eyeball if everything went fine")
ap2 = ap.add_argument_group('network options')
ap2.add_argument("-i", metavar="IP", type=u, default="0.0.0.0", help="ip to bind (comma-sep.)")
@@ -755,6 +756,12 @@ def main(argv: Optional[list[str]] = None) -> None:
except:
raise Exception("invalid value for -p")
+ for arg, kname, okays in [["--u2sort", "u2sort", "s n fs fn"]]:
+ val = unicode(getattr(al, kname))
+ if val not in okays.split():
+ zs = "argument {} cannot be '{}'; try one of these: {}"
+ raise Exception(zs.format(arg, val, okays))
+
if HAVE_SSL:
if al.ssl_ver:
configure_ssl_ver(al)
diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py
index 094c1186..a54bce3e 100644
--- a/copyparty/httpcli.py
+++ b/copyparty/httpcli.py
@@ -2413,6 +2413,7 @@ class HttpCli(object):
"dtheme": self.args.theme,
"themes": self.args.themes,
"turbolvl": self.args.turbo,
+ "u2sort": self.args.u2sort,
}
if self.args.js_browser:
diff --git a/copyparty/web/browser.html b/copyparty/web/browser.html
index e082a8b2..39285bae 100644
--- a/copyparty/web/browser.html
+++ b/copyparty/web/browser.html
@@ -148,7 +148,8 @@
have_del = {{ have_del|tojson }},
have_unpost = {{ have_unpost|tojson }},
have_zip = {{ have_zip|tojson }},
- turbolvl = {{ turbolvl|tojson }},
+ turbolvl = {{ turbolvl }},
+ u2sort = "{{ u2sort }}",
have_emp = {{ have_emp|tojson }},
txt_ext = "{{ txt_ext }}",
{% if no_prism %}no_prism = 1,{% endif %}
diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js
index 0ea105a5..cb54bc2c 100644
--- a/copyparty/web/browser.js
+++ b/copyparty/web/browser.js
@@ -113,6 +113,8 @@ var Ls = {
"cut_flag": "ensure only one tab is uploading at a time $N -- other tabs must have this enabled too $N -- only affects tabs on the same domain",
+ "cut_az": "upload files in alphabetical order, rather than smallest-file-first$N$Nalphabetical order can make it easier to eyeball if something went wrong on the server, but it makes uploading slightly slower on fiber / LAN",
+
"cft_text": "favicon text (blank and refresh to disable)",
"cft_fg": "foreground color",
"cft_bg": "background color",
@@ -438,6 +440,8 @@ var Ls = {
"cut_flag": "samkjører nettleserfaner slik at bare én $N kan holde på med befaring / opplastning $N -- andre faner må også ha denne skrudd på $N -- fungerer kun innenfor samme domene",
+ "cut_az": "last opp filer i alfabetisk rekkefølge, istedenfor minste-fil-først$N$Nalfabetisk kan gjøre det lettere å anslå om alt gikk bra, men er bittelitt tregere på fiber / LAN",
+
"cft_text": "ikontekst (blank ut og last siden på nytt for å deaktivere)",
"cft_fg": "farge",
"cft_bg": "bakgrunnsfarge",
@@ -824,6 +828,7 @@ ebi('op_cfg').innerHTML = (
' turbo\n' +
' date-chk\n' +
' 💤\n' +
+ ' az\n' +
' \n' +
' \n' +
'\n' +
diff --git a/copyparty/web/md2.js b/copyparty/web/md2.js
index 81ed2fdb..7bdadb72 100644
--- a/copyparty/web/md2.js
+++ b/copyparty/web/md2.js
@@ -510,14 +510,15 @@ function setsel(s) {
// cut/copy current line
-function md_cut() {
+function md_cut(cut) {
var s = linebounds();
if (s.car != s.cdr)
return;
dom_src.setSelectionRange(s.n1, s.n2 + 1, 'forward');
setTimeout(function () {
- dom_src.setSelectionRange(s.n1, s.n1, 'forward');
+ var i = cut ? s.n1 : s.car;
+ dom_src.setSelectionRange(i, i, 'forward');
}, 1);
}
@@ -969,7 +970,7 @@ var set_lno = (function () {
return false;
}
if (ev.code == "KeyX" || ev.code == "KeyC") {
- md_cut();
+ md_cut(ev.code == "KeyX");
return true; //sic
}
}
diff --git a/copyparty/web/up2k.js b/copyparty/web/up2k.js
index 5f042b59..8eb5e299 100644
--- a/copyparty/web/up2k.js
+++ b/copyparty/web/up2k.js
@@ -663,6 +663,7 @@ function up2k_init(subtle) {
bcfg_bind(uc, 'fsearch', 'fsearch', false, set_fsearch, false);
bcfg_bind(uc, 'turbo', 'u2turbo', turbolvl > 1, draw_turbo, false);
bcfg_bind(uc, 'datechk', 'u2tdate', turbolvl < 3, null, false);
+ bcfg_bind(uc, 'az', 'u2sort', u2sort.indexOf('n') + 1, set_u2sort, false);
var st = {
"files": [],
@@ -1018,6 +1019,13 @@ function up2k_init(subtle) {
var evpath = get_evpath(),
draw_each = good_files.length < 50;
+ if (!uc.az)
+ good_files.sort(function (a, b) {
+ a = a[0].size;
+ b = b[0].size;
+ return a < b ? -1 : a > b ? 1 : 0;
+ });
+
for (var a = 0; a < good_files.length; a++) {
var fobj = good_files[a][0],
name = good_files[a][1],
@@ -1066,9 +1074,9 @@ function up2k_init(subtle) {
entry.purl + uricom_enc(entry.name)).join(' '),
'📐 ' + L.u_hashing,
''
- ], fobj.size, draw_each);
+ ], entry.size, draw_each);
- st.bytes.total += fobj.size;
+ st.bytes.total += entry.size;
st.files.push(entry);
if (!entry.size)
push_t(st.todo.handshake, entry);
@@ -1203,6 +1211,9 @@ function up2k_init(subtle) {
return false;
if (uc.multitask) {
+ if (!uc.az)
+ return st.todo.handshake.length + st.busy.handshake.length < 2;
+
var ahead = st.bytes.hashed - st.bytes.finished,
nmax = ahead < biggest_file / 8 ? 32 : 16;
@@ -2117,6 +2128,14 @@ function up2k_init(subtle) {
}
}
+ function set_u2sort() {
+ if (u2sort.indexOf('f') < 0)
+ return;
+
+ bcfg_set('u2sort', uc.az = u2sort.indexOf('n') + 1);
+ localStorage.removeItem('u2sort');
+ }
+
function nop(e) {
ev(e);
this.click();