Compare commits

...

14 Commits

Author SHA1 Message Date
ed
ed48c2d0ed v0.13.11 2021-08-30 22:32:16 +02:00
ed
26fe84b660 smaller sfx 2021-08-30 22:27:10 +02:00
ed
5938230270 more tray ui nitpicks 2021-08-30 22:25:07 +02:00
ed
1a33a047fa fix listening on single interface 2021-08-30 21:39:44 +02:00
ed
43a8bcefb9 v0.13.10 2021-08-30 03:02:11 +02:00
ed
2e740e513f cheap performance fix 2021-08-30 02:38:48 +02:00
ed
8a21a86b61 better iOS error-handling 2021-08-30 02:29:38 +02:00
ed
f600116205 login returns to volume listing 2021-08-30 01:55:24 +02:00
ed
1c03705de8 upload filedrops in alphabetical order 2021-08-30 01:50:12 +02:00
ed
f7e461fac6 add humantime 2021-08-30 01:16:20 +02:00
ed
03ce6c97ff better crash-handler ui 2021-08-30 01:15:37 +02:00
ed
ffd9e76e07 select all text in modal.prompt 2021-08-30 01:11:00 +02:00
ed
fc49cb1e67 add js repl 2021-08-30 01:09:27 +02:00
ed
f5712d9f25 v0.13.9 2021-08-29 02:24:09 +02:00
16 changed files with 175 additions and 62 deletions

View File

@@ -1,8 +1,8 @@
# coding: utf-8
VERSION = (0, 13, 8)
VERSION = (0, 13, 11)
CODENAME = "future-proof"
BUILD_DT = (2021, 8, 29)
BUILD_DT = (2021, 8, 30)
S_VERSION = ".".join(map(str, VERSION))
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)

View File

@@ -873,7 +873,7 @@ class HttpCli(object):
self.parser.drop()
ck, msg = self.get_pwd_cookie(pwd)
html = self.j2("msg", h1=msg, h2='<a href="/">ack</a>', redir="/")
html = self.j2("msg", h1=msg, h2='<a href="/?h">ack</a>', redir="/?h")
self.reply(html.encode("utf-8"), headers={"Set-Cookie": ck})
return True

View File

@@ -177,7 +177,7 @@ class TcpSrv(object):
eps = self.ips_linux()
if "0.0.0.0" not in listen_ips:
eps = {k: v for k, v in eps if k in listen_ips}
eps = {k: v for k, v in eps.items() if k in listen_ips}
default_route = None
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

View File

@@ -204,6 +204,9 @@ a, #files tbody div a:last-child {
color: #f4c;
border-bottom: 1px solid rgba(255,68,204,0.6);
}
#repl {
padding: .33em;
}
#files tbody a.play {
color: #e70;
padding: .2em;
@@ -340,17 +343,19 @@ html.light #ggrid>a.sel {
}
#wtgrid,
#wtico {
cursor: url(/.cpr/dd/4.png), pointer;
animation: cursor 500ms;
position: relative;
font-size: .9em;
top: -.04em;
}
#wtgrid {
font-size: .75em;
padding: .1em;
top: -.12em;
}
#wtgrid:hover,
#wtico {
cursor: url(/.cpr/dd/4.png), pointer;
animation: cursor 500ms;
}
#wtico:hover {
animation: cursor 500ms infinite;
}
@@ -378,23 +383,25 @@ html.light #ggrid>a.sel {
background: #3c3c3c;
box-shadow: 0 0 .5em #222;
border-radius: .3em 0 0 0;
padding: 0;
padding: 0 0 0 .1em;
color: #fff;
}
#wzip, #wnp {
#wfm, #wzip, #wnp {
display: none;
margin-right: .3em;
padding-right: .3em;
}
#wzip, #wnp {
margin-right: .2em;
padding-right: .2em;
border-right: .1em solid #555;
}
#wnp a {
position: relative;
font-size: .47em;
margin: 0 .1em;
top: -.4em;
#wfm.act+#wzip,
#wfm.act+#wzip+#wnp {
margin-left: .2em;
padding-left: .2em;
border-left: .1em solid #555;
}
#wnp a+a {
margin-left: .33em;
#wfm.act {
display: inline-block;
}
#wtoggle,
#wtoggle * {
@@ -408,6 +415,7 @@ html.light #ggrid>a.sel {
display: none;
}
#wfm a,
#wnp a,
#wzip a {
font-size: .5em;
padding: 0 .3em;
@@ -415,10 +423,14 @@ html.light #ggrid>a.sel {
position: relative;
display: inline-block;
}
#wfm span {
#wfm span,
#wnp span {
font-size: .6em;
display: block;
}
#wnp span {
font-size: .7em;
}
#wfm a:not(.en) {
opacity: .3;
color: #f6c;

