diff --git a/app/css/art.less b/app/css/art.less index 375e2b1..364870e 100644 --- a/app/css/art.less +++ b/app/css/art.less @@ -1,6 +1,4 @@ .art { margin-right: var(--icon-spacing); - .icon, img { - vertical-align: top; - } + .icon, img { display: block; } } diff --git a/app/css/component.less b/app/css/component.less deleted file mode 100644 index bf9d6ab..0000000 --- a/app/css/component.less +++ /dev/null @@ -1,58 +0,0 @@ -.component { - header { - .flex-row; - padding: var(--spacing); - - button { - font-size: var(--font-size-large); - font-weight: bold; - .icon { margin-right: var(--icon-spacing); } - overflow: hidden; - } - - } - - ul { - flex-grow: 1; - overflow: auto; - list-style: none; - margin: 0; - padding: 0; - } - - li { - .flex-row; - - .info { - flex-grow: 1; - overflow: hidden; - - .icon { - color: var(--primary); - margin-right: var(--icon-spacing); - filter: drop-shadow(var(--text-shadow)); - } - - h2 { - font-size: var(--font-size-large); - margin: 0; - } - -// h2, div { .long-line; } - } - - &.has-art { - - } - - &:not(.has-art) { - padding: 8px; - } - - button .icon { width: 32px; } - } - - li:nth-child(odd) { - background-color: var(--bg-alt); - } -} diff --git a/app/css/cyp.less b/app/css/cyp.less index 5f6e604..7a9cc6e 100644 --- a/app/css/cyp.less +++ b/app/css/cyp.less @@ -65,9 +65,6 @@ select { @import "font.less"; @import "icons.less"; @import "mixins.less"; -@import "component.less"; -@import "library.less"; -@import "fs.less"; @import "search.less"; @import "art.less"; @import "variables.less"; diff --git a/app/css/elements/tag.less b/app/css/elements/tag.less index e54bc19..5605a56 100644 --- a/app/css/elements/tag.less +++ b/app/css/elements/tag.less @@ -1,3 +1,16 @@ cyp-tag { .item; + + padding: 0; + + .art { + img, .icon { + width: 64px; + height: 64px; + } + + .icon { + filter: drop-shadow(var(--text-shadow)); + } + } } diff --git a/app/css/elements/yt.less b/app/css/elements/yt.less index b668a08..c87b7cc 100644 --- a/app/css/elements/yt.less +++ b/app/css/elements/yt.less @@ -1,6 +1,4 @@ cyp-yt { - .component; - header { border-bottom: 1px solid var(--fg); diff --git a/app/css/fs.less b/app/css/fs.less deleted file mode 100644 index 493ade7..0000000 --- a/app/css/fs.less +++ /dev/null @@ -1,20 +0,0 @@ -#fs { - .component; - - header { - white-space: pre; // separator - } - - .search { - order: 1; - &.open ~ * { display: none; } - } - - .group { - cursor: pointer; - } - - .info { -// .multiline; FIXME - } -} diff --git a/app/css/icons.less b/app/css/icons.less index bf403e7..3d36bcc 100644 --- a/app/css/icons.less +++ b/app/css/icons.less @@ -1,6 +1,6 @@ .icon { width: 24px; -// flex-shrink: 0; + flex: none; path, polygon, circle { &:not([fill]) { diff --git a/app/css/library.less b/app/css/library.less deleted file mode 100644 index 38c6461..0000000 --- a/app/css/library.less +++ /dev/null @@ -1,43 +0,0 @@ -#library { - .component; - - header { - white-space: pre; // separator - } - - .search { - order: 1; - &.open ~ * { display: none; } - } - - .art img, .art .icon { - width: 64px; - } - - .art .icon { - filter: drop-shadow(var(--text-shadow)); - } - - .group { - cursor: pointer; - h2 { font-weight: normal; } - } - - .tiles { - display: grid; - grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); - grid-gap: 2px; - - li { - text-align: center; - cursor: pointer; - background-color: rgba(255, 255, 255, 0.08); - height: 200px; - - h2 { - font-size: 150%; - margin: 4px 0; - } - } - } -} diff --git a/app/css/mixins.less b/app/css/mixins.less index e16a6ca..96c7fdc 100644 --- a/app/css/mixins.less +++ b/app/css/mixins.less @@ -14,21 +14,32 @@ text-overflow: ellipsis; } -/* -.multiline { - .flex-row; - - h2 { font-weight: normal; } -} -*/ - .selectable { - border-left: var(--border-width) solid transparent; cursor: pointer; + position: relative; // kotva pro selected::before &.selected { - border-left-color: var(--primary); - background-color: var(--primary-tint); + xbackground-color: var(--primary-tint); // FIXME jak zvyraznovat? + + &::before { + content: ""; + position: absolute; + left: 0; + top: 0; + bottom: 0; + width: var(--border-width); + background-color: var(--primary); + } + + &::after { + content: ""; + position: absolute; + left: 0; + top: 0; + bottom: 0; + right: 0; + background-color: var(--primary-tint); + } } } @@ -37,14 +48,12 @@ .selectable; padding: 8px; - padding-left: calc(8px - var(--border-width)); - &:nth-child(odd) { // FIXME nutno poresit lepe s ohledem na search + &:nth-child(odd) { background-color: var(--bg-alt); } > .icon { - flex: none; margin-right: var(--icon-spacing); filter: drop-shadow(var(--text-shadow)); } @@ -61,5 +70,4 @@ &:first-of-type { margin-left: auto; } .icon { width: 32px; } } - } diff --git a/app/cyp.css b/app/cyp.css index f4c5343..e7851c8 100644 --- a/app/cyp.css +++ b/app/cyp.css @@ -1 +1 @@ -*,*::before,*::after{box-sizing:inherit}html{background-color:var(--fg)}body{margin:0}main{flex:auto;overflow:auto}header,footer{flex:none;z-index:1;box-shadow:var(--box-shadow)}footer{position:relative;overflow:hidden;height:56px}@media (max-width:480px){footer{height:40px}}input,select,button{color:inherit;font:inherit}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;flex-direction:row;align-items:center;flex:none;background-color:transparent;padding:0;border:none;line-height:1;cursor:pointer}button:not([hidden]){display:flex}@media (hover:hover){button:not(:disabled):not(:hover):not(.-thumb){opacity:.9}}select{background-color:transparent;border:1px solid var(--fg);border-radius:4px;padding:2px 4px}@font-face{font-family:"Lato";src:url("font/LatoLatin-Regular.woff2") format("woff2");font-style:normal;font-weight:normal}@font-face{font-family:"Lato";src:url("font/LatoLatin-Bold.woff2") format("woff2");font-style:normal;font-weight:bold}.icon{width:24px}.icon path:not([fill]),.icon polygon:not([fill]),.icon circle:not([fill]){fill:currentColor}.flex-row{flex-direction:row;align-items:center}.flex-row:not([hidden]){display:flex}.flex-column{flex-direction:column}.flex-column:not([hidden]){display:flex}.ellipsis{overflow:hidden;text-overflow:ellipsis}.selectable{border-left:var(--border-width) solid transparent;cursor:pointer}.selectable.selected{border-left-color:var(--primary);background-color:var(--primary-tint)}.item{flex-direction:row;align-items:center;border-left:var(--border-width) solid transparent;cursor:pointer;padding:8px;padding-left:calc(8px - var(--border-width))}.item:not([hidden]){display:flex}.item.selected{border-left-color:var(--primary);background-color:var(--primary-tint)}.item:nth-child(odd){background-color:var(--bg-alt)}.item>.icon{flex:none;margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}.item .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}.item button:first-of-type{margin-left:auto}.item button .icon{width:32px}.component header{flex-direction:row;align-items:center;padding:var(--spacing)}.component header:not([hidden]){display:flex}.component header button{font-size:var(--font-size-large);font-weight:bold;overflow:hidden}.component header button .icon{margin-right:var(--icon-spacing)}.component ul{flex-grow:1;overflow:auto;list-style:none;margin:0;padding:0}.component li{flex-direction:row;align-items:center}.component li:not([hidden]){display:flex}.component li .info{flex-grow:1;overflow:hidden}.component li .info .icon{color:var(--primary);margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}.component li .info h2{font-size:var(--font-size-large);margin:0}.component li:not(.has-art){padding:8px}.component li button .icon{width:32px}.component li:nth-child(odd){background-color:var(--bg-alt)}#library header{flex-direction:row;align-items:center;padding:var(--spacing)}#library header:not([hidden]){display:flex}#library header button{font-size:var(--font-size-large);font-weight:bold;overflow:hidden}#library header button .icon{margin-right:var(--icon-spacing)}#library ul{flex-grow:1;overflow:auto;list-style:none;margin:0;padding:0}#library li{flex-direction:row;align-items:center}#library li:not([hidden]){display:flex}#library li .info{flex-grow:1;overflow:hidden}#library li .info .icon{color:var(--primary);margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}#library li .info h2{font-size:var(--font-size-large);margin:0}#library li:not(.has-art){padding:8px}#library li button .icon{width:32px}#library li:nth-child(odd){background-color:var(--bg-alt)}#library header{white-space:pre}#library .search{order:1}#library .search.open~*{display:none}#library .art img,#library .art .icon{width:64px}#library .art .icon{filter:drop-shadow(var(--text-shadow))}#library .group{cursor:pointer}#library .group h2{font-weight:normal}#library .tiles{display:grid;grid-template-columns:repeat(auto-fill, minmax(200px, 1fr));grid-gap:2px}#library .tiles li{text-align:center;cursor:pointer;background-color:rgba(255,255,255,0.08);height:200px}#library .tiles li h2{font-size:150%;margin:4px 0}#fs header{flex-direction:row;align-items:center;padding:var(--spacing)}#fs header:not([hidden]){display:flex}#fs header button{font-size:var(--font-size-large);font-weight:bold;overflow:hidden}#fs header button .icon{margin-right:var(--icon-spacing)}#fs ul{flex-grow:1;overflow:auto;list-style:none;margin:0;padding:0}#fs li{flex-direction:row;align-items:center}#fs li:not([hidden]){display:flex}#fs li .info{flex-grow:1;overflow:hidden}#fs li .info .icon{color:var(--primary);margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}#fs li .info h2{font-size:var(--font-size-large);margin:0}#fs li:not(.has-art){padding:8px}#fs li button .icon{width:32px}#fs li:nth-child(odd){background-color:var(--bg-alt)}#fs header{white-space:pre}#fs .search{order:1}#fs .search.open~*{display:none}#fs .group{cursor:pointer}.search{flex-direction:row;align-items:center;margin-left:auto;transition:all 300ms;width:32px;max-width:20ch}.search:not([hidden]){display:flex}.search .icon{width:32px;cursor:pointer}.search input{border:none;outline:none;color:inherit;background-color:inherit;border-bottom:1px solid var(--fg);width:0;padding:0;flex-grow:1}.search.open{flex:1}.art{margin-right:var(--icon-spacing)}.art .icon,.art img{vertical-align:top}cyp-app{--font-size-large:112.5%;--icon-spacing:4px;--primary:rgb(var(--primary-raw));--primary-tint:rgba(var(--primary-raw), .1);--box-shadow:0 0 3px #000;--border-width:4px}cyp-app[theme=light]{--fg:#333;--bg:#f0f0f0;--bg-alt:#e0e0e0;--text-shadow:none}cyp-app[theme=dark]{--fg:#f0f0f0;--bg:#333;--bg-alt:#555;--text-shadow:0 1px 1px rgba(0,0,0,0.8)}@media (prefers-color-scheme:dark){cyp-app[theme=auto]{--fg:#f0f0f0;--bg:#333;--bg-alt:#555;--text-shadow:0 1px 1px rgba(0,0,0,0.8)}}@media (prefers-color-scheme:light){cyp-app[theme=auto]{--fg:#333;--bg:#f0f0f0;--bg-alt:#e0e0e0;--text-shadow:none}}cyp-app[color=dodgerblue]{--primary-raw:30, 144, 255}cyp-app[color=darkorange]{--primary-raw:255, 140, 0}cyp-app[color=limegreen]{--primary-raw:50, 205, 50}cyp-app{flex-direction:column;box-sizing:border-box;margin:0 auto;max-width:800px;height:100vh;font-family:lato,sans-serif;line-height:1.25;background-color:var(--bg);color:var(--fg);text-shadow:var(--text-shadow);white-space:nowrap}cyp-app:not([hidden]){display:flex}cyp-menu,cyp-commands{flex-direction:row;align-items:center;height:100%}cyp-menu:not([hidden]),cyp-commands:not([hidden]){display:flex}cyp-menu button,cyp-commands button{height:100%;flex-direction:column;align-items:center;justify-content:center}cyp-menu button:not([hidden]),cyp-commands button:not([hidden]){display:flex}@media (max-width:480px){cyp-menu button,cyp-commands button{flex-direction:row}cyp-menu button span:not([id]),cyp-commands button span:not([id]){display:none}}cyp-menu button .icon+*,cyp-commands button .icon+*{margin-top:2px}cyp-menu button{flex:1 0 0;border-top:var(--border-width) solid transparent;border-bottom:var(--border-width) solid transparent}cyp-menu button .icon{margin-right:var(--icon-spacing)}cyp-menu button.active{border-top-color:var(--primary);color:var(--primary);background-color:var(--primary-tint)}cyp-commands{position:absolute;left:0;top:0;width:100%;transition:top 300ms;background-color:var(--bg)}cyp-commands[hidden]{display:flex;top:100%}cyp-commands button{flex:0 1 80px}cyp-commands button.last{order:1;margin-left:auto}cyp-song{flex-direction:row;align-items:center;border-left:var(--border-width) solid transparent;cursor:pointer;padding:8px;padding-left:calc(8px - var(--border-width))}cyp-song:not([hidden]){display:flex}cyp-song.selected{border-left-color:var(--primary);background-color:var(--primary-tint)}cyp-song:nth-child(odd){background-color:var(--bg-alt)}cyp-song>.icon{flex:none;margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-song .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-song button:first-of-type{margin-left:auto}cyp-song button .icon{width:32px}cyp-song .multiline{flex-direction:column;min-width:0}cyp-song .multiline:not([hidden]){display:flex}cyp-song .multiline .subtitle{overflow:hidden;text-overflow:ellipsis}cyp-queue cyp-song .track{display:none}cyp-player{flex-direction:row;align-items:center;align-items:stretch}cyp-player:not([hidden]){display:flex}cyp-player:not([data-state=play]) .pause{display:none}cyp-player[data-state=play] .play{display:none}cyp-player:not([data-flags~=random]) .random,cyp-player:not([data-flags~=repeat]) .repeat{opacity:.5}cyp-player x-range{flex-grow:1;--elapsed-color:var(--primary)}cyp-player .art{margin-right:0;height:96px}cyp-player .art img,cyp-player .art .icon{width:96px}cyp-player .info{flex-grow:2;flex-basis:0;padding:0 var(--icon-spacing);overflow:hidden;flex-direction:column;justify-content:space-around}cyp-player .info:not([hidden]){display:flex}cyp-player .info h2{font-size:125%;margin:0}cyp-player .info .title,cyp-player .info .subtitle{overflow:hidden;text-overflow:ellipsis}cyp-player .timeline{flex-direction:row;align-items:center}cyp-player .timeline:not([hidden]){display:flex}cyp-player .timeline .duration,cyp-player .timeline .elapsed{flex-basis:5ch;text-align:center}cyp-player .controls{flex-grow:1;flex-basis:0;max-width:220px;flex-direction:column;justify-content:space-around}cyp-player .controls:not([hidden]){display:flex}cyp-player .controls .playback{flex-direction:row;align-items:center;justify-content:space-around}cyp-player .controls .playback:not([hidden]){display:flex}cyp-player .controls .playback .icon{width:40px}cyp-player .controls .playback .icon-play,cyp-player .controls .playback .icon-pause{width:64px}cyp-player .controls .volume{flex-direction:row;align-items:center}cyp-player .controls .volume:not([hidden]){display:flex}cyp-player .controls .volume .mute{margin-right:4px}cyp-player .misc{display:flex;flex-direction:column;align-self:stretch;justify-content:space-around}cyp-player .misc .icon{width:32px}@media (max-width:519px){cyp-player{flex-wrap:wrap;justify-content:space-between}cyp-player .info{order:1;flex-basis:100%;height:96px}}cyp-queue .current{color:var(--primary)}cyp-settings{--spacing:8px;font-size:var(--font-size-large)}cyp-settings dl{margin:var(--spacing);display:grid;grid-template-columns:max-content 1fr;align-items:center;grid-gap:var(--spacing)}cyp-settings dt{font-weight:bold}cyp-settings dd{margin:0;flex-direction:column;align-items:start}cyp-settings dd:not([hidden]){display:flex}cyp-settings label{flex-direction:row;align-items:center}cyp-settings label:not([hidden]){display:flex}cyp-settings label [type=radio],cyp-settings label [type=checkbox]{margin:0 4px 0 0}cyp-yt header{flex-direction:row;align-items:center;padding:var(--spacing)}cyp-yt header:not([hidden]){display:flex}cyp-yt header button{font-size:var(--font-size-large);font-weight:bold;overflow:hidden}cyp-yt header button .icon{margin-right:var(--icon-spacing)}cyp-yt ul{flex-grow:1;overflow:auto;list-style:none;margin:0;padding:0}cyp-yt li{flex-direction:row;align-items:center}cyp-yt li:not([hidden]){display:flex}cyp-yt li .info{flex-grow:1;overflow:hidden}cyp-yt li .info .icon{color:var(--primary);margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-yt li .info h2{font-size:var(--font-size-large);margin:0}cyp-yt li:not(.has-art){padding:8px}cyp-yt li button .icon{width:32px}cyp-yt li:nth-child(odd){background-color:var(--bg-alt)}cyp-yt header{border-bottom:1px solid var(--fg)}cyp-yt header button+button{margin-left:16px}cyp-yt .clear{margin-left:auto}cyp-yt pre{margin:.5em .5ch;flex-grow:1;overflow:auto;white-space:pre-wrap}cyp-yt.pending header{background-image:linear-gradient(var(--primary), var(--primary));background-repeat:no-repeat;background-size:25% 4px;animation:bar ease-in-out 3s alternate infinite}@keyframes bar{0%{background-position:0 100%}100%{background-position:100% 100%}}x-range{--thumb-size:8px;--thumb-color:#ddd;--thumb-shadow:#000;--thumb-hover-color:#fff;--track-size:4px;--track-color:#888;--track-shadow:#000;--elapsed-color:#ddd;--remaining-color:transparent;--radius:calc(var(--track-size)/2);display:inline-block;position:relative;width:192px;height:16px}x-range .-track,x-range .-elapsed,x-range .-remaining{position:absolute;top:calc(50% - var(--track-size)/2);height:var(--track-size);border-radius:var(--radius)}x-range .-track{width:100%;left:0;background-color:var(--track-color);box-shadow:0 0 1px var(--thumb-shadow)}x-range .-elapsed{left:0;background-color:var(--elapsed-color)}x-range .-remaining{right:0;background-color:var(--remaining-color)}x-range .-inner{position:absolute;left:var(--thumb-size);right:var(--thumb-size);top:0;bottom:0}x-range .-thumb{all:unset;position:absolute;top:50%;transform:translate(-50%, -50%);border-radius:50%;width:calc(2*var(--thumb-size));height:calc(2*var(--thumb-size));background-color:var(--thumb-color);box-shadow:0 0 2px var(--thumb-shadow)}x-range[disabled]{opacity:.5}x-range:not([disabled]) .-thumb:hover{background-color:var(--thumb-hover-color)}cyp-playlist{flex-direction:row;align-items:center;border-left:var(--border-width) solid transparent;cursor:pointer;padding:8px;padding-left:calc(8px - var(--border-width))}cyp-playlist:not([hidden]){display:flex}cyp-playlist.selected{border-left-color:var(--primary);background-color:var(--primary-tint)}cyp-playlist:nth-child(odd){background-color:var(--bg-alt)}cyp-playlist>.icon{flex:none;margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-playlist .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-playlist button:first-of-type{margin-left:auto}cyp-playlist button .icon{width:32px}cyp-playlist:nth-child(odd){background-color:var(--bg-alt)}cyp-tag{flex-direction:row;align-items:center;border-left:var(--border-width) solid transparent;cursor:pointer;padding:8px;padding-left:calc(8px - var(--border-width))}cyp-tag:not([hidden]){display:flex}cyp-tag.selected{border-left-color:var(--primary);background-color:var(--primary-tint)}cyp-tag:nth-child(odd){background-color:var(--bg-alt)}cyp-tag>.icon{flex:none;margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-tag .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-tag button:first-of-type{margin-left:auto}cyp-tag button .icon{width:32px}cyp-back{flex-direction:row;align-items:center;border-left:var(--border-width) solid transparent;cursor:pointer;padding:8px;padding-left:calc(8px - var(--border-width))}cyp-back:not([hidden]){display:flex}cyp-back.selected{border-left-color:var(--primary);background-color:var(--primary-tint)}cyp-back:nth-child(odd){background-color:var(--bg-alt)}cyp-back>.icon{flex:none;margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-back .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-back button:first-of-type{margin-left:auto}cyp-back button .icon{width:32px}cyp-path{flex-direction:row;align-items:center;border-left:var(--border-width) solid transparent;cursor:pointer;padding:8px;padding-left:calc(8px - var(--border-width))}cyp-path:not([hidden]){display:flex}cyp-path.selected{border-left-color:var(--primary);background-color:var(--primary-tint)}cyp-path:nth-child(odd){background-color:var(--bg-alt)}cyp-path>.icon{flex:none;margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-path .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-path button:first-of-type{margin-left:auto}cyp-path button .icon{width:32px} \ No newline at end of file +*,*::before,*::after{box-sizing:inherit}html{background-color:var(--fg)}body{margin:0}main{flex:auto;overflow:auto}header,footer{flex:none;z-index:1;box-shadow:var(--box-shadow)}footer{position:relative;overflow:hidden;height:56px}@media (max-width:480px){footer{height:40px}}input,select,button{color:inherit;font:inherit}button{-webkit-appearance:none;-moz-appearance:none;appearance:none;flex-direction:row;align-items:center;flex:none;background-color:transparent;padding:0;border:none;line-height:1;cursor:pointer}button:not([hidden]){display:flex}@media (hover:hover){button:not(:disabled):not(:hover):not(.-thumb){opacity:.9}}select{background-color:transparent;border:1px solid var(--fg);border-radius:4px;padding:2px 4px}@font-face{font-family:"Lato";src:url("font/LatoLatin-Regular.woff2") format("woff2");font-style:normal;font-weight:normal}@font-face{font-family:"Lato";src:url("font/LatoLatin-Bold.woff2") format("woff2");font-style:normal;font-weight:bold}.icon{width:24px;flex:none}.icon path:not([fill]),.icon polygon:not([fill]),.icon circle:not([fill]){fill:currentColor}.flex-row{flex-direction:row;align-items:center}.flex-row:not([hidden]){display:flex}.flex-column{flex-direction:column}.flex-column:not([hidden]){display:flex}.ellipsis{overflow:hidden;text-overflow:ellipsis}.selectable{cursor:pointer;position:relative}.selectable.selected{xbackground-color:var(--primary-tint)}.selectable.selected::before{content:"";position:absolute;left:0;top:0;bottom:0;width:var(--border-width);background-color:var(--primary)}.selectable.selected::after{content:"";position:absolute;left:0;top:0;bottom:0;right:0;background-color:var(--primary-tint)}.item{flex-direction:row;align-items:center;cursor:pointer;position:relative;padding:8px}.item:not([hidden]){display:flex}.item.selected{xbackground-color:var(--primary-tint)}.item.selected::before{content:"";position:absolute;left:0;top:0;bottom:0;width:var(--border-width);background-color:var(--primary)}.item.selected::after{content:"";position:absolute;left:0;top:0;bottom:0;right:0;background-color:var(--primary-tint)}.item:nth-child(odd){background-color:var(--bg-alt)}.item>.icon{margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}.item .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}.item button:first-of-type{margin-left:auto}.item button .icon{width:32px}.search{flex-direction:row;align-items:center;margin-left:auto;transition:all 300ms;width:32px;max-width:20ch}.search:not([hidden]){display:flex}.search .icon{width:32px;cursor:pointer}.search input{border:none;outline:none;color:inherit;background-color:inherit;border-bottom:1px solid var(--fg);width:0;padding:0;flex-grow:1}.search.open{flex:1}.art{margin-right:var(--icon-spacing)}.art .icon,.art img{display:block}cyp-app{--font-size-large:112.5%;--icon-spacing:4px;--primary:rgb(var(--primary-raw));--primary-tint:rgba(var(--primary-raw), .1);--box-shadow:0 0 3px #000;--border-width:4px}cyp-app[theme=light]{--fg:#333;--bg:#f0f0f0;--bg-alt:#e0e0e0;--text-shadow:none}cyp-app[theme=dark]{--fg:#f0f0f0;--bg:#333;--bg-alt:#555;--text-shadow:0 1px 1px rgba(0,0,0,0.8)}@media (prefers-color-scheme:dark){cyp-app[theme=auto]{--fg:#f0f0f0;--bg:#333;--bg-alt:#555;--text-shadow:0 1px 1px rgba(0,0,0,0.8)}}@media (prefers-color-scheme:light){cyp-app[theme=auto]{--fg:#333;--bg:#f0f0f0;--bg-alt:#e0e0e0;--text-shadow:none}}cyp-app[color=dodgerblue]{--primary-raw:30, 144, 255}cyp-app[color=darkorange]{--primary-raw:255, 140, 0}cyp-app[color=limegreen]{--primary-raw:50, 205, 50}cyp-app{flex-direction:column;box-sizing:border-box;margin:0 auto;max-width:800px;height:100vh;font-family:lato,sans-serif;line-height:1.25;background-color:var(--bg);color:var(--fg);text-shadow:var(--text-shadow);white-space:nowrap}cyp-app:not([hidden]){display:flex}cyp-menu,cyp-commands{flex-direction:row;align-items:center;height:100%}cyp-menu:not([hidden]),cyp-commands:not([hidden]){display:flex}cyp-menu button,cyp-commands button{height:100%;flex-direction:column;align-items:center;justify-content:center}cyp-menu button:not([hidden]),cyp-commands button:not([hidden]){display:flex}@media (max-width:480px){cyp-menu button,cyp-commands button{flex-direction:row}cyp-menu button span:not([id]),cyp-commands button span:not([id]){display:none}}cyp-menu button .icon+*,cyp-commands button .icon+*{margin-top:2px}cyp-menu button{flex:1 0 0;border-top:var(--border-width) solid transparent;border-bottom:var(--border-width) solid transparent}cyp-menu button .icon{margin-right:var(--icon-spacing)}cyp-menu button.active{border-top-color:var(--primary);color:var(--primary);background-color:var(--primary-tint)}cyp-commands{position:absolute;left:0;top:0;width:100%;transition:top 300ms;background-color:var(--bg)}cyp-commands[hidden]{display:flex;top:100%}cyp-commands button{flex:0 1 80px}cyp-commands button.last{order:1;margin-left:auto}cyp-song{flex-direction:row;align-items:center;cursor:pointer;position:relative;padding:8px}cyp-song:not([hidden]){display:flex}cyp-song.selected{xbackground-color:var(--primary-tint)}cyp-song.selected::before{content:"";position:absolute;left:0;top:0;bottom:0;width:var(--border-width);background-color:var(--primary)}cyp-song.selected::after{content:"";position:absolute;left:0;top:0;bottom:0;right:0;background-color:var(--primary-tint)}cyp-song:nth-child(odd){background-color:var(--bg-alt)}cyp-song>.icon{margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-song .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-song button:first-of-type{margin-left:auto}cyp-song button .icon{width:32px}cyp-song .multiline{flex-direction:column;min-width:0}cyp-song .multiline:not([hidden]){display:flex}cyp-song .multiline .subtitle{overflow:hidden;text-overflow:ellipsis}cyp-queue cyp-song .track{display:none}cyp-player{flex-direction:row;align-items:center;align-items:stretch}cyp-player:not([hidden]){display:flex}cyp-player:not([data-state=play]) .pause{display:none}cyp-player[data-state=play] .play{display:none}cyp-player:not([data-flags~=random]) .random,cyp-player:not([data-flags~=repeat]) .repeat{opacity:.5}cyp-player x-range{flex-grow:1;--elapsed-color:var(--primary)}cyp-player .art{margin-right:0;height:96px}cyp-player .art img,cyp-player .art .icon{width:96px}cyp-player .info{flex-grow:2;flex-basis:0;padding:0 var(--icon-spacing);overflow:hidden;flex-direction:column;justify-content:space-around}cyp-player .info:not([hidden]){display:flex}cyp-player .info h2{font-size:125%;margin:0}cyp-player .info .title,cyp-player .info .subtitle{overflow:hidden;text-overflow:ellipsis}cyp-player .timeline{flex-direction:row;align-items:center}cyp-player .timeline:not([hidden]){display:flex}cyp-player .timeline .duration,cyp-player .timeline .elapsed{flex-basis:5ch;text-align:center}cyp-player .controls{flex-grow:1;flex-basis:0;max-width:220px;flex-direction:column;justify-content:space-around}cyp-player .controls:not([hidden]){display:flex}cyp-player .controls .playback{flex-direction:row;align-items:center;justify-content:space-around}cyp-player .controls .playback:not([hidden]){display:flex}cyp-player .controls .playback .icon{width:40px}cyp-player .controls .playback .icon-play,cyp-player .controls .playback .icon-pause{width:64px}cyp-player .controls .volume{flex-direction:row;align-items:center}cyp-player .controls .volume:not([hidden]){display:flex}cyp-player .controls .volume .mute{margin-right:4px}cyp-player .misc{display:flex;flex-direction:column;align-self:stretch;justify-content:space-around}cyp-player .misc .icon{width:32px}@media (max-width:519px){cyp-player{flex-wrap:wrap;justify-content:space-between}cyp-player .info{order:1;flex-basis:100%;height:96px}}cyp-queue .current{color:var(--primary)}cyp-settings{--spacing:8px;font-size:var(--font-size-large)}cyp-settings dl{margin:var(--spacing);display:grid;grid-template-columns:max-content 1fr;align-items:center;grid-gap:var(--spacing)}cyp-settings dt{font-weight:bold}cyp-settings dd{margin:0;flex-direction:column;align-items:start}cyp-settings dd:not([hidden]){display:flex}cyp-settings label{flex-direction:row;align-items:center}cyp-settings label:not([hidden]){display:flex}cyp-settings label [type=radio],cyp-settings label [type=checkbox]{margin:0 4px 0 0}cyp-yt header{border-bottom:1px solid var(--fg)}cyp-yt header button+button{margin-left:16px}cyp-yt .clear{margin-left:auto}cyp-yt pre{margin:.5em .5ch;flex-grow:1;overflow:auto;white-space:pre-wrap}cyp-yt.pending header{background-image:linear-gradient(var(--primary), var(--primary));background-repeat:no-repeat;background-size:25% 4px;animation:bar ease-in-out 3s alternate infinite}@keyframes bar{0%{background-position:0 100%}100%{background-position:100% 100%}}x-range{--thumb-size:8px;--thumb-color:#ddd;--thumb-shadow:#000;--thumb-hover-color:#fff;--track-size:4px;--track-color:#888;--track-shadow:#000;--elapsed-color:#ddd;--remaining-color:transparent;--radius:calc(var(--track-size)/2);display:inline-block;position:relative;width:192px;height:16px}x-range .-track,x-range .-elapsed,x-range .-remaining{position:absolute;top:calc(50% - var(--track-size)/2);height:var(--track-size);border-radius:var(--radius)}x-range .-track{width:100%;left:0;background-color:var(--track-color);box-shadow:0 0 1px var(--thumb-shadow)}x-range .-elapsed{left:0;background-color:var(--elapsed-color)}x-range .-remaining{right:0;background-color:var(--remaining-color)}x-range .-inner{position:absolute;left:var(--thumb-size);right:var(--thumb-size);top:0;bottom:0}x-range .-thumb{all:unset;position:absolute;top:50%;transform:translate(-50%, -50%);border-radius:50%;width:calc(2*var(--thumb-size));height:calc(2*var(--thumb-size));background-color:var(--thumb-color);box-shadow:0 0 2px var(--thumb-shadow)}x-range[disabled]{opacity:.5}x-range:not([disabled]) .-thumb:hover{background-color:var(--thumb-hover-color)}cyp-playlist{flex-direction:row;align-items:center;cursor:pointer;position:relative;padding:8px}cyp-playlist:not([hidden]){display:flex}cyp-playlist.selected{xbackground-color:var(--primary-tint)}cyp-playlist.selected::before{content:"";position:absolute;left:0;top:0;bottom:0;width:var(--border-width);background-color:var(--primary)}cyp-playlist.selected::after{content:"";position:absolute;left:0;top:0;bottom:0;right:0;background-color:var(--primary-tint)}cyp-playlist:nth-child(odd){background-color:var(--bg-alt)}cyp-playlist>.icon{margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-playlist .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-playlist button:first-of-type{margin-left:auto}cyp-playlist button .icon{width:32px}cyp-playlist:nth-child(odd){background-color:var(--bg-alt)}cyp-tag{flex-direction:row;align-items:center;cursor:pointer;position:relative;padding:8px;padding:0}cyp-tag:not([hidden]){display:flex}cyp-tag.selected{xbackground-color:var(--primary-tint)}cyp-tag.selected::before{content:"";position:absolute;left:0;top:0;bottom:0;width:var(--border-width);background-color:var(--primary)}cyp-tag.selected::after{content:"";position:absolute;left:0;top:0;bottom:0;right:0;background-color:var(--primary-tint)}cyp-tag:nth-child(odd){background-color:var(--bg-alt)}cyp-tag>.icon{margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-tag .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-tag button:first-of-type{margin-left:auto}cyp-tag button .icon{width:32px}cyp-tag .art img,cyp-tag .art .icon{width:64px;height:64px}cyp-tag .art .icon{filter:drop-shadow(var(--text-shadow))}cyp-back{flex-direction:row;align-items:center;cursor:pointer;position:relative;padding:8px}cyp-back:not([hidden]){display:flex}cyp-back.selected{xbackground-color:var(--primary-tint)}cyp-back.selected::before{content:"";position:absolute;left:0;top:0;bottom:0;width:var(--border-width);background-color:var(--primary)}cyp-back.selected::after{content:"";position:absolute;left:0;top:0;bottom:0;right:0;background-color:var(--primary-tint)}cyp-back:nth-child(odd){background-color:var(--bg-alt)}cyp-back>.icon{margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-back .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-back button:first-of-type{margin-left:auto}cyp-back button .icon{width:32px}cyp-path{flex-direction:row;align-items:center;cursor:pointer;position:relative;padding:8px}cyp-path:not([hidden]){display:flex}cyp-path.selected{xbackground-color:var(--primary-tint)}cyp-path.selected::before{content:"";position:absolute;left:0;top:0;bottom:0;width:var(--border-width);background-color:var(--primary)}cyp-path.selected::after{content:"";position:absolute;left:0;top:0;bottom:0;right:0;background-color:var(--primary-tint)}cyp-path:nth-child(odd){background-color:var(--bg-alt)}cyp-path>.icon{margin-right:var(--icon-spacing);filter:drop-shadow(var(--text-shadow))}cyp-path .title{font-weight:bold;font-size:var(--font-size-large);min-width:0;overflow:hidden;text-overflow:ellipsis}cyp-path button:first-of-type{margin-left:auto}cyp-path button .icon{width:32px} \ No newline at end of file diff --git a/app/js/component.js b/app/js/component.js index 9a47501..e830cd7 100644 --- a/app/js/component.js +++ b/app/js/component.js @@ -14,7 +14,7 @@ export default class Component extends HasApp { connectedCallback() { this._app.addEventListener("load", _ => this._onAppLoad()); this._app.addEventListener("component-change", _ => { - const component = this._app.getAttribute("component"); + const component = this._app.component; const isThis = (this.nodeName.toLowerCase() == `cyp-${component}`); this._onComponentChange(component, isThis); }); diff --git a/app/js/elements/app.js b/app/js/elements/app.js index b02d130..7d3b4ef 100644 --- a/app/js/elements/app.js +++ b/app/js/elements/app.js @@ -42,8 +42,8 @@ class App extends HTMLElement { this.dispatchEvent(new CustomEvent("load")); const onHashChange = () => { - const hash = location.hash.substring(1); - this.setAttribute("component", hash || "queue"); + const component = location.hash.substring(1) || "queue"; + if (component != this.component) { this.component = component; } } window.addEventListener("hashchange", onHashChange); onHashChange(); @@ -58,6 +58,9 @@ class App extends HTMLElement { break; } } + + get component() { return this.getAttribute("component"); } + set component(component) { return this.setAttribute("component", component); } } customElements.define("cyp-app", App); diff --git a/app/js/elements/library.js b/app/js/elements/library.js index b7e64dd..ab91001 100644 --- a/app/js/elements/library.js +++ b/app/js/elements/library.js @@ -9,14 +9,18 @@ import { escape, serializeFilter } from "../mpd.js"; const SORT = "-Track"; +function nonempty(str) { return (str.length > 0); } + function createEnqueueCommand(node) { if (node instanceof Song) { return `add "${escape(node.data["file"])}"`; + } else if (node instanceof Path) { + return `add "${escape(node.file)}"`; } else if (node instanceof Tag) { return [ "findadd", serializeFilter(node.createChildFilter()), - `sort ${SORT}` + // `sort ${SORT}` // MPD >= 0.22, not yet released ].join(" "); } else { throw new Error(`Cannot create enqueue command for "${node.nodeName}"`); @@ -37,7 +41,7 @@ class Library extends Component { const wasHidden = this.hidden; this.hidden = !isThis; - if (!wasHidden) { this._showRoot(); } + if (!wasHidden && isThis) { this._showRoot(); } } _showRoot() { @@ -58,7 +62,7 @@ class Library extends Component { html.clear(this); if ("AlbumArtist" in filter) { this._buildBack(filter); } - values.forEach(value => this._buildTag(tag, value, filter)); + values.filter(nonempty).forEach(value => this._buildTag(tag, value, filter)); } async _listPath(path) { diff --git a/app/js/elements/path.js b/app/js/elements/path.js index ddcea64..b7d3ba8 100644 --- a/app/js/elements/path.js +++ b/app/js/elements/path.js @@ -9,19 +9,21 @@ function baseName(path) { export default class Path extends Item { constructor(data) { super(); - this.data = data; - // FIXME spis ._data a .url + this._data = data; + + if ("directory" in this._data) { + this.file = data["directory"]; + } else { + this.file = data["file"]; + } } connectedCallback() { - let path; - if ("directory" in this.data) { + if ("directory" in this._data) { this.appendChild(html.icon("folder")); - path = this.data["directory"]; } else { this.appendChild(html.icon("music")); - path = this.data["file"]; } - this._buildTitle(baseName(path)); + this._buildTitle(baseName(this.file)); } } diff --git a/app/js/elements/player.js b/app/js/elements/player.js index f0a3fe2..31b438b 100644 --- a/app/js/elements/player.js +++ b/app/js/elements/player.js @@ -120,7 +120,7 @@ class Player extends Component { let artistOld = this._current["AlbumArtist"] || this._current["Artist"]; if (artistNew != artistOld || data["Album"] != this._current["Album"]) { // changed album (art) html.clear(DOM.art); - art.get(artistNew, data["Album"], data["file"]).then(src => { + art.get(this._mpd, artistNew, data["Album"], data["file"]).then(src => { if (src) { html.node("img", {src}, "", DOM.art); } else { diff --git a/app/js/elements/tag.js b/app/js/elements/tag.js index 3c45b84..e3d72d8 100644 --- a/app/js/elements/tag.js +++ b/app/js/elements/tag.js @@ -8,7 +8,6 @@ const ICONS = { "Album": "album" } - export default class Tag extends Item { constructor(type, value, filter) { super();