music widget

This commit is contained in:
Til Schmitter 2026-05-11 22:53:18 +02:00
parent 1ffe3bf967
commit 98ee68daf2
5 changed files with 180 additions and 62 deletions

View file

@ -119,7 +119,7 @@ body.untz {
if (--uofs >= 0) {
document.body.style.marginLeft = hrand() * uofs + 'px';
ebi('tree').style.marginLeft = hrand() * uofs + 'px';
for (var a of QSA('#ops>a, #path>a, #pctl>a'))
for (var a of QSA('#ops>a, #path>a, .pctl>a'))
a.style.transform = 'translate(' + hrand() * uofs * 1 + 'px, ' + hrand() * uofs * 0.7 + 'px) rotate(' + Math.random() * uofs * 0.7 + 'deg)'
}

View file

@ -1020,6 +1020,7 @@ tr.play td:nth-child(1) a {
text-shadow: none;
font-family: monospace;
}
.thumbed,
#ggrid>a.thumbed {
.thumb,
.th_ext {
@ -1500,10 +1501,12 @@ html:not(.e):not(.d) #up_quick .btn.on {
overflow: hidden;
text-overflow: ellipsis;
margin-left: .3em;
padding: 1.2em 0;
}
#progbar {
display: none;
margin: 0 .3em;
font-size: 20px;
}
#progbar.vis {
display: block;
@ -1550,11 +1553,11 @@ html:not(.e):not(.d) #up_quick .btn.on {
margin-left: .1em;
padding: .1em;
}
#pctl .icon {
.pctl .icon {
width: 1.5em;
height: 1.5em;
}
#pctl .icon.btn {
.pctl .icon.btn {
padding: .2em;
margin: .1em;
}
@ -1563,17 +1566,17 @@ html:not(.e):not(.d) #up_quick .btn.on {
vertical-align: top;
height: 1.5em;
}
#pctl svg {
.pctl svg {
width: 1.5em;
height: 1.5em;
}
#pctl .btn {
.pctl .btn {
font-size: 1em;
padding: 0;
opacity: .4;
cursor: pointer;
}
#pctl .btn.on {
.pctl .btn.on {
opacity: 1;
}
#pvol {
@ -1615,6 +1618,72 @@ html:not(.e):not(.d) #up_quick .btn.on {
max-width: 5.8em;
border-radius: 0;
}
#music {
margin: 0;
border-radius: 0;
border: none;
background: #ccc;
background: var(--bg-u2);
}
#music a {
cursor: pointer;
}
html.b #music {
background: color-mix(in oklab, var(--bg-u2) 70%, transparent);
backdrop-filter: blur(50px);
}
#h_music {
position: absolute;
top: 0;
left: 0;
}
#mu_inner {
align-content: center;
text-align: center;
}
#mu_th {
cursor: default !important;
display: flex;
position: relative;
height: 35vh;
}
#mu_th svg {
margin: 0 auto;
}
#mu_th span {
font-size: 8vh;
}
#mu_th img {
opacity: 0;
margin: 0 auto;
}
#mu_tn {
display: block;
margin-top: .5em;
min-height: 2em;
font-size: 1.3em;
}
#mu_pbc {
font-size: 1.6em;
}
#mu_pbb {
height: 3em;
margin: .5em 0;
width: 80vw;
display: block;
position: relative;
align-content: center;
text-align: left;
}
#mu_vol {
position: absolute;
right: 1em;
bottom: 1em;
font-size: 1.2em;
}
.opview {
display: none;
margin-bottom: 1em;
@ -2868,15 +2937,25 @@ html.c .modalcontent {
.modalheader:hover {
color: var(--fg);
}
#cfg_mu,
.close{
position: absolute;
cursor: default;
top: 0;
right: 0;
margin: .5em;
margin: .3em;
color: var(--fg);
box-shadow: 0 0 .3em var(--mp-sh);
border: 1px solid var(--bg-u3);
height: 1.8em;
aspect-ratio: 1 / 1;
text-align: center;
display: block;
padding: 0;
align-content: center;
}
#cfg_mu {
right: 2.3em;
}
.closepane {
position: absolute;
@ -4228,6 +4307,7 @@ html.e {
--g-sel-fg: #fff;
}
html.e * {
--radius: 0;
border-radius: 0 !important;
}
html.e #ggrid > a.sel {
@ -4257,14 +4337,13 @@ html.e body {
background: var(--bg);
}
html.e summary,
html.e #pctl a,
html.e .pctl a,
html.e #repl,
html.e #wfp a,
html.e .btn,
html.e .eq_step,
html.e input[type="submit"] {
box-shadow: var(--shadow-outset);
border-radius: var(--radius);
background: var(--bg);
border: 0;
}
@ -4280,7 +4359,7 @@ html.e input[type="submit"]:active {
}
html.e summary:hover,
html.e #ops a:hover,
html.e #pctl a:hover,
html.e .pctl a:hover,
html.e #repl:hover,
html.e #wfp a:hover,
html.e .btn:hover,
@ -4301,7 +4380,7 @@ html.e tr:focus {
box-shadow: none;
}
html.e summary:focus,
html.e #pctl a:focus,
html.e .pctl a:focus,
html.e #repl:hover,
html.e #wfp a:focus,
html.e .btn:focus,
@ -4391,11 +4470,6 @@ html.e #u2cards a.act {
}
html.e #u2btn {
border: var(--border-dashed-black);
border-radius: var(--border-radius);
}
html.e #ops,
html.e #ops a {
border-radius: var(--radius);
}
@media only screen and (max-width: 600px) {
html.e #acc_info {
@ -4480,21 +4554,8 @@ html.e :focus,
html.e :focus + label {
border: 0 !important;
outline-offset: 1px;
border-radius: var(--radius) !important;
box-shadow: inherit;
}
html.e #opa_x {
text-shadow: 0 0 0 var(--transparent) !important;
color: var(--bg) !important;
display: flex;
}
html.e #opa_x:before {
content: "";
color: var(--fg) !important;
margin-top: -0.1em;
font-size: 1.75em;
position: absolute;
}
html.e .opbox {
margin: -.3em 0 0;
box-shadow: var(--shadow-inset-bottom), var(--shadow-inset-left),
@ -4505,7 +4566,6 @@ html.e .opbox {
}
html.e #srch_form {
margin: 0;
border-radius: var(--radius);
}
html.e #op_unpost {
max-width: 100vw;
@ -4555,7 +4615,6 @@ html.e select {
box-shadow: var(--shadow-input) !important;
box-sizing: border-box;
padding: 3px 4px;
border-radius: var(--radius);
border: 0;
}
html.e #gfiles {
@ -4579,11 +4638,9 @@ html.e #ghead {
gap: 0.4em;
padding-top: .2em;
top: 2.3em;
border-radius: 0px;
}
html.e #ghead a {
margin: 0;
border-radius: var(--radius);
}
html.e #treeToggleBtn {
margin: 0;
@ -4685,7 +4742,6 @@ html.e .ntree a:first-child {
aspect-ratio: 1/1;
text-align: center;
align-content: center;
border-radius: var(--radius) !important;
padding: 0.057em;
border: 1px solid var(--black);
}
@ -4722,7 +4778,6 @@ html.e #tree li {
html.e .ntree a:hover {
outline-offset: -2px;
color: var(--fg);
border-radius: var(--radius) !important;
}
html.e #treepar {
width: calc(-1em + var(--nav-sz) - var(--sbw));
@ -4823,7 +4878,6 @@ html.e #wfm.act + #wzip1 + #wzip + #wnp {
border-left-width: 1px;
}
html.e #barpos {
/* border-radius: var(--radius); */
box-shadow: var(--shadow-inset);
}
html.e #goh + span {
@ -4854,7 +4908,6 @@ html.e #doc {
box-shadow: var(--shadow-inset);
background: var(--inset-bg);
margin: 0.2em;
border-radius: var(--radius);
}
html.e #detree {

View file

@ -177,6 +177,27 @@
</div>
</div>
<div id="music" class="modal">
<a id="h_music" class="modalheader" href="#">💿 Music Player</a>
<div id="mu_inner">
<a id="mu_th">
<svg class="thumb" width="100%" height="100%" version="1.1">
<use href="#file-icon"/>
</svg>
<span class="th_ext"></span>
<img onload="th_onload(this)"/>
</a>
<span id="mu_tn"></span>
<span id="mu_deets"></span>
<div id="mu_pbb"></div>
<div id="mu_pbc" class="pctl"></div>
<div id="mu_toggles"></div>
<div id="mu_vol"></div>
</div>
<a id="cfg_mu" class="btn" href="#h_mp">⚙️</a>
<a id="cl_mu" class="close btn"></a>
</div>
<!-- define symbol in hidden svg document -->
<svg style="display: none" version="1.1">
<defs>

View file

@ -964,11 +964,11 @@ ebi('widget').innerHTML = (
'<div id="widgeti">' +
' <div id="pbarthinpos"></div>' +
' <div id="pctl">' +
' <div id="pctl" class="pctl">' +
' <a href="#" id="bprev" class="icon btn on" tt="' + L.wt_prev + '">' + svg_prev + '</a>' +
' <a href="#" id="bplay" class="icon btn on" tt="' + L.wt_play + '">' + svg_play + '</a>' +
' <a href="#" id="bnext" class="icon btn on" tt="' + L.wt_next + '">' + svg_next + '</a>' +
' <span id="trackname"></span>' +
' <a id="trackname" href="#h_music"></a>' +
' <div id="progbar" style="position: relative; height: 80%;">' +
' <canvas id="barbuf"></canvas>' +
' <canvas id="barpos"></canvas>' +
@ -996,6 +996,12 @@ ebi('widget').innerHTML = (
'</div>'
);
ebi('mu_pbc').innerHTML = (
'<a href="#" id="bprev2" class="icon btn on" tt="' + L.wt_prev + '">' + svg_prev + '</a>' +
'<a href="#" id="bplay2" class="icon btn on" tt="' + L.wt_play + '">' + svg_play + '</a>' +
'<a href="#" id="bnext2" class="icon btn on" tt="' + L.wt_next + '">' + svg_next + '</a>'
);
ebi('wtoggle').addEventListener('wheel', function (e) {
scroll_v_to_h(e, this);
});
@ -1547,6 +1553,8 @@ function modaltoggle(dest, show){
if (show == false || show == 't' && QS('#' + dest + '.vis'))
dest = '';
var layoutchange = dest == 'music' || QS('#music.vis');
swrite('opmode', dest || null);
goto(dest);
@ -1556,6 +1564,9 @@ function modaltoggle(dest, show){
tt.skip = true;
input.focus();
}
if(layoutchange)
onwidgetresize();
}
function opclick(e) {
var dest = this.getAttribute('data-dest');
@ -1595,7 +1606,7 @@ function goto(dest) {
if (dest) {
var lnk = QS('#ops>a[data-dest=' + dest + ']'),
nps = lnk.getAttribute('data-perm');
nps = lnk && lnk.getAttribute('data-perm');
nps = nps && nps.length ? nps.split(' ') : [];
@ -1673,7 +1684,7 @@ window.onhashchange = function() {
return;
if(!clgot(p_modal, 'vis')){
console.log('forcing modal open due to subheader hash');
modaltoggle(p_modal.id);
modaltoggle(p_modal.id, true);
}
ebi(location.hash.slice(1)).scrollIntoView();
}
@ -2481,7 +2492,8 @@ var widget = (function () {
r.paused = function (paused) {
if (was_paused != paused) {
was_paused = paused;
ebi('bplay').innerHTML = paused ? svg_play : svg_pause;
ebi('bplay').innerHTML = ebi('bplay2').innerHTML =
paused ? svg_play : svg_pause;
}
};
r.setvis = function () {
@ -2812,7 +2824,7 @@ var pbar = (function () {
var m1 = pctx.measureText(t1),
m1b = pctx.measureText(t1 + ":88"),
m2 = pctx.measureText(t2),
yt = pc.h * 0.7,
yt = pc.h * 0.65,
xt1 = pc.w - (m1.width + 12),
xt2 = x < m1.width * 1.4 ? (x + 12) : (Math.min(pc.w - m1b.width, x - 12) - m2.width);
@ -3118,9 +3130,9 @@ function mpause(e) {
// hook up the widget buttons
(function () {
ebi('bplay').onclick = playpause;
ebi('bprev').onclick = prev_song;
ebi('bnext').onclick = next_song;
ebi('bplay').onclick = ebi('bplay2').onclick = playpause;
ebi('bprev').onclick = ebi('bprev2').onclick = prev_song;
ebi('bnext').onclick = ebi('bnext2').onclick = next_song;
var bar = ebi('barpos');
@ -3870,10 +3882,18 @@ function play(tid, is_ev, seek) {
}
mp.au.osrc = decodeURI(mp.tracks[tid].split('/').pop());
ebi('trackname').innerHTML = esc(uricom_dec(mp.au.osrc));
ebi('trackname').setAttribute('tt', ebi('trackname').innerHTML);
var tname = esc(uricom_dec(mp.au.osrc));
ebi('trackname').innerHTML = tname;
ebi('trackname').setAttribute('tt', tname);
afilt.apply();
// popup player
ebi('mu_tn').innerHTML = tname.replace(/\..*$/, '');
var m_ext = tname.match(/[^\.]*$/);
if(m_ext){
QS('#mu_th>svg').style.color = intToHSL(hashCode(m_ext[0]))
QS('#mu_th>span').innerHTML = m_ext[0];
}
setTimeout(function () {
mpl.unbuffer(url);
}, 500);
@ -3895,6 +3915,15 @@ function play(tid, is_ev, seek) {
clmod(t_tr, 'play', 1);
clmod(ebi('wtoggle'), 'np', mpl.clip);
clmod(ebi('wtoggle'), 'm3u', mpl.m3uen);
try{
var gridimg = QS('a[ref=' + t_tr.childNodes[1].firstChild.id + '] img')
QS('#mu_th>img').setAttribute('src', gridimg.src.replace(/th=.*(&|$)/, 'th=wf3&'));
}
catch(ex){
console.log(ex);
}
if (thegrid)
thegrid.loadsel();
@ -6547,17 +6576,6 @@ window.thegrid = (function () {
drag.initgrid();
}
function hashCode (str) {
var hash = 0;
for(var i = 0; i < str.length; i++){
hash = str.charCodeAt(i) + 130 * ((hash << 5) - hash);
}
return hash
}
function intToHSL(i){
return 'hsl(' + i % 360 + 'deg 100% 50%)'
}
r.bagit = function (isrc) {
console.log('init image viewer');
@ -6746,6 +6764,17 @@ function testImage(el) {
tester.src=URL;
}
function hashCode (str) {
var hash = 0;
for(var i = 0; i < str.length; i++){
hash = str.charCodeAt(i) + 130 * ((hash << 5) - hash);
}
return hash
}
function intToHSL(i){
return 'hsl(' + i % 360 + 'deg 100% 50%)'
}
function tree_scrollto(e) {
ev(e);
tree_scrolltoo('#treeul a.hl');
@ -7714,9 +7743,21 @@ var filecolwidth = (function () {
onresize100.add(filecolwidth, true);
function onwidgetresize(){
var mumodal = QS('#music.vis');
var widget = ebi('widget');
var bar = ebi('pctl');
var pbarthinpos = ebi('pbarthinpos');
if(mumodal){
var pb_container = ebi('mu_pbb');
pb_container.appendChild(ebi('progbar'));
pb_container.appendChild(ebi('altprogbar'));
ebi('altprogbar').maxWidth = '';
ebi('mu_vol').appendChild(ebi('pvolbg'));
pbar.onresize();
return;
}
var width = widget.offsetWidth;
var thin = width < 800; //px
@ -7740,8 +7781,7 @@ function onwidgetresize(){
thin = true;
}
}
gtc = 'max-content max-content max-content ' + (thin ? '' : '20%') + ' auto max-content max-content max-content';
if(thin && bar.children.length > gtc.split(' ').length){
if(thin && pbarthinpos.children.length < 2){
//thin
pbarthinpos.appendChild(ebi('progbar'));
pbarthinpos.appendChild(ebi('altprogbar'));
@ -7752,6 +7792,10 @@ function onwidgetresize(){
clmod(widget, 'thin', thin);
if(ebi('mu_vol').children.length > 0){
bar.appendChild(ebi('pvolbg'));
}
pbar.onresize();
// keep path scrolled right

View file

@ -452,7 +452,7 @@ html.y #tth {
}
*:focus-visible,
*:focus-visible+label,
#pctl *:focus-visible,
.pctl *:focus-visible,
.btn:focus-visible {
/* box-shadow: 0 .1em .2em #fc0 inset; */
outline: var(--a) solid .1em;