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.

feat: extract preload behaviour into a prelude facet

+72 -31
+7
src/_data/facets.json
··· 107 107 "desc": "The default setup for user-data storage output. Adds support for: AT Protocol and S3-compatible storage. For both of these a custom local-first syncing algorithm is used." 108 108 }, 109 109 { 110 + "url": "facets/playback/preload/prelude/index.html", 111 + "title": "Preload Tracks", 112 + "kind": "prelude", 113 + "category": "Playback", 114 + "desc": "Automatically preload the next track in the queue." 115 + }, 116 + { 110 117 "url": "facets/data/process-tracks/prelude/index.html", 111 118 "title": "Process Tracks", 112 119 "kind": "prelude",
+1
src/common/facets/constants.js
··· 12 12 "facets/data/output-bundle/index.html", 13 13 "facets/data/process-tracks/prelude/index.html", 14 14 "facets/playback/auto-queue/prelude/index.html", 15 + "facets/playback/preload/prelude/index.html", 15 16 ];
-31
src/components/orchestrator/queue-audio/element.js
··· 73 73 if (!queue) return; 74 74 75 75 const activeItem = queue.now(); 76 - const nextItem = queue.future()[0] ?? null; 77 76 const tracksCol = this.output?.tracks.collection(); 78 77 const tracks = tracksCol?.state === "loaded" ? tracksCol.data : undefined; 79 78 80 79 const activeTrack = activeItem 81 80 ? tracks?.find((t) => t.id === activeItem.id) 82 - : undefined; 83 - 84 - const nextTrack = nextItem 85 - ? tracks?.find((t) => t.id === nextItem.id) 86 81 : undefined; 87 82 88 83 if ((await this.isLeader()) === false) return; ··· 114 109 audio: activeAudio, 115 110 play: activeItem && isPlaying ? { audioId: activeItem.id } : undefined, 116 111 }); 117 - 118 - // Preload next track after a delay 119 - clearTimeout(this._preloadTimeout); 120 - if (!nextTrack) return; 121 - 122 - this._preloadTimeout = setTimeout(async () => { 123 - const resolvedNextUri = await input.resolve({ 124 - method: "GET", 125 - uri: nextTrack.uri, 126 - }); 127 - 128 - const nextUrl = resolvedNextUri && !("stream" in resolvedNextUri) 129 - ? resolvedNextUri.url 130 - : undefined; 131 - 132 - if (!nextUrl) return; 133 - 134 - audio.supply({ 135 - audio: [...activeAudio, { 136 - id: nextItem.id, 137 - isPreload: true, 138 - url: nextUrl, 139 - track: nextTrack, 140 - }], 141 - }); 142 - }, 30_000); 143 112 } 144 113 145 114 async monitorAudioEnd() {
+1
src/facets/playback/preload/prelude/index.html
··· 1 + <script type="module" src="facets/playback/preload/prelude/index.inline.js"></script>
+63
src/facets/playback/preload/prelude/index.inline.js
··· 1 + import foundation from "~/common/foundation.js"; 2 + import { effect } from "~/common/signal.js"; 3 + 4 + effect(() => { 5 + // Trigger setup when audio is used 6 + if (foundation.signals.engine.audio()) { 7 + setup(); 8 + } 9 + }); 10 + 11 + async function setup() { 12 + const [audio, input, output, queue] = await Promise.all([ 13 + foundation.engine.audio(), 14 + foundation.configurator.input(), 15 + foundation.orchestrator.output(), 16 + foundation.engine.queue(), 17 + ]); 18 + 19 + await Promise.all([ 20 + customElements.whenDefined(audio.localName), 21 + customElements.whenDefined(input.localName), 22 + customElements.whenDefined(queue.localName), 23 + ]); 24 + 25 + /** @type {number | undefined} */ 26 + let preloadTimeout; 27 + 28 + effect(() => { 29 + const nextItem = queue.future()[0] ?? null; 30 + const tracksCol = output?.tracks.collection(); 31 + const tracks = tracksCol?.state === "loaded" ? tracksCol.data : undefined; 32 + const nextTrack = nextItem 33 + ? tracks?.find((t) => t.id === nextItem.id) 34 + : undefined; 35 + 36 + clearTimeout(preloadTimeout); 37 + if (!nextTrack) return; 38 + 39 + preloadTimeout = setTimeout(async () => { 40 + const resolvedNextUri = await input.resolve({ 41 + method: "GET", 42 + uri: nextTrack.uri, 43 + }); 44 + 45 + const nextUrl = resolvedNextUri && !("stream" in resolvedNextUri) 46 + ? resolvedNextUri.url 47 + : undefined; 48 + 49 + if (!nextUrl) return; 50 + 51 + const activeItems = audio.items().filter((i) => !i.isPreload); 52 + 53 + audio.supply({ 54 + audio: [...activeItems, { 55 + id: nextItem.id, 56 + isPreload: true, 57 + url: nextUrl, 58 + track: nextTrack, 59 + }], 60 + }); 61 + }, 30_000); 62 + }); 63 + }