design
This commit is contained in:
parent
d8644edd7e
commit
3a75581863
16 changed files with 177 additions and 52 deletions
99
app/app.css
99
app/app.css
|
@ -1,4 +1,11 @@
|
||||||
|
html {
|
||||||
|
background-color: #fff;
|
||||||
|
font-family: lato, sans-serif;
|
||||||
|
}
|
||||||
body {
|
body {
|
||||||
|
background-color: #888;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 1px 1px #000;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -10,6 +17,18 @@ body > header,
|
||||||
body > footer {
|
body > footer {
|
||||||
box-shadow: 0 0 3px #000;
|
box-shadow: 0 0 3px #000;
|
||||||
}
|
}
|
||||||
|
@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: bold;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
main {
|
main {
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -23,7 +42,7 @@ nav ul {
|
||||||
}
|
}
|
||||||
nav ul li {
|
nav ul li {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex-grow: 1;
|
flex: 1 0 0;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
}
|
}
|
||||||
nav ul li:hover {
|
nav ul li:hover {
|
||||||
|
@ -57,6 +76,27 @@ nav ul li.active {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
}
|
||||||
|
.component ul {
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: auto;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
.component .grid li {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
.component .grid li h2 {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
.component .grid li:nth-child(odd) {
|
||||||
|
background-color: #666;
|
||||||
|
}
|
||||||
#queue {
|
#queue {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
|
@ -69,6 +109,20 @@ nav ul li.active {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
#queue .grid li {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
#queue .grid li h2 {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
#queue .grid li:nth-child(odd) {
|
||||||
|
background-color: #666;
|
||||||
|
}
|
||||||
#queue li {
|
#queue li {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -76,9 +130,6 @@ nav ul li.active {
|
||||||
#queue li + li {
|
#queue li + li {
|
||||||
border-top: 1px solid #888;
|
border-top: 1px solid #888;
|
||||||
}
|
}
|
||||||
#queue .info {
|
|
||||||
flex-grow: 1;
|
|
||||||
}
|
|
||||||
#queue .current {
|
#queue .current {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
@ -94,3 +145,43 @@ nav ul li.active {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
#library .grid li {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
#library .grid li h2 {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
#library .grid li:nth-child(odd) {
|
||||||
|
background-color: #666;
|
||||||
|
}
|
||||||
|
#fs {
|
||||||
|
height: 100%;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
#fs ul {
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: auto;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#fs .grid li {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
#fs .grid li h2 {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
#fs .grid li:nth-child(odd) {
|
||||||
|
background-color: #666;
|
||||||
|
}
|
||||||
|
|
|
@ -1,4 +1,12 @@
|
||||||
|
html {
|
||||||
|
background-color: #fff;
|
||||||
|
font-family: lato, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
background-color: #888;
|
||||||
|
color: #fff;
|
||||||
|
text-shadow: 0 1px 1px #000;
|
||||||
max-width: 800px;
|
max-width: 800px;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
@ -12,9 +20,11 @@ body {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@import "font.less";
|
||||||
@import "main.less";
|
@import "main.less";
|
||||||
@import "nav.less";
|
@import "nav.less";
|
||||||
@import "player.less";
|
@import "player.less";
|
||||||
@import "component.less";
|
@import "component.less";
|
||||||
@import "queue.less";
|
@import "queue.less";
|
||||||
@import "library.less";
|
@import "library.less";
|
||||||
|
@import "fs.less";
|
||||||
|
|
|
@ -2,4 +2,31 @@
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
}
|
|
||||||
|
ul {
|
||||||
|
flex-grow: 1;
|
||||||
|
overflow: auto;
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.grid {
|
||||||
|
li {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
flex-grow: 1;
|
||||||
|
margin: 0;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
li:nth-child(odd) {
|
||||||
|
background-color: #666;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
13
app/css/font.less
Normal file
13
app/css/font.less
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
@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: bold;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
3
app/css/fs.less
Normal file
3
app/css/fs.less
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
#fs {
|
||||||
|
.component;
|
||||||
|
}
|
|
@ -1,14 +1,3 @@
|
||||||
#library {
|
#library {
|
||||||
.component;
|
.component;
|
||||||
|
|
||||||
ul {
|
|
||||||
flex-grow: 1;
|
|
||||||
overflow: auto;
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ nav ul {
|
||||||
|
|
||||||
li {
|
li {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
flex-grow: 1;
|
flex: 1 0 0;
|
||||||
line-height: 40px;
|
line-height: 40px;
|
||||||
|
|
||||||
&:hover { background-color:red;}
|
&:hover { background-color:red;}
|
||||||
|
|
|
@ -1,14 +1,6 @@
|
||||||
#queue {
|
#queue {
|
||||||
.component;
|
.component;
|
||||||
|
|
||||||
ul {
|
|
||||||
flex-grow: 1;
|
|
||||||
overflow: auto;
|
|
||||||
list-style: none;
|
|
||||||
margin: 0;
|
|
||||||
padding: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
li {
|
li {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
|
@ -18,6 +10,5 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.info { flex-grow: 1; }
|
|
||||||
.current { font-weight: bold; }
|
.current { font-weight: bold; }
|
||||||
}
|
}
|
BIN
app/font/LatoLatin-Bold.woff2
Normal file
BIN
app/font/LatoLatin-Bold.woff2
Normal file
Binary file not shown.
BIN
app/font/LatoLatin-Regular.woff2
Normal file
BIN
app/font/LatoLatin-Regular.woff2
Normal file
Binary file not shown.
|
@ -26,7 +26,7 @@
|
||||||
<main>
|
<main>
|
||||||
<section id="queue">
|
<section id="queue">
|
||||||
<header></header>
|
<header></header>
|
||||||
<ul></ul>
|
<ul class="grid"></ul>
|
||||||
</section>
|
</section>
|
||||||
<section id="playlists"></section>
|
<section id="playlists"></section>
|
||||||
<section id="library">
|
<section id="library">
|
||||||
|
@ -35,14 +35,17 @@
|
||||||
</section>
|
</section>
|
||||||
<section id="fs">
|
<section id="fs">
|
||||||
<header></header>
|
<header></header>
|
||||||
<ul></ul>
|
<ul class="grid"></ul>
|
||||||
</section>
|
</section>
|
||||||
<section id="misc"></section>
|
<section id="misc"></section>
|
||||||
</main>
|
</main>
|
||||||
<footer>
|
<footer>
|
||||||
<nav>
|
<nav>
|
||||||
<ul>
|
<ul>
|
||||||
<li data-for="queue">Q</li>
|
<li data-for="queue">
|
||||||
|
Q
|
||||||
|
<span id="queue-length"></span>
|
||||||
|
</li>
|
||||||
<li data-for="playlists">Playlists</li>
|
<li data-for="playlists">Playlists</li>
|
||||||
<li data-for="library">Library</li>
|
<li data-for="library">Library</li>
|
||||||
<li data-for="fs">FS</li>
|
<li data-for="fs">FS</li>
|
||||||
|
|
|
@ -22,13 +22,14 @@ export function activate(what) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function init() {
|
async function init() {
|
||||||
|
await mpd.init();
|
||||||
|
|
||||||
nav.init(document.querySelector("nav"));
|
nav.init(document.querySelector("nav"));
|
||||||
for (let id in components) {
|
for (let id in components) {
|
||||||
let node = document.querySelector(`#${id}`);
|
let node = document.querySelector(`#${id}`);
|
||||||
components[id].init(node);
|
components[id].init(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
await mpd.init();
|
|
||||||
player.init(document.querySelector("#player"));
|
player.init(document.querySelector("#player"));
|
||||||
|
|
||||||
activate("fs");
|
activate("fs");
|
||||||
|
|
25
app/js/fs.js
25
app/js/fs.js
|
@ -8,26 +8,17 @@ import * as ui from "./lib/ui.js";
|
||||||
let node;
|
let node;
|
||||||
|
|
||||||
function buildHeader(path) {
|
function buildHeader(path) {
|
||||||
filter = filter || {};
|
|
||||||
let header = node.querySelector("header");
|
let header = node.querySelector("header");
|
||||||
html.clear(header);
|
html.clear(header);
|
||||||
|
|
||||||
let button = html.button({}, "Music Library", header);
|
let button = html.button({}, "/", header);
|
||||||
button.addEventListener("click", e => listArtists());
|
button.addEventListener("click", e => list(""));
|
||||||
|
|
||||||
let artist = filter["Artist"];
|
path.split("/").filter(x => x).forEach((name, index, all) => {
|
||||||
if (artist) {
|
let button = html.button({}, name, header);
|
||||||
let artistFilter = {"Artist":artist};
|
let path = all.slice(0, index+1).join("/");
|
||||||
let button = html.button({}, artist, header);
|
button.addEventListener("click", e => list(path));
|
||||||
button.addEventListener("click", e => listAlbums(artistFilter));
|
});
|
||||||
|
|
||||||
let album = filter["Album"];
|
|
||||||
if (album) {
|
|
||||||
let albumFilter = Object.assign({}, artistFilter, {"Album":album});
|
|
||||||
let button = html.button({}, album, header);
|
|
||||||
button.addEventListener("click", e => listSongs(albumFilter));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function buildDirectory(data, parent) {
|
function buildDirectory(data, parent) {
|
||||||
|
@ -53,7 +44,7 @@ function buildResults(results) {
|
||||||
async function list(path) {
|
async function list(path) {
|
||||||
let results = await mpd.listPath(path);
|
let results = await mpd.listPath(path);
|
||||||
buildResults(results);
|
buildResults(results);
|
||||||
// buildHeader(path);
|
buildHeader(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function activate() {
|
export async function activate() {
|
||||||
|
|
|
@ -100,11 +100,10 @@ export function song(type, data, parent) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function group(type, label, urlOrFilter, parent) {
|
export function group(type, label, urlOrFilter, parent) {
|
||||||
let node = html.node("li", {}, label, parent);
|
let node = html.node("li", {}, "", parent);
|
||||||
|
|
||||||
if (type == GROUP_DIRECTORY) {
|
if (type == GROUP_DIRECTORY) { label = `📁 ${label}`; }
|
||||||
node.insertBefore(html.text("📁 "), node.firstChild);
|
html.node("h2", {}, label, node);
|
||||||
}
|
|
||||||
|
|
||||||
addAndPlayButton(urlOrFilter, node);
|
addAndPlayButton(urlOrFilter, node);
|
||||||
addButton(urlOrFilter, node);
|
addButton(urlOrFilter, node);
|
||||||
|
|
|
@ -44,6 +44,8 @@ function buildArtist(artist, filter, parent) {
|
||||||
function buildSongs(songs, filter) {
|
function buildSongs(songs, filter) {
|
||||||
let ul = node.querySelector("ul");
|
let ul = node.querySelector("ul");
|
||||||
html.clear(ul);
|
html.clear(ul);
|
||||||
|
ul.classList.remove("tiles");
|
||||||
|
ul.classList.add("grid");
|
||||||
|
|
||||||
songs.map(song => ui.song(ui.SONG_LIBRARY, song, ul));
|
songs.map(song => ui.song(ui.SONG_LIBRARY, song, ul));
|
||||||
}
|
}
|
||||||
|
@ -51,6 +53,8 @@ function buildSongs(songs, filter) {
|
||||||
function buildAlbums(albums, filter) {
|
function buildAlbums(albums, filter) {
|
||||||
let ul = node.querySelector("ul");
|
let ul = node.querySelector("ul");
|
||||||
html.clear(ul);
|
html.clear(ul);
|
||||||
|
ul.classList.add("tiles");
|
||||||
|
ul.classList.remove("grid");
|
||||||
|
|
||||||
albums.map(album => buildAlbum(album, filter, ul));
|
albums.map(album => buildAlbum(album, filter, ul));
|
||||||
}
|
}
|
||||||
|
@ -58,6 +62,8 @@ function buildAlbums(albums, filter) {
|
||||||
function buildArtists(artists, filter) {
|
function buildArtists(artists, filter) {
|
||||||
let ul = node.querySelector("ul");
|
let ul = node.querySelector("ul");
|
||||||
html.clear(ul);
|
html.clear(ul);
|
||||||
|
ul.classList.add("tiles");
|
||||||
|
ul.classList.remove("grid");
|
||||||
|
|
||||||
artists.map(artist => buildArtist(artist, filter, ul));
|
artists.map(artist => buildArtist(artist, filter, ul));
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ function onQueueChange(message, publisher, data) {
|
||||||
async function syncQueue() {
|
async function syncQueue() {
|
||||||
let songs = await mpd.listQueue();
|
let songs = await mpd.listQueue();
|
||||||
buildSongs(songs);
|
buildSongs(songs);
|
||||||
// FIXME updateCount(songs.length)
|
document.querySelector("#queue-length").textContent = `(${songs.length})`;
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function activate() {
|
export async function activate() {
|
||||||
|
@ -43,6 +43,7 @@ export async function activate() {
|
||||||
|
|
||||||
export function init(n) {
|
export function init(n) {
|
||||||
node = n;
|
node = n;
|
||||||
|
syncQueue();
|
||||||
pubsub.subscribe("song-change", onSongChange);
|
pubsub.subscribe("song-change", onSongChange);
|
||||||
pubsub.subscribe("queue-change", onQueueChange);
|
pubsub.subscribe("queue-change", onQueueChange);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue