A music player that connects to your cloud/distributed storage.
at v4 98 lines 2.9 kB view raw
1import { BroadcastableDiffuseElement, query } from "~/common/element.js"; 2 3/** 4 * @import {DiffuseElement} from "~/common/element.js"; 5 * @import {SignalReader} from "~/common/signal.d.ts"; 6 * @import {Track} from "~/definitions/types.d.ts" 7 * @import RepeatShuffleEngine from "~/components/engine/repeat-shuffle/element.js" 8 */ 9 10//////////////////////////////////////////// 11// ELEMENT 12//////////////////////////////////////////// 13 14/** 15 * Update the queue pool whenever tracks have been loaded, 16 * or the tracks collection changes. 17 */ 18class AutoTracksOrchestrator extends BroadcastableDiffuseElement { 19 static NAME = "diffuse/orchestrator/auto-queue"; 20 21 // LIFECYCLE 22 23 /** 24 * @override 25 */ 26 async connectedCallback() { 27 // Broadcast if needed 28 if (this.hasAttribute("group")) { 29 this.broadcast(this.identifier, {}); 30 } 31 32 // Super 33 super.connectedCallback(); 34 35 /** @type {import("~/components/engine/queue/element.js").CLASS} */ 36 const queue = query(this, "queue-engine-selector"); 37 38 /** @type {RepeatShuffleEngine} */ 39 const repeatShuffle = query(this, "repeat-shuffle-engine-selector"); 40 41 /** @type {DiffuseElement & { tracks: SignalReader<Track[]> }} */ 42 const tracksElement = query(this, "tracks-selector"); 43 44 // When defined 45 await customElements.whenDefined(queue.localName); 46 await customElements.whenDefined(repeatShuffle.localName); 47 await customElements.whenDefined(tracksElement.localName); 48 49 // Watch tracks 50 this.effect(() => { 51 const tracks = tracksElement.tracks(); 52 53 this.isLeader().then(async (isLeader) => { 54 if (!isLeader) return; 55 queue.supply({ trackIds: tracks.map((t) => t.id) }); 56 }); 57 }); 58 59 // Automatically fill queue 60 let lastShuffle = repeatShuffle.shuffle(); 61 let lastFingerprint = queue.supplyFingerprint(); 62 63 this.effect(() => { 64 const trigger = queue.now(); 65 const fingerprint = queue.supplyFingerprint(); 66 const shuffled = repeatShuffle.shuffle(); 67 68 this.isLeader().then((isLeader) => { 69 if (!isLeader) return; 70 71 // Clear non-manual items from the queue 72 // when 'shuffle' gets turned off or on; 73 // or when queue supply changes. 74 if (shuffled !== lastShuffle || fingerprint !== lastFingerprint) { 75 lastShuffle = shuffled; 76 lastFingerprint = fingerprint; 77 queue.clear({ manualOnly: true }); 78 } 79 80 queue.fill({ amount: 10, shuffled: repeatShuffle.shuffle() }); 81 82 // Insert now-playing track if there's none 83 if (!trigger) queue.shift(); 84 }); 85 }); 86 } 87} 88 89export default AutoTracksOrchestrator; 90 91//////////////////////////////////////////// 92// REGISTER 93//////////////////////////////////////////// 94 95export const CLASS = AutoTracksOrchestrator; 96export const NAME = "do-auto-queue"; 97 98customElements.define(NAME, CLASS);