View File

@@ -113,6 +113,8 @@
<div id="epi" class="logue">{{ logues[1] }}</div>
<h2><a href="/?h">control-panel</a></h2>
<a href="#" id="repl">π</a>
</div>

View File

@@ -40,8 +40,8 @@ ebi('widget').innerHTML = (
' href="#" id="selinv" tt="invert selection">sel.<br />inv.</a><a' +
' href="#" id="selzip" tt="download selection as archive">zip</a>' +
'</span><span id="wnp"><a' +
' href="#" id="npirc" tt="copy irc-formatted track info">📋irc</a><a' +
' href="#" id="nptxt" tt="copy plaintext track info">📋txt</a>' +
' href="#" id="npirc" tt="copy irc-formatted track info">📋<span>irc</span></a><a' +
' href="#" id="nptxt" tt="copy plaintext track info">📋<span>txt</span></a>' +
'</span><a' +
' href="#" id="wtgrid" tt="toggle grid/list view$NHotkey: G">田</a><a' +
' href="#" id="wtico">♫</a>' +
@@ -284,7 +284,7 @@ var mpl = (function () {
r.os_ctl = !r.os_ctl && have_mctl;
bcfg_set('au_os_ctl', r.os_ctl);
if (!have_mctl)
toast.err(5, 'need firefox 82+ or chrome 73+');
toast.err(5, 'need firefox 82+ or chrome 73+\n(or iOS 15+ supposedly)');
};
ebi('au_osd_cv').onclick = function (e) {
@@ -704,7 +704,7 @@ var pbar = (function () {
pctx.clearRect(0, 0, pc.w, pc.h);
if (!mp.au || mp.loading || isNaN(adur = mp.au.duration) || isNaN(apos = mp.au.currentTime))
if (!mp.au || mp.loading || isNaN(adur = mp.au.duration) || isNaN(apos = mp.au.currentTime) || apos < 0 || adur < apos)
return; // not-init || unsupp-codec
var sm = bc.w * 1.0 / adur;
@@ -1293,12 +1293,21 @@ function play(tid, is_ev, seek, call_depth) {
var url = mp.tracks[tid];
if (need_ogv_for(url)) {
var m = /.* Version\/([0-9]+)\.[0-9\.]+ Mobile\/[^ ]+ Safari\/[0-9\.]+$/.exec(navigator.userAgent),
safari = m ? parseInt(m[1]) : 99;
if (mp.au_ogvjs) {
mp.au = mp.au_ogvjs;
}
else if (window['OGVPlayer']) {
mp.loading = true;
mp.au = mp.au_ogvjs = new OGVPlayer();
try {
mp.au = mp.au_ogvjs = new OGVPlayer();
}
catch (ex) {
return toast.err(30, 'your browser cannot play ogg/vorbis/opus\n\n' + ex +
'\n\n<a href="#" onclick="new OGVPlayer();">click here</a> for a full crash report');
}
attempt_play = is_ev;
mp.au.onerror = evau_error;
mp.au.onprogress = pbar.drawpos;
@@ -1308,6 +1317,9 @@ function play(tid, is_ev, seek, call_depth) {
};
widget.open();
}
else if (safari < 14) {
return toast.err(0, 'because this is an apple device,\nsafari 14 or newer is required to play ogg/vorbis/opus files\n\nyou are using safari ' + safari + '\n(every iOS browser is actually safari)');
}
else {
if (call_depth !== undefined)
return toast.err(0, 'failed to load ogv.js:\ncannot play ogg/opus in this browser\n(try a non-apple device)');
@@ -1317,10 +1329,6 @@ function play(tid, is_ev, seek, call_depth) {
import_js('/.cpr/deps/ogv.js', function () {
toast.hide();
play(tid, false, seek, 1);
var m = /.* Version\/([0-9]+)\.[0-9\.]+ Mobile\/[^ ]+ Safari\/[0-9\.]+$/.exec(navigator.userAgent);
if (m && parseInt(m[1]) < 14)
toast.err(0, 'because this is an apple device,\nsafari 14 or newer is required\n\nyou are using safari version ' + m[1] + ', so playback of ogg/vorbis/opus files will be buggy\n\nnote: every iOS browser is safari');
});
return;
@@ -1710,7 +1718,7 @@ var fileman = (function () {
bcut.style.display = have_mv && has(perms, 'move') ? '' : 'none';
bpst.style.display = have_mv && has(perms, 'write') ? '' : 'none';
bpst.setAttribute('tt', 'paste ' + r.clip.length + ' items$NHotkey: ctrl-V');
ebi('wfm').style.display = QS('#wfm a.en:not([display])') ? '' : 'none';
clmod(ebi('wfm'), 'act', QS('#wfm a.en:not([style])'));
};
r.rename = function (e) {
@@ -1791,6 +1799,7 @@ var fileman = (function () {
'</table></div>'
]);
var cheap = f.length > 500;
if (sel.length == 1)
html.push(
'<div><table id="rn_f">\n' +
@@ -1803,8 +1812,9 @@ var fileman = (function () {
for (var a = 0; a < f.length; a++)
html.push(
'<tr><td>' +
'<button class="rn_dec" n="' + a + '">decode</button>',
'<button class="rn_reset" n="' + a + '">↺ reset</button></td>',
(cheap ? '</td>' :
'<button class="rn_dec" n="' + a + '">decode</button>' +
'<button class="rn_reset" n="' + a + '">↺ reset</button></td>') +
'<td><input type="text" id="rn_new" n="' + a + '" /></td>' +
'<td><input type="text" id="rn_old" n="' + a + '" readonly /></td></tr>');
}
@@ -1825,23 +1835,26 @@ var fileman = (function () {
f[a].inew = QS('#rn_new' + k);
f[a].inew.value = f[a].iold.value = f[a].ofn;
(function (a) {
f[a].inew.onkeydown = function (e) {
rn_ok(a, true);
if (!cheap)
(function (a) {
f[a].inew.onkeydown = function (e) {
rn_ok(a, true);
if (e.key == 'Escape')
return rn_cancel();
if (e.key == 'Escape')
return rn_cancel();
if (e.key == 'Enter')
return rn_apply();
};
QS('.rn_dec' + k).onclick = function () {
f[a].inew.value = uricom_dec(f[a].inew.value)[0];
};
QS('.rn_reset' + k).onclick = function () {
rn_reset(a);
};
})(a);
if (e.key == 'Enter')
return rn_apply();
};
QS('.rn_dec' + k).onclick = function (e) {
ev(e);
f[a].inew.value = uricom_dec(f[a].inew.value)[0];
};
QS('.rn_reset' + k).onclick = function (e) {
ev(e);
rn_reset(a);
};
})(a);
}
rn_reset(0);
tt.att(rui);

View File

@@ -8,6 +8,14 @@ html, body {
font-family: sans-serif;
line-height: 1.5em;
}
#repl {
position: absolute;
top: 0;
right: .2em;
border: none;
color: inherit;
background: none;
}
#mtw {
display: none;
}
@@ -506,6 +514,9 @@ blink {
border-bottom: .07em solid #4ac;
padding: 0 .3em;
}
#repl {
display: none;
}
#toc>ul {
border-left: .1em solid #84c4dd;
}

View File

@@ -45,6 +45,7 @@
</div>
<div id="mp"></div>
</div>
<a href="#" id="repl">π</a>
{%- if edit %}
<div id="helpbox">

View File

@@ -22,6 +22,15 @@ html, body {
bottom: auto;
top: 1.4em;
}
#repl {
position: absolute;
top: 0;
right: .5em;
border: none;
color: inherit;
background: none;
text-decoration: none;
}
#mn {
font-weight: normal;
margin: 1.3em 0 .7em 1em;

View File

@@ -21,6 +21,7 @@
<textarea id="mt" style="display:none" autocomplete="off">{{ md }}</textarea>
</div>
</div>
<a href="#" id="repl">π</a>
<script>
var last_modified = {{ lastmod }};

View File

@@ -29,6 +29,12 @@ a {
border-radius: .2em;
padding: .2em .8em;
}
#repl {
border: none;
background: none;
color: inherit;
padding: 0;
}
table {
border-collapse: collapse;
}

View File

@@ -7,6 +7,7 @@
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=0.8">
<link rel="stylesheet" media="screen" href="/.cpr/splash.css?_={{ ts }}">
<link rel="stylesheet" media="screen" href="/.cpr/ui.css?_={{ ts }}">
</head>
<body>
@@ -66,11 +67,13 @@
</form>
</ul>
</div>
<a href="#" id="repl">π</a>
<script>
if (localStorage.getItem('lightmode') != 1)
document.documentElement.setAttribute("class", "dark");
</script>
<script src="/.cpr/util.js?_={{ ts }}"></script>
</body>
</html>
</html>

View File

@@ -26,7 +26,9 @@ html {
right: -1em;
line-height: 1.5em;
padding: 1em 1.3em;
margin-left: 3em;
border-width: .4em 0;
overflow-wrap: break-word;
transform: translateX(100%);
transition:
transform .4s cubic-bezier(.2, 1.2, .5, 1),
@@ -34,7 +36,14 @@ html {
text-shadow: 1px 1px 0 #000;
color: #fff;
}
#toastc {
#toast a {
color: inherit;
text-shadow: inherit;
background: rgba(0, 0, 0, 0.4);
border-radius: .3em;
padding: .2em .3em;
}
#toast a#toastc {
display: inline-block;
position: absolute;
overflow: hidden;
@@ -107,6 +116,7 @@ html {
padding: 1.5em 2em;
border-width: .5em 0;
}
#modalc code,
#tt code {
background: #3c3c3c;
padding: .1em .3em;
@@ -125,6 +135,7 @@ html.light #tt,
html.light #toast {
box-shadow: 0 .3em 1em rgba(0,0,0,0.4);
}
#modalc code,
html.light #tt code {
background: #060;
color: #fff;
@@ -207,6 +218,8 @@ html.light #tt em {
}
#modali {
display: block;
background: #fff;
color: #000;
width: calc(100% - 1.25em);
margin: 1em -.1em 0 -.1em;
padding: .5em;

View File

@@ -800,6 +800,12 @@ function up2k_init(subtle) {
});
}
good_files.sort(function (a, b) {
a = a[1];
b = b[1];
return a < b ? -1 : a > b ? 1 : 0;
});
var msg = ['{0} these {1} files?<ul>'.format(fsearch ? 'search' : 'upload', good_files.length)];
for (var a = 0, aa = Math.min(20, good_files.length); a < aa; a++)
msg.push('<li>' + esc(good_files[a][1]) + '</li>');
@@ -906,7 +912,7 @@ function up2k_init(subtle) {
td = (now - (etaref || now)) / 1000.0;
etaref = now;
//ebi('acc_info').innerHTML = f2f(st.time.busy, 1) + ' ' + f2f(now / 1000, 1);
//ebi('acc_info').innerHTML = humantime(st.time.busy) + ' ' + f2f(now / 1000, 1);
if (!nhash)
ebi('u2etah').innerHTML = 'Done ({0}, {1} files)'.format(humansize(st.bytes.hashed), pvis.ctr["ok"] + pvis.ctr["ng"]);
@@ -954,14 +960,8 @@ function up2k_init(subtle) {
if (etaskip)
continue;
if (eta < 60 * 60 * 24)
try {
eta = /.*(..:..:..).*/.exec(new Date(eta * 1000).toUTCString())[1];
}
catch (ex) { }
ebi(t[a][0]).innerHTML = '{0}, {1}/s, {2}'.format(
humansize(rem), humansize(bps, 1), eta);
humansize(rem), humansize(bps, 1), humantime(eta));
}
if (++etaskip > 2)
etaskip = 0;
@@ -1852,7 +1852,7 @@ function up2k_init(subtle) {
flag = up2k_flagbus();
}
catch (ex) {
console.log("flag error: " + ex.toString());
toast.err(5, "not supported on your browser:\n" + ex);
tgl_flag_en();
}
}

View File

@@ -39,7 +39,8 @@ function vis_exh(msg, url, lineNo, columnNo, error) {
crashed = true;
window.onerror = undefined;
var html = ['<h1>you hit a bug!</h1><p style="font-size:1.3em;margin:0">try to <a href="#" onclick="localStorage.clear();location.reload();">reset copyparty settings</a> if you are stuck here, or <a href="#" onclick="ignex();">ignore this</a> / <a href="#" onclick="ignex(true);">ignore all</a></p><p>please send me a screenshot arigathanks gozaimuch: <code>ed/irc.rizon.net</code> or <code>ed#2644</code><br />&nbsp; (and if you can, press F12 and include the "Console" tab in the screenshot too)</p><p>',
var con = is_touch ? '' : '<br />&nbsp; (and if you can, press F12 and include the "Console" tab in the screenshot too)',
html = ['<h1>you hit a bug!</h1><p style="font-size:1.3em;margin:0">try to <a href="#" onclick="localStorage.clear();location.reload();">reset copyparty settings</a> if you are stuck here, or <a href="#" onclick="ignex();">ignore this</a> / <a href="#" onclick="ignex(true);">ignore all</a></p><p>please send me a screenshot arigathanks gozaimuch: <code>ed/irc.rizon.net</code> or <code>ed#2644</code>' + con + '</p><p>',
esc(url + ' @' + lineNo + ':' + columnNo), '<br />' + esc(String(msg)) + '</p>'];
try {
@@ -63,10 +64,10 @@ function vis_exh(msg, url, lineNo, columnNo, error) {
document.body.appendChild(exbox);
var s = mknod('style');
s.innerHTML = '#exbox{background:#333;color:#ddd;font-family:sans-serif;font-size:0.8em;padding:0 1em 1em 1em;z-index:80386;position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%} #exbox h1{margin:.5em 1em 0 0;padding:0} #exbox h3{border-top:1px solid #999;margin:1em 0 0 0} #exbox a{text-decoration:underline;color:#fc0} #exbox code{color:#bf7;background:#222;padding:.1em;margin:.2em;font-size:1.1em;font-family:monospace,monospace} #exbox *{line-height:1.5em}';
s.innerHTML = '#exbox{background:#333;color:#ddd;font-family:sans-serif;font-size:0.8em;padding:0 1em 1em 1em;z-index:80386;position:fixed;top:0;left:0;right:0;bottom:0;width:100%;height:100%;overflow:auto;width:calc(100% - 2em)} #exbox h1{margin:.5em 1em 0 0;padding:0} #exbox h3{border-top:1px solid #999;margin:1em 0 0 0} #exbox a{text-decoration:underline;color:#fc0} #exbox code{color:#bf7;background:#222;padding:.1em;margin:.2em;font-size:1.1em;font-family:monospace,monospace} #exbox,#exbox *{line-height:1.5em;overflow-wrap:break-word}';
document.head.appendChild(s);
}
exbox.innerHTML = html.join('\n');
exbox.innerHTML = html.join('\n').replace(/https?:\/\/[^ \/]+\//g, '/');
exbox.style.display = 'block';
}
catch (e) {
@@ -429,6 +430,19 @@ function humansize(b, terse) {
}
function humantime(v) {
if (v >= 60 * 60 * 24)
return v;
try {
return /.*(..:..:..).*/.exec(new Date(v * 1000).toUTCString())[1];
}
catch (ex) {
return v;
}
}
function clamp(v, a, b) {
return Math.min(Math.max(v, a), b);
}
@@ -782,7 +796,13 @@ var modal = (function () {
a = ebi('modal-ok');
a.onclick = ok;
(ebi('modali') || a).focus();
var inp = ebi('modali');
(inp || a).focus();
if (inp)
setTimeout(function () {
inp.setSelectionRange(0, inp.value.length, "forward");
}, 0);
document.addEventListener('focus', onfocus);
timer.add(onfocus);
};
@@ -892,3 +912,24 @@ function winpopup(txt) {
body: 'msg=' + uricom_enc(Date.now() + ', ' + txt)
});
}
function repl(e) {
ev(e);
modal.prompt('js repl (prefix with <code>,</code> to allow raise)', 'var v=Object.keys(localStorage); v.sort(); JSON.stringify(v)', function (cmd) {
if (!cmd)
return toast.inf(3, 'eval aborted');
if (cmd.startsWith(','))
return modal.alert(esc(eval(cmd.slice(1)) + ''))
try {
modal.alert(esc(eval(cmd) + ''));
}
catch (ex) {
modal.alert('<h6>exception</h6>' + esc(ex + ''));
}
});
}
if (ebi('repl'))
ebi('repl').onclick = repl;

View File

@@ -37,6 +37,7 @@ gtar=$(command -v gtar || command -v gnutar) || true
sed() { gsed "$@"; }
find() { gfind "$@"; }
sort() { gsort "$@"; }
shuf() { gshuf "$@"; }
sha1sum() { shasum "$@"; }
unexpand() { gunexpand "$@"; }
command -v grealpath >/dev/null &&
@@ -303,7 +304,7 @@ for d in copyparty dep-j2; do find $d -type f; done |
sed -r 's/(.*)\.(.*)/\2 \1/' | LC_ALL=C sort |
sed -r 's/([^ ]*) (.*)/\2.\1/' | grep -vE '/list1?$' > list1
(grep -vE '\.(gz|br)$' list1; grep -E '\.(gz|br)$' list1) >list || true
(grep -vE '\.(gz|br)$' list1; grep -E '\.(gz|br)$' list1 | shuf) >list || true
echo creating tar
args=(--owner=1000 --group=1000)