diff --git a/.vscode/launch.json b/.vscode/launch.json
index fdaaf284..d0afa1ef 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -13,10 +13,13 @@
"-ed",
"-emp",
"-e2dsa",
+ "-e2ts",
"-a",
"ed:wark",
"-v",
- "srv::r:aed:cnodupe"
+ "srv::r:aed:cnodupe",
+ "-v",
+ "dist:dist:r"
]
},
{
diff --git a/.vscode/tasks.json b/.vscode/tasks.json
index f4a637f1..c08c4620 100644
--- a/.vscode/tasks.json
+++ b/.vscode/tasks.json
@@ -8,7 +8,7 @@
},
{
"label": "no_dbg",
- "command": "${config:python.pythonPath} -m copyparty -ed -emp -e2dsa -a ed:wark -v srv::r:aed:cnodupe ;exit 1",
+ "command": "${config:python.pythonPath} -m copyparty -ed -emp -e2dsa -e2ts -a ed:wark -v srv::r:aed:cnodupe -v dist:dist:r ;exit 1",
"type": "shell"
}
]
diff --git a/copyparty/__main__.py b/copyparty/__main__.py
index 30628444..09798a17 100644
--- a/copyparty/__main__.py
+++ b/copyparty/__main__.py
@@ -257,7 +257,7 @@ def main():
ap2.add_argument("--no-mutagen", action="store_true", help="use ffprobe for tags instead")
ap2.add_argument("-mtm", metavar="M=t,t,t", action="append", type=str, help="add/replace metadata mapping")
ap2.add_argument("-mte", metavar="M,M,M", type=str, help="tags to index/display (comma-sep.)",
- default="circle,album,.tn,artist,title,.dur,.q")
+ default="circle,album,.tn,artist,title,.bpm,key,.dur,.q")
ap2 = ap.add_argument_group('SSL/TLS options')
ap2.add_argument("--http-only", action="store_true", help="disable ssl/tls")
diff --git a/copyparty/web/browser.css b/copyparty/web/browser.css
index 5453a6e8..4995ec63 100644
--- a/copyparty/web/browser.css
+++ b/copyparty/web/browser.css
@@ -96,7 +96,10 @@ a,
}
#files td {
border-bottom: 1px solid #111;
+}
+#files td+td+td {
max-width: 30em;
+ overflow: hidden;
}
#files tr+tr td {
border-top: 1px solid #383838;
@@ -168,7 +171,8 @@ a,
margin: -.2em;
}
#files tbody a.play.act {
- color: #af0;
+ color: #840;
+ text-shadow: 0 0 .3em #b80;
}
#blocked {
position: fixed;
@@ -299,6 +303,20 @@ a,
width: calc(100% - 10.5em);
background: rgba(0,0,0,0.2);
}
+@media (min-width: 100em) {
+ #barpos,
+ #barbuf {
+ width: calc(100% - 24em);
+ left: 10em;
+ top: .7em;
+ height: 1.6em;
+ bottom: auto;
+ }
+ #widget {
+ bottom: -3.2em;
+ height: 3.2em;
+ }
+}
@@ -496,3 +514,42 @@ input[type="checkbox"]:checked+label {
position: absolute;
z-index: 9;
}
+#files .cfg {
+ display: none;
+ font-size: 2em;
+ white-space: nowrap;
+}
+#files th:hover .cfg,
+#files th.min .cfg {
+ display: block;
+ width: 1em;
+ border-radius: .2em;
+ margin: -1.3em auto 0 auto;
+ background: #444;
+}
+#files th.min .cfg {
+ margin: -.6em;
+}
+#files>thead>tr>th.min span {
+ position: absolute;
+ transform: rotate(270deg);
+ background: linear-gradient(90deg, #222, #444);
+ margin-left: -4.6em;
+ padding: .4em;
+ top: 5.4em;
+ width: 8em;
+ text-align: right;
+ letter-spacing: .04em;
+}
+#files td:nth-child(2n) {
+ color: #f5a;
+}
+#files td.min a {
+ display: none;
+}
+#files tr.play td {
+ background: #fc4;
+ border-color: transparent;
+ color: #400;
+ text-shadow: none;
+}
\ No newline at end of file
diff --git a/copyparty/web/browser.html b/copyparty/web/browser.html
index d9bbc576..30b4f114 100644
--- a/copyparty/web/browser.html
+++ b/copyparty/web/browser.html
@@ -58,17 +58,17 @@
|
- File Name |
- Size |
+ File Name |
+ Size |
{%- for k in taglist %}
{%- if k.startswith('.') %}
- {{ k[1:] }} |
+ {{ k[1:] }} |
{%- else %}
- {{ k[0]|upper }}{{ k[1:] }} |
+ {{ k[0]|upper }}{{ k[1:] }} |
{%- endif %}
{%- endfor %}
- T |
- Date |
+ T |
+ Date |
diff --git a/copyparty/web/browser.js b/copyparty/web/browser.js
index da7420a1..15cfd063 100644
--- a/copyparty/web/browser.js
+++ b/copyparty/web/browser.js
@@ -6,21 +6,6 @@ function dbg(msg) {
ebi('path').innerHTML = msg;
}
-function ev(e) {
- e = e || window.event;
- if (!e)
- return;
-
- if (e.preventDefault)
- e.preventDefault()
-
- if (e.stopPropagation)
- e.stopPropagation();
-
- e.returnValue = false;
- return e;
-}
-
makeSortable(ebi('files'));
@@ -55,7 +40,7 @@ function init_mp() {
for (var a = 0, aa = tracks.length; a < aa; a++)
ebi('trk' + a).onclick = ev_play;
- ret.vol = localStorage.getItem('vol');
+ ret.vol = sread('vol');
if (ret.vol !== null)
ret.vol = parseFloat(ret.vol);
else
@@ -67,7 +52,7 @@ function init_mp() {
ret.setvol = function (vol) {
ret.vol = Math.max(Math.min(vol, 1), 0);
- localStorage.setItem('vol', vol);
+ swrite('vol', vol);
if (ret.au)
ret.au.volume = ret.expvol();
@@ -460,6 +445,11 @@ function play(tid, call_depth) {
mp.au.volume = mp.expvol();
var oid = 'trk' + tid;
setclass(oid, 'play act');
+ var trs = ebi('files').getElementsByTagName('tbody')[0].getElementsByTagName('tr');
+ for (var a = 0, aa = trs.length; a < aa; a++) {
+ trs[a].className = trs[a].className.replace(/ *play */, "");
+ }
+ ebi(oid).parentElement.parentElement.className += ' play';
try {
if (hack_attempt_play)
@@ -708,6 +698,7 @@ function autoplay_blocked() {
ofiles.innerHTML = html.join('\n');
ofiles.setAttribute("ts", this.ts);
+ filecols.set_style();
reload_browser();
ebi('unsearch').onclick = unsearch;
@@ -741,7 +732,7 @@ function autoplay_blocked() {
treefiles.appendChild(ebi('files'));
treefiles.appendChild(ebi('epi'));
- localStorage.setItem('entreed', 'tree');
+ swrite('entreed', 'tree');
get_tree("", get_vpath());
}
@@ -911,6 +902,7 @@ function autoplay_blocked() {
ebi('pro').innerHTML = res.logues ? res.logues[0] || "" : "";
ebi('epi').innerHTML = res.logues ? res.logues[1] || "" : "";
+ filecols.set_style();
reload_tree();
reload_browser();
}
@@ -955,12 +947,12 @@ function autoplay_blocked() {
ebi('path').style.display = 'inline-block';
treetab.style.display = 'none';
- localStorage.setItem('entreed', 'na');
+ swrite('entreed', 'na');
}
ebi('entree').onclick = entree;
ebi('detree').onclick = detree;
- if (window.localStorage && localStorage.getItem('entreed') == 'tree')
+ if (sread('entreed') == 'tree')
entree();
window.onpopstate = function (e) {
@@ -973,7 +965,7 @@ function autoplay_blocked() {
};
if (window.history && history.pushState) {
- var u = get_vpath();
+ var u = get_vpath() + window.location.hash;
history.replaceState(ebi('files').innerHTML, u, u);
}
})();
@@ -1032,28 +1024,118 @@ function apply_perms(perms) {
function mk_files_header(taglist) {
- var html = ['', ' | ', 'File Name | ', 'Size | '];
+ var html = [
+ '',
+ ' | ',
+ 'File Name | ',
+ 'Size | '
+ ];
for (var a = 0; a < taglist.length; a++) {
var tag = taglist[a];
var c1 = tag.slice(0, 1).toUpperCase();
tag = c1 + tag.slice(1);
if (c1 == '.')
- tag = '' + tag.slice(1);
+ tag = ' | ' + tag.slice(1);
else
- tag = ' | ' + tag;
+ tag = ' | ' + tag;
- html.push(tag + ' | ');
+ html.push(tag + '');
}
html = html.concat([
- 'T | ',
- 'Date | ',
+ 'T | ',
+ 'Date | ',
'',
]);
return html;
}
+var filecols = (function () {
+ var hidden = jread('filecols', []);
+
+ var add_btns = function () {
+ var ths = document.querySelectorAll('#files th>span');
+ for (var a = 0, aa = ths.length; a < aa; a++) {
+ var th = ths[a].parentElement;
+ var is_hidden = has(hidden, ths[a].textContent);
+ th.innerHTML = '' + ths[a].outerHTML;
+
+ th.getElementsByTagName('a')[0].onclick = ev_row_tgl;
+ }
+ };
+
+ var set_style = function () {
+ add_btns();
+
+ var ohidden = [],
+ ths = document.querySelectorAll('#files th'),
+ ncols = ths.length;
+
+ for (var a = 0; a < ncols; a++) {
+ var span = ths[a].getElementsByTagName('span');
+ if (span.length <= 0)
+ continue;
+
+ var name = span[0].textContent,
+ cls = '';
+
+ if (has(hidden, name)) {
+ ohidden.push(a);
+ cls = ' min';
+ }
+ ths[a].className = ths[a].className.replace(/ *min */, " ") + cls;
+ }
+ for (var a = 0; a < ncols; a++) {
+ var cls = has(ohidden, a) ? 'min' : '';
+ var tds = document.querySelectorAll('#files>tbody>tr>td:nth-child(' + (a + 1) + ')');
+ for (var b = 0, bb = tds.length; b < bb; b++) {
+ tds[b].setAttribute('class', cls);
+ if (a < 2)
+ continue;
+
+ if (cls) {
+ if (!tds[b].hasAttribute('html')) {
+ tds[b].setAttribute('html', tds[b].innerHTML);
+ tds[b].innerHTML = '...';
+ }
+ }
+ else if (tds[b].hasAttribute('html')) {
+ tds[b].innerHTML = tds[b].getAttribute('html');
+ tds[b].removeAttribute('html');
+ }
+ }
+ }
+ };
+ set_style();
+
+ var toggle = function (name) {
+ var ofs = hidden.indexOf(name);
+ if (ofs !== -1)
+ hidden.splice(ofs, 1);
+ else
+ hidden.push(name);
+
+ jwrite("filecols", hidden);
+ set_style();
+ };
+
+ return {
+ "add_btns": add_btns,
+ "set_style": set_style,
+ "toggle": toggle,
+ };
+})();
+
+
+function ev_row_tgl(e) {
+ ev(e);
+ filecols.toggle(this.parentElement.parentElement.getElementsByTagName('span')[0].textContent);
+}
+
+
function reload_browser(not_mp) {
+ filecols.set_style();
makeSortable(ebi('files'));
var parts = get_vpath().split('/');
diff --git a/copyparty/web/md.js b/copyparty/web/md.js
index 5a752a9a..6c258b2e 100644
--- a/copyparty/web/md.js
+++ b/copyparty/web/md.js
@@ -524,11 +524,9 @@ dom_navtgl.onclick = function () {
dom_navtgl.innerHTML = hidden ? 'show nav' : 'hide nav';
dom_nav.style.display = hidden ? 'none' : 'block';
- if (window.localStorage)
- localStorage.setItem('hidenav', hidden ? 1 : 0);
-
+ swrite('hidenav', hidden ? 1 : 0);
redraw();
};
-if (window.localStorage && localStorage.getItem('hidenav') == 1)
+if (sread('hidenav') == 1)
dom_navtgl.onclick();
diff --git a/copyparty/web/up2k.js b/copyparty/web/up2k.js
index f6b750ea..128006f8 100644
--- a/copyparty/web/up2k.js
+++ b/copyparty/web/up2k.js
@@ -210,7 +210,7 @@ function up2k_init(have_crypto) {
}
function cfg_get(name) {
- var val = localStorage.getItem(name);
+ var val = sread(name);
if (val === null)
return parseInt(ebi(name).value);
@@ -223,7 +223,7 @@ function up2k_init(have_crypto) {
if (!o)
return defval;
- var val = localStorage.getItem(name);
+ var val = sread(name);
if (val === null)
val = defval;
else
@@ -234,8 +234,7 @@ function up2k_init(have_crypto) {
}
function bcfg_set(name, val) {
- localStorage.setItem(
- name, val ? '1' : '0');
+ swrite(name, val ? '1' : '0');
var o = ebi(name);
if (o)
@@ -1033,7 +1032,7 @@ function up2k_init(have_crypto) {
return;
parallel_uploads = v;
- localStorage.setItem('nthread', v);
+ swrite('nthread', v);
obj.style.background = '#444';
return;
}
diff --git a/copyparty/web/util.js b/copyparty/web/util.js
index 1d1575b9..2f3699fd 100644
--- a/copyparty/web/util.js
+++ b/copyparty/web/util.js
@@ -43,6 +43,21 @@ function ebi(id) {
return document.getElementById(id);
}
+function ev(e) {
+ e = e || window.event;
+ if (!e)
+ return;
+
+ if (e.preventDefault)
+ e.preventDefault()
+
+ if (e.stopPropagation)
+ e.stopPropagation();
+
+ e.returnValue = false;
+ return e;
+}
+
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
if (!String.prototype.endsWith) {
@@ -79,10 +94,10 @@ function sortTable(table, col) {
var tb = table.tBodies[0],
th = table.tHead.rows[0].cells,
tr = Array.prototype.slice.call(tb.rows, 0),
- i, reverse = th[col].className == 'sort1' ? -1 : 1;
+ i, reverse = th[col].className.indexOf('sort1') !== -1 ? -1 : 1;
for (var a = 0, thl = th.length; a < thl; a++)
- th[a].className = '';
- th[col].className = 'sort' + reverse;
+ th[a].className = th[a].className.replace(/ *sort-?1 */, " ");
+ th[col].className += ' sort' + reverse;
var stype = th[col].getAttribute('sort');
tr = tr.sort(function (a, b) {
if (!a.cells[col])
@@ -107,7 +122,8 @@ function makeSortable(table) {
if (th) i = th.length;
else return; // if no `` then do nothing
while (--i >= 0) (function (i) {
- th[i].onclick = function () {
+ th[i].onclick = function (e) {
+ ev(e);
sortTable(table, i);
};
}(i));
@@ -123,16 +139,13 @@ function makeSortable(table) {
})();
-function opclick(ev) {
- if (ev) //ie
- ev.preventDefault();
+function opclick(e) {
+ ev(e);
var dest = this.getAttribute('data-dest');
goto(dest);
- // writing a blank value makes ie8 segfault w
- if (window.localStorage)
- localStorage.setItem('opmode', dest || '.');
+ swrite('opmode', dest || undefined);
var input = document.querySelector('.opview.act input:not([type="hidden"])')
if (input)
@@ -167,11 +180,9 @@ function goto(dest) {
(function () {
goto();
- if (window.localStorage) {
- var op = localStorage.getItem('opmode');
- if (op !== null && op !== '.')
- goto(op);
- }
+ var op = sread('opmode');
+ if (op !== null && op !== '.')
+ goto(op);
})();
@@ -238,3 +249,35 @@ function has(haystack, needle) {
return false;
}
+
+
+function sread(key) {
+ if (window.localStorage)
+ return localStorage.getItem(key);
+
+ return '';
+}
+
+function swrite(key, val) {
+ if (window.localStorage) {
+ if (val === undefined)
+ localStorage.removeItem(key);
+ else
+ localStorage.setItem(key, val);
+ }
+}
+
+function jread(key, fb) {
+ var str = sread(key);
+ if (!str)
+ return fb;
+
+ return JSON.parse(str);
+}
+
+function jwrite(key, val) {
+ if (!val)
+ swrite(key);
+ else
+ swrite(key, JSON.stringify(val));
+}