A music player that connects to your cloud/distributed storage. diffuse.sh
Something went wrong. Try again.
4.4 kB · 161 lines
JavaScript
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162import foundation from "~/common/foundation.js";import { effect } from "~/common/signal.js";import * as Playlist from "~/common/playlist.js";
const ACTIVE_CLASS = "button--active";
// Set doc titlefoundation.setup({ title: "Automatic Queue | Diffuse" });
// Setupconst main = /** @type {HTMLElement} */ (document.querySelector("main"));await foundation.orchestrator.autoQueue();
const [repeatShuffle, scope, output, scopedTracks] = await Promise.all([ foundation.engine.repeatShuffle(), foundation.engine.scope(), foundation.orchestrator.output(), foundation.orchestrator.scopedTracks(),]);
// Elementsconst repeatBtn = /** @type {HTMLButtonElement} */ (document.querySelector("#repeat"));const shuffleBtn = /** @type {HTMLButtonElement} */ (document.querySelector("#shuffle"));const searchInput = /** @type {HTMLInputElement} */ (document.querySelector("#search"));const playlistSelect = /** @type {HTMLSelectElement} */ (document.querySelector("#playlist"));const sortBySelect = /** @type {HTMLSelectElement} */ (document.querySelector("#sort-by"));const sortDirectionBtn = /** @type {HTMLButtonElement} */ (document.querySelector("#sort-direction"));const groupBySelect = /** @type {HTMLSelectElement} */ (document.querySelector("#group-by"));
// Repeat & Shuffle stateeffect(() => { repeatBtn.classList.toggle(ACTIVE_CLASS, repeatShuffle.repeat());});
effect(() => { shuffleBtn.classList.toggle(ACTIVE_CLASS, repeatShuffle.shuffle());});
// ActionsrepeatBtn.onclick = () => { repeatShuffle.setRepeat(!repeatShuffle.repeat());};
shuffleBtn.onclick = () => { repeatShuffle.setShuffle(!repeatShuffle.shuffle());};
// Search stateeffect(() => { searchInput.value = scope.searchTerm() ?? "";});
searchInput.oninput = () => { scope.setSearchTerm(searchInput.value.trim() || undefined);};
// Playlist stateeffect(() => { const col = output.playlistItems.collection(); const items = col.state === "loaded" ? col.data : []; const currentPlaylist = scope.playlist();
// Group items by playlist name const playlistMap = Playlist.gather(items); const all = [...playlistMap.values()].sort((a, b) => a.name.localeCompare(b.name) );
const ordered = all.filter((p) => !p.unordered); const unordered = all.filter((p) => p.unordered);
playlistSelect.innerHTML = `<option value="">All tracks</option>`;
for ( const [label, group] of [ ["Ordered", ordered], ["Unordered", unordered], ] ) { if (group.length === 0) continue;
const optgroup = document.createElement("optgroup"); optgroup.label = /** @type {string} */ (label);
for (const playlist of group) { if (typeof playlist === "string") continue; const option = document.createElement("option");
option.value = playlist.name; option.textContent = playlist.name; option.selected = playlist.name === currentPlaylist;
optgroup.appendChild(option); }
playlistSelect.appendChild(optgroup); }});
playlistSelect.onchange = () => { scope.setPlaylist( playlistSelect.value.length ? playlistSelect.value : undefined, );};
// Sort by stateeffect(() => { const ordered = scopedTracks.playlistIsOrdered?.() ?? false; const current = ordered ? "[]" : JSON.stringify(scope.sortBy()); for (const option of sortBySelect.options) { if (JSON.stringify(JSON.parse(option.value)) === current) { sortBySelect.value = option.value; break; } }});
sortBySelect.onchange = () => { scope.setSortBy(JSON.parse(sortBySelect.value));};
// Sort direction stateeffect(() => { const dir = scope.sortDirection() ?? "desc"; sortDirectionBtn.textContent = dir.toUpperCase();});
sortDirectionBtn.onclick = () => { const dir = scope.sortDirection() ?? "desc"; scope.setSortDirection(dir === "asc" ? "desc" : "asc");};
// Group by stateeffect(() => { const groupBy = scope.groupBy(); groupBySelect.value = groupBy?.startsWith("firstLetter:") ? "firstLetter" : (groupBy ?? "");});
groupBySelect.onchange = () => { const raw = groupBySelect.value; if (!raw) { scope.setGroupBy(undefined); } else if (raw === "firstLetter") { scope.setGroupBy(`firstLetter:${scope.sortBy()[0] ?? "tags.artist"}`); } else { scope.setGroupBy(raw); }};
////////////////////////////////////////////// 🚀////////////////////////////////////////////
foundation.ready();