tag/path queueing
This commit is contained in:
parent
aca1f44a60
commit
c3871fa486
16 changed files with 62 additions and 161 deletions
|
@ -1,6 +1,4 @@
|
|||
.art {
|
||||
margin-right: var(--icon-spacing);
|
||||
.icon, img {
|
||||
vertical-align: top;
|
||||
}
|
||||
.icon, img { display: block; }
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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";
|
||||
|
|
|
@ -1,3 +1,16 @@
|
|||
cyp-tag {
|
||||
.item;
|
||||
|
||||
padding: 0;
|
||||
|
||||
.art {
|
||||
img, .icon {
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
}
|
||||
|
||||
.icon {
|
||||
filter: drop-shadow(var(--text-shadow));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,4 @@
|
|||
cyp-yt {
|
||||
.component;
|
||||
|
||||
header {
|
||||
border-bottom: 1px solid var(--fg);
|
||||
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
#fs {
|
||||
.component;
|
||||
|
||||
header {
|
||||
white-space: pre; // separator
|
||||
}
|
||||
|
||||
.search {
|
||||
order: 1;
|
||||
&.open ~ * { display: none; }
|
||||
}
|
||||
|
||||
.group {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.info {
|
||||
// .multiline; FIXME
|
||||
}
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
.icon {
|
||||
width: 24px;
|
||||
// flex-shrink: 0;
|
||||
flex: none;
|
||||
|
||||
path, polygon, circle {
|
||||
&:not([fill]) {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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; }
|
||||
}
|
||||
|
||||
}
|
||||
|
|
File diff suppressed because one or more lines are too long
|
@ -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);
|
||||
});
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -8,7 +8,6 @@ const ICONS = {
|
|||
"Album": "album"
|
||||
}
|
||||
|
||||
|
||||
export default class Tag extends Item {
|
||||
constructor(type, value, filter) {
|
||||
super();
|
||||
|
|
Loading…
Reference in a new issue