tag/path queueing

This commit is contained in:
Ondrej Zara 2020-03-13 16:52:24 +01:00
parent aca1f44a60
commit c3871fa486
16 changed files with 62 additions and 161 deletions

View file

@ -1,6 +1,4 @@
.art { .art {
margin-right: var(--icon-spacing); margin-right: var(--icon-spacing);
.icon, img { .icon, img { display: block; }
vertical-align: top;
}
} }

View file

@ -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);
}
}

View file

@ -65,9 +65,6 @@ select {
@import "font.less"; @import "font.less";
@import "icons.less"; @import "icons.less";
@import "mixins.less"; @import "mixins.less";
@import "component.less";
@import "library.less";
@import "fs.less";
@import "search.less"; @import "search.less";
@import "art.less"; @import "art.less";
@import "variables.less"; @import "variables.less";

View file

@ -1,3 +1,16 @@
cyp-tag { cyp-tag {
.item; .item;
padding: 0;
.art {
img, .icon {
width: 64px;
height: 64px;
}
.icon {
filter: drop-shadow(var(--text-shadow));
}
}
} }

View file

@ -1,6 +1,4 @@
cyp-yt { cyp-yt {
.component;
header { header {
border-bottom: 1px solid var(--fg); border-bottom: 1px solid var(--fg);

View file

@ -1,20 +0,0 @@
#fs {
.component;
header {
white-space: pre; // separator
}
.search {
order: 1;
&.open ~ * { display: none; }
}
.group {
cursor: pointer;
}
.info {
// .multiline; FIXME
}
}

View file

@ -1,6 +1,6 @@
.icon { .icon {
width: 24px; width: 24px;
// flex-shrink: 0; flex: none;
path, polygon, circle { path, polygon, circle {
&:not([fill]) { &:not([fill]) {

View file

@ -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;
}
}
}
}

View file

@ -14,37 +14,46 @@
text-overflow: ellipsis; text-overflow: ellipsis;
} }
/*
.multiline {
.flex-row;
h2 { font-weight: normal; }
}
*/
.selectable { .selectable {
border-left: var(--border-width) solid transparent;
cursor: pointer; cursor: pointer;
position: relative; // kotva pro selected::before
&.selected { &.selected {
border-left-color: var(--primary); 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); background-color: var(--primary-tint);
} }
} }
}
.item { .item {
.flex-row; .flex-row;
.selectable; .selectable;
padding: 8px; 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); background-color: var(--bg-alt);
} }
> .icon { > .icon {
flex: none;
margin-right: var(--icon-spacing); margin-right: var(--icon-spacing);
filter: drop-shadow(var(--text-shadow)); filter: drop-shadow(var(--text-shadow));
} }
@ -61,5 +70,4 @@
&:first-of-type { margin-left: auto; } &:first-of-type { margin-left: auto; }
.icon { width: 32px; } .icon { width: 32px; }
} }
} }

File diff suppressed because one or more lines are too long

View file

@ -14,7 +14,7 @@ export default class Component extends HasApp {
connectedCallback() { connectedCallback() {
this._app.addEventListener("load", _ => this._onAppLoad()); this._app.addEventListener("load", _ => this._onAppLoad());
this._app.addEventListener("component-change", _ => { this._app.addEventListener("component-change", _ => {
const component = this._app.getAttribute("component"); const component = this._app.component;
const isThis = (this.nodeName.toLowerCase() == `cyp-${component}`); const isThis = (this.nodeName.toLowerCase() == `cyp-${component}`);
this._onComponentChange(component, isThis); this._onComponentChange(component, isThis);
}); });

View file

@ -42,8 +42,8 @@ class App extends HTMLElement {
this.dispatchEvent(new CustomEvent("load")); this.dispatchEvent(new CustomEvent("load"));
const onHashChange = () => { const onHashChange = () => {
const hash = location.hash.substring(1); const component = location.hash.substring(1) || "queue";
this.setAttribute("component", hash || "queue"); if (component != this.component) { this.component = component; }
} }
window.addEventListener("hashchange", onHashChange); window.addEventListener("hashchange", onHashChange);
onHashChange(); onHashChange();
@ -58,6 +58,9 @@ class App extends HTMLElement {
break; break;
} }
} }
get component() { return this.getAttribute("component"); }
set component(component) { return this.setAttribute("component", component); }
} }
customElements.define("cyp-app", App); customElements.define("cyp-app", App);

View file

@ -9,14 +9,18 @@ import { escape, serializeFilter } from "../mpd.js";
const SORT = "-Track"; const SORT = "-Track";
function nonempty(str) { return (str.length > 0); }
function createEnqueueCommand(node) { function createEnqueueCommand(node) {
if (node instanceof Song) { if (node instanceof Song) {
return `add "${escape(node.data["file"])}"`; return `add "${escape(node.data["file"])}"`;
} else if (node instanceof Path) {
return `add "${escape(node.file)}"`;
} else if (node instanceof Tag) { } else if (node instanceof Tag) {
return [ return [
"findadd", "findadd",
serializeFilter(node.createChildFilter()), serializeFilter(node.createChildFilter()),
`sort ${SORT}` // `sort ${SORT}` // MPD >= 0.22, not yet released
].join(" "); ].join(" ");
} else { } else {
throw new Error(`Cannot create enqueue command for "${node.nodeName}"`); throw new Error(`Cannot create enqueue command for "${node.nodeName}"`);
@ -37,7 +41,7 @@ class Library extends Component {
const wasHidden = this.hidden; const wasHidden = this.hidden;
this.hidden = !isThis; this.hidden = !isThis;
if (!wasHidden) { this._showRoot(); } if (!wasHidden && isThis) { this._showRoot(); }
} }
_showRoot() { _showRoot() {
@ -58,7 +62,7 @@ class Library extends Component {
html.clear(this); html.clear(this);
if ("AlbumArtist" in filter) { this._buildBack(filter); } 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) { async _listPath(path) {

View file

@ -9,19 +9,21 @@ function baseName(path) {
export default class Path extends Item { export default class Path extends Item {
constructor(data) { constructor(data) {
super(); super();
this.data = data; this._data = data;
// FIXME spis ._data a .url
if ("directory" in this._data) {
this.file = data["directory"];
} else {
this.file = data["file"];
}
} }
connectedCallback() { connectedCallback() {
let path; if ("directory" in this._data) {
if ("directory" in this.data) {
this.appendChild(html.icon("folder")); this.appendChild(html.icon("folder"));
path = this.data["directory"];
} else { } else {
this.appendChild(html.icon("music")); this.appendChild(html.icon("music"));
path = this.data["file"];
} }
this._buildTitle(baseName(path)); this._buildTitle(baseName(this.file));
} }
} }

View file

@ -120,7 +120,7 @@ class Player extends Component {
let artistOld = this._current["AlbumArtist"] || this._current["Artist"]; let artistOld = this._current["AlbumArtist"] || this._current["Artist"];
if (artistNew != artistOld || data["Album"] != this._current["Album"]) { // changed album (art) if (artistNew != artistOld || data["Album"] != this._current["Album"]) { // changed album (art)
html.clear(DOM.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) { if (src) {
html.node("img", {src}, "", DOM.art); html.node("img", {src}, "", DOM.art);
} else { } else {

View file

@ -8,7 +8,6 @@ const ICONS = {
"Album": "album" "Album": "album"
} }
export default class Tag extends Item { export default class Tag extends Item {
constructor(type, value, filter) { constructor(type, value, filter) {
super(); super();