Personal Site

Pause animations when nothing playing

- 🟠 figure out what causes "The connection to http://localhost:3000/now-playing-sse was interrupted while the page was loading." error
- 🟠 preload all assets
- 🟠 figure out why firefox warns about unused box-circle-mask.png preload when it is used in bsky pfp in landing

vielle.dev f170b7ea 427fda1f

verified
+47 -19
+47 -19
src/components/playing/NowPlaying.astro
··· 49 --small-box-mask-png: url("${smallBoxMask.src}"); 50 `} 51 > 52 - <div class="player" tabindex="0" aria-label="Record player"> 53 <div class="spinner"></div> 54 55 <div class="record"> ··· 78 <span slot="album">{dataTrack(track) ? track.album.name : null}</span> 79 <span slot="artists"> 80 { 81 - dataTrack(track) 82 - ? track.artists 83 - .map((artist) => ( 84 - <a href={artist.external_urls.spotify}>{artist.name}</a> 85 - )) 86 - // inject a comma before each entry in the list except the first one 87 - // flatmap flattens the returned array into the new map 88 - .flatMap((x, i) => (i === 0 ? x : [", ", x])) 89 - : null 90 } 91 </span> 92 <img ··· 242 243 animation: 30s linear forwards infinite spin; 244 245 & .art { 246 position: absolute; 247 top: calc((50 / 3) * 1cqw); ··· 266 height: calc((60 / 3) * 1cqw); 267 268 animation: 60s linear 2.5s infinite forwards head-move; 269 270 &.hidden { 271 background: none; ··· 500 let lastValidArtist = elIs( 501 this.elements.artists.children[0], 502 HTMLElement, 503 ); 504 replaceArtists.forEach((artist, i) => { 505 // if this index exists in both arrays, update in place ··· 552 spinner: Array.from(querySelectorAll(".player .spinner", HTMLDivElement)), 553 recordArt: querySelector(".record .art", HTMLImageElement), 554 nowPlaying: querySelector("now-playing", HTMLNowPlayingElement), 555 }; 556 557 if (elements.spinner.length !== 2) ··· 598 iterations: Infinity, 599 }), 600 ); 601 602 /************ 603 * LISTENER * ··· 641 // 1. pause current animation. 642 animations.forEach((anim) => anim.pause()); 643 elements.spinner.forEach((el) => 644 - // 2. send the playback head to the start 645 el 646 .animate(goToStartAnimation, { 647 duration: 2.5 * 1000, 648 easing: "ease-in-out", 649 }) 650 // 3. when the playback head is at the start 651 - .finished.then(async (x) => { 652 - 653 // 4. update the record art 654 elements.recordArt.src = data 655 ? data?.album.images[0].url 656 : "https://undefined"; 657 658 - // 5. reset the position of the infinite animation 659 animations.forEach((anim) => (anim.currentTime = 0)); 660 661 - // 6. after 2s 662 - setTimeout(() => { 663 - // resume the infinite animation 664 - animations.forEach((anim) => anim.play()); 665 - }, 2000); 666 }), 667 ); 668 }
··· 49 --small-box-mask-png: url("${smallBoxMask.src}"); 50 `} 51 > 52 + <div 53 + class="player" 54 + tabindex="0" 55 + aria-label="Record player" 56 + data-playing={dataTrack(track) ? "true" : "false"} 57 + > 58 <div class="spinner"></div> 59 60 <div class="record"> ··· 83 <span slot="album">{dataTrack(track) ? track.album.name : null}</span> 84 <span slot="artists"> 85 { 86 + dataTrack(track) ? ( 87 + track.artists 88 + .map((artist) => ( 89 + <a href={artist.external_urls.spotify}>{artist.name}</a> 90 + )) 91 + // inject a comma before each entry in the list except the first one 92 + // flatmap flattens the returned array into the new map 93 + .flatMap((x, i) => (i === 0 ? x : [", ", x])) 94 + ) : ( 95 + // artist defined by default because 96 + // i cant be bothered to do client error handling 97 + // and this is easier 98 + <a href="#">Artist Name</a> 99 + ) 100 } 101 </span> 102 <img ··· 252 253 animation: 30s linear forwards infinite spin; 254 255 + [data-playing="false"] & { 256 + animation-play-state: paused; 257 + } 258 + 259 & .art { 260 position: absolute; 261 top: calc((50 / 3) * 1cqw); ··· 280 height: calc((60 / 3) * 1cqw); 281 282 animation: 60s linear 2.5s infinite forwards head-move; 283 + 284 + [data-playing="false"] & { 285 + animation-play-state: paused; 286 + } 287 288 &.hidden { 289 background: none; ··· 518 let lastValidArtist = elIs( 519 this.elements.artists.children[0], 520 HTMLElement, 521 + "artist", 522 ); 523 replaceArtists.forEach((artist, i) => { 524 // if this index exists in both arrays, update in place ··· 571 spinner: Array.from(querySelectorAll(".player .spinner", HTMLDivElement)), 572 recordArt: querySelector(".record .art", HTMLImageElement), 573 nowPlaying: querySelector("now-playing", HTMLNowPlayingElement), 574 + player: querySelector(".player", HTMLElement), 575 }; 576 577 if (elements.spinner.length !== 2) ··· 618 iterations: Infinity, 619 }), 620 ); 621 + 622 + if (elements.player.dataset.playing === "false") { 623 + // dont play animations 624 + animations.forEach((anim) => anim.pause()); 625 + } 626 627 /************ 628 * LISTENER * ··· 666 // 1. pause current animation. 667 animations.forEach((anim) => anim.pause()); 668 elements.spinner.forEach((el) => 669 + // 2. send the playback head to the start 670 el 671 .animate(goToStartAnimation, { 672 duration: 2.5 * 1000, 673 easing: "ease-in-out", 674 }) 675 // 3. when the playback head is at the start 676 + .finished.then(async () => { 677 // 4. update the record art 678 elements.recordArt.src = data 679 ? data?.album.images[0].url 680 : "https://undefined"; 681 682 + // 5. reset the position of the infinite animation 683 animations.forEach((anim) => (anim.currentTime = 0)); 684 685 + // 6. if new track is not null then, after 2s 686 + if (data) 687 + setTimeout(() => { 688 + // 7. resume the infinite animation 689 + animations.forEach((anim) => anim.play()); 690 + }, 2000); 691 + 692 + // 8. make sure the record is in the right state (playing or paused) 693 + elements.player.dataset.playing = data ? "true" : "false"; 694 }), 695 ); 696 }