Compare commits

..

11 Commits

Author SHA1 Message Date
ed
264b497681 v0.11.19 2021-06-19 01:32:17 +02:00
ed
372b949622 fix tooltip indicator 2021-06-19 01:25:07 +02:00
ed
789a602914 save some more bytes on the wire 2021-06-19 01:18:48 +02:00
ed
093e955100 move stuff that needs javascript out of the html 2021-06-19 01:10:40 +02:00
ed
c32a89bebf minor lightmode tweaks 2021-06-19 00:17:39 +02:00
ed
c0bebe9f9f eq-param error-hilight in lightmode 2021-06-18 23:51:26 +02:00
ed
57579b2fe5 fix android-chrome layout glitch in up2k 2021-06-18 23:38:43 +02:00
ed
51d14a6b4d fix toolbar tooltips on android 2021-06-18 22:11:01 +02:00
ed
c50f1b64e5 dodge android-chrome bug: canvas aspect ratio 2021-06-18 21:46:15 +02:00
ed
98aaab02c5 block scroll events, hilight selected radios 2021-06-18 20:49:38 +02:00
ed
0fc7973d8b add shadow to playback times 2021-06-18 20:24:36 +02:00
9 changed files with 436 additions and 368 deletions

View File

@@ -1,8 +1,8 @@
# coding: utf-8
VERSION = (0, 11, 18)
VERSION = (0, 11, 19)
CODENAME = "the grid"
BUILD_DT = (2021, 6, 18)
BUILD_DT = (2021, 6, 19)
S_VERSION = ".".join(map(str, VERSION))
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)

View File

@@ -172,7 +172,7 @@ class HttpConn(object):
self.log("client rejected our certificate (nice)")
elif "ALERT_CERTIFICATE_UNKNOWN" in em:
# chrome-android keeps doing this
# android-chrome keeps doing this
pass
else:

View File

@@ -311,6 +311,7 @@ html.light #ggrid a.sel {
height: 6em;
width: 100%;
z-index: 3;
touch-action: none;
transition: bottom 0.15s;
}
#widget.open {
@@ -535,7 +536,9 @@ html.light #ggrid a.sel {
border-radius: .2em;
padding: .2em .3em;
}
.opview input.err {
.opview input.err,
html.light .opview input[type="text"].err {
color: #fff;
background: #a20;
border-color: #f00;
box-shadow: 0 0 .7em #f00;
@@ -548,6 +551,12 @@ input[type="checkbox"]+label {
input[type="checkbox"]:checked+label {
color: #fc5;
}
input[type="radio"]:checked+label {
color: #fc0;
}
html.light input[type="radio"]:checked+label {
color: #07c;
}
input.eq_gain {
width: 3em;
text-align: center;
@@ -656,6 +665,7 @@ input.eq_gain {
}
#thx_ff {
padding: 5em 0;
/* widget */
}
#tree::-webkit-scrollbar-track,
#tree::-webkit-scrollbar {
@@ -716,10 +726,10 @@ input.eq_gain {
#treeul a.hl {
color: #400;
background: #fc4;
border-radius: .3em;
text-shadow: none;
}
#treeul a {
border-radius: .3em;
display: inline-block;
}
#treeul a+a {
@@ -960,7 +970,10 @@ html.light #treeul a.hl {
color: #fff;
}
html.light #tree li {
border-color: #ddd #fff #f7f7f7 #fff;
border-color: #f7f7f7 #fff #ddd #fff;
}
html.light #tree a:hover {
background: #fff;
}
html.light #tree ul {
border-color: #ccc;
@@ -978,14 +991,14 @@ html.light #files {
}
html.light #files thead th {
background: #eee;
border-right: 1px solid #ccc;
border-bottom: 1px solid #ccc;
border: 1px solid #ccc;
border-top: none;
}
html.light #files thead th {
html.light #files thead th+th {
border-left: 1px solid #f7f7f7;
}
html.light #files td {
border-color: #ddd #fff #fff #ddd;
border-color: #fff #fff #ddd #ddd;
}
html.light #files tbody tr:last-child td {
border-bottom: .2em solid #ccc;
@@ -1040,6 +1053,9 @@ html.light #wzip,
html.light #wnp {
border-color: #ccc;
}
html.light #barbuf {
background: none;
}
html.light #files tr.sel:hover td {
background: #c37;
}
@@ -1112,6 +1128,7 @@ html.light #tree::-webkit-scrollbar {
opacity: 0;
position: fixed;
overflow: hidden;
touch-action: none;
top: 0;
left: 0;
width: 100%;

View File

