mirror of
				https://github.com/9001/copyparty.git
				synced 2025-11-04 05:43:17 +00:00 
			
		
		
		
	Compare commits
	
		
			21 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					941aedb177 | ||
| 
						 | 
					87a0d502a3 | ||
| 
						 | 
					cab7c1b0b8 | ||
| 
						 | 
					d5892341b6 | ||
| 
						 | 
					646557a43e | ||
| 
						 | 
					ed8d34ab43 | ||
| 
						 | 
					5e34463c77 | ||
| 
						 | 
					1b14eb7959 | ||
| 
						 | 
					ed48c2d0ed | ||
| 
						 | 
					26fe84b660 | ||
| 
						 | 
					5938230270 | ||
| 
						 | 
					1a33a047fa | ||
| 
						 | 
					43a8bcefb9 | ||
| 
						 | 
					2e740e513f | ||
| 
						 | 
					8a21a86b61 | ||
| 
						 | 
					f600116205 | ||
| 
						 | 
					1c03705de8 | ||
| 
						 | 
					f7e461fac6 | ||
| 
						 | 
					03ce6c97ff | ||
| 
						 | 
					ffd9e76e07 | ||
| 
						 | 
					fc49cb1e67 | 
@@ -1,8 +1,8 @@
 | 
			
		||||
# coding: utf-8
 | 
			
		||||
 | 
			
		||||
VERSION = (0, 13, 9)
 | 
			
		||||
VERSION = (0, 13, 12)
 | 
			
		||||
CODENAME = "future-proof"
 | 
			
		||||
BUILD_DT = (2021, 8, 29)
 | 
			
		||||
BUILD_DT = (2021, 9, 1)
 | 
			
		||||
 | 
			
		||||
S_VERSION = ".".join(map(str, VERSION))
 | 
			
		||||
S_BUILD_DT = "{0:04d}-{1:02d}-{2:02d}".format(*BUILD_DT)
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -114,6 +114,8 @@
 | 
			
		||||
 | 
			
		||||
	<h2><a href="/?h">control-panel</a></h2>
 | 
			
		||||
	
 | 
			
		||||
	<a href="#" id="repl">π</a>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
	{%- if srv_info %}
 | 
			
		||||
 
 | 
			
		||||
