cyp/app/js/elements/queue.js

118 lines
2.8 KiB
JavaScript
Raw Permalink Normal View History

2020-03-10 05:24:31 +08:00
import * as html from "../html.js";
import Component from "../component.js";
import Song from "./song.js";
2020-03-13 06:03:26 +08:00
import { escape } from "../mpd.js";
2019-03-22 22:35:04 +08:00
2020-03-10 17:07:30 +08:00
2020-03-10 21:08:18 +08:00
function generateMoveCommands(items, diff, all) {
const COMPARE = (a, b) => all.indexOf(a) - all.indexOf(b);
return items.sort(COMPARE)
.map(item => {
let index = all.indexOf(item) + diff;
if (index < 0 || index >= all.length) { return null; } // this does not move
2020-03-14 06:01:16 +08:00
return `moveid ${item.songId} ${index}`;
2020-03-10 21:08:18 +08:00
})
.filter(command => command);
}
2020-03-09 05:11:46 +08:00
class Queue extends Component {
constructor() {
2020-03-10 17:07:30 +08:00
super({selection:"multi"});
2020-03-09 05:11:46 +08:00
this._currentId = null;
2020-03-10 05:24:31 +08:00
this._initCommands();
2020-03-09 05:11:46 +08:00
}
2019-03-22 22:35:04 +08:00
2020-03-09 05:11:46 +08:00
handleEvent(e) {
switch (e.type) {
case "song-change":
this._currentId = e.detail["Id"];
this._updateCurrent();
break;
2019-03-22 22:35:04 +08:00
2020-05-06 05:03:36 +08:00
case "idle-change":
e.detail.includes("playlist") && this._sync();
2020-03-09 05:11:46 +08:00
break;
}
}
2019-03-26 17:09:26 +08:00
2020-03-09 16:26:10 +08:00
_onAppLoad() {
2020-05-08 02:06:43 +08:00
this._app.addEventListener("idle-change", this);
2020-03-09 16:26:10 +08:00
this._app.addEventListener("song-change", this);
this._sync();
}
2020-03-09 05:11:46 +08:00
_onComponentChange(c, isThis) {
this.hidden = !isThis;
}
2019-03-22 22:35:04 +08:00
2020-03-09 05:11:46 +08:00
async _sync() {
2020-03-09 16:26:10 +08:00
let songs = await this._mpd.listQueue();
2020-03-09 05:11:46 +08:00
this._buildSongs(songs);
2020-03-17 05:57:13 +08:00
let e = new CustomEvent("queue-length-change", {detail:songs.length});
this._app.dispatchEvent(e);
2020-03-09 05:11:46 +08:00
}
_updateCurrent() {
2020-03-17 18:02:38 +08:00
Array.from(this.children).forEach(/** @param {Song} node */ node => {
node.playing = (node.songId == this._currentId);
2020-03-09 05:11:46 +08:00
});
}
_buildSongs(songs) {
2020-03-09 21:26:39 +08:00
html.clear(this);
2020-03-10 17:07:30 +08:00
this.selection.clear();
2020-03-09 05:11:46 +08:00
2020-03-11 05:11:36 +08:00
songs.forEach(song => {
const node = new Song(song);
this.appendChild(node);
2020-03-13 06:03:26 +08:00
node.addButton("play", async _ => {
2020-03-14 06:01:16 +08:00
await this._mpd.command(`playid ${node.songId}`);
2020-03-11 05:11:36 +08:00
});
});
2020-03-09 05:11:46 +08:00
this._updateCurrent();
}
2020-03-10 05:24:31 +08:00
_initCommands() {
const sel = this.selection;
2020-03-09 21:26:39 +08:00
2020-03-10 05:24:31 +08:00
sel.addCommandAll();
2020-03-09 21:26:39 +08:00
2020-05-06 05:03:36 +08:00
sel.addCommand(items => {
2020-03-10 21:08:18 +08:00
const commands = generateMoveCommands(items, -1, Array.from(this.children));
2020-05-06 05:03:36 +08:00
this._mpd.command(commands);
2020-03-10 21:08:18 +08:00
}, {label:"Up", icon:"arrow-up-bold"});
2020-05-06 05:03:36 +08:00
sel.addCommand(items => {
2020-03-10 21:08:18 +08:00
const commands = generateMoveCommands(items, +1, Array.from(this.children));
2020-05-06 05:03:36 +08:00
this._mpd.command(commands.reverse()); // move last first
2020-03-10 21:08:18 +08:00
}, {label:"Down", icon:"arrow-down-bold"});
2020-05-06 05:03:36 +08:00
sel.addCommand(items => {
2020-03-10 05:24:31 +08:00
let name = prompt("Save selected songs as a playlist?", "name");
if (name === null) { return; }
2020-03-09 21:26:39 +08:00
2020-03-13 06:03:26 +08:00
name = escape(name);
2020-03-10 05:24:31 +08:00
const commands = items.map(item => {
2020-03-14 06:01:16 +08:00
return `playlistadd "${name}" "${escape(item.file)}"`;
2020-03-10 05:24:31 +08:00
});
2020-03-09 21:26:39 +08:00
2020-05-06 05:03:36 +08:00
this._mpd.command(commands); // FIXME notify?
2020-03-10 05:24:31 +08:00
}, {label:"Save", icon:"content-save"});
2020-03-09 21:26:39 +08:00
2020-03-10 05:24:31 +08:00
sel.addCommand(async items => {
if (!confirm(`Remove these ${items.length} songs from the queue?`)) { return; }
2020-03-09 21:26:39 +08:00
2020-03-14 06:01:16 +08:00
const commands = items.map(item => `deleteid ${item.songId}`);
2020-05-06 05:03:36 +08:00
this._mpd.command(commands);
2020-03-10 05:24:31 +08:00
}, {label:"Remove", icon:"delete"});
2020-03-09 21:26:39 +08:00
2020-03-10 17:07:30 +08:00
sel.addCommandCancel();
2020-03-09 21:26:39 +08:00
}
}
2020-03-10 05:24:31 +08:00
customElements.define("cyp-queue", Queue);