diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css
index 3032deb9..b6c109d5 100644
--- a/copyparty/web/browser.css
+++ b/copyparty/web/browser.css
@@ -29,10 +29,10 @@ body {
position: fixed;
max-width: 34em;
background: #222;
- border: 0 solid #555;
+ border: 0 solid #777;
overflow: hidden;
margin-top: 1em;
- padding: 0 1em;
+ padding: 0 1.3em;
height: 0;
opacity: .1;
transition: opacity 0.14s, height 0.14s, padding 0.14s;
@@ -40,19 +40,31 @@ body {
border-radius: .4em;
z-index: 9001;
}
+#tt.b {
+ padding: 0 2em;
+ border-radius: .5em;
+ box-shadow: 0 .2em 1em #000;
+}
#tt.show {
- padding: 1em;
+ padding: 1em 1.3em;
+ border-width: .4em 0;
height: auto;
- border-width: .2em 0;
opacity: 1;
}
+#tt.show.b {
+ padding: 1.5em 2em;
+ border-width: .5em 0;
+}
#tt code {
background: #3c3c3c;
- padding: .2em .3em;
+ padding: .1em .3em;
border-top: 1px solid #777;
border-radius: .3em;
font-family: monospace, monospace;
- line-height: 2em;
+ line-height: 1.7em;
+}
+#tt em {
+ color: #f6a;
}
#path,
#path * {
@@ -812,11 +824,13 @@ input.eq_gain {
border-bottom: 1px solid #555;
}
#thumbs,
-#au_osd_cv {
+#au_osd_cv,
+#u2tdate {
opacity: .3;
}
#griden.on+#thumbs,
-#au_os_ctl.on+#au_osd_cv {
+#au_os_ctl.on+#au_osd_cv,
+#u2turbo.on+#u2tdate {
opacity: 1;
}
#ghead {
@@ -921,13 +935,16 @@ html.light {
}
html.light #tt {
background: #fff;
- border-color: #888;
+ border-color: #888 #000 #777 #000;
box-shadow: 0 .3em 1em rgba(0,0,0,0.4);
}
html.light #tt code {
background: #060;
color: #fff;
}
+html.light #tt em {
+ color: #d38;
+}
html.light #ops,
html.light .opbox,
html.light #srch_form {
diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js
index 2bbfca51..68ab9e9f 100644
--- a/copyparty/web/browser.js
+++ b/copyparty/web/browser.js
@@ -133,6 +133,13 @@ ebi('op_cfg').innerHTML = (
(have_zip ? (
'
\n'
) : '') +
+ '\n' +
+ '
up2k switches
\n' +
+ '
\n' +
+ '
\n' +
'\n' +
''
);
diff --git a/copyparty/web/up2k.js b/copyparty/web/up2k.js
index e08d021d..84432899 100644
--- a/copyparty/web/up2k.js
+++ b/copyparty/web/up2k.js
@@ -308,6 +308,12 @@ function U2pvis(act, btns) {
throw 42;
}
+ //console.log("oldcat %s %d, newcat %s %d, head=%d, tail=%d, file=%d, act.old=%s, act.new=%s, bz_act=%s",
+ // oldcat, this.ctr[oldcat],
+ // newcat, this.ctr[newcat],
+ // this.head, this.tail, nfile,
+ // this.is_act(oldcat), this.is_act(newcat), bz_act);
+
fo.in = newcat;
this.ctr[oldcat]--;
this.ctr[newcat]++;
@@ -319,7 +325,7 @@ function U2pvis(act, btns) {
this.addrow(nfile);
}
else if (this.is_act(oldcat)) {
- while (this.head < Math.min(this.tab.length, this.tail) && (this.head == nfile || !this.is_act(this.tab[this.head].in)))
+ while (this.head < Math.min(this.tab.length, this.tail) && this.precard[this.tab[this.head].in])
this.head++;
if (!bz_act) {
@@ -327,9 +333,10 @@ function U2pvis(act, btns) {
tr.parentNode.removeChild(tr);
}
}
- if (bz_act) {
+ else return;
+
+ if (bz_act)
this.bzw();
- }
};
this.bzw = function () {
@@ -343,7 +350,8 @@ function U2pvis(act, btns) {
while (this.head - first > this.wsz) {
var obj = ebi('f' + (first++));
- obj.parentNode.removeChild(obj);
+ if (obj)
+ obj.parentNode.removeChild(obj);
}
while (last - this.tail < this.wsz && last < this.tab.length - 2) {
var obj = ebi('f' + (++last));
@@ -376,6 +384,8 @@ function U2pvis(act, btns) {
this.changecard = function (card) {
this.act = card;
+ this.precard = has(["ok", "ng", "done"], this.act) ? {} : this.act == "bz" ? { "ok": 1, "ng": 1 } : { "ok": 1, "ng": 1, "bz": 1 };
+ this.postcard = has(["ok", "ng", "done"], this.act) ? { "bz": 1, "q": 1 } : this.act == "bz" ? { "q": 1 } : {};
this.head = -1;
this.tail = -1;
var html = [];
@@ -390,16 +400,13 @@ function U2pvis(act, btns) {
}
}
if (this.head == -1) {
- var precard = has(["ok", "ng", "done"], this.act) ? {} : this.act == "bz" ? { "ok": 1, "ng": 1 } : { "ok": 1, "ng": 1, "bz": 1 },
- postcard = has(["ok", "ng", "done"], this.act) ? { "bz": 1, "q": 1 } : this.act == "bz" ? { "q": 1 } : {};
-
for (var a = 0; a < this.tab.length; a++) {
var rt = this.tab[a].in;
- if (precard[rt]) {
+ if (this.precard[rt]) {
this.head = a + 1;
this.tail = a;
}
- else if (postcard[rt]) {
+ else if (this.postcard[rt]) {
this.head = a;
this.tail = a - 1;
break;
@@ -452,6 +459,8 @@ function U2pvis(act, btns) {
that.changecard(newtab);
};
}
+
+ this.changecard(this.act);
}
@@ -548,17 +557,21 @@ function up2k_init(subtle) {
ask_up = bcfg_get('ask_up', true),
flag_en = bcfg_get('flag_en', false),
fsearch = bcfg_get('fsearch', false),
+ turbo = bcfg_get('u2turbo', false),
+ datechk = bcfg_get('u2tdate', true),
fdom_ctr = 0,
min_filebuf = 0;
var st = {
"files": [],
"todo": {
+ "head": [],
"hash": [],
"handshake": [],
"upload": []
},
"busy": {
+ "head": [],
"hash": [],
"handshake": [],
"upload": []
@@ -569,6 +582,15 @@ function up2k_init(subtle) {
}
};
+ function push_t(arr, t) {
+ var sort = arr.length && arr[arr.length - 1].n > t.n;
+ arr.push(t);
+ if (sort)
+ arr.sort(function (a, b) {
+ return a.n < b.n ? -1 : 1;
+ });
+ }
+
var pvis = new U2pvis("bz", '#u2cards');
var bobslice = null;
@@ -796,7 +818,10 @@ function up2k_init(subtle) {
], fobj.size, draw_each);
st.files.push(entry);
- st.todo.hash.push(entry);
+ if (turbo)
+ push_t(st.todo.head, entry);
+ else
+ push_t(st.todo.hash, entry);
}
if (!draw_each) {
pvis.drawcard("q");
@@ -891,9 +916,11 @@ function up2k_init(subtle) {
while (window['vis_exh']) {
var now = Date.now(),
is_busy = 0 !=
+ st.todo.head.length +
st.todo.hash.length +
st.todo.handshake.length +
st.todo.upload.length +
+ st.busy.head.length +
st.busy.hash.length +
st.busy.handshake.length +
st.busy.upload.length;
@@ -943,6 +970,12 @@ function up2k_init(subtle) {
}
}
+ if (st.todo.head.length &&
+ st.busy.head.length < parallel_uploads) {
+ exec_head();
+ mou_ikkai = true;
+ }
+
if (handshakes_permitted() &&
st.todo.handshake.length) {
exec_handshake();
@@ -1160,6 +1193,53 @@ function up2k_init(subtle) {
segm_next();
}
+ /////
+ ////
+ /// head
+ //
+
+ function exec_head() {
+ var t = st.todo.head.shift();
+ st.busy.head.push(t);
+
+ var xhr = new XMLHttpRequest();
+ xhr.onerror = function () {
+ console.log('head onerror, retrying', t);
+ apop(st.busy.head, t);
+ st.todo.head.unshift(t);
+ tasker();
+ };
+ function orz(e) {
+ var ok = false;
+ if (xhr.status == 200) {
+ var srv_sz = xhr.getResponseHeader('Content-Length'),
+ srv_ts = xhr.getResponseHeader('Last-Modified');
+
+ ok = t.size == srv_sz;
+ if (ok && datechk) {
+ srv_ts = new Date(srv_ts) / 1000;
+ ok = Math.abs(srv_ts - t.lmod) < 2;
+ }
+ }
+ apop(st.busy.head, t);
+ if (!ok)
+ return push_t(st.todo.hash, t);
+
+ t.done = true;
+ st.bytes.hashed += t.size;
+ st.bytes.uploaded += t.size;
+ pvis.seth(t.n, 1, 'YOLO');
+ pvis.seth(t.n, 2, "turbo'd");
+ pvis.move(t.n, 'ok');
+ };
+ xhr.onload = function (e) {
+ try { orz(e); } catch (ex) { vis_exh(ex + '', '', '', '', ex); }
+ };
+
+ xhr.open('HEAD', t.purl + t.name, true);
+ xhr.send();
+ }
+
/////
////
/// handshake
@@ -1268,14 +1348,24 @@ function up2k_init(subtle) {
msg = '🎷🐛';
if (t.postlist.length) {
+ var arr = st.todo.upload,
+ sort = arr.length && arr[arr.length - 1].nfile > t.n;
+
for (var a = 0; a < t.postlist.length; a++)
- st.todo.upload.push({
+ arr.push({
'nfile': t.n,
'npart': t.postlist[a]
});
msg = 'uploading';
done = false;
+
+ if (sort)
+ arr.sort(function (a, b) {
+ return a.nfile < b.nfile ? -1 :
+ /* */ a.nfile > b.nfile ? 1 :
+ a.npart < b.npart ? -1 : 1;
+ });
}
pvis.seth(t.n, 1, msg);
apop(st.busy.handshake, t);
@@ -1527,6 +1617,30 @@ function up2k_init(subtle) {
set_fsearch(!fsearch);
}
+ function tgl_turbo() {
+ turbo = !turbo;
+ bcfg_set('u2turbo', turbo);
+ draw_turbo();
+ }
+
+ function tgl_datechk() {
+ datechk = !datechk;
+ bcfg_set('u2tdate', datechk);
+ }
+
+ function draw_turbo() {
+ var msg = 'WARNING: turbo enabled, client may not detect and resume incomplete uploads; see turbo-button tooltip
',
+ html = ebi('u2foot').innerHTML;
+
+ if (turbo && html.indexOf(msg) === -1)
+ html += msg;
+ else if (!turbo)
+ html = html.replace(msg, '');
+
+ ebi('u2foot').innerHTML = html;
+ }
+ draw_turbo();
+
function set_fsearch(new_state) {
var fixed = false;
@@ -1608,6 +1722,8 @@ function up2k_init(subtle) {
ebi('multitask').addEventListener('click', tgl_multitask, false);
ebi('ask_up').addEventListener('click', tgl_ask_up, false);
ebi('flag_en').addEventListener('click', tgl_flag_en, false);
+ ebi('u2turbo').addEventListener('click', tgl_turbo, false);
+ ebi('u2tdate').addEventListener('click', tgl_datechk, false);
var o = ebi('fsearch');
if (o)
o.addEventListener('click', tgl_fsearch, false);
diff --git a/copyparty/web/upload.css b/copyparty/web/upload.css
index 0ff5edea..d1c25375 100644
--- a/copyparty/web/upload.css
+++ b/copyparty/web/upload.css
@@ -215,9 +215,31 @@
color: #fff;
font-style: italic;
}
+#u2foot .warn {
+ font-size: 1.3em;
+ padding: .5em .8em;
+ margin: 1em -.6em;
+ color: #f74;
+ background: #322;
+ border: 1px solid #633;
+ border-width: .1em 0;
+ text-align: center;
+}
+#u2foot .warn span {
+ color: #f86;
+}
+html.light #u2foot .warn {
+ color: #b00;
+ background: #fca;
+ border-color: #f70;
+}
+html.light #u2foot .warn span {
+ color: #930;
+}
#u2foot span {
color: #999;
font-size: .9em;
+ font-weight: normal;
}
#u2footfoot {
margin-bottom: -1em;
diff --git a/copyparty/web/util.js b/copyparty/web/util.js
index 5464a687..2b0e63a3 100644
--- a/copyparty/web/util.js
+++ b/copyparty/web/util.js
@@ -514,8 +514,10 @@ var tt = (function () {
var pos = this.getBoundingClientRect(),
left = pos.left < window.innerWidth / 2,
- top = pos.top < window.innerHeight / 2;
+ top = pos.top < window.innerHeight / 2,
+ big = this.className.indexOf(' ttb') !== -1;
+ clmod(r.tt, 'b', big);
r.tt.style.top = top ? pos.bottom + 'px' : 'auto';
r.tt.style.bottom = top ? 'auto' : (window.innerHeight - pos.top) + 'px';
r.tt.style.left = left ? pos.left + 'px' : 'auto';