@@ -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) {
 | 
			
		||||
@@ -1252,6 +1252,9 @@ function play(tid, is_ev, seek, call_depth) {
 | 
			
		||||
	if (mp.order.length == 0)
 | 
			
		||||
		return console.log('no audio found wait what');
 | 
			
		||||
 | 
			
		||||
	if (crashed)
 | 
			
		||||
		return;
 | 
			
		||||
 | 
			
		||||
	mp.stopfade(true);
 | 
			
		||||
 | 
			
		||||
	var tn = tid;
 | 
			
		||||
@@ -1293,12 +1296,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;
 | 
			
		||||
			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 +1320,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 +1332,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 +1721,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 +1802,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 +1815,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,6 +1838,7 @@ var fileman = (function () {
 | 
			
		||||
			f[a].inew = QS('#rn_new' + k);
 | 
			
		||||
			f[a].inew.value = f[a].iold.value = f[a].ofn;
 | 
			
		||||
 | 
			
		||||
			if (!cheap)
 | 
			
		||||
				(function (a) {
 | 
			
		||||
					f[a].inew.onkeydown = function (e) {
 | 
			
		||||
						rn_ok(a, true);
 | 
			
		||||
@@ -1835,10 +1849,12 @@ var fileman = (function () {
 | 
			
		||||
						if (e.key == 'Enter')
 | 
			
		||||
							return rn_apply();
 | 
			
		||||
					};
 | 
			
		||||
				QS('.rn_dec' + k).onclick = function () {
 | 
			
		||||
					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 () {
 | 
			
		||||
					QS('.rn_reset' + k).onclick = function (e) {
 | 
			
		||||
						ev(e);
 | 
			
		||||
						rn_reset(a);
 | 
			
		||||
					};
 | 
			
		||||
				})(a);
 | 
			
		||||
@@ -2076,9 +2092,18 @@ var fileman = (function () {
 | 
			
		||||
				clmod(els[a], 'fcut', 1);
 | 
			
		||||
		}, 1);
 | 
			
		||||
 | 
			
		||||
		toast.inf(1.5, 'cut ' + sel.length + ' items');
 | 
			
		||||
		jwrite('fman_clip', vps);
 | 
			
		||||
		try {
 | 
			
		||||
			vps = JSON.stringify(vps);
 | 
			
		||||
			if (vps.length > 1024 * 1024)
 | 
			
		||||
				throw 'a';
 | 
			
		||||
 | 
			
		||||
			swrite('fman_clip', vps);
 | 
			
		||||
			r.tx(1);
 | 
			
		||||
			toast.inf(1.5, 'cut ' + sel.length + ' items');
 | 
			
		||||
		}
 | 
			
		||||
		catch (ex) {
 | 
			
		||||
			toast.warn(30, 'cut ' + sel.length + ' items\n\nbut: only <b>this</b> browser-tab can paste them\n(since the selection is so absolutely massive)');
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	r.paste = function (e) {
 | 
			
		||||
@@ -2687,10 +2712,10 @@ document.onkeydown = function (e) {
 | 
			
		||||
			return ebi('gridsel').click();
 | 
			
		||||
 | 
			
		||||
		if (k == 'KeyA')
 | 
			
		||||
			return QSA('#ghead>a[z]')[0].click();
 | 
			
		||||
			return QSA('#ghead a[z]')[0].click();
 | 
			
		||||
 | 
			
		||||
		if (k == 'KeyD')
 | 
			
		||||
			return QSA('#ghead>a[z]')[1].click();
 | 
			
		||||
			return QSA('#ghead a[z]')[1].click();
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
	}
 | 
			
		||||
 
 | 
			
		||||
@@ -45,6 +45,7 @@
 | 
			
		||||
		</div>
 | 
			
		||||
		<div id="mp"></div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<a href="#" id="repl">π</a>
 | 
			
		||||
	
 | 
			
		||||
	{%- if edit %}
 | 
			
		||||
	<div id="helpbox">
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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 }};
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,12 @@ a {
 | 
			
		||||
	border-radius: .2em;
 | 
			
		||||
	padding: .2em .8em;
 | 
			
		||||
}
 | 
			
		||||
#repl {
 | 
			
		||||
	border: none;
 | 
			
		||||
	background: none;
 | 
			
		||||
	color: inherit;
 | 
			
		||||
	padding: 0;
 | 
			
		||||
}
 | 
			
		||||
table {
 | 
			
		||||
	border-collapse: collapse;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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>
 | 
			
		||||
@@ -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;
 | 
			
		||||
@@ -43,7 +52,7 @@ html {
 | 
			
		||||
	opacity: 0;
 | 
			
		||||
	padding: .3em 0;
 | 
			
		||||
	margin: -.3em 0 0 0;
 | 
			
		||||
	line-height: 1.5em;
 | 
			
		||||
	line-height: 1.3em;
 | 
			
		||||
	color: #000;
 | 
			
		||||
	border: none;
 | 
			
		||||
	outline: none;
 | 
			
		||||
@@ -51,6 +60,15 @@ html {
 | 
			
		||||
	border-radius: .5em 0 0 .5em;
 | 
			
		||||
	transition: left .3s, width .3s, padding .3s, opacity .3s;
 | 
			
		||||
}
 | 
			
		||||
#toastb {
 | 
			
		||||
	max-height: 70vh;
 | 
			
		||||
	overflow-y: auto;
 | 
			
		||||
}
 | 
			
		||||
#toast.scroll #toastb {
 | 
			
		||||
	overflow-y: scroll;
 | 
			
		||||
	margin-right: -1.2em;
 | 
			
		||||
	padding-right: .7em;
 | 
			
		||||
}
 | 
			
		||||
#toast pre {
 | 
			
		||||
	margin: 0;
 | 
			
		||||
}
 | 
			
		||||
@@ -107,6 +125,7 @@ html {
 | 
			
		||||
	padding: 1.5em 2em;
 | 
			
		||||
	border-width: .5em 0;
 | 
			
		||||
}
 | 
			
		||||
#modalc code,
 | 
			
		||||
#tt code {
 | 
			
		||||
	background: #3c3c3c;
 | 
			
		||||
	padding: .1em .3em;
 | 
			
		||||
@@ -125,6 +144,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 +227,8 @@ html.light #tt em {
 | 
			
		||||
}
 | 
			
		||||
#modali {
 | 
			
		||||
	display: block;
 | 
			
		||||
	background: #fff;
 | 
			
		||||
	color: #000;
 | 
			
		||||
	width: calc(100% - 1.25em);
 | 
			
		||||
    margin: 1em -.1em 0 -.1em;
 | 
			
		||||
	padding: .5em;
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -39,19 +39,50 @@ 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 />  (and if you can, press F12 and include the "Console" tab in the screenshot too)</p><p>',
 | 
			
		||||
        esc(url + ' @' + lineNo + ':' + columnNo), '<br />' + esc(String(msg)) + '</p>'];
 | 
			
		||||
    var con = is_touch ? '' : '<br />  (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 style="color:#fff">please send me a screenshot arigathanks gozaimuch: <code>ed/irc.rizon.net</code> or <code>ed#2644</code>' + con + '</p>',
 | 
			
		||||
            '<p class="b">' + esc(url + ' @' + lineNo + ':' + columnNo), '<br />' + esc(String(msg)) + '</p>',
 | 
			
		||||
            '<p><b>UA:</b> ' + esc(navigator.userAgent + '')
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        var ua = '',
 | 
			
		||||
            ad = navigator.userAgentData,
 | 
			
		||||
            adb = ad.brands;
 | 
			
		||||
 | 
			
		||||
        for (var a = 0; a < adb.length; a++)
 | 
			
		||||
            if (adb[a].brand.indexOf('Not;A') < 0)
 | 
			
		||||
                ua += adb[a].brand + '/' + adb[a].version + ', ';
 | 
			
		||||
        ua += ad.platform;
 | 
			
		||||
 | 
			
		||||
        html.push('<br /><b>UAD:</b> ' + esc(ua.slice(0, 100)));
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) { }
 | 
			
		||||
    html.push('</p>');
 | 
			
		||||
 | 
			
		||||
    try {
 | 
			
		||||
        if (error) {
 | 
			
		||||
            var find = ['desc', 'stack', 'trace'];
 | 
			
		||||
            for (var a = 0; a < find.length; a++)
 | 
			
		||||
                if (String(error[find[a]]) !== 'undefined')
 | 
			
		||||
                    html.push('<h3>' + find[a] + '</h3>' +
 | 
			
		||||
                        esc(String(error[find[a]])).replace(/\n/g, '<br />\n'));
 | 
			
		||||
                    html.push('<p class="b"><b>' + find[a] + ':</b><br />' +
 | 
			
		||||
                        esc(String(error[find[a]])).replace(/\n/g, '<br />\n') + '</p>');
 | 
			
		||||
        }
 | 
			
		||||
        ignexd[ekey] = true;
 | 
			
		||||
        html.push('<h3>localStore</h3>' + esc(JSON.stringify(localStorage)));
 | 
			
		||||
 | 
			
		||||
        var ls = jcp(localStorage);
 | 
			
		||||
        if (ls.fman_clip)
 | 
			
		||||
            ls.fman_clip = ls.fman_clip.length + ' items';
 | 
			
		||||
 | 
			
		||||
        var lsk = Object.keys(ls);
 | 
			
		||||
        lsk.sort();
 | 
			
		||||
        html.push('<p class="b">');
 | 
			
		||||
        for (var a = 0; a < lsk.length; a++)
 | 
			
		||||
            html.push(' <b>' + esc(lsk[a]) + '</b> <code>' + esc(ls[lsk[a]]) + '</code> ');
 | 
			
		||||
        html.push('</p>');
 | 
			
		||||
    }
 | 
			
		||||
    catch (e) { }
 | 
			
		||||
 | 
			
		||||
@@ -63,10 +94,18 @@ 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,#exbox *{line-height:1.5em;overflow-wrap:break-word} ' +
 | 
			
		||||
                '#exbox code{color:#bf7;background:#222;padding:.1em;margin:.2em;font-size:1.1em;font-family:monospace,monospace} ' +
 | 
			
		||||
                '#exbox a{text-decoration:underline;color:#fc0} ' +
 | 
			
		||||
                '#exbox h1{margin:.5em 1em 0 0;padding:0} ' +
 | 
			
		||||
                '#exbox p.b{border-top:1px solid #999;margin:1em 0 0 0;font-size:1em} ' +
 | 
			
		||||
                '#exbox b{color:#fff}'
 | 
			
		||||
            );
 | 
			
		||||
            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 +468,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);
 | 
			
		||||
}
 | 
			
		||||
