mirror of
https://github.com/9001/copyparty.git
synced 2025-08-16 16:42:13 -06:00
make browser columns compactable
This commit is contained in:
parent
46e10b0e9f
commit
61a6bc3a65
5
.vscode/launch.json
vendored
5
.vscode/launch.json
vendored
|
@ -13,10 +13,13 @@
|
|||
"-ed",
|
||||
"-emp",
|
||||
"-e2dsa",
|
||||
"-e2ts",
|
||||
"-a",
|
||||
"ed:wark",
|
||||
"-v",
|
||||
"srv::r:aed:cnodupe"
|
||||
"srv::r:aed:cnodupe",
|
||||
"-v",
|
||||
"dist:dist:r"
|
||||
]
|
||||
},
|
||||
{
|
||||
|
|
2
.vscode/tasks.json
vendored
2
.vscode/tasks.json
vendored
|
@ -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"
|
||||
}
|
||||
]
|
||||
|
|
|
@ -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")
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -58,17 +58,17 @@
|
|||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>File Name</th>
|
||||
<th sort="int">Size</th>
|
||||
<th><span>File Name</span></th>
|
||||
<th sort="int"><span>Size</span></th>
|
||||
{%- for k in taglist %}
|
||||
{%- if k.startswith('.') %}
|
||||
<td sort="int">{{ k[1:] }}</td>
|
||||
<th sort="int"><span>{{ k[1:] }}</span></th>
|
||||
{%- else %}
|
||||
<td>{{ k[0]|upper }}{{ k[1:] }}</td>
|
||||
<th><span>{{ k[0]|upper }}{{ k[1:] }}</span></th>
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
<th>T</th>
|
||||
<th>Date</th>
|
||||
<th><span>T</span></th>
|
||||
<th><span>Date</span></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
|
|
|
@ -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 = ['<thead>', '<th></th>', '<th>File Name</th>', '<th sort="int">Size</th>'];
|
||||
var html = [
|
||||
'<thead>',
|
||||
'<th></th>',
|
||||
'<th><span>File Name</span></th>',
|
||||
'<th sort="int"><span>Size</span></th>'
|
||||
];
|
||||
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 = '<th sort="int">' + tag.slice(1);
|
||||
tag = '<th sort="int"><span>' + tag.slice(1);
|
||||
else
|
||||
tag = '<th>' + tag;
|
||||
tag = '<th><span>' + tag;
|
||||
|
||||
html.push(tag + '</th>');
|
||||
html.push(tag + '</span></th>');
|
||||
}
|
||||
html = html.concat([
|
||||
'<th>T</th>',
|
||||
'<th>Date</th>',
|
||||
'<th><span>T</span></th>',
|
||||
'<th><span>Date</span></th>',
|
||||
'</thead>',
|
||||
]);
|
||||
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 = '<div class="cfg"><a href="#">' +
|
||||
(is_hidden ? '+' : '-') + '</a></div>' + 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('/');
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 `<thead>` 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));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue