diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css
index 5453eecf..1111deba 100644
--- a/copyparty/web/browser.css
+++ b/copyparty/web/browser.css
@@ -507,6 +507,11 @@ html.light #wfm a:not(.en) {
box-shadow: 0 -.15em .2em #000 inset;
padding-bottom: .3em;
}
+#ops a svg {
+ width: 1.75em;
+ height: 1.75em;
+ margin: -.5em -.3em;
+}
#ops {
margin: 1.7em 1.5em 0 1.5em;
padding: .3em .6em;
@@ -1117,6 +1122,9 @@ html.light #ops a.act {
border-color: #07a;
padding-top: .4em;
}
+html.light #ops svg circle {
+ stroke: black;
+}
html.light #op_cfg h3 {
border-color: #ccc;
}
diff --git a/copyparty/web/up2k.js b/copyparty/web/up2k.js
index 71b109d0..ce5a24e9 100644
--- a/copyparty/web/up2k.js
+++ b/copyparty/web/up2k.js
@@ -477,6 +477,52 @@ function U2pvis(act, btns) {
}
+function Donut(st) {
+ var r = this,
+ el = null,
+ o = 20 * 2 * Math.PI,
+ optab = QS('#ops a[data-dest="up2k"]');
+
+ optab.setAttribute('ico', optab.textContent);
+
+ function svg(v) {
+ var ico = v !== undefined,
+ bg = ico ? '#333' : 'transparent';
+
+ return (
+ ''
+ );
+ }
+
+ r.on = function (ya) {
+ r.fc = 99;
+ r.base = st.bytes.finished;
+ optab.innerHTML = ya ? svg() : optab.getAttribute('ico');
+ el = QS('#ops a .donut');
+ if (!ya)
+ favico.upd();
+ };
+ r.do = function () {
+ if (!el)
+ return;
+
+ var t = st.bytes.total - r.base,
+ v = st.bytes.finished - r.base,
+ ofs = el.style.strokeDashoffset = o - o * v / t;
+
+ if (favico.txt && ++r.fc > 4) {
+ favico.upd(svg(ofs));
+ r.fc = 0;
+ }
+ };
+}
+
+
function fsearch_explain(n) {
if (n)
return toast.inf(60, 'your access to this folder is Read-Only\n\n' + (acct == '*' ? 'you are currently not logged in' : 'you are currently logged in as "' + acct + '"'));
@@ -623,7 +669,8 @@ function up2k_init(subtle) {
});
}
- var pvis = new U2pvis("bz", '#u2cards');
+ var pvis = new U2pvis("bz", '#u2cards'),
+ donut = new Donut(st);
var bobslice = null;
if (window.File)
@@ -1175,6 +1222,8 @@ function up2k_init(subtle) {
window[(is_busy ? "add" : "remove") +
"EventListener"]("beforeunload", warn_uploader_busy);
+ donut.on(is_busy);
+
if (!is_busy) {
var k = uc.fsearch ? 'searches' : 'uploads',
ks = uc.fsearch ? 'Search' : 'Upload',
@@ -1196,9 +1245,11 @@ function up2k_init(subtle) {
toast.err(t, '{0} {1}'.format(ks, tng));
timer.rm(etafun);
+ timer.rm(donut.do);
op_minh = 0;
}
else {
+ timer.add(donut.do);
timer.add(etafun, false);
ebi('u2etas').style.textAlign = 'left';
}
diff --git a/copyparty/web/util.js b/copyparty/web/util.js
index 1dd44828..7c7c56d9 100644
--- a/copyparty/web/util.js
+++ b/copyparty/web/util.js
@@ -1221,28 +1221,31 @@ if (ebi('repl'))
ebi('repl').onclick = repl;
+var svg_decl = '\n';
+
+
var favico = (function () {
var r = {};
r.en = true;
+ r.tag = null;
function gx(txt) {
- return (
- '\n' +
- ''
+ ' fill="#' + r.fg + '">' + txt + ''
);
}
- r.upd = function () {
- var i = QS('link[rel="icon"]'), b64;
+ r.upd = function (svg) {
if (!r.txt)
return;
+ var b64;
try {
- b64 = btoa(gx(r.txt));
+ b64 = btoa(svg ? svg_decl + svg : gx(r.txt));
}
catch (ex) {
b64 = encodeURIComponent(r.txt).replace(/%([0-9A-F]{2})/g,
@@ -1251,12 +1254,12 @@ var favico = (function () {
b64 = btoa(gx(unescape(encodeURIComponent(r.txt))));
}
- if (!i) {
- i = mknod('link');
- i.rel = 'icon';
- document.head.appendChild(i);
+ if (!r.tag) {
+ r.tag = mknod('link');
+ r.tag.rel = 'icon';
+ document.head.appendChild(r.tag);
}
- i.href = 'data:image/svg+xml;base64,' + b64;
+ r.tag.href = 'data:image/svg+xml;base64,' + b64;
};
r.init = function () {