@@ -713,6 +765,7 @@ function lf2br(txt) {
 | 
			
		||||
var toast = (function () {
 | 
			
		||||
    var r = {},
 | 
			
		||||
        te = null,
 | 
			
		||||
        scrolling = false,
 | 
			
		||||
        obj = mknod('div');
 | 
			
		||||
 | 
			
		||||
    obj.setAttribute('id', 'toast');
 | 
			
		||||
@@ -720,8 +773,30 @@ var toast = (function () {
 | 
			
		||||
    r.visible = false;
 | 
			
		||||
    r.txt = null;
 | 
			
		||||
 | 
			
		||||
    function scrollchk() {
 | 
			
		||||
        if (scrolling)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        var tb = ebi('toastb'),
 | 
			
		||||
            vis = tb.offsetHeight,
 | 
			
		||||
            all = tb.scrollHeight;
 | 
			
		||||
 | 
			
		||||
        if (8 + vis >= all)
 | 
			
		||||
            return;
 | 
			
		||||
 | 
			
		||||
        clmod(obj, 'scroll', 1);
 | 
			
		||||
        scrolling = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function unscroll() {
 | 
			
		||||
        timer.rm(scrollchk);
 | 
			
		||||
        clmod(obj, 'scroll');
 | 
			
		||||
        scrolling = false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    r.hide = function (e) {
 | 
			
		||||
        ev(e);
 | 
			
		||||
        unscroll();
 | 
			
		||||
        clearTimeout(te);
 | 
			
		||||
        clmod(obj, 'vis');
 | 
			
		||||
        r.visible = false;
 | 
			
		||||
@@ -732,11 +807,12 @@ var toast = (function () {
 | 
			
		||||
        if (ms)
 | 
			
		||||
            te = setTimeout(r.hide, ms * 1000);
 | 
			
		||||
 | 
			
		||||
        obj.innerHTML = '<a href="#" id="toastc">x</a>' + lf2br(txt);
 | 
			
		||||
        obj.innerHTML = '<a href="#" id="toastc">x</a><div id="toastb">' + lf2br(txt) + '</div>';
 | 
			
		||||
        obj.className = cl;
 | 
			
		||||
        ms += obj.offsetWidth;
 | 
			
		||||
        obj.className += ' vis';
 | 
			
		||||
        ebi('toastc').onclick = r.hide;
 | 
			
		||||
        timer.add(scrollchk);
 | 
			
		||||
        r.visible = true;
 | 
			
		||||
        r.txt = txt;
 | 
			
		||||
    };
 | 
			
		||||
@@ -782,7 +858,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 +974,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;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,7 @@
 | 
			
		||||
/* video */
 | 
			
		||||
/* video, alternative 1:
 | 
			
		||||
   top-left icon, just like the other formats
 | 
			
		||||
=======================================================================
 | 
			
		||||
 | 
			
		||||
#ggrid>a:is(
 | 
			
		||||
[href$=".mkv"i],
 | 
			
		||||
[href$=".mp4"i],
 | 
			
		||||
@@ -6,6 +9,40 @@
 | 
			
		||||
):before {
 | 
			
		||||
    content: '📺';
 | 
			
		||||
}
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* video, alternative 2:
 | 
			
		||||
   play-icon in the middle of the thumbnail
 | 
			
		||||
=======================================================================
 | 
			
		||||
*/
 | 
			
		||||
#ggrid>a:is(
 | 
			
		||||
[href$=".mkv"i],
 | 
			
		||||
[href$=".mp4"i],
 | 
			
		||||
[href$=".webm"i],
 | 
			
		||||
) {
 | 
			
		||||
	position: relative;
 | 
			
		||||
	overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
#ggrid>a:is(
 | 
			
		||||
[href$=".mkv"i],
 | 
			
		||||
[href$=".mp4"i],
 | 
			
		||||
[href$=".webm"i],
 | 
			
		||||
):before {
 | 
			
		||||
    content: '▶';
 | 
			
		||||
	opacity: .8;
 | 
			
		||||
	margin: 0;
 | 
			
		||||
	padding: 1em .5em 1em .7em;
 | 
			
		||||
	border-radius: 9em;
 | 
			
		||||
	line-height: 0;
 | 
			
		||||
	color: #fff;
 | 
			
		||||
	text-shadow: none;
 | 
			
		||||
	background: rgba(0, 0, 0, 0.7);
 | 
			
		||||
	left: calc(50% - 1em);
 | 
			
		||||
	top: calc(50% - 1.4em);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* audio */
 | 
			
		||||
@@ -21,6 +58,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* image */
 | 
			
		||||
#ggrid>a:is(
 | 
			
		||||
[href$=".jpg"i],
 | 
			
		||||
 
 | 
			
		||||
@@ -130,6 +130,9 @@ sqlite3 .hist/up2k.db 'select * from mt where k="fgsfds" or k="t:mtp"' | tee /de
 | 
			
		||||
for ((f=420;f<1200;f++)); do sz=$(ffmpeg -y -f lavfi -i sine=frequency=$f:duration=2 -vf volume=0.1 -ac 1 -ar 44100 -f s16le /dev/shm/a.wav 2>/dev/null; base64 -w0 </dev/shm/a.wav | gzip -c | wc -c); printf '%d %d\n' $f $sz; done | tee /dev/stderr | sort -nrk2,2
 | 
			
		||||
ffmpeg -y -f lavfi -i sine=frequency=1050:duration=2 -vf volume=0.1 -ac 1 -ar 44100 /dev/shm/a.wav
 | 
			
		||||
 | 
			
		||||
# play icon calibration pics
 | 
			
		||||
for w in 150 170 190 210 230 250; do for h in 130 150 170 190 210; do /c/Program\ Files/ImageMagick-7.0.11-Q16-HDRI/magick.exe convert -size ${w}x${h} xc:brown -fill orange -draw "circle $((w/2)),$((h/2)) $((w/2)),$((h/3))" $w-$h.png; done; done
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
##
 | 
			
		||||
## vscode
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user