@@ -2,140 +2,134 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>⇆🎉 {{ title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.8">
<link rel="stylesheet" type="text/css" media="screen" href="/.cpr/browser.css{{ ts }}">
<link rel="stylesheet" type="text/css" media="screen" href="/.cpr/upload.css{{ ts }}">
{%- if css %}
<link rel="stylesheet" type="text/css" media="screen" href="{{ css }}{{ ts }}">
{%- endif %}
<meta charset="utf-8">
<title>⇆🎉 {{ title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.8">
<link rel="stylesheet" type="text/css" media="screen" href="/.cpr/browser.css{{ ts }}">
<link rel="stylesheet" type="text/css" media="screen" href="/.cpr/upload.css{{ ts }}">
{%- if css %}
<link rel="stylesheet" type="text/css" media="screen" href="{{ css }}{{ ts }}">
{%- endif %}
</head>
<body>
<div id="ops">
<a href="#" data-dest="" tt="close submenu">---</a>
{%- if have_up2k_idx %}
<a href="#" data-perm="read" data-dest="search" tt="search for files by attributes, path/name, music tags, or any combination of those.&lt;br /&gt;&lt;br /&gt;&lt;code&gt;foo bar&lt;/code&gt; = must contain both foo and bar,&lt;br /&gt;&lt;code&gt;foo -bar&lt;/code&gt; = must contain foo but not bar,&lt;br /&gt;&lt;code&gt;^yana .opus$&lt;/code&gt; = must start with yana and have the opus extension">🔎</a>
<a href="#" data-dest="up2k" tt="up2k: upload files (if you have write-access) or toggle into the search-mode and drag files onto the search button to see if they exist somewhere on the server">🚀</a>
{%- else %}
<a href="#" data-perm="write" data-dest="up2k" tt="up2k: upload files with resume support (close your browser and drop the same files in later)">🚀</a>
{%- endif %}
<a href="#" data-perm="write" data-dest="bup" tt="bup: basic uploader, even supports netscape 4.0">🎈</a>
<a href="#" data-perm="write" data-dest="mkdir" tt="mkdir: create a new directory">📂</a>
<a href="#" data-perm="read write" data-dest="new_md" tt="new-md: create a new markdown document">📝</a>
<a href="#" data-perm="write" data-dest="msg" tt="msg: send a message to the server log">📟</a>
<a href="#" data-dest="player" tt="media player options">🎺</a>
<a href="#" data-dest="cfg" tt="configuration options">⚙️</a>
<div id="opdesc"></div>
</div>
<div id="ops"></div>
<div id="op_search" class="opview">
{%- if have_tags_idx %}
<div id="srch_form" class="tags"></div>
{%- else %}
<div id="srch_form"></div>
{%- endif %}
<div id="srch_q"></div>
</div>
<div id="op_search" class="opview">
{%- if have_tags_idx %}
<div id="srch_form" class="tags"></div>
{%- else %}
<div id="srch_form"></div>
{%- endif %}
<div id="srch_q"></div>
</div>
<div id="op_player" class="opview opbox opwide"></div>
<div id="op_player" class="opview opbox opwide"></div>
{%- include 'upload.html' %}
<div id="op_bup" class="opview opbox act">
<div id="u2err"></div>
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="{{ url_suf }}">
<input type="hidden" name="act" value="bput" />
<input type="file" name="f" multiple><br />
<input type="submit" value="start upload">
</form>
</div>
<div id="op_cfg" class="opview opbox opwide">
<div>
<h3>switches</h3>
<div>
<a id="tooltips" class="tgl btn" href="#" tt="◔ ◡ ◔"> tooltips</a>
<a id="lightmode" class="tgl btn" href="#">☀️ lightmode</a>
<a id="griden" class="tgl btn" href="#" tt="toggle icons or list-view$NHotkey: G">田 the grid</a>
<a id="thumbs" class="tgl btn" href="#" tt="in icon view, toggle icons or thumbnails$NHotkey: T">🖼️ thumbs</a>
</div>
</div>
{%- if have_zip %}
<div><h3>folder download</h3><div id="arc_fmt"></div></div>
{%- endif %}
<div><h3>key notation</h3><div id="key_notation"></div></div>
<div class="fill"><h3>hidden columns</h3><div id="hcols"></div></div>
</div>
<h1 id="path">
<a href="#" id="entree" tt="show directory tree$NHotkey: B">🌲</a>
{%- for n in vpnodes %}
<a href="/{{ n[0] }}">{{ n[1] }}</a>
{%- endfor %}
</h1>
<div id="tree">
<div id="treeh">
<a href="#" id="detree" tt="show breadcrumbs$NHotkey: B">🍞...</a>
<a href="#" class="btn" step="2" id="twobytwo">+</a>
<a href="#" class="btn" step="-2" id="twig">&ndash;</a>
<a href="#" class="tgl btn" id="dyntree" tt="autogrow as tree expands">a</a>
</div>
<ul id="treeul"></ul>
<div id="thx_ff">&nbsp;</div>
</div>
<div id="op_mkdir" class="opview opbox act">
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="{{ url_suf }}">
<input type="hidden" name="act" value="mkdir" />
<input type="text" name="name" size="30">
<input type="submit" value="mkdir">
</form>
</div>
<div id="op_new_md" class="opview opbox">
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="{{ url_suf }}">
<input type="hidden" name="act" value="new_md" />
<input type="text" name="name" size="30">
<input type="submit" value="create doc">
</form>
</div>
<div id="op_msg" class="opview opbox act">
<form method="post" enctype="application/x-www-form-urlencoded" accept-charset="utf-8" action="{{ url_suf }}">
<input type="text" name="msg" size="30">
<input type="submit" value="send msg">
</form>
</div>
<div id="op_up2k" class="opview"></div>
<div id="op_cfg" class="opview opbox opwide"></div>
<h1 id="path">
<a href="#" id="entree" tt="show directory tree$NHotkey: B">🌲</a>
{%- for n in vpnodes %}
<a href="/{{ n[0] }}">{{ n[1] }}</a>
{%- endfor %}
</h1>
<div id="tree"></div>
<div id="wrap">
<div id="pro" class="logue">{{ logues[0] }}</div>
<div id="pro" class="logue">{{ logues[0] }}</div>
<table id="files">
<thead>
<tr>
<th name="lead"><span>c</span></th>
<th name="href"><span>File Name</span></th>
<th name="sz" sort="int"><span>Size</span></th>
{%- for k in taglist %}
{%- if k.startswith('.') %}
<th name="tags/{{ k }}" sort="int"><span>{{ k[1:] }}</span></th>
{%- else %}
<th name="tags/{{ k }}"><span>{{ k[0]|upper }}{{ k[1:] }}</span></th>
{%- endif %}
{%- endfor %}
<th name="ext"><span>T</span></th>
<th name="ts"><span>Date</span></th>
</tr>
</thead>
<tbody>
<table id="files">
<thead>
<tr>
<th name="lead"><span>c</span></th>
<th name="href"><span>File Name</span></th>
<th name="sz" sort="int"><span>Size</span></th>
{%- for k in taglist %}
{%- if k.startswith('.') %}
<th name="tags/{{ k }}" sort="int"><span>{{ k[1:] }}</span></th>
{%- else %}
<th name="tags/{{ k }}"><span>{{ k[0]|upper }}{{ k[1:] }}</span></th>
{%- endif %}
{%- endfor %}
<th name="ext"><span>T</span></th>
<th name="ts"><span>Date</span></th>
</tr>
</thead>
<tbody>
{%- for f in files %}
<tr><td>{{ f.lead }}</td><td><a href="{{ f.href }}">{{ f.name|e }}</a></td><td>{{ f.sz }}</td>
{%- if f.tags is defined %}
{%- for k in taglist %}
<td>{{ f.tags[k] }}</td>
{%- endfor %}
{%- endif %}
<td>{{ f.ext }}</td><td>{{ f.dt }}</td></tr>
<tr><td>{{ f.lead }}</td><td><a href="{{ f.href }}">{{ f.name|e }}</a></td><td>{{ f.sz }}</td>
{%- if f.tags is defined %}
{%- for k in taglist %}
<td>{{ f.tags[k] }}</td>
{%- endfor %}
{%- endif %}
<td>{{ f.ext }}</td><td>{{ f.dt }}</td></tr>
{%- endfor %}
</tbody>
</table>
<div id="epi" class="logue">{{ logues[1] }}</div>
</tbody>
</table>
<div id="epi" class="logue">{{ logues[1] }}</div>
<h2><a href="?h">control-panel</a></h2>
<h2><a href="?h">control-panel</a></h2>
</div>
{%- if srv_info %}
<div id="srv_info"><span>{{ srv_info }}</span></div>
{%- endif %}
{%- if srv_info %}
<div id="srv_info"><span>{{ srv_info }}</span></div>
{%- endif %}
<div id="widget"></div>
<div id="widget"></div>
<script>
var tag_order_cfg = {{ tag_order }};
</script>
<script src="/.cpr/util.js{{ ts }}"></script>
<script src="/.cpr/browser.js{{ ts }}"></script>
<script src="/.cpr/up2k.js{{ ts }}"></script>
<script>
apply_perms({{ perms }});
</script>
<script>
var perms = {{ perms }},
tag_order_cfg = {{ tag_order }},
have_up2k_idx = {{ have_up2k_idx|tojson }},
have_tags_idx = {{ have_tags_idx|tojson }},
have_zip = {{ have_zip|tojson }};
</script>
<script src="/.cpr/util.js{{ ts }}"></script>
<script src="/.cpr/browser.js{{ ts }}"></script>
<script src="/.cpr/up2k.js{{ ts }}"></script>
</body>
</html>

View File

@@ -7,7 +7,26 @@ function dbg(msg) {
}
// add widget buttons
// toolbar
ebi('ops').innerHTML = (
'<a href="#" data-dest="" tt="close submenu">---</a>\n' +
(have_up2k_idx ? (
'<a href="#" data-perm="read" data-dest="search" tt="search for files by attributes, path/name, music tags, or any combination of those.$N$N&lt;code&gt;foo bar&lt;/code&gt; = must contain both foo and bar,$N&lt;code&gt;foo -bar&lt;/code&gt; = must contain foo but not bar,$N&lt;code&gt;^yana .opus$&lt;/code&gt; = must start with yana and have the opus extension">🔎</a>\n' +
'<a href="#" data-dest="up2k" tt="up2k: upload files (if you have write-access) or toggle into the search-mode and drag files onto the search button to see if they exist somewhere on the server">🚀</a>\n'
) : (
'<a href="#" data-perm="write" data-dest="up2k" tt="up2k: upload files with resume support (close your browser and drop the same files in later)">🚀</a>\n'
)) +
'<a href="#" data-perm="write" data-dest="bup" tt="bup: basic uploader, even supports netscape 4.0">🎈</a>\n' +
'<a href="#" data-perm="write" data-dest="mkdir" tt="mkdir: create a new directory">📂</a>\n' +
'<a href="#" data-perm="read write" data-dest="new_md" tt="new-md: create a new markdown document">📝</a>\n' +
'<a href="#" data-perm="write" data-dest="msg" tt="msg: send a message to the server log">📟</a>\n' +
'<a href="#" data-dest="player" tt="media player options">🎺</a>\n' +
'<a href="#" data-dest="cfg" tt="configuration options">⚙️</a>\n' +
'<div id="opdesc"></div>'
);
// media player
ebi('widget').innerHTML = (
'<div id="wtoggle">' +
'<span id="wzip"><a' +
@@ -29,6 +48,166 @@ ebi('widget').innerHTML = (
);
// up2k ui
ebi('op_up2k').innerHTML = (
'<form id="u2form" method="post" enctype="multipart/form-data" onsubmit="return false;"></form>\n' +
'<table id="u2conf">\n' +
' <tr>\n' +
' <td><br />parallel uploads:</td>\n' +
' <td rowspan="2">\n' +
' <input type="checkbox" id="multitask" />\n' +
' <label for="multitask" tt="continue hashing other files while uploading">🏃</label>\n' +
' </td>\n' +
' <td rowspan="2">\n' +
' <input type="checkbox" id="ask_up" />\n' +
' <label for="ask_up" tt="ask for confirmation befofre upload starts">💭</label>\n' +
' </td>\n' +
' <td rowspan="2">\n' +
' <input type="checkbox" id="flag_en" />\n' +
' <label for="flag_en" tt="ensure only one tab is uploading at a time $N (other tabs must have this enabled too)">💤</label>\n' +
' </td>\n' +
(have_up2k_idx ? (
' <td data-perm="read" rowspan="2">\n' +
' <input type="checkbox" id="fsearch" />\n' +
' <label for="fsearch" tt="don\'t actually upload, instead check if the files already $N exist on the server (will scan all folders you can read)">🔎</label>\n' +
' </td>\n'
) : '') +
' <td data-perm="read" rowspan="2" id="u2btn_cw"></td>\n' +
' </tr>\n' +
' <tr>\n' +
' <td>\n' +
' <a href="#" id="nthread_sub">&ndash;</a><input\n' +
' class="txtbox" id="nthread" value="2"/><a\n' +
' href="#" id="nthread_add">+</a><br />&nbsp;\n' +
' </td>\n' +
' </tr>\n' +
'</table>\n' +
'<div id="u2notbtn"></div>\n' +
'<div id="u2btn_ct">\n' +
' <div id="u2btn">\n' +
' <span id="u2bm"></span><br />\n' +
' drag/drop files<br />\n' +
' and folders here<br />\n' +
' (or click me)\n' +
' </div>\n' +
'</div>\n' +
'<div id="u2cards">\n' +
' <a href="#" act="ok" tt="completed successfully">ok <span>0</span></a><a\n' +
' href="#" act="ng" tt="failed / rejected / not-found">ng <span>0</span></a><a\n' +
' href="#" act="done" tt="ok and ng combined">done <span>0</span></a><a\n' +
' href="#" act="bz" tt="hashing or uploading" class="act">busy <span>0</span></a><a\n' +
' href="#" act="q" tt="idle, pending">que <span>0</span></a>\n' +
'</div>\n' +
'<table id="u2tab">\n' +
' <thead>\n' +
' <tr>\n' +
' <td>filename</td>\n' +
' <td>status</td>\n' +
' <td>progress<a href="#" id="u2cleanup" tt="remove completed uploads$N(makes it possible to upload a file after searching for it)">cleanup</a></td>\n' +
' </tr>\n' +
' </thead>\n' +
' <tbody></tbody>\n' +
'</table>\n' +
'<p id="u2foot"></p>\n' +
'<p id="u2footfoot" data-perm="write">( you can use the <a href="#" id="u2nope">basic uploader</a> if you don\'t need lastmod timestamps, resumable uploads, or progress bars )</p>'
);
// config panel
ebi('op_cfg').innerHTML = (
'<div>\n' +
' <h3>switches</h3>\n' +
' <div>\n' +
' <a id="tooltips" class="tgl btn" href="#" tt="◔ ◡ ◔"> tooltips</a>\n' +
' <a id="lightmode" class="tgl btn" href="#">☀️ lightmode</a>\n' +
' <a id="griden" class="tgl btn" href="#" tt="toggle icons or list-view$NHotkey: G">田 the grid</a>\n' +
' <a id="thumbs" class="tgl btn" href="#" tt="in icon view, toggle icons or thumbnails$NHotkey: T">🖼️ thumbs</a>\n' +
' </div>\n' +
'</div>\n' +
(have_zip ? (
'<div><h3>folder download</h3><div id="arc_fmt"></div></div>\n'
) : '') +
'<div><h3>key notation</h3><div id="key_notation"></div></div>\n' +
'<div class="fill"><h3>hidden columns</h3><div id="hcols"></div></div>'
);
// tree sidebar
ebi('tree').innerHTML = (
'<div id="treeh">\n' +
' <a href="#" id="detree" tt="show breadcrumbs$NHotkey: B">🍞...</a>\n' +
' <a href="#" class="btn" step="2" id="twobytwo">+</a>\n' +
' <a href="#" class="btn" step="-2" id="twig">&ndash;</a>\n' +
' <a href="#" class="tgl btn" id="dyntree" tt="autogrow as tree expands">a</a>\n' +
'</div>\n' +
'<ul id="treeul"></ul>\n' +
'<div id="thx_ff">&nbsp;</div>'
);
(function () {
var ops = QSA('#ops>a');
for (var a = 0; a < ops.length; a++) {
ops[a].onclick = opclick;
}
})();
function opclick(e) {
ev(e);
var dest = this.getAttribute('data-dest');
goto(dest);
swrite('opmode', dest || null);
var input = QS('.opview.act input:not([type="hidden"])')
if (input && !is_touch)
input.focus();
}
function goto(dest) {
var obj = QSA('.opview.act');
for (var a = obj.length - 1; a >= 0; a--)
clmod(obj[a], 'act');
obj = QSA('#ops>a');
for (var a = obj.length - 1; a >= 0; a--)
clmod(obj[a], 'act');
if (dest) {
var ui = ebi('op_' + dest);
clmod(ui, 'act', true);
QS('#ops>a[data-dest=' + dest + ']').className += " act";
var fn = window['goto_' + dest];
if (fn)
fn();
}
if (window['treectl'])
treectl.onscroll();
}
(function () {
goto();
var op = sread('opmode');
if (op !== null && op !== '.')
try {
goto(op);
}
catch (ex) { }
})();
var have_webp = null;
(function () {
var img = new Image();
@@ -298,7 +477,7 @@ var pbar = (function () {
gradh = -1,
grad;
function onresize() {
r.onresize = function () {
r.buf = canvas_cfg(ebi('barbuf'));
r.pos = canvas_cfg(ebi('barpos'));
r.drawbuf();
@@ -352,23 +531,28 @@ var pbar = (function () {
pctx.fillStyle = '#573'; pctx.fillRect((x - w / 2) - 1, 0, w + 2, pc.h);
pctx.fillStyle = '#dfc'; pctx.fillRect((x - w / 2), 0, 8, pc.h);
pctx.lineWidth = 2.5;
pctx.fillStyle = '#fff';
pctx.strokeStyle = 'rgba(24,56,0,0.4)';
pctx.font = '1em sans-serif';
var txt = s2ms(mp.au.duration),
tw = pctx.measureText(txt).width;
pctx.fillText(txt, pc.w - (tw + 8), pc.h / 3 * 2);
var m = pctx.measureText.bind(pctx),
t1 = s2ms(mp.au.duration),
t2 = s2ms(mp.au.currentTime),
yt = pc.h / 3 * 2.1,
xt1 = pc.w - (m(t1).width + 12),
xt2 = x < pc.w / 2 ? (x + 12) : (Math.min(pc.w - m(t1 + ":88").width, x - 12) - m(t2).width);
txt = s2ms(mp.au.currentTime);
tw = pctx.measureText(txt).width;
var gw = pctx.measureText("88:88::").width,
xt = x < pc.w / 2 ? (x + 8) : (Math.min(pc.w - gw, x - 8) - tw);
pctx.fillText(txt, xt, pc.h / 3 * 2);
pctx.strokeText(t1, xt1 + 1, yt + 1);
pctx.strokeText(t2, xt2 + 1, yt + 1);
pctx.strokeText(t1, xt1, yt);
pctx.strokeText(t2, xt2, yt);
pctx.fillText(t1, xt1, yt);
pctx.fillText(t2, xt2, yt);
};
window.addEventListener('resize', onresize);
onresize();
window.addEventListener('resize', r.onresize);
r.onresize();
return r;
})();
@@ -379,7 +563,7 @@ var vbar = (function () {
gradh = -1,
can, ctx, w, h, grad1, grad2;
function onresize() {
r.onresize = function () {
r.can = canvas_cfg(ebi('pvol'));
can = r.can.can;
ctx = r.can.ctx;
@@ -398,8 +582,8 @@ var vbar = (function () {
ctx.fillStyle = grad2; ctx.fillRect(0, 0, w, h);
ctx.fillStyle = grad1; ctx.fillRect(0, 0, w * mp.vol, h);
};
window.addEventListener('resize', onresize);
onresize();
window.addEventListener('resize', r.onresize);
r.onresize();
var rect;
function mousedown(e) {
@@ -537,14 +721,23 @@ var mpui = (function () {
// indicate playback state in ui
widget.paused(mp.au.paused);
// draw current position in song
if (!mp.au.paused)
pbar.drawpos();
// occasionally draw buffered regions
if (++nth == 5) {
pbar.drawbuf();
if (++nth > 69) {
// android-chrome breaks aspect ratio with unannounced viewport changes
nth = 0;
if (is_touch) {
nth = 1;
pbar.onresize();
vbar.onresize();
}
}
else {
// draw current position in song
if (!mp.au.paused)
pbar.drawpos();
// occasionally draw buffered regions
if (++nth % 5 == 0)
pbar.drawbuf();
}
// preload next song
@@ -762,7 +955,7 @@ var audio_eq = (function () {
}
var html = ['<table><tr><td rowspan="4">',
'<a id="au_eq" class="tgl btn" href="#" tt="enables the equalizer and gain control">enable</a></td>'],
'<a id="au_eq" class="tgl btn" href="#" tt="enables the equalizer and gain control;$Nboost 0 = unmodified 100% volume">enable</a></td>'],
h2 = [], h3 = [], h4 = [];
var vs = [];
@@ -815,7 +1008,7 @@ var audio_eq = (function () {
// plays the tid'th audio file on the page
function play(tid, seek, call_depth) {
if (mp.order.length == 0)
return alert('no audio found wait what');
return console.log('no audio found wait what');
var tn = tid;
if ((tn + '').indexOf('f-') === 0)
@@ -1082,6 +1275,8 @@ var thegrid = (function () {
lfiles.style.display = '';
gfiles.style.display = 'none';
}
pbar.onresize();
vbar.onresize();
};
var btnclick = function (e) {
@@ -2026,8 +2221,8 @@ function despin(sel) {
}
function apply_perms(perms) {
perms = perms || [];
function apply_perms(newperms) {
perms = newperms || [];
var o = QSA('#ops>a[data-perm], #u2footfoot');
for (var a = 0; a < o.length; a++) {
@@ -2049,8 +2244,16 @@ function apply_perms(perms) {
var have_write = has(perms, "write"),
have_read = has(perms, "read"),
de = document.documentElement,
tds = QSA('#u2conf td');
/* good idea maybe
clmod(de, "read", have_read);
clmod(de, "write", have_write);
clmod(de, "nread", !have_read);
clmod(de, "nwrite", !have_write);
*/
for (var a = 0; a < tds.length; a++) {
tds[a].style.display =
(have_write || tds[a].getAttribute('data-perm') == 'read') ?
@@ -2344,7 +2547,7 @@ var light;
light = bcfg_get('lightmode', false);
function freshen() {
document.documentElement.setAttribute("class", light ? "light" : "");
clmod(document.documentElement, "light", light);
pbar.drawbuf();
pbar.drawpos();
vbar.draw();

View File

@@ -2,59 +2,59 @@
<html lang="en">
<head>
<meta charset="utf-8">
<title>{{ title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.8">
<style>
html{font-family:sans-serif}
td{border:1px solid #999;border-width:1px 1px 0 0;padding:0 5px}
a{display:block}
</style>
<meta charset="utf-8">
<title>{{ title }}</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.8">
<style>
html{font-family:sans-serif}
td{border:1px solid #999;border-width:1px 1px 0 0;padding:0 5px}
a{display:block}
</style>
</head>
<body>
{%- if srv_info %}
<p><span>{{ srv_info }}</span></p>
{%- endif %}
{%- if srv_info %}
<p><span>{{ srv_info }}</span></p>
{%- endif %}
{%- if have_b_u %}
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="{{ url_suf }}">
<input type="hidden" name="act" value="bput" />
<input type="file" name="f" multiple /><br />
<input type="submit" value="start upload" />
</form>
<br />
{%- endif %}
{%- if have_b_u %}
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="{{ url_suf }}">
<input type="hidden" name="act" value="bput" />
<input type="file" name="f" multiple /><br />
<input type="submit" value="start upload" />
</form>
<br />
{%- endif %}
{%- if logues[0] %}
<div>{{ logues[0] }}</div><br />
{%- endif %}
{%- if logues[0] %}
<div>{{ logues[0] }}</div><br />
{%- endif %}
<table id="files">
<thead>
<tr>
<th name="lead"><span>c</span></th>
<th name="href"><span>File Name</span></th>
<th name="sz" sort="int"><span>Size</span></th>
<th name="ts"><span>Date</span></th>
</tr>
</thead>
<tbody>
<tr><td></td><td><a href="../{{ url_suf }}">parent folder</a></td><td>-</td><td>-</td></tr>
<table id="files">
<thead>
<tr>
<th name="lead"><span>c</span></th>
<th name="href"><span>File Name</span></th>
<th name="sz" sort="int"><span>Size</span></th>
<th name="ts"><span>Date</span></th>
</tr>
</thead>
<tbody>
<tr><td></td><td><a href="../{{ url_suf }}">parent folder</a></td><td>-</td><td>-</td></tr>
{%- for f in files %}
<tr><td>{{ f.lead }}</td><td><a href="{{ f.href }}{{ url_suf }}">{{ f.name|e }}</a></td><td>{{ f.sz }}</td><td>{{ f.dt }}</td></tr>
<tr><td>{{ f.lead }}</td><td><a href="{{ f.href }}{{ url_suf }}">{{ f.name|e }}</a></td><td>{{ f.sz }}</td><td>{{ f.dt }}</td></tr>
{%- endfor %}
</tbody>
</table>
{%- if logues[1] %}
<div>{{ logues[1] }}</div><br />
{%- endif %}
<h2><a href="{{ url_suf }}{{ url_suf and '&amp;' or '?' }}h">control-panel</a></h2>
</tbody>
</table>
{%- if logues[1] %}
<div>{{ logues[1] }}</div><br />
{%- endif %}
<h2><a href="{{ url_suf }}{{ url_suf and '&amp;' or '?' }}h">control-panel</a></h2>
</body>
</html>

View File

@@ -444,8 +444,7 @@ function up2k_init(subtle) {
}
// show uploader if the user only has write-access
var perms = document.body.getAttribute('perms');
if (perms && !has(perms.split(' '), 'read'))
if (perms.length && !has(perms, 'read'))
goto('up2k');
// shows or clears a message in the basic uploader ui
@@ -1265,7 +1264,7 @@ function up2k_init(subtle) {
fpx = parseInt(getComputedStyle(bar)['font-size']),
wem = wpx * 1.0 / fpx,
wide = wem > 54,
parent = ebi(wide ? 'u2btn_cw' : 'u2btn_ct'),
parent = ebi(wide && has(perms, 'write') ? 'u2btn_cw' : 'u2btn_ct'),
btn = ebi('u2btn');
//console.log([wpx, fpx, wem]);
@@ -1278,6 +1277,13 @@ function up2k_init(subtle) {
window.addEventListener('resize', onresize);
onresize();
if (is_touch) {
// android-chrome wobbles for a bit; firefox / iOS-safari are OK
setTimeout(onresize, 20);
setTimeout(onresize, 100);
setTimeout(onresize, 500);
}
var o = QSA('#u2conf *[tt]');
for (var a = o.length - 1; a >= 0; a--) {
o[a].parentNode.getElementsByTagName('input')[0].setAttribute('tt', o[a].getAttribute('tt'));
@@ -1330,14 +1336,12 @@ function up2k_init(subtle) {
}
function set_fsearch(new_state) {
var perms = document.body.getAttribute('perms'),
fixed = false;
var fixed = false;
if (!ebi('fsearch')) {
new_state = false;
}
else if (perms) {
perms = perms.split(' ');
else if (perms.length) {
if (!has(perms, 'write')) {
new_state = true;
fixed = true;
@@ -1367,6 +1371,8 @@ function up2k_init(subtle) {
ebi('u2bm').innerHTML = ico + ' <sup>' + desc + '</sup>';
}
catch (ex) { }
onresize();
}
function tgl_flag_en() {
@@ -1434,3 +1440,5 @@ tt.init();
if (QS('#op_up2k.act'))
goto_up2k();
apply_perms(perms);

View File

@@ -1,101 +0,0 @@
<div id="op_bup" class="opview opbox act">
<div id="u2err"></div>
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="{{ url_suf }}">
<input type="hidden" name="act" value="bput" />
<input type="file" name="f" multiple><br />
<input type="submit" value="start upload">
</form>
</div>
<div id="op_mkdir" class="opview opbox act">
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="{{ url_suf }}">
<input type="hidden" name="act" value="mkdir" />
<input type="text" name="name" size="30">
<input type="submit" value="mkdir">
</form>
</div>
<div id="op_new_md" class="opview opbox">
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="{{ url_suf }}">
<input type="hidden" name="act" value="new_md" />
<input type="text" name="name" size="30">
<input type="submit" value="create doc">
</form>
</div>
<div id="op_msg" class="opview opbox act">
<form method="post" enctype="application/x-www-form-urlencoded" accept-charset="utf-8" action="{{ url_suf }}">
<input type="text" name="msg" size="30">
<input type="submit" value="send msg">
</form>
</div>
<div id="op_up2k" class="opview">
<form id="u2form" method="post" enctype="multipart/form-data" onsubmit="return false;"></form>
<table id="u2conf">
<tr>
<td><br />parallel uploads:</td>
<td rowspan="2">
<input type="checkbox" id="multitask" />
<label for="multitask" tt="continue hashing other files while uploading">🏃</label>
</td>
<td rowspan="2">
<input type="checkbox" id="ask_up" />
<label for="ask_up" tt="ask for confirmation befofre upload starts">💭</label>
</td>
<td rowspan="2">
<input type="checkbox" id="flag_en" />
<label for="flag_en" tt="ensure only one tab is uploading at a time $N (other tabs must have this enabled too)">💤</label>
</td>
{%- if have_up2k_idx %}
<td data-perm="read" rowspan="2">
<input type="checkbox" id="fsearch" />
<label for="fsearch" tt="don't actually upload, instead check if the files already $N exist on the server (will scan all folders you can read)">🔎</label>
</td>
{%- endif %}
<td data-perm="read" rowspan="2" id="u2btn_cw"></td>
</tr>
<tr>
<td>
<a href="#" id="nthread_sub">&ndash;</a><input
class="txtbox" id="nthread" value="2"/><a
href="#" id="nthread_add">+</a><br />&nbsp;
</td>
</tr>
</table>
<div id="u2notbtn"></div>
<div id="u2btn_ct">
<div id="u2btn">
<span id="u2bm"></span><br />
drag/drop files<br />
and folders here<br />
(or click me)
</div>
</div>
<div id="u2cards">
<a href="#" act="ok" tt="completed successfully">ok <span>0</span></a><a
href="#" act="ng" tt="failed / rejected / not-found">ng <span>0</span></a><a
href="#" act="done" tt="ok and ng combined">done <span>0</span></a><a
href="#" act="bz" tt="hashing or uploading" class="act">busy <span>0</span></a><a
href="#" act="q" tt="idle, pending">que <span>0</span></a>
</div>
<table id="u2tab">
<thead>
<tr>
<td>filename</td>
<td>status</td>
<td>progress<a href="#" id="u2cleanup" tt="remove completed uploads$N(makes it possible to upload a file after searching for it)">cleanup</a></td>
</tr>
</thead>
<tbody></tbody>
</table>
<p id="u2foot"></p>
<p id="u2footfoot" data-perm="write">( you can use the <a href="#" id="u2nope">basic uploader</a> if you don't need lastmod timestamps, resumable uploads, or progress bars )</p>
</div>

View File

@@ -6,7 +6,7 @@ if (!window['console'])
};
var clickev = window.Touch ? 'touchstart' : 'click',
var is_touch = 'ontouchstart' in window,
ANDROID = /(android)/i.test(navigator.userAgent);
@@ -285,63 +285,6 @@ function makeSortable(table, cb) {
}
(function () {
var ops = QSA('#ops>a');
for (var a = 0; a < ops.length; a++) {
ops[a].onclick = opclick;
}
})();
function opclick(e) {
ev(e);
var dest = this.getAttribute('data-dest');
goto(dest);
swrite('opmode', dest || null);
var input = QS('.opview.act input:not([type="hidden"])')
if (input)
input.focus();
}
function goto(dest) {
var obj = QSA('.opview.act');
for (var a = obj.length - 1; a >= 0; a--)
clmod(obj[a], 'act');
obj = QSA('#ops>a');
for (var a = obj.length - 1; a >= 0; a--)
clmod(obj[a], 'act');
if (dest) {
var ui = ebi('op_' + dest);
clmod(ui, 'act', true);
QS('#ops>a[data-dest=' + dest + ']').className += " act";
var fn = window['goto_' + dest];
if (fn)
fn();
}
if (window['treectl'])
treectl.onscroll();
}
(function () {
goto();
var op = sread('opmode');
if (op !== null && op !== '.')
try {
goto(op);
}
catch (ex) { }
})();
function linksplit(rp) {
var ret = [];
var apath = '/';
@@ -533,7 +476,7 @@ function hist_replace(url) {
var tt = (function () {
var r = {
"tt": mknod("div"),
"en": bcfg_get('tooltips', true),
"en": true
};
r.tt.setAttribute('id', 'tt');
@@ -566,6 +509,17 @@ var tt = (function () {
}
r.init = function () {
var ttb = ebi('tooltips');
if (ttb) {
ttb.onclick = function (e) {
ev(e);
r.en = !r.en;
bcfg_set('tooltips', r.en);
r.init();
};
r.en = bcfg_get('tooltips', true)
}
var _show = r.en ? show : null,
_hide = r.en ? hide : null;
@@ -579,12 +533,5 @@ var tt = (function () {
hide();
};
ebi('tooltips').onclick = function (e) {
ev(e);
r.en = !r.en;
bcfg_set('tooltips', r.en);
r.init();
};
return r;
})();