website/src/components/windows/main/SpotifyCard.astro
2025-04-21 06:42:14 -05:00

194 lines
No EOL
4.2 KiB
Text

---
import LastFMIcon from "@assets/svg/fm.svg"
---
<div class="spotify-card-wrapper-shadow">
<h4>I'm listening to</h4>
<div class="spotify-card-wrapper">
<div class="spotify-card">
<svg aria-hidden="true" class="blur">
<filter id='sharpBlur' color-interpolation-filters="sRGB">
<feGaussianBlur stdDeviation='100'></feGaussianBlur>
<feColorMatrix type='matrix' values='1 0 0 0 0, 0 1 0 0 0, 0 0 1 0 0, 0 0 0 9 0'></feColorMatrix>
<feComposite in2='SourceGraphic' operator='in'></feComposite>
</filter>
</svg>
<div class="spotify-card-background"></div>
<div class="spotify-card-art-shadow">
<div class="spotify-card-art"></div>
</div>
<div class="spotfiy-card-track-info">
<div class="spotify-card-track-name"></div>
<div class="spotify-card-track-artist"></div>
<div class="spotify-card-track-album"></div>
</div>
<div class="links">
<a class="lastfm-link" href="https://www.last.fm/user/nin0dev"><LastFMIcon /></a>
</div>
</div>
</div>
</div>
<style>
h4 {
color: var(--subtext0);
margin-bottom: 10px;
}
.blur {
display: none;
}
.spotify-card-wrapper-shadow {
display: none;
filter: drop-shadow(0 0 5px #00000040);
}
.spotify-card-wrapper {
position: relative;
display: flex;
background: var(--album-color);
clip-path: var(--clip-sp-1);
}
.spotify-card {
display: flex;
flex: 1;
gap: 12px;
padding: 15px;
align-items: center;
clip-path: var(--clip-sp-2);
}
.spotify-card-background {
position: absolute;
left: 0;
top: 0;
width: 105%;
height: 105%;
background: var(--album-art);
background-size: 100% 100%;
filter: url("#sharpBlur") brightness(0.75);
z-index: -1;
}
.spotify-card-art-shadow {
filter: drop-shadow(0 0 5px #00000040);
}
.spotify-card-art-wrapper {
clip-path: var(--clip-sp-art-wrapper);
background: var(--album-color);
}
.spotify-card-art {
background-image: var(--album-art);
background-size: 100%;
width: 4rem;
height: 4rem;
clip-path: var(--clip-sp-art);
}
.spotfiy-card-track-info {
display: flex;
flex-direction: column;
line-height: 1;
}
.spotify-card-track-name {
margin-bottom: 5px;
}
.spotify-card-track-name::after {
content: var(--track);
font-weight: 500;
font-size: 1.05rem;
color: #ffffffd5;
filter: drop-shadow(0 0 5px #0000006d);
}
.spotify-card-track-artist::after, .spotify-card-track-album::after {
color: #ffffffa1;
font-weight: 500;
font-size: 0.85rem;
filter: drop-shadow(0 0 5px #00000040);
}
.spotify-card-track-artist::after {
content: var(--artist);
}
.spotify-card-track-album::after {
content: var(--album);
}
.links {
position: absolute;
bottom: 0;
right: 0;
margin: 10px;
display: flex;
gap: 7px;
}
.links a {
color: rgba(255, 255, 255, 0.516);
text-decoration: none;
}
</style>
<script>
import { mergeStyles } from "utils/mergeStyles";
import { average } from "color.js";
import { LASTFM_KEY, LASTFM_API, LASTFM_USER } from "utils/constants";
import {
type FMResponse,
type FMRawTrack,
type FMTrack,
transformRawTrack
} from "types/lastfm";
const spotifyCardWrapper: HTMLElement = document.querySelector(".spotify-card-wrapper-shadow");
async function getLastFmTracks() {
const params = new URLSearchParams({
method: "user.getrecenttracks",
api_key: LASTFM_KEY,
user: LASTFM_USER,
limit: "50",
format: "json",
extended: "true"
});
const response: FMResponse = await(
await fetch(`${LASTFM_API}${params}`)
).json();
if (
response.recenttracks.track.some(t => {
try {
return t["@attr"].nowplaying === "true";
} catch (e) {
return false;
}
})
) {
const rawTrack: FMRawTrack = response.recenttracks.track[0];
const track: FMTrack = transformRawTrack(rawTrack);
mergeStyles({
"display": "block",
"--track": `'${track.name}'`,
"--artist": `'${track.artist}'`,
"--album": `'${track.album}'`,
"--album-art": `url("${track.albumArt}")`,
"--album-color": await average(
track.albumArt,
{ format: "hex" }
)
}, spotifyCardWrapper.style);
(document.querySelector(".lastfm-link") as HTMLLinkElement).href = track.url;
}
}
getLastFmTracks();
setInterval(getLastFmTracks, 10000);
</script>