Add Docker support and implement Bun for dependency management
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m25s
Some checks failed
Build and Push Docker Image / build-and-push (push) Failing after 1m25s
- Introduced .dockerignore to exclude unnecessary files from Docker context. - Updated Dockerfile to use Bun for building and running the application. - Removed entrypoint.sh as it is no longer needed. - Modified build-and-dockerise.yml to set up Bun and install dependencies. - Enhanced index.html with improved structure and hover effects. - Updated client.ts to include tooltips for music display. - Implemented caching in server.ts for Last.fm data. - Added custom styles for hover effects and tooltips in style.css.
This commit is contained in:
parent
be5a61185b
commit
214982649f
9 changed files with 272 additions and 107 deletions
|
@ -92,9 +92,16 @@ function updateLastSongDisplay(song: LastSong | null, errorMessage?: string): vo
|
|||
return;
|
||||
}
|
||||
|
||||
const statusText = song.nowPlaying ? 'Currently listening to' : 'Last listened to';
|
||||
const statusText = song.nowPlaying ? 'Currently Listening To' : 'Last Played';
|
||||
const imageUrl = getOptimalImageUrl(song.image);
|
||||
|
||||
// Create tooltip content for music
|
||||
const tooltipContent = `
|
||||
<div class="song-name">${song.name}</div>
|
||||
<div class="artist-name">by ${song.artist}</div>
|
||||
${song.album ? `<div class="album-name">from "${song.album}"</div>` : ''}
|
||||
`;
|
||||
|
||||
const imageElement = imageUrl
|
||||
? `<img src="${imageUrl}" alt="${song.name}" class="w-24 h-24 rounded-lg object-cover mx-auto border border-white/20" loading="lazy">`
|
||||
: `<div class="w-16 h-16 rounded-lg bg-gradient-to-br from-cyan-500/20 to-purple-500/20 flex items-center justify-center mx-auto border border-white/20">
|
||||
|
@ -105,14 +112,17 @@ function updateLastSongDisplay(song: LastSong | null, errorMessage?: string): vo
|
|||
|
||||
container.innerHTML = `
|
||||
<div class="flex flex-col items-center space-y-3">
|
||||
${imageElement}
|
||||
<div class="text-center w-full">
|
||||
<p class="text-sm text-cyan-300 font-medium">${statusText}</p>
|
||||
<a href="${song.url}" target="_blank" class="block hover:text-cyan-200 transition-colors duration-200">
|
||||
<p class="font-semibold text-white">${song.name}</p>
|
||||
<p class="text-sm text-gray-300">by ${song.artist}</p>
|
||||
${song.album ? `<p class="text-xs text-white-400">from ${song.album}</p>` : ''}
|
||||
<div class="tooltip music-tooltip">
|
||||
<a href="${song.url}" target="_blank" class="block hover:text-cyan-200 transition-colors duration-200 w-36">
|
||||
${imageElement}
|
||||
<div class="text-center w-full">
|
||||
<p class="text-sm text-cyan-300 font-medium w-36">${statusText}</p>
|
||||
<div class="font-semibold text-white-900 text-ellipsis overflow-hidden whitespace-nowrap max-w-full">${song.name}</div>
|
||||
<div class="text-sm text-white-200 text-ellipsis overflow-hidden whitespace-nowrap max-w-full">${song.artist}</div>
|
||||
${song.album ? `<div class="text-xs text-white-600 text-ellipsis overflow-hidden whitespace-nowrap max-w-full">${song.album}</div>` : ''}
|
||||
</div>
|
||||
</a>
|
||||
<span class="tooltip-text">${tooltipContent}</span>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
|
|
|
@ -1,6 +1,35 @@
|
|||
import { Elysia, t } from 'elysia';
|
||||
import { staticPlugin } from '@elysiajs/static';
|
||||
|
||||
// Simple cache implementation
|
||||
interface CacheEntry {
|
||||
data: any;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
const cache = new Map<string, CacheEntry>();
|
||||
const CACHE_TTL = 30 * 1000; // 30 seconds in milliseconds
|
||||
|
||||
function getCachedData(key: string): any | null {
|
||||
const entry = cache.get(key);
|
||||
if (!entry) return null;
|
||||
|
||||
const now = Date.now();
|
||||
if (now - entry.timestamp > CACHE_TTL) {
|
||||
cache.delete(key);
|
||||
return null;
|
||||
}
|
||||
|
||||
return entry.data;
|
||||
}
|
||||
|
||||
function setCachedData(key: string, data: any): void {
|
||||
cache.set(key, {
|
||||
data,
|
||||
timestamp: Date.now()
|
||||
});
|
||||
}
|
||||
|
||||
const app = new Elysia()
|
||||
.use(staticPlugin({
|
||||
assets: 'dist',
|
||||
|
@ -17,13 +46,22 @@ const app = new Elysia()
|
|||
);
|
||||
}
|
||||
|
||||
// Check cache first
|
||||
const cacheKey = `lastfm:${username}`;
|
||||
const cachedData = getCachedData(cacheKey);
|
||||
if (cachedData) {
|
||||
console.log('Returning cached Last.fm data');
|
||||
return cachedData;
|
||||
}
|
||||
|
||||
const url = `https://ws.audioscrobbler.com/2.0/?method=user.getrecenttracks&user=${username}&api_key=${apiKey}&format=json&limit=1`;
|
||||
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
const data = await response.json();
|
||||
const track = data.recenttracks.track[0];
|
||||
return {
|
||||
|
||||
const result = {
|
||||
name: track.name,
|
||||
artist: track.artist['#text'],
|
||||
album: track.album['#text'],
|
||||
|
@ -31,6 +69,12 @@ const app = new Elysia()
|
|||
nowPlaying: track['@attr']?.nowplaying === 'true',
|
||||
image: track.image || [],
|
||||
};
|
||||
|
||||
// Cache the result
|
||||
setCachedData(cacheKey, result);
|
||||
console.log('Fetched and cached new Last.fm data');
|
||||
|
||||
return result;
|
||||
} catch (error) {
|
||||
console.error('Error fetching from Last.fm:', error);
|
||||
return new Response(JSON.stringify({ error: 'Failed to fetch last song' }), {
|
||||
|
@ -39,7 +83,10 @@ const app = new Elysia()
|
|||
});
|
||||
}
|
||||
})
|
||||
.listen(3000);
|
||||
.listen({
|
||||
port: process.env.PORT || 3000,
|
||||
hostname: process.env.NODE_ENV === 'production' ? '0.0.0.0' : 'localhost'
|
||||
});
|
||||
|
||||
console.log(
|
||||
`🦊 Elysia is running at http://${app.server?.hostname}:${app.server?.port}`
|
||||
|
|
|
@ -78,14 +78,16 @@ body {
|
|||
}
|
||||
}
|
||||
|
||||
/* Custom styling for skill tags and buttons */
|
||||
.skill-tag {
|
||||
/* Custom styling for hoverable elements */
|
||||
.hover-glass {
|
||||
background: rgba(255, 255, 255, 0.15);
|
||||
transition: background 0.3s ease, transform 0.3s ease;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0);
|
||||
transition: background 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease, color 0.3s ease;
|
||||
}
|
||||
|
||||
.skill-tag:hover {
|
||||
.hover-glass:hover {
|
||||
background: rgba(255, 255, 255, 0.3);
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.2);
|
||||
transform: translateY(-2px);
|
||||
}
|
||||
|
||||
|
@ -109,4 +111,67 @@ body {
|
|||
100% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
|
||||
/* Tooltip styles */
|
||||
.tooltip {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.tooltip .tooltip-text {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
width: max-content;
|
||||
max-width: 200px;
|
||||
background: rgba(43, 85, 131, 0.9);
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
border-radius: 8px;
|
||||
padding: 8px 12px;
|
||||
position: absolute;
|
||||
z-index: 1000;
|
||||
bottom: -25%;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
white-space: nowrap;
|
||||
backdrop-filter: blur(10px);
|
||||
-webkit-backdrop-filter: blur(10px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.3);
|
||||
transition: opacity 0.3s ease, visibility 0.3s ease, transform 0.3s ease;
|
||||
}
|
||||
|
||||
.tooltip:hover .tooltip-text {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
transform: translateX(-50%) translateY(-5px);
|
||||
}
|
||||
|
||||
/* Music tooltip specific styling */
|
||||
.music-tooltip .tooltip-text {
|
||||
white-space: normal;
|
||||
text-align: left;
|
||||
max-width: 250px;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.music-tooltip .tooltip-text .song-name {
|
||||
font-weight: 600;
|
||||
color: #4dd0e1;
|
||||
margin-bottom: 2px;
|
||||
}
|
||||
|
||||
.music-tooltip .tooltip-text .artist-name {
|
||||
font-weight: 500;
|
||||
color: #e2e8f0;
|
||||
margin-bottom: 1px;
|
||||
}
|
||||
|
||||
.music-tooltip .tooltip-text .album-name {
|
||||
font-weight: 400;
|
||||
color: #cbd5e0;
|
||||
font-size: 12px;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue