From 234eddec90754ef6164fbc88b9ae9658ae9185fb Mon Sep 17 00:00:00 2001 From: ed Date: Sun, 28 Sep 2025 01:14:00 +0000 Subject: [PATCH] filesize formats; closes #184 --- copyparty/__main__.py | 1 + copyparty/authsrv.py | 1 + copyparty/web/browser.css | 22 ++++++++++ copyparty/web/browser.js | 61 ++++++++++++++++++++------ copyparty/web/util.js | 90 ++++++++++++++++++++++++++++++++++++--- tests/util.py | 2 +- 6 files changed, 158 insertions(+), 19 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 7b52db4f..1a0009f2 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1757,6 +1757,7 @@ def add_ui(ap, retry: int): ap2.add_argument("--grid", action="store_true", help="show grid/thumbnails by default (volflag=grid)") ap2.add_argument("--gsel", action="store_true", help="select files in grid by ctrl-click (volflag=gsel)") ap2.add_argument("--localtime", action="store_true", help="default to local timezone instead of UTC") + ap2.add_argument("--ui-filesz", metavar="FMT", type=u, default="1", help="default filesize format; one of these: 0, 1, 2, 2c, 3, 3c, 4, 4c, 5, 5c, fuzzy (see UI)") ap2.add_argument("--lang", metavar="LANG", type=u, default="eng", help="language, for example \033[32meng\033[0m / \033[32mnor\033[0m / ...") ap2.add_argument("--theme", metavar="NUM", type=int, default=0, help="default theme to use (0..%d)" % (THEMES - 1,)) ap2.add_argument("--themes", metavar="NUM", type=int, default=THEMES, help="number of themes installed") diff --git a/copyparty/authsrv.py b/copyparty/authsrv.py index 7f3097b4..69f4caf2 100644 --- a/copyparty/authsrv.py +++ b/copyparty/authsrv.py @@ -3003,6 +3003,7 @@ class AuthSrv(object): "dvol": self.args.au_vol, "idxh": int(self.args.ih), "dutc": not self.args.localtime, + "dfszf": self.args.ui_filesz, "themes": self.args.themes, "turbolvl": self.args.turbo, "nosubtle": self.args.nosubtle, diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css index 30f3a375..0885ce76 100644 --- a/copyparty/web/browser.css +++ b/copyparty/web/browser.css @@ -84,6 +84,13 @@ --sort-1: #fb0; --sort-2: #d09; + --sz-b: #aaa; + --sz-k: #4ff; + --sz-m: var(--tab-alt); + --sz-g: var(--a); + --sz-t: var(--sz-g); + --sz-p: var(--sz-t); + --srv-1: #aaa; --srv-2: #a73; --srv-3: #f4c; @@ -187,6 +194,9 @@ html.y { --sort-1: #059; --sort-2: #f5d; + --sz-b: #777; + --sz-k: #380; + --srv-1: #555; --srv-2: #c83; --srv-3: #c0a; @@ -344,6 +354,9 @@ html.cz { --btn-1-bb: .2em solid #e90; --btn-1-bs: 0 .1em .8em rgba(255,205,0,0.9); + --sz-b: #ddd; + --sz-k: #c9f; + --srv-3: #fff; --u2-tab-b1: var(--bg-d3); @@ -740,6 +753,15 @@ html.y #files tr.fade a { #files tbody tr td:last-child { white-space: nowrap; } +#files span.fsz_B { color: var(--sz-b); } +#files span.fsz_K { color: var(--sz-k); } +#files span.fsz_M { color: var(--sz-m); } +#files span.fsz_G { color: var(--sz-g); } +#files span.fsz_T { color: var(--sz-t); } +#files span.fsz_P { color: var(--sz-p); } +html.y #files span.fsz_G, +html.y #files span.fsz_T, +html.y #files span.fsz_P { font-weight: bold } #files thead th[style] { width: auto !important; } diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js index b81d5d8a..503da0c0 100644 --- a/copyparty/web/browser.js +++ b/copyparty/web/browser.js @@ -209,6 +209,7 @@ var Ls = { "u_nav_b": 'FilesOne folder', "cl_opts": "switches", + "cl_hfsz": "filesize", "cl_themes": "theme", "cl_langs": "language", "cl_ziptype": "folder download", @@ -11148,7 +11149,7 @@ var Ls = { "fd_warn2": "Sista chansen! Det finns inget sätt att ångra detta. Radera?", "fc_ok": "klippte {0} objekt", - "fc_warn": 'klippte {0} objekt, men:\n\nendast denna webbläsarflik kan klistra in dem\n(eftersom urvalet är så enormt stort)', + "fc_warn": 'klippte {0} objekt, men:\n\nendast denna webbläsarflik kan klistra in dem\n(eftersom urvalet är så enormt stort)', "fcc_ok": "kopierade {0} objekt till urklippet", "fcc_warn": 'kopierade {0} objekt till urklippet, men:\n\nendast denna webbläsarflik kan klistra in dem\n(eftersom urvalet är så enormt stort)', @@ -12858,6 +12859,22 @@ ebi('op_cfg').innerHTML = ( ' \n' + '\n' + '
\n' + + '

' + L.cl_hfsz + '

\n' + + '
\n' + + '
\n' + + '
\n' + '

' + L.cl_themes + '

\n' + '
\n' + '
\n' + @@ -18301,7 +18318,8 @@ var search_ui = (function () { for (var a = 0; a < res.hits.length; a++) { var r = res.hits[a], ts = parseInt(r.ts), - sz = esc(r.sz + ''), + sz = parseInt(r.sz), + hsz = filesizefun(sz), rp = esc(uricom_dec(r.rp + '')), ext = rp.lastIndexOf('.') > 0 ? rp.split('.').pop().split('?')[0] : '%', id = 'f-' + ('00000000' + crc32(rp)).slice(-8); @@ -18314,7 +18332,8 @@ var search_ui = (function () { ext = '%'; var links = linksplit(r.rp + '', id).join('/'), - nodes = ['-
' + links + '
', sz]; + nodes = ['-
' + links + + '
' + hsz]; for (var b = 0; b < tagord.length; b++) { var k = esc(tagord[b]), @@ -19240,7 +19259,8 @@ var treectl = (function () { var cl = /\.PARTIAL$/.exec(fname) ? ' class="fade"' : '', ln = ['' + tn.lead + '' + hname + '', tn.sz]; + top + tn.href + '" id="' + id + '">' + hname + + '' + filesizefun(tn.sz)]; for (var b = 0; b < res.taglist.length; b++) { var k = esc(res.taglist[b]), @@ -20086,6 +20106,31 @@ var settheme = (function () { })(); +var setfszf = (function () { + function freshen() { + var cb = ebi('fszfmt'), + fmt = sread("fszfmt", humansize_fmts) || window.dfszf; + if (!has(humansize_fmts, fmt)) + fmt = '1'; + window.filesizefun = window['humansize_' + fmt]; + cb.onchange = onch; + if (cb.value != fmt) + cb.value = fmt; + } + function onch(e) { + ev(e); + setfmt(ebi('fszfmt').value) + } + function setfmt(fmt) { + swrite("fszfmt", fmt); + freshen(); + treectl.gentab(get_evpath(), treectl.lsc); + } + freshen(); + return setfmt; +})(); + + (function () { function freshen() { lang = sread("cpp_lang", LANGS) || lang; @@ -21245,14 +21290,6 @@ function reload_browser() { ebi('path').appendChild(o); } - var oo = QSA('#files>tbody>tr>td:nth-child(3)'); - for (var a = 0, aa = oo.length; a < aa; a++) { - var sz = oo[a].textContent.replace(/ +/g, ""), - hsz = sz.replace(/\B(?=(\d{3})+(?!\d))/g, " "); - - oo[a].textContent = hsz; - } - reload_mp(); try { showsort(ftab); } catch (ex) { } makeSortable(ftab, function () { diff --git a/copyparty/web/util.js b/copyparty/web/util.js index 5a8769a0..95043b4a 100644 --- a/copyparty/web/util.js +++ b/copyparty/web/util.js @@ -960,15 +960,93 @@ function f2f(val, nd) { } +var HSZ_U = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; function humansize(b, terse) { - var i = 0, u = ['B', 'KB', 'MB', 'GB', 'TB', 'PB']; - while (b >= 1000 && i < u.length - 1) { - b /= 1024; - i += 1; - } + var i = 0; + while (b >= 1000 && i < 5) { b /= 1024; i += 1; } return (f2f(b, b >= 100 ? 0 : b >= 10 ? 1 : 2) + - ' ' + (terse ? u[i].charAt(0) : u[i])); + ' ' + (terse ? HSZ_U[i].charAt(0) : HSZ_U[i])); } +function humansize_su(b) { + var i = 0; + while (b >= 1000 && i < 5) { b /= 1024; i += 1; } + return [b, HSZ_U[i]]; +} +function humansize_0(b) { + return '' + b; +} +function humansize_1(b) { + return ('' + b).replace(/\B(?=(\d{3})+(?!\d))/g, " "); +} +function humansize_2g(b) { + var z = humansize_su(b), u = z[1].charAt(0); b = z[0]; + return [f2f(b, b >= 100 ? 0 : b >= 10 ? 1 : 2) + ' ' + u, u]; +} +function humansize_3g(b) { + var z = humansize_su(b), u = z[1].charAt(0); b = z[0]; + return [f2f(b, b >= 10 ? 0 : 1) + ' ' + u, u]; +} +function humansize_4g(b) { + var z = humansize_su(b), u = z[1]; b = z[0]; + return [parseFloat(b.toFixed(b >= 100 ? 0 : b >= 10 ? 1 : 2)) + ' ' + u, u.charAt(0)]; +} +function humansize_5g(b) { + var z = humansize_su(b), u = z[1]; b = z[0]; + return [parseFloat(b.toFixed(b >= 10 ? 0 : 1)) + ' ' + u, u.charAt(0)]; +} +function humansize_2(b) { + return humansize_2g(b)[0]; +} +function humansize_3(b) { + return humansize_3g(b)[0]; +} +function humansize_4(b) { + return humansize_4g(b)[0]; +} +function humansize_5(b) { + return humansize_5g(b)[0]; +} +function humansize_2c(b) { + var v = humansize_2g(b); + return '' + v[0] + ''; +} +function humansize_3c(b) { + var v = humansize_3g(b); + return '' + v[0] + ''; +} +function humansize_4c(b) { + var v = humansize_4g(b); + return '' + v[0] + ''; +} +function humansize_5c(b) { + var v = humansize_5g(b); + return '' + v[0] + ''; +} +function humansize_fuzzy(b) { + if (b <= 0) return "yes"; + if (b <= 80) return "hullkort"; + if (b <= 368640) return "5¼ DD"; + if (b <= 1474560) return "save icon"; + if (b <= 2880000) return "3½ Extended"; + if (b <= 13107200) return "C90 Tape"; + if (b <= 21000000) return "Floptical"; + if (b <= 33554432) return "MPMan F10"; + if (b <= 50000000) return "creditcardCD"; + if (b <= 100663296) return "Zipdisk"; + if (b <= 170000000) return "MD"; + if (b <= 220200960) return "8cm CD"; + if (b <= 737280000) return "CD-R"; + if (b <= 900000000) return "UMD"; + if (b <= 1300000000) return "GD-ROM"; + if (b <= 4700000000) return "DVD"; + if (b <= 9400000000) return "DVD-DL"; + return "LTO"; +} +var humansize_fmts = ['0', '1', '2', '2c', '3', '3c', '4', '4c', '5', '5c', 'fuzzy']; +window.filesizefun = (function () { + var v = sread('fszfmt', humansize_fmts); + return window['humansize_' + (v || window.dfszf)] || humansize_1; +})(); function humantime(v) { diff --git a/tests/util.py b/tests/util.py index 7438ab23..f8448474 100644 --- a/tests/util.py +++ b/tests/util.py @@ -155,7 +155,7 @@ class Cfg(Namespace): ex = "gid uid" ka.update(**{k: -1 for k in ex.split()}) - ex = "hash_mt hsortn qdel safe_dedup scan_pr_r scan_pr_s scan_st_r srch_time tail_fd tail_rate th_spec_p u2abort u2j u2sz unp_who" + ex = "hash_mt hsortn qdel safe_dedup scan_pr_r scan_pr_s scan_st_r srch_time tail_fd tail_rate th_spec_p u2abort u2j u2sz ui_filesz unp_who" ka.update(**{k: 1 for k in ex.split()}) ex = "ac_convt au_vol dl_list du_iwho mtab_age reg_cap s_thead s_tbody tail_tmax tail_who th_convt ups_who ver_iwho zip_who"