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.

chore: move "toggle favourite" action to artwork controller

+68 -86
-24
src/facets/tools/auto-queue.html.txt
··· 7 7 <button id="shuffle" title="Toggle shuffle"> 8 8 <span class="with-icon"><i class="ph-bold ph-shuffle"></i> Shuffle</span> 9 9 </button> 10 - <button id="favourite" title="Toggle favourite"> 11 - <span class="with-icon"><i class="ph-bold ph-star"></i> Favourite</span> 12 - </button> 13 10 </div> 14 11 <hr /> 15 12 <div class="row"> ··· 62 59 const queue = foundation.engine.queue(); 63 60 const repeatShuffle = foundation.engine.repeatShuffle(); 64 61 const scope = foundation.engine.scope(); 65 - const favourites = foundation.orchestrator.favourites(); 66 62 const output = foundation.orchestrator.output(); 67 63 68 64 // Elements 69 65 const repeatBtn = document.querySelector("#repeat"); 70 66 const shuffleBtn = document.querySelector("#shuffle"); 71 - const favouriteBtn = document.querySelector("#favourite"); 72 67 const playlistSelect = document.querySelector("#playlist"); 73 68 74 69 // Repeat & Shuffle state ··· 80 75 shuffleBtn.classList.toggle(ACTIVE_CLASS, repeatShuffle.shuffle()); 81 76 }); 82 77 83 - // Favourite state 84 - const isFavourited = computed(() => { 85 - const track = queue.now(); 86 - if (!track) return false; 87 - 88 - return favourites.isFavourite(track); 89 - }); 90 - 91 - effect(() => { 92 - const track = queue.now(); 93 - favouriteBtn.disabled = !track; 94 - favouriteBtn.classList.toggle(ACTIVE_CLASS, isFavourited()); 95 - }); 96 - 97 78 // Actions 98 79 repeatBtn.onclick = () => { 99 80 repeatShuffle.setRepeat(!repeatShuffle.repeat()); ··· 101 82 102 83 shuffleBtn.onclick = () => { 103 84 repeatShuffle.setShuffle(!repeatShuffle.shuffle()); 104 - }; 105 - 106 - favouriteBtn.onclick = () => { 107 - const track = queue.now(); 108 - if (track) favourites.toggle(track); 109 85 }; 110 86 111 87 // Playlist state
+66 -60
src/themes/blur/artwork-controller/element.js
··· 22 22 * @import AudioEngine from "@components/engine/audio/element.js" 23 23 * @import QueueEngine from "@components/engine/queue/element.js" 24 24 * @import ArtworkProcessor from "@components/processor/artwork/element.js" 25 - * @import RepeatShuffleEngine from "@components/engine/repeat-shuffle/element.js" 25 + * @import FavouritesOrchestrator from "@components/orchestrator/favourites/element.js" 26 26 */ 27 27 28 28 class ArtworkController extends DiffuseElement { ··· 56 56 57 57 $artwork = signal(/** @type {ArtworkProcessor | undefined} */ (undefined)); 58 58 $audio = signal(/** @type {AudioEngine | undefined} */ (undefined)); 59 + $favourites = signal( 60 + /** @type {FavouritesOrchestrator | undefined} */ (undefined), 61 + ); 59 62 $input = signal(/** @type {InputElement | undefined} */ (undefined)); 60 63 $queue = signal(/** @type {QueueEngine | undefined} */ (undefined)); 61 - $repeatShuffle = signal(/** @type {RepeatShuffleEngine | undefined} */ (undefined)); 62 64 63 65 // SIGNALS - COMPUTED 64 66 ··· 91 93 /** @type {QueueEngine} */ 92 94 const queue = query(this, "queue-engine-selector"); 93 95 94 - /** @type {RepeatShuffleEngine} */ 95 - const repeatShuffle = query(this, "repeat-shuffle-engine-selector"); 96 + /** @type {FavouritesOrchestrator} */ 97 + const favourites = query(this, "favourites-orchestrator-selector"); 96 98 97 - this.$artwork.value = artwork; 98 - this.$audio.value = audio; 99 - this.$input.value = input; 100 - this.$queue.value = queue; 101 - this.$repeatShuffle.value = repeatShuffle; 99 + whenElementsDefined({ audio, artwork, favourites, input, queue }).then( 100 + () => { 101 + this.$artwork.value = artwork; 102 + this.$audio.value = audio; 103 + this.$input.value = input; 104 + this.$queue.value = queue; 105 + this.$favourites.value = favourites; 102 106 103 - whenElementsDefined({ audio, artwork, input, queue, repeatShuffle }).then(() => { 104 - // Changed artwork based on active queue item. 105 - const debouncedChangeArtwork = debounce( 106 - 1000, 107 - this.#setArtwork.bind(this), 108 - ); 107 + // Changed artwork based on active queue item. 108 + const debouncedChangeArtwork = debounce( 109 + 1000, 110 + this.#setArtwork.bind(this), 111 + ); 109 112 110 - this.effect(() => { 111 - const _trigger = queue.now(); 112 - debouncedChangeArtwork(); 113 - }); 113 + this.effect(() => { 114 + const _trigger = queue.now(); 115 + debouncedChangeArtwork(); 116 + }); 114 117 115 - this.effect(() => this.#formatTimestamps()); 116 - this.effect(() => this.#lightOrDark()); 118 + this.effect(() => this.#formatTimestamps()); 119 + this.effect(() => this.#lightOrDark()); 117 120 118 - this.effect(() => { 119 - const now = !!queue.now(); 120 - const aud = this.#audio()?.loadingState(); 121 - const bool = now && aud !== "loaded"; 121 + this.effect(() => { 122 + const now = !!queue.now(); 123 + const aud = this.#audio()?.loadingState(); 124 + const bool = now && aud !== "loaded"; 122 125 123 - if (this.#isLoadingTimeout) { 124 - clearTimeout(this.#isLoadingTimeout); 125 - } 126 + if (this.#isLoadingTimeout) { 127 + clearTimeout(this.#isLoadingTimeout); 128 + } 126 129 127 - if (bool) { 128 - this.#isLoadingTimeout = setTimeout( 129 - () => this.#isLoading.value = true, 130 - 2000, 131 - ); 132 - } else { 133 - this.#isLoading.value = false; 134 - } 135 - }); 136 - }); 130 + if (bool) { 131 + this.#isLoadingTimeout = setTimeout( 132 + () => this.#isLoading.value = true, 133 + 2000, 134 + ); 135 + } else { 136 + this.#isLoading.value = false; 137 + } 138 + }); 139 + }, 140 + ); 137 141 } 138 142 139 143 //////////////////////////////////////////// ··· 306 310 previous: this.#artwork.value.previous, 307 311 current: { ...this.#artwork.value.current, loaded: true }, 308 312 }; 309 - } 313 + }; 310 314 311 315 fullVolume = () => { 312 316 this.$audio.value?.adjustVolume({ volume: 1 }); 313 - } 317 + }; 314 318 315 319 mute = () => { 316 320 this.$audio.value?.adjustVolume({ volume: 0 }); 317 - } 321 + }; 318 322 319 323 next = () => { 320 324 this.$queue.value?.shift(); 321 - } 325 + }; 322 326 323 327 playPause = () => { 324 328 const audioId = this.$queue.value?.now()?.id; ··· 328 332 } else if (audioId) { 329 333 this.$audio.value?.play({ audioId }); 330 334 } 331 - } 335 + }; 332 336 333 337 previous = () => { 334 338 this.$queue.value?.unshift(); 335 - } 339 + }; 336 340 337 341 /** 338 342 * @param {MouseEvent} event ··· 345 349 const audioId = this.$queue.value?.now()?.id; 346 350 347 351 if (audioId) this.$audio.value?.seek({ audioId, percentage }); 348 - } 352 + }; 349 353 350 354 /** 351 355 * @param {MouseEvent} event ··· 357 361 358 362 const percentage = target ? event.offsetX / target.clientWidth : 0; 359 363 this.$audio.value?.adjustVolume({ volume: percentage }); 360 - } 364 + }; 361 365 362 - toggleRepeat = () => { 363 - const rs = this.$repeatShuffle.value 364 - if (!rs) return 365 - rs.setRepeat(!rs.repeat()) 366 - } 366 + toggleFavourite = () => { 367 + const activeQueueItem = this.$queue.value?.now(); 368 + if (!activeQueueItem) return; 367 369 368 - toggleShuffle = () => { 369 - const rs = this.$repeatShuffle.value 370 - if (!rs) return 371 - rs.setShuffle(!rs.shuffle()) 372 - } 370 + this.$favourites.value?.toggle(activeQueueItem); 371 + }; 373 372 374 373 // RENDER 375 374 ··· 378 377 */ 379 378 render({ html }) { 380 379 const activeQueueItem = this.$queue.value?.now(); 380 + const isFav = activeQueueItem 381 + ? this.$favourites.value?.isFavourite(activeQueueItem) ?? false 382 + : false; 381 383 382 384 // Artwork 383 385 const artworkArr = [ ··· 521 523 .fullVolume}" class="ph-fill ph-speaker-high"></i> 522 524 </div> 523 525 524 - <!--<footer> 526 + <footer> 525 527 <div class="button-row"> 526 - <button title="Toggle favourite"> 527 - <i class="ph-bold ph-star"></i> 528 + <button 529 + title="Toggle favourite" 530 + data-enabled="${isFav ? `t` : `f`}" 531 + @click="${this.toggleFavourite}" 532 + > 533 + <i class="ph-${isFav ? `fill` : `bold`} ph-star"></i> 528 534 </button> 529 535 </div> 530 - </footer>--> 536 + </footer> 531 537 </section> 532 538 </section> 533 539 </main>
+2 -2
src/themes/blur/artwork-controller/facet.html.txt
··· 14 14 15 15 const aud = foundation.engine.audio(); 16 16 const art = foundation.processor.artwork(); 17 + const fav = foundation.orchestrator.favourites(); 17 18 const inp = foundation.orchestrator.input(); 18 19 const que = foundation.engine.queue(); 19 - const rse = foundation.engine.repeatShuffle(); 20 20 21 21 // Controller 22 22 const dac = new ArtworkController(); ··· 24 24 dac.setAttribute("audio-engine-selector", aud.selector); 25 25 dac.setAttribute("input-selector", inp.selector); 26 26 dac.setAttribute("queue-engine-selector", que.selector); 27 - dac.setAttribute("repeat-shuffle-engine-selector", rse.selector); 27 + dac.setAttribute("favourites-orchestrator-selector", fav.selector); 28 28 29 29 // Add to DOM 30 30 document.body.append(dac);