styling
This commit is contained in:
parent
76802bc630
commit
37fdd5413c
10 changed files with 87 additions and 14 deletions
29
app/app.css
29
app/app.css
|
@ -4,6 +4,10 @@ body {
|
|||
flex-direction: column;
|
||||
height: 100vh;
|
||||
}
|
||||
header,
|
||||
footer {
|
||||
box-shadow: 0 0 3px #000;
|
||||
}
|
||||
main {
|
||||
flex-grow: 1;
|
||||
overflow-x: hidden;
|
||||
|
@ -27,6 +31,16 @@ nav ul li:hover {
|
|||
nav ul li.active {
|
||||
background-color: green;
|
||||
}
|
||||
#player {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
#player .art img {
|
||||
vertical-align: top;
|
||||
}
|
||||
#player .info {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#player:not([data-state=play]) .pause {
|
||||
display: none;
|
||||
}
|
||||
|
@ -37,6 +51,21 @@ nav ul li.active {
|
|||
#player:not([data-flags~=repeat]) .repeat {
|
||||
opacity: 0.5;
|
||||
}
|
||||
#queue ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
#queue li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
#queue li + li {
|
||||
border-top: 1px solid #888;
|
||||
}
|
||||
#queue .info {
|
||||
flex-grow: 1;
|
||||
}
|
||||
#queue .current {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,10 @@ body {
|
|||
height: 100vh;
|
||||
}
|
||||
|
||||
header, footer {
|
||||
box-shadow: 0 0 3px #000;
|
||||
}
|
||||
|
||||
@import "main.less";
|
||||
@import "nav.less";
|
||||
@import "player.less";
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
#player {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
.art img { vertical-align: top; }
|
||||
.info { flex-grow: 1; }
|
||||
|
||||
&:not([data-state=play]) .pause { display: none; }
|
||||
&[data-state=play] .play { display: none; }
|
||||
|
||||
|
||||
&:not([data-flags~=random]) .random, &:not([data-flags~=repeat]) .repeat { opacity: 0.5; }
|
||||
}
|
|
@ -1,3 +1,19 @@
|
|||
#queue {
|
||||
ul {
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
li {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
|
||||
+ li {
|
||||
border-top: 1px solid #888;
|
||||
}
|
||||
}
|
||||
|
||||
.info { flex-grow: 1; }
|
||||
.current { font-weight: bold; }
|
||||
}
|
|
@ -10,9 +10,10 @@
|
|||
<header>
|
||||
<section id="player">
|
||||
<span class="art"></span>
|
||||
<span class="title"></span>
|
||||
<span class="artist"></span>
|
||||
<span class="album"></span>
|
||||
<div class="info">
|
||||
<h2 class="title"></h2>
|
||||
<span class="artist-album"></span>
|
||||
</div>
|
||||
<span class="elapsed"></span>/<span class="duration"></span>
|
||||
<button class="play">⏯️▶</button>
|
||||
<button class="pause">⏸️</button>
|
||||
|
|
1
app/js/conf.js
Normal file
1
app/js/conf.js
Normal file
|
@ -0,0 +1 @@
|
|||
export const artSize = 96;
|
|
@ -1,11 +1,11 @@
|
|||
import * as mpd from "./mpd.js";
|
||||
import * as parser from "./parser.js";
|
||||
import * as html from "./html.js";
|
||||
import * as conf from "../conf.js";
|
||||
|
||||
let cache = {};
|
||||
const SIZE = 64;
|
||||
const MIME = "image/jpeg";
|
||||
const STORAGE_PREFIX = `art-${SIZE}` ;
|
||||
const STORAGE_PREFIX = `art-${conf.artSize}` ;
|
||||
|
||||
function store(key, data) {
|
||||
localStorage.setItem(`${STORAGE_PREFIX}-${key}`, data);
|
||||
|
@ -38,9 +38,9 @@ async function bytesToImage(bytes) {
|
|||
}
|
||||
|
||||
function resize(image) {
|
||||
let canvas = html.node("canvas", {width:SIZE, height:SIZE});
|
||||
let canvas = html.node("canvas", {width:conf.artSize, height:conf.artSize});
|
||||
let ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(image, 0, 0, SIZE, SIZE);
|
||||
ctx.drawImage(image, 0, 0, canvas.width, canvas.height);
|
||||
return canvas;
|
||||
}
|
||||
|
||||
|
|
|
@ -4,3 +4,10 @@ export function time(sec) {
|
|||
let s = sec % 60;
|
||||
return `${m}:${s.toString().padStart(2, "0")}`;
|
||||
}
|
||||
|
||||
export function artistAlbum(artist, album) {
|
||||
let tokens = [];
|
||||
artist && tokens.push(artist);
|
||||
album && tokens.push(album);
|
||||
return tokens.join(" – ");
|
||||
}
|
|
@ -17,8 +17,7 @@ function sync(data) {
|
|||
if (data["file"] != current["file"]) { // changed song
|
||||
DOM.duration.textContent = format.time(Number(data["duration"] || 0));
|
||||
DOM.title.textContent = data["Title"] || "";
|
||||
DOM.album.textContent = data["Album"] || "";
|
||||
DOM.artist.textContent = data["Artist"] || "";
|
||||
DOM["artist-album"].textContent = format.artistAlbum(data["Artist"], data["Album"]);
|
||||
pubsub.publish("song-change", null, data);
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,7 @@ import * as mpd from "./lib/mpd.js";
|
|||
import * as html from "./lib/html.js";
|
||||
import * as player from "./player.js";
|
||||
import * as pubsub from "./lib/pubsub.js";
|
||||
import * as format from "./lib/format.js";
|
||||
|
||||
let node;
|
||||
let currentId;
|
||||
|
@ -18,15 +19,26 @@ async function playSong(id) {
|
|||
player.update();
|
||||
}
|
||||
|
||||
async function deleteSong(id) {
|
||||
await mpd.command(`deleteid ${id}`);
|
||||
activate();
|
||||
}
|
||||
|
||||
function buildSong(song) {
|
||||
let id = Number(song["Id"]);
|
||||
|
||||
let node = html.node("li");
|
||||
node.dataset.songId = id;
|
||||
|
||||
node.textContent = song["file"];
|
||||
let play = html.button({}, "▶", node);
|
||||
play.addEventListener("click", e => playSong(id));
|
||||
html.button({className:"play"}, "▶", node).addEventListener("click", e => playSong(id));
|
||||
|
||||
let info = html.node("div", {className:"info"}, "", node);
|
||||
|
||||
html.node("h2", {className:"title"}, song["Title"], info);
|
||||
html.node("span", {className:"artist-album"}, format.artistAlbum(song["Artist"], song["Album"]), info);
|
||||
html.node("span", {className:"duration"}, format.time(Number(song["duration"])), info);
|
||||
|
||||
html.button({className:"delete"}, "🗙", node).addEventListener("click", e => deleteSong(id));
|
||||
|
||||
return node;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue