feat: create a lastfm widget instead of the text

This commit is contained in:
Kentai Radiquum 2025-01-10 20:18:55 +05:00
parent d453c1f57e
commit 986b26576d
Signed by: Radiquum
GPG key ID: 858E8EE696525EED
7 changed files with 159 additions and 71 deletions

View file

@ -98,12 +98,23 @@
class="inline sm:hidden">.</span></a>
</div>
<p
class="flex flex-col flex-wrap items-center justify-center order-4 gap-2 px-2 text-2xl text-white sm:flex-row md:order-3">
<span data-i18n="QUICK_BIO_LASTFM">Now listening to:</span> <a class="text-bg-pink hover:underline"
href="https://last.fm/user/radiquum" id="track-name" target="_blank" referrerpolicy="origin">LOADING . .
.</a>
</p>
<div class="relative order-4 h-24 md:order-3 min-w-[372px] max-w-[512px] mx-auto">
<img id="lastfm_image" src="https://lastfm.freetls.fastly.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png" alt="" class="absolute object-cover inset-0 w-full max-h-[calc(100%+16px)] md:-z-10" />
<div class="flex gap-4 p-2 text-white bg-black bg-opacity-75 backdrop-blur-md">
<img id="lastfm_image" src="https://lastfm.freetls.fastly.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png" alt="" class="w-24 h-24" />
<div>
<a id="lastfm_songlink" class="block">
<span class="flex items-center justify-start gap-1 -ml-1"><img src="./static/material-symbols--pause.svg" alt="Paused" class="h-6 invert" id="lastfm_state" /><p id="lastfm_title" class="overflow-hidden text-xl truncate text-nowrap whitespace-nowrap">Loading...</p></span>
<p id="lastfm_artist" class="overflow-hidden text-sm truncate text-nowrap whitespace-nowrap"></p>
<p id="lastfm_album" class="overflow-hidden text-sm truncate text-nowrap whitespace-nowrap"></p>
</a>
<a href="https://www.last.fm/user/Radiquum" class="flex items-center gap-2 mt-2 text-white">
<img src="./static/fa6-brands--lastfm.svg" alt="" class="w-6 h-6 invert"/>
<span data-i18n="QUICK_BIO_LASTFM">My profile</span>
</a>
</div>
</div>
</div>
<div
class="flex flex-row flex-wrap items-center justify-center order-3 gap-8 py-4 -mt-4 text-white md:mt-auto md:order-4">

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="0 0 512 512"><path fill="currentColor" d="m225.8 367.1l-18.8-51s-30.5 34-76.2 34c-40.5 0-69.2-35.2-69.2-91.5c0-72.1 36.4-97.9 72.1-97.9c66.5 0 74.8 53.3 100.9 134.9c18.8 56.9 54 102.6 155.4 102.6c72.7 0 122-22.3 122-80.9c0-72.9-62.7-80.6-115-92.1c-25.8-5.9-33.4-16.4-33.4-34c0-19.9 15.8-31.7 41.6-31.7c28.2 0 43.4 10.6 45.7 35.8l58.6-7c-4.7-52.8-41.1-74.5-100.9-74.5c-52.8 0-104.4 19.9-104.4 83.9c0 39.9 19.4 65.1 68 76.8c44.9 10.6 79.8 13.8 79.8 45.7c0 21.7-21.1 30.5-61 30.5c-59.2 0-83.9-31.1-97.9-73.9c-32-96.8-43.6-163-161.3-163C45.7 113.8 0 168.3 0 261c0 89.1 45.7 137.2 127.9 137.2c66.2 0 97.9-31.1 97.9-31.1"/></svg>

After

(image error) Size: 697 B

View file

