A music player that connects to your cloud/distributed storage.
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v4 140 lines 3.8 kB view raw
1import foundation from "~/common/foundation.js"; 2import { effect } from "~/common/signal.js"; 3import * as Playlist from "~/common/playlist.js"; 4 5const ACTIVE_CLASS = "button--active"; 6 7// Set doc title 8foundation.setup({ title: "Automatic Queue | Diffuse" }); 9 10// Setup 11const main = /** @type {HTMLElement} */ (document.querySelector("main")); 12await foundation.orchestrator.autoQueue(); 13 14const [repeatShuffle, scope, output] = await Promise.all([ 15 foundation.engine.repeatShuffle(), 16 foundation.engine.scope(), 17 foundation.orchestrator.output(), 18]); 19 20// Elements 21const repeatBtn = 22 /** @type {HTMLButtonElement} */ (document.querySelector("#repeat")); 23const shuffleBtn = 24 /** @type {HTMLButtonElement} */ (document.querySelector("#shuffle")); 25const searchInput = 26 /** @type {HTMLInputElement} */ (document.querySelector("#search")); 27const playlistSelect = 28 /** @type {HTMLSelectElement} */ (document.querySelector("#playlist")); 29const sortBySelect = 30 /** @type {HTMLSelectElement} */ (document.querySelector("#sort-by")); 31const sortDirectionBtn = 32 /** @type {HTMLButtonElement} */ (document.querySelector("#sort-direction")); 33 34// Repeat & Shuffle state 35effect(() => { 36 repeatBtn.classList.toggle(ACTIVE_CLASS, repeatShuffle.repeat()); 37}); 38 39effect(() => { 40 shuffleBtn.classList.toggle(ACTIVE_CLASS, repeatShuffle.shuffle()); 41}); 42 43// Actions 44repeatBtn.onclick = () => { 45 repeatShuffle.setRepeat(!repeatShuffle.repeat()); 46}; 47 48shuffleBtn.onclick = () => { 49 repeatShuffle.setShuffle(!repeatShuffle.shuffle()); 50}; 51 52// Search state 53effect(() => { 54 searchInput.value = scope.searchTerm() ?? ""; 55}); 56 57searchInput.oninput = () => { 58 scope.setSearchTerm(searchInput.value.trim() || undefined); 59}; 60 61// Playlist state 62effect(() => { 63 const col = output.playlistItems.collection(); 64 const items = col.state === "loaded" ? col.data : []; 65 const currentPlaylist = scope.playlist(); 66 67 // Group items by playlist name 68 const playlistMap = Playlist.gather(items); 69 const all = [...playlistMap.values()].sort((a, b) => 70 a.name.localeCompare(b.name) 71 ); 72 73 const ordered = all.filter((p) => !p.unordered); 74 const unordered = all.filter((p) => p.unordered); 75 76 playlistSelect.innerHTML = `<option value="">All tracks</option>`; 77 78 for ( 79 const [label, group] of [ 80 ["Ordered", ordered], 81 ["Unordered", unordered], 82 ] 83 ) { 84 if (group.length === 0) continue; 85 86 const optgroup = document.createElement("optgroup"); 87 optgroup.label = /** @type {string} */ (label); 88 89 for (const playlist of group) { 90 if (typeof playlist === "string") continue; 91 const option = document.createElement("option"); 92 93 option.value = playlist.name; 94 option.textContent = playlist.name; 95 option.selected = playlist.name === currentPlaylist; 96 97 optgroup.appendChild(option); 98 } 99 100 playlistSelect.appendChild(optgroup); 101 } 102}); 103 104playlistSelect.onchange = () => { 105 scope.setPlaylist( 106 playlistSelect.value.length ? playlistSelect.value : undefined, 107 ); 108}; 109 110// Sort by state 111effect(() => { 112 const current = JSON.stringify(scope.sortBy()); 113 for (const option of sortBySelect.options) { 114 if (JSON.stringify(JSON.parse(option.value)) === current) { 115 sortBySelect.value = option.value; 116 break; 117 } 118 } 119}); 120 121sortBySelect.onchange = () => { 122 scope.setSortBy(JSON.parse(sortBySelect.value)); 123}; 124 125// Sort direction state 126effect(() => { 127 const dir = scope.sortDirection() ?? "desc"; 128 sortDirectionBtn.textContent = dir.toUpperCase(); 129}); 130 131sortDirectionBtn.onclick = () => { 132 const dir = scope.sortDirection() ?? "desc"; 133 scope.setSortDirection(dir === "asc" ? "desc" : "asc"); 134}; 135 136//////////////////////////////////////////// 137// 🚀 138//////////////////////////////////////////// 139 140foundation.ready();