diff --git a/copyparty/__main__.py b/copyparty/__main__.py
index f59b390f..76a11d38 100755
--- a/copyparty/__main__.py
+++ b/copyparty/__main__.py
@@ -806,6 +806,7 @@ def add_upload(ap):
ap2.add_argument("--no-dedup", action="store_true", help="disable symlink/hardlink creation; copy file contents instead (volflag=copydupes)")
ap2.add_argument("--no-dupe", action="store_true", help="reject duplicate files during upload; only matches within the same volume (volflag=nodupe)")
ap2.add_argument("--no-snap", action="store_true", help="disable snapshots -- forget unfinished uploads on shutdown; don't create .hist/up2k.snap files -- abandoned/interrupted uploads must be cleaned up manually")
+ ap2.add_argument("--u2ts", metavar="TXT", type=u, default="c", help="how to timestamp uploaded files; [\033[32mc\033[0m]=client-last-modified, [\033[32mu\033[0m]=upload-time, [\033[32mfc\033[0m]=force-c, [\033[32mfu\033[0m]=force-u (volflag=u2ts)")
ap2.add_argument("--rand", action="store_true", help="force randomized filenames, --nrand chars long (volflag=rand)")
ap2.add_argument("--nrand", metavar="NUM", type=int, default=9, help="randomized filenames length (volflag=nrand)")
ap2.add_argument("--magic", action="store_true", help="enable filetype detection on nameless uploads (volflag=magic)")
diff --git a/copyparty/cfg.py b/copyparty/cfg.py
index 53b3c318..82379761 100644
--- a/copyparty/cfg.py
+++ b/copyparty/cfg.py
@@ -42,7 +42,7 @@ def vf_bmap() -> dict[str, str]:
def vf_vmap() -> dict[str, str]:
"""argv-to-volflag: simple values"""
ret = {"th_convt": "convt", "th_size": "thsize"}
- for k in ("dbd", "lg_sbf", "md_sbf", "nrand", "sort", "unlist"):
+ for k in ("dbd", "lg_sbf", "md_sbf", "nrand", "sort", "unlist", "u2ts"):
ret[k] = k
return ret
diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py
index 22ed8d97..feb306f9 100644
--- a/copyparty/httpcli.py
+++ b/copyparty/httpcli.py
@@ -3834,6 +3834,7 @@ class HttpCli(object):
"idx": e2d,
"itag": e2t,
"dsort": vf["sort"],
+ "u2ts": vf["u2ts"],
"lifetime": vn.flags.get("lifetime") or 0,
"frand": bool(vn.flags.get("rand")),
"unlist": unlist,
@@ -3845,6 +3846,7 @@ class HttpCli(object):
"ls0": None,
"acct": self.uname,
"perms": perms,
+ "u2ts": vf["u2ts"],
"lifetime": ls_ret["lifetime"],
"frand": bool(vn.flags.get("rand")),
"def_hcols": [],
diff --git a/copyparty/up2k.py b/copyparty/up2k.py
index fc424554..ddb5a4c7 100644
--- a/copyparty/up2k.py
+++ b/copyparty/up2k.py
@@ -2339,6 +2339,9 @@ class Up2k(object):
vols = [(ptop, jcur)] if jcur else []
if vfs.flags.get("xlink"):
vols += [(k, v) for k, v in self.cur.items() if k != ptop]
+ if vfs.flags.get("up_ts", "") == "fu" or not cj["lmod"]:
+ # force upload time rather than last-modified
+ cj["lmod"] = int(time.time())
alts: list[tuple[int, int, dict[str, Any]]] = []
for ptop, cur in vols:
diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css
index 2fa65426..59879600 100644
--- a/copyparty/web/browser.css
+++ b/copyparty/web/browser.css
@@ -2502,14 +2502,14 @@ html.y #bbox-overlay figcaption a {
min-width: 24em;
}
#u2cards.w {
- width: 44em;
+ width: 48em;
text-align: left;
}
#u2cards.ww {
display: inline-block;
}
#u2etaw.w {
- width: 52em;
+ width: 55em;
text-align: right;
margin: 2em auto -2.7em auto;
}
@@ -2554,10 +2554,10 @@ html.y #bbox-overlay figcaption a {
width: 30em;
}
#u2conf.w {
- width: 48em;
+ width: 51em;
}
#u2conf.ww {
- width: 78em;
+ width: 82em;
}
#u2conf.ww #u2c3w {
width: 29em;
@@ -3054,6 +3054,16 @@ html.d #treepar {
+@media (max-width: 32em) {
+ #u2conf {
+ font-size: .9em;
+ }
+}
+@media (max-width: 28em) {
+ #u2conf {
+ font-size: .8em;
+ }
+}
@media (min-width: 70em) {
#barpos,
#barbuf {
diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js
index 46683cf6..3d0b12f3 100644
--- a/copyparty/web/browser.js
+++ b/copyparty/web/browser.js
@@ -137,6 +137,7 @@ var Ls = {
"ul_par": "parallel uploads:",
"ut_rand": "randomize filenames",
+ "ut_u2ts": "copy the last-modified timestamp$Nfrom your filesystem to the server",
"ut_mt": "continue hashing other files while uploading$N$Nmaybe disable if your CPU or HDD is a bottleneck",
"ut_ask": "ask for confirmation before upload starts",
"ut_pot": "improve upload speed on slow devices$Nby making the UI less complex",
@@ -168,6 +169,7 @@ var Ls = {
"utl_prog": "progress",
"ul_flagblk": "the files were added to the queue
however there is a busy up2k in another browser tab,
so waiting for that to finish first",
+ "ul_btnlk": "the server configuration has locked this switch into this state",
"udt_up": "Upload",
"udt_srch": "Search",
@@ -606,6 +608,7 @@ var Ls = {
"ul_par": "samtidige handl.:",
"ut_rand": "finn opp nye tilfeldige filnavn",
+ "ut_u2ts": "gi filen på serveren samme$Ntidsstempel som lokalt hos deg",
"ut_mt": "fortsett å befare køen mens opplastning foregår$N$Nskru denne av dersom du har en$Ntreg prosessor eller harddisk",
"ut_ask": "bekreft filutvalg før opplastning starter",
"ut_pot": "forbedre ytelsen på trege enheter ved å$Nforenkle brukergrensesnittet",
@@ -637,6 +640,7 @@ var Ls = {
"utl_prog": "fremdrift",
"ul_flagblk": "filene har blitt lagt i køen
men det er en annen nettleserfane som holder på med befaring eller opplastning akkurat nå,
så venter til den er ferdig først",
+ "ul_btnlk": "bryteren har blitt låst til denne tilstanden i serverens konfigurasjon",
"udt_up": "Last opp",
"udt_srch": "Søk",
@@ -1042,6 +1046,10 @@ ebi('op_up2k').innerHTML = (
' \n' +
' \n' +
' \n' +
+ '