refactored ui
This commit is contained in:
parent
0e43a33c4a
commit
d8644edd7e
7 changed files with 109 additions and 63 deletions
|
@ -1,5 +1,7 @@
|
|||
body {
|
||||
margin: 0;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
body {
|
||||
margin: 0;
|
||||
max-width: 800px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
|
|
|
@ -6,7 +6,6 @@ import * as format from "./lib/format.js";
|
|||
import * as ui from "./lib/ui.js";
|
||||
|
||||
let node;
|
||||
const SORT = "-Track";
|
||||
|
||||
function buildHeader(path) {
|
||||
filter = filter || {};
|
||||
|
@ -33,13 +32,14 @@ function buildHeader(path) {
|
|||
|
||||
function buildDirectory(data, parent) {
|
||||
let path = data["directory"];
|
||||
let node = ui.group(path, {}, parent);
|
||||
let name = path.split("/").pop();
|
||||
let node = ui.group(ui.GROUP_DIRECTORY, name, path, parent);
|
||||
node.addEventListener("click", e => list(path));
|
||||
return node;
|
||||
}
|
||||
|
||||
function buildFile(data, parent) {
|
||||
return ui.song(data, parent);
|
||||
return ui.song(ui.SONG_FILE, data, parent);
|
||||
}
|
||||
|
||||
function buildResults(results) {
|
||||
|
|
|
@ -77,13 +77,13 @@ export async function listQueue() {
|
|||
return parser.songList(lines);
|
||||
}
|
||||
|
||||
export async function enqueue(fileOrFilter, sort = null) {
|
||||
if (typeof(fileOrFilter) == "string") {
|
||||
return command(`addid "${escape(fileOrFilter)}"`);
|
||||
export async function enqueue(urlOrFilter, sort = null) {
|
||||
if (typeof(urlOrFilter) == "string") {
|
||||
return command(`add "${escape(urlOrFilter)}"`);
|
||||
}
|
||||
|
||||
let tokens = ["findadd"];
|
||||
tokens.push(serializeFilter(fileOrFilter));
|
||||
tokens.push(serializeFilter(urlOrFilter));
|
||||
// sort && tokens.push("sort", sort); FIXME not implemented in MPD
|
||||
return command(tokens.join(" "));
|
||||
}
|
||||
|
|
|
@ -1,47 +1,113 @@
|
|||
import * as mpd from "./mpd.js";
|
||||
import * as html from "./html.js";
|
||||
import * as pubsub from "./pubsub.js";
|
||||
import * as format from "./format.js";
|
||||
import * as player from "../player.js";
|
||||
|
||||
function playButton(fileOrFilter, parent) {
|
||||
export const SONG_FILE = 1;
|
||||
export const SONG_LIBRARY = 2;
|
||||
export const SONG_QUEUE = 3;
|
||||
export const GROUP_DIRECTORY = 4;
|
||||
export const GROUP_LIBRARY = 5;
|
||||
|
||||
const SORT = "-Track";
|
||||
|
||||
function fileName(data) {
|
||||
return data["file"].split("/").pop();
|
||||
}
|
||||
|
||||
function formatTitle(type, data) {
|
||||
switch (type) {
|
||||
case SONG_FILE:
|
||||
return `🎵 ${fileName(data)}`;
|
||||
break;
|
||||
|
||||
case SONG_LIBRARY:
|
||||
return data["Artist"] || fileName(data);
|
||||
break;
|
||||
|
||||
case SONG_QUEUE:
|
||||
let tokens = [];
|
||||
data["Artist"] && tokens.push(data["Artist"]);
|
||||
data["Title"] && tokens.push(data["Title"]);
|
||||
if (!tokens.length) { tokens.push(fileName(data)); }
|
||||
return tokens.join(" - ");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function playButton(id, parent) {
|
||||
let button = html.button({className:"play"}, "▶", parent);
|
||||
button.addEventListener("click", async e => {
|
||||
await mpd.command(`playid ${id}`);
|
||||
player.update();
|
||||
});
|
||||
}
|
||||
|
||||
function deleteButton(id, parent) {
|
||||
let button = html.button({className:"delete"}, "🗙", parent);
|
||||
button.addEventListener("click", async e => {
|
||||
await mpd.command(`deleteid ${id}`);
|
||||
pubsub.publish("queue-change");
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
||||
function addAndPlayButton(urlOrFilter, parent) {
|
||||
let button = html.button({}, "▶", parent);
|
||||
button.addEventListener("click", async e => {
|
||||
e.stopPropagation();
|
||||
await mpd.command("clear");
|
||||
await mpd.enqueue(fileOrFilter, SORT);
|
||||
await mpd.enqueue(urlOrFilter, SORT);
|
||||
await mpd.command("play");
|
||||
app.activate("queue");
|
||||
pubsub.publish("queue-change");
|
||||
player.update();
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
||||
function addButton(fileOrFilter, parent) {
|
||||
function addButton(urlOrFilter, parent) {
|
||||
let button = html.button({}, "+", parent);
|
||||
button.addEventListener("click", async e => {
|
||||
e.stopPropagation();
|
||||
await mpd.enqueue(fileOrFilter, SORT);
|
||||
await mpd.enqueue(urlOrFilter, SORT);
|
||||
pubsub.publish("queue-change");
|
||||
// fixme notification?
|
||||
});
|
||||
return button;
|
||||
}
|
||||
|
||||
|
||||
export function song(data, parent) {
|
||||
export function song(type, data, parent) {
|
||||
let node = html.node("li", {}, "", parent);
|
||||
|
||||
let file = data["file"];
|
||||
playButton(file, node);
|
||||
addButton(file, node);
|
||||
let title = formatTitle(type, data);
|
||||
html.node("h2", {}, title, node);
|
||||
|
||||
html.node("h3", {}, data["Title"], node);
|
||||
html.node("span", {className:"duration"}, format.time(Number(data["duration"])), node);
|
||||
|
||||
if (type == SONG_QUEUE) {
|
||||
let id = data["Id"];
|
||||
node.dataset.songId = id;
|
||||
playButton(id, node);
|
||||
deleteButton(id, node);
|
||||
} else {
|
||||
let url = data["file"];
|
||||
addAndPlayButton(url, node);
|
||||
addButton(url, node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function group(label, filter, parent) {
|
||||
export function group(type, label, urlOrFilter, parent) {
|
||||
let node = html.node("li", {}, label, parent);
|
||||
|
||||
playButton(filter, node);
|
||||
addButton(filter, node);
|
||||
if (type == GROUP_DIRECTORY) {
|
||||
node.insertBefore(html.text("📁 "), node.firstChild);
|
||||
}
|
||||
|
||||
addAndPlayButton(urlOrFilter, node);
|
||||
addButton(urlOrFilter, node);
|
||||
|
||||
return node;
|
||||
}
|
|
@ -1,12 +1,8 @@
|
|||
import * as app from "./app.js";
|
||||
import * as mpd from "./lib/mpd.js";
|
||||
import * as html from "./lib/html.js";
|
||||
import * as player from "./player.js";
|
||||
import * as format from "./lib/format.js";
|
||||
import * as ui from "./lib/ui.js";
|
||||
|
||||
let node;
|
||||
const SORT = "-Track";
|
||||
|
||||
function buildHeader(filter) {
|
||||
filter = filter || {};
|
||||
|
@ -33,14 +29,14 @@ function buildHeader(filter) {
|
|||
|
||||
function buildAlbum(album, filter, parent) {
|
||||
let childFilter = Object.assign({}, filter, {"Album": album});
|
||||
let node = ui.group(album, childFilter, parent);
|
||||
let node = ui.group(ui.GROUP_LIBRARY, album, childFilter, parent);
|
||||
node.addEventListener("click", e => listSongs(childFilter));
|
||||
return node;
|
||||
}
|
||||
|
||||
function buildArtist(artist, filter, parent) {
|
||||
let childFilter = Object.assign({}, filter, {"Artist": artist});
|
||||
let node = ui.group(artist, childFilter, parent);
|
||||
let node = ui.group(ui.GROUP_LIBRARY, artist, childFilter, parent);
|
||||
node.addEventListener("click", e => listAlbums(childFilter));
|
||||
return node;
|
||||
}
|
||||
|
@ -49,7 +45,7 @@ function buildSongs(songs, filter) {
|
|||
let ul = node.querySelector("ul");
|
||||
html.clear(ul);
|
||||
|
||||
songs.map(song => ui.song(song, ul));
|
||||
songs.map(song => ui.song(ui.SONG_LIBRARY, song, ul));
|
||||
}
|
||||
|
||||
function buildAlbums(albums, filter) {
|
||||
|
|
|
@ -1,8 +1,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";
|
||||
import * as ui from "./lib/ui.js";
|
||||
|
||||
let node;
|
||||
let currentId;
|
||||
|
@ -14,40 +13,11 @@ function updateCurrent() {
|
|||
});
|
||||
}
|
||||
|
||||
async function playSong(id) {
|
||||
await mpd.command(`playid ${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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
function buildSongs(songs) {
|
||||
let ul = node.querySelector("ul");
|
||||
html.clear(ul);
|
||||
|
||||
songs.map(buildSong).forEach(li => ul.appendChild(li));
|
||||
songs.map(song => ui.song(ui.SONG_QUEUE, song, ul));
|
||||
|
||||
updateCurrent();
|
||||
}
|
||||
|
@ -57,12 +27,22 @@ function onSongChange(message, publisher, data) {
|
|||
updateCurrent();
|
||||
}
|
||||
|
||||
export async function activate() {
|
||||
function onQueueChange(message, publisher, data) {
|
||||
syncQueue();
|
||||
}
|
||||
|
||||
async function syncQueue() {
|
||||
let songs = await mpd.listQueue();
|
||||
buildSongs(songs);
|
||||
// FIXME updateCount(songs.length)
|
||||
}
|
||||
|
||||
export async function activate() {
|
||||
syncQueue();
|
||||
}
|
||||
|
||||
export function init(n) {
|
||||
node = n;
|
||||
pubsub.subscribe("song-change", onSongChange);
|
||||
pubsub.subscribe("queue-change", onQueueChange);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue