diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css
index 4930ccee..8953d35e 100644
--- a/copyparty/web/browser.css
+++ b/copyparty/web/browser.css
@@ -579,3 +579,16 @@ input[type="checkbox"]:checked+label {
color: #300;
background: #fea;
}
+#op_cfg {
+ max-width: none;
+ margin-right: 1.5em;
+}
+#key_notation>span {
+ display: inline-block;
+ padding: .2em .4em;
+}
+#op_cfg h3 {
+ margin: .8em 0 0 .6em;
+ padding: 0;
+ border-bottom: 1px solid #555;
+}
diff --git a/copyparty/web/browser.html b/copyparty/web/browser.html
index 121869cf..eb58810d 100644
--- a/copyparty/web/browser.html
+++ b/copyparty/web/browser.html
@@ -23,6 +23,7 @@
📂
📝
📟
+ ⚙️
@@ -33,7 +34,13 @@
{%- endif %}
+
{%- include 'upload.html' %}
+
+
🌲
diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js
index 2bc3d661..8625b548 100644
--- a/copyparty/web/browser.js
+++ b/copyparty/web/browser.js
@@ -945,6 +945,7 @@ function autoplay_blocked() {
ebi('epi').innerHTML = res.logues ? res.logues[1] || "" : "";
filecols.set_style();
+ mukey.render();
reload_tree();
reload_browser();
}
@@ -1193,6 +1194,108 @@ var filecols = (function () {
})();
+var mukey = (function () {
+ var maps = {
+ "rekobo_alnum": [
+ "1B ", "2B ", "3B ", "4B ", "5B ", "6B ", "7B ", "8B ", "9B ", "10B", "11B", "12B",
+ "1A ", "2A ", "3A ", "4A ", "5A ", "6A ", "7A ", "8A ", "9A ", "10A", "11A", "12A"
+ ],
+ "rekobo_classic": [
+ "B ", "F# ", "Db ", "Ab ", "Eb ", "Bb ", "F ", "C ", "G ", "D ", "A ", "E ",
+ "Abm", "Ebm", "Bbm", "Fm ", "Cm ", "Gm ", "Dm ", "Am ", "Em ", "Bm ", "F#m", "Dbm"
+ ],
+ "traktor_musical": [
+ "B ", "Gb ", "Db ", "Ab ", "Eb ", "Bb ", "F ", "C ", "G ", "D ", "A ", "E ",
+ "Abm", "Ebm", "Bbm", "Fm ", "Cm ", "Gm ", "Dm ", "Am ", "Em ", "Bm ", "Gbm", "Dbm"
+ ],
+ "traktor_sharps": [
+ "B ", "F# ", "C# ", "G# ", "D# ", "A# ", "F ", "C ", "G ", "D ", "A ", "E ",
+ "G#m", "D#m", "A#m", "Fm ", "Cm ", "Gm ", "Dm ", "Am ", "Em ", "Bm ", "F#m", "C#m"
+ ],
+ "traktor_open": [
+ "6d ", "7d ", "8d ", "9d ", "10d", "11d", "12d", "1d ", "2d ", "3d ", "4d ", "5d ",
+ "6m ", "7m ", "8m ", "9m ", "10m", "11m", "12m", "1m ", "2m ", "3m ", "4m ", "5m "
+ ]
+ };
+ var map = {};
+
+ var html = [];
+ for (var k in maps) {
+ if (!maps.hasOwnProperty(k))
+ continue;
+
+ html.push(
+ '' +
+ '');
+
+ for (var a = 0; a < 24; a++)
+ maps[k][a] = maps[k][a].trim();
+ }
+ ebi('key_notation').innerHTML = html.join('\n');
+
+ function set_key_notation(e) {
+ ev(e);
+ var notation = this.getAttribute('value');
+ load_notation(notation);
+ render();
+ }
+
+ function load_notation(notation) {
+ swrite("key_notation", notation);
+ map = {};
+ var dst = maps[notation];
+ for (var k in maps)
+ if (k != notation && maps.hasOwnProperty(k))
+ for (var a = 0; a < 24; a++)
+ if (maps[k][a] != dst[a])
+ map[maps[k][a]] = dst[a];
+ }
+
+ function render() {
+ var tds = ebi('files').tHead.getElementsByTagName('th');
+ var i = -1;
+ var min = false;
+ for (var a = 0; a < tds.length; a++) {
+ var spans = tds[a].getElementsByTagName('span');
+ if (spans.length && spans[0].textContent == 'Key') {
+ min = tds[a].getAttribute('class').indexOf('min') !== -1;
+ i = a;
+ break;
+ }
+ }
+
+ if (i == -1)
+ return;
+
+ var rows = ebi('files').tBodies[0].rows;
+
+ if (min)
+ for (var a = 0, aa = rows.length; a < aa; a++) {
+ var v = rows[a].cells[i].getAttribute('html');
+ rows[a].cells[i].setAttribute('html', map[v] || v);
+ }
+ else
+ for (var a = 0, aa = rows.length; a < aa; a++) {
+ var v = rows[a].cells[i].textContent;
+ rows[a].cells[i].textContent = map[v] || v;
+ }
+ }
+
+ var notation = sread("key_notation") || "rekobo_alnum";
+ ebi('key_' + notation).checked = true;
+ load_notation(notation);
+
+ var o = document.querySelectorAll('#key_notation input');
+ for (var a = 0; a < o.length; a++) {
+ o[a].onchange = set_key_notation;
+ }
+
+ return {
+ "render": render
+ };
+})();
+
+
function ev_row_tgl(e) {
ev(e);
filecols.toggle(this.parentElement.parentElement.getElementsByTagName('span')[0].textContent);
@@ -1238,3 +1341,4 @@ function reload_browser(not_mp) {
up2k.set_fsearch();
}
reload_browser(true);
+mukey.render();
diff --git a/copyparty/web/util.js b/copyparty/web/util.js
index 96cd563b..fc08bde6 100644
--- a/copyparty/web/util.js
+++ b/copyparty/web/util.js
@@ -23,6 +23,7 @@ function esc(txt) {
}
function vis_exh(msg, url, lineNo, columnNo, error) {
window.onerror = undefined;
+ window['vis_exh'] = null;
var html = ['you hit a bug!
please screenshot this error and send me a copy arigathanks gozaimuch (ed/irc.rizon.net or ed#2644)
',
esc(String(msg)), '
', esc(url + ' @' + lineNo + ':' + columnNo), '
'];
diff --git a/docs/notes.sh b/docs/notes.sh
index 9b3449c3..6f6e6ce2 100644
--- a/docs/notes.sh
+++ b/docs/notes.sh
@@ -11,6 +11,13 @@ gzip -d < .hist/up2k.snap | jq -r '.[].tnam' | while IFS= read -r f; do rm -f --
gzip -d < .hist/up2k.snap | jq -r '.[].name' | while IFS= read -r f; do wc -c -- "$f" | grep -qiE '^[^0-9a-z]*0' && rm -f -- "$f"; done
+##
+## detect partial uploads based on file contents
+## (in case of context loss or old copyparties)
+
+echo; find -type f | while IFS= read -r x; do printf '\033[A\033[36m%s\033[K\033[0m\n' "$x"; tail -c$((1024*1024)) <"$x" | xxd -a | awk 'NR==1&&/^[0: ]+.{16}$/{next} NR==2&&/^\*$/{next} NR==3&&/^[0f]+: [0 ]+65 +.{16}$/{next} {e=1} END {exit e}' || continue; printf '\033[A\033[31msus:\033[33m %s \033[0m\n\n' "$x"; done
+
+
##
## create a test payload