@ -8,7 +8,7 @@ const i18n_ru = {
QUICK_BIO_CODER: "Программист",
QUICK_BIO_PHOTOGRAPHER: "Фотограф",
QUICK_BIO_ENTHUSIAST: "Селф-Хостинг Энтузиаст",
QUICK_BIO_LASTFM: "Сейчас слушает: ",
QUICK_BIO_LASTFM: "Мой профиль",
// BUTTONS
BTN_ABOUT_ME: "ОБО МНЕ",

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M14 19V5h4v14zm-8 0V5h4v14z"/></svg>

After

(image error) Size: 148 B

View file

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24"><path fill="currentColor" d="M8 19V5l11 7z"/></svg>

After

(image error) Size: 134 B

View file

@ -1,6 +1,5 @@
// Animation durations in ms
const SONG_CHANGE_DELAY = 180000;
const SYMBOL_DELAY = 150;
const IMAGE_CHANGE_DELAY = 6000;
const ARTS_CHANGE_DELAY = 6500;
@ -10,59 +9,14 @@ const IMAGE_TRANSITION_DELAY = 1000;
// Header percentages
const HEADER_ACTIVATION_PERCENT = 0.8;
// THIS IS NOT CONSTANTS, BUT A GLOBAL VAR FOR TIMERS IN SONG NAME CHANGE!!!
let DELETE_INTERVAL = null;
let UPDATE_INTERVAL = null;
function deletePreviousTrack(newTrackName) {
const trackName = document.getElementById("track-name");
const prevTrackNameLen = trackName.innerHTML.length;
trackName.style.setProperty("--cursor-animation", "none");
clearInterval(DELETE_INTERVAL);
clearInterval(UPDATE_INTERVAL);
let removed = 0;
DELETE_INTERVAL = setInterval(() => {
removed += 1;
trackName.innerHTML = trackName.innerHTML.substring(
0,
prevTrackNameLen - removed
);
if (removed == prevTrackNameLen) {
clearInterval(DELETE_INTERVAL);
updateTrack(newTrackName);
return true;
}
}, SYMBOL_DELAY);
}
function updateTrack(newTrackName) {
const trackName = document.getElementById("track-name");
const TrackNameLen = newTrackName.length;
clearInterval(DELETE_INTERVAL);
clearInterval(UPDATE_INTERVAL);
let added = 0;
UPDATE_INTERVAL = setInterval(() => {
if (added < TrackNameLen) {
trackName.innerHTML += newTrackName[added];
added += 1;
}
if (added == TrackNameLen) {
clearInterval(UPDATE_INTERVAL);
trackName.style.setProperty("--cursor-animation", "blink");
setTimeout(() => {
trackName.style.setProperty("--cursor-color", "transparent");
}, SYMBOL_DELAY * 3);
return true;
}
}, SYMBOL_DELAY);
}
async function updatePlayingTrack() {
const trackName = document.getElementById("track-name");
const prevTrackName = trackName.innerHTML;
const images = document.querySelectorAll("#lastfm_image");
const state = document.getElementById("lastfm_state");
const title = document.getElementById("lastfm_title");
const artist = document.getElementById("lastfm_artist");
const album = document.getElementById("lastfm_album");
const link = document.getElementById("lastfm_songlink");
fetch("https://lastfm-last-played.biancarosa.com.br/radiquum/latest-song")
.then((res) => {
@ -73,21 +27,39 @@ async function updatePlayingTrack() {
})
.then((data) => {
if (
prevTrackName != `${data.track.artist["#text"]} - ${data.track.name}`
title.innerHTML != data.track.name
) {
trackName.style.setProperty("--cursor-color", "#fff");
trackName.style.setProperty("--cursor-animation", "blink");
setTimeout(() => {
deletePreviousTrack(
`${data.track.artist["#text"]} - ${data.track.name}`
);
}, SYMBOL_DELAY * 4);
if (!data.track) throw new Error("No track is provided");
if (data.track.hasOwnProperty("image") && data.track.image.length > 0) {
images.forEach((img) => {img.src = data.track.image[data.track.image.length - 1]["#text"]});
} else {
images.forEach((img) => {img.src = "https://lastfm.freetls.fastly.net/i/u/34s/2a96cbd8b46e442fc41c2b86b821562f.png"});
}
if (data.track.hasOwnProperty("@attr") && data.track["@attr"].nowplaying) {
state.src = "./static/material-symbols--play-arrow.svg";
state.alt = "Playing";
} else {
state.src = "./static/material-symbols--pause.svg";
state.alt = "Paused";
}
if (data.track.hasOwnProperty("album")) {
album.innerHTML = data.track.album["#text"];
} else {
album.innerHTML = "";
}
if (data.track.hasOwnProperty("artist")) {
artist.innerHTML = data.track.artist["#text"];
} else {
artist.innerHTML = "";
}
title.innerHTML = data.track.name;
link.href = data.track.url
}
})
.catch((err) => {
deletePreviousTrack("ERROR: last.fm is not reachable");
console.log(err);
console.log("lastfm is unreachable:", err);
return
});
}
@ -235,7 +207,7 @@ function changeArtsSectionImage() {
window.onload = () => {
updatePlayingTrack();
setInterval(updatePlayingTrack, 180000);
setInterval(updatePlayingTrack, SONG_CHANGE_DELAY);
setPhotoSectionImagesMargin();
setInterval(changePhotoSectionImage, IMAGE_CHANGE_DELAY);
setArtsSectionImagesMargin();

View file

@ -730,6 +730,14 @@ video {
margin-top: 0.5rem;
}
.-ml-2 {
margin-left: -0.5rem;
}
.-ml-1 {
margin-left: -0.25rem;
}
.block {
display: block;
}
@ -786,6 +794,10 @@ video {
height: 170px;
}
.h-6 {
height: 1.5rem;
}
.max-h-\[182px\] {
max-height: 182px;
}
@ -794,6 +806,22 @@ video {
max-height: 50vh;
}
.max-h-\[calc\(100\%-2px\)\] {
max-height: calc(100% - 2px);
}
.max-h-\[calc\(100\%\+2px\)\] {
max-height: calc(100% + 2px);
}
.max-h-\[calc\(100\%\+8px\)\] {
max-height: calc(100% + 8px);
}
.max-h-\[calc\(100\%\+16px\)\] {
max-height: calc(100% + 16px);
}
.min-h-screen {
min-height: 100vh;
}
@ -839,10 +867,18 @@ video {
width: max-content;
}
.w-6 {
width: 1.5rem;
}
.min-w-\[170px\] {
min-width: 170px;
}
.min-w-\[372px\] {
min-width: 372px;
}
.max-w-\[50vw\] {
max-width: 50vw;
}
@ -851,6 +887,10 @@ video {
max-width: 170px;
}
.max-w-\[512px\] {
max-width: 512px;
}
.flex-1 {
flex: 1 1 0%;
}
@ -990,6 +1030,20 @@ video {
scroll-behavior: smooth;
}
.truncate {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.whitespace-nowrap {
white-space: nowrap;
}
.text-nowrap {
text-wrap: nowrap;
}
.break-words {
overflow-wrap: break-word;
}
@ -1203,6 +1257,22 @@ video {
--tw-bg-opacity: 0.5;
}
.bg-opacity-55 {
--tw-bg-opacity: 0.55;
}
.bg-opacity-25 {
--tw-bg-opacity: 0.25;
}
.bg-opacity-75 {
--tw-bg-opacity: 0.75;
}
.bg-opacity-5 {
--tw-bg-opacity: 0.05;
}
.object-contain {
-o-object-fit: contain;
object-fit: contain;
@ -1297,6 +1367,11 @@ video {
line-height: 1.75rem;
}
.text-sm {
font-size: 0.875rem;
line-height: 1.25rem;
}
.font-bold {
font-weight: 700;
}
@ -1343,10 +1418,33 @@ video {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.invert {
--tw-invert: invert(100%);
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.filter {
filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow);
}
.backdrop-blur-md {
--tw-backdrop-blur: blur(12px);
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.backdrop-blur-sm {
--tw-backdrop-blur: blur(4px);
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.backdrop-blur-lg {
--tw-backdrop-blur: blur(16px);
-webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
}
.transition-\[border-color\] {
transition-property: border-color;
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
@ -1573,6 +1671,10 @@ body {
}
@media (min-width: 768px) {
.md\:-z-10 {
z-index: -10;
}
.md\:order-3 {
order: 3;
}