improved artist ui
This commit is contained in:
@@ -74,52 +74,6 @@ body {
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Playlist Header */
|
||||
#playlist-header {
|
||||
display: flex;
|
||||
gap: 20px;
|
||||
margin-bottom: 2rem;
|
||||
align-items: center;
|
||||
padding-bottom: 1.5rem;
|
||||
border-bottom: 1px solid #2a2a2a;
|
||||
flex-wrap: wrap;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
|
||||
#playlist-image {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
object-fit: cover;
|
||||
border-radius: 8px;
|
||||
flex-shrink: 0;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
#playlist-image:hover {
|
||||
transform: scale(1.02);
|
||||
}
|
||||
|
||||
#playlist-info {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
#playlist-name {
|
||||
font-size: 2.5rem;
|
||||
margin-bottom: 0.5rem;
|
||||
background: linear-gradient(90deg, #1db954, #17a44b);
|
||||
-webkit-background-clip: text;
|
||||
-webkit-text-fill-color: transparent;
|
||||
}
|
||||
|
||||
#playlist-owner,
|
||||
#playlist-stats,
|
||||
#playlist-description {
|
||||
font-size: 1.1rem;
|
||||
color: #b3b3b3;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
/* Tracks Container */
|
||||
#tracks-container {
|
||||
margin-top: 2rem;
|
||||
@@ -182,17 +136,6 @@ body {
|
||||
color: #b3b3b3;
|
||||
}
|
||||
|
||||
.track-album {
|
||||
max-width: 200px;
|
||||
font-size: 0.9rem;
|
||||
color: #b3b3b3;
|
||||
margin-left: 1rem;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.track-duration {
|
||||
width: 60px;
|
||||
text-align: right;
|
||||
@@ -244,27 +187,37 @@ body {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* Circular Variant for Compact Areas (e.g., in a queue list) */
|
||||
/* Circular Variant for Compact Areas */
|
||||
.download-btn--circle {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
padding: 0;
|
||||
border-radius: 50%;
|
||||
font-size: 0;
|
||||
}
|
||||
|
||||
.download-btn--circle::before {
|
||||
content: "↓";
|
||||
font-size: 16px;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Icon next to text */
|
||||
.download-btn .btn-icon {
|
||||
margin-right: 0.5rem;
|
||||
font-size: 0; /* Hide any text */
|
||||
background-color: #1db954;
|
||||
border: none;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
cursor: pointer;
|
||||
transition: background-color 0.2s ease, transform 0.2s ease;
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
.download-btn--circle img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
filter: brightness(0) invert(1);
|
||||
display: block;
|
||||
}
|
||||
|
||||
.download-btn--circle:hover {
|
||||
background-color: #17a44b;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.download-btn--circle:active {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* Home Button Styling */
|
||||
@@ -279,7 +232,7 @@ body {
|
||||
.home-btn img {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
filter: invert(1); /* Makes the SVG icon appear white */
|
||||
filter: invert(1);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
@@ -291,11 +244,8 @@ body {
|
||||
transform: scale(0.98);
|
||||
}
|
||||
|
||||
/* Download Queue Toggle Button */
|
||||
/* Queue Toggle Button */
|
||||
.queue-toggle {
|
||||
position: fixed;
|
||||
bottom: 20px;
|
||||
right: 20px;
|
||||
background: #1db954;
|
||||
color: #fff;
|
||||
border: none;
|
||||
@@ -308,125 +258,130 @@ body {
|
||||
box-shadow: 0 2px 8px rgba(0,0,0,0.3);
|
||||
transition: background-color 0.3s ease, transform 0.2s ease;
|
||||
z-index: 1002;
|
||||
/* Remove any fixed positioning by default for mobile; fixed positioning remains for larger screens */
|
||||
}
|
||||
|
||||
.queue-toggle:hover {
|
||||
background: #1ed760;
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
.queue-toggle:active {
|
||||
transform: scale(1);
|
||||
/* Actions Container for Small Screens */
|
||||
#album-actions {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
/* Responsive Styles */
|
||||
|
||||
/* Medium Devices (Tablets) */
|
||||
@media (max-width: 768px) {
|
||||
#album-header, #playlist-header {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
#album-header {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
#album-image, #playlist-image {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
margin-bottom: 1rem;
|
||||
#album-image {
|
||||
width: 180px;
|
||||
height: 180px;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
#album-name, #playlist-name {
|
||||
font-size: 2rem;
|
||||
#album-name {
|
||||
font-size: 2rem;
|
||||
}
|
||||
|
||||
#album-artist,
|
||||
#album-stats,
|
||||
#playlist-owner,
|
||||
#playlist-stats,
|
||||
#playlist-description {
|
||||
font-size: 1rem;
|
||||
#album-stats {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.track {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.track-album,
|
||||
|
||||
.track-duration {
|
||||
margin-left: 0;
|
||||
margin-top: 0.5rem;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
margin-left: 0;
|
||||
margin-top: 0.5rem;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
}
|
||||
|
||||
/* Small Devices (Mobile Phones) */
|
||||
@media (max-width: 480px) {
|
||||
#app {
|
||||
padding: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
#album-name, #playlist-name {
|
||||
font-size: 1.75rem;
|
||||
|
||||
#album-header {
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
/* Center the album cover */
|
||||
#album-image {
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
#album-name {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
#album-artist,
|
||||
#album-stats,
|
||||
#album-copyright,
|
||||
#playlist-owner,
|
||||
#playlist-stats,
|
||||
#playlist-description {
|
||||
font-size: 0.9rem;
|
||||
#album-copyright {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
|
||||
|
||||
.track {
|
||||
padding: 0.8rem;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
padding: 0.8rem;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
|
||||
.track-number {
|
||||
font-size: 0.9rem;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: 0.9rem;
|
||||
margin-right: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.track-info {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.track-album,
|
||||
|
||||
.track-duration {
|
||||
margin-left: 0;
|
||||
margin-top: 0.5rem;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
margin-left: 0;
|
||||
margin-top: 0.5rem;
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Ensure the actions container lays out buttons properly */
|
||||
#album-actions {
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
/* Remove extra margins from the queue toggle */
|
||||
.queue-toggle {
|
||||
position: static;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prevent anchor links from appearing all blue */
|
||||
a {
|
||||
color: inherit; /* Inherit color from the parent */
|
||||
text-decoration: none; /* Remove default underline */
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
transition: color 0.2s ease;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
a:focus {
|
||||
color: #1db954; /* Change to a themed green on hover/focus */
|
||||
color: #1db954;
|
||||
text-decoration: underline;
|
||||
}
|
||||
/* Override the default pseudo-element for the circular download button */
|
||||
|
||||
/* (Optional) Override for circular download button pseudo-element */
|
||||
.download-btn--circle::before {
|
||||
content: none;
|
||||
}
|
||||
|
||||
/* Style the icon inside the circular download button */
|
||||
.download-btn--circle img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
filter: brightness(0) invert(1); /* ensures the icon appears white */
|
||||
display: block;
|
||||
}
|
||||
|
||||
@@ -98,7 +98,49 @@ body {
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
/* Track Card (for Albums) */
|
||||
/* Unified Album Card (Desktop & Mobile) */
|
||||
.album-card {
|
||||
background: #181818;
|
||||
border-radius: 8px;
|
||||
overflow: hidden;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
|
||||
transition: transform 0.2s ease, box-shadow 0.2s ease;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
.album-card:hover {
|
||||
transform: translateY(-5px);
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.3);
|
||||
}
|
||||
|
||||
/* Album Cover Image */
|
||||
.album-cover {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
object-fit: cover;
|
||||
border-radius: 4px;
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
/* Album Info */
|
||||
.album-info {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.album-title {
|
||||
font-size: 1rem;
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.25rem;
|
||||
}
|
||||
|
||||
.album-artist {
|
||||
font-size: 0.9rem;
|
||||
color: #b3b3b3;
|
||||
}
|
||||
|
||||
/* Track Card (for Albums or Songs) */
|
||||
.track {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
@@ -221,7 +263,6 @@ body {
|
||||
margin: 0.5rem;
|
||||
}
|
||||
|
||||
/* Image inside circular download button */
|
||||
.download-btn--circle img {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
@@ -302,7 +343,6 @@ body {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
|
||||
/* Adjust album card layout */
|
||||
.track {
|
||||
padding: 0.8rem;
|
||||
flex-direction: column;
|
||||
@@ -327,6 +367,38 @@ body {
|
||||
width: 100%;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
/* Mobile Album Grid Styles Inspired by Spotify */
|
||||
.albums-list {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 1rem;
|
||||
}
|
||||
|
||||
/* Adjust album card for mobile grid */
|
||||
.album-card {
|
||||
flex-direction: column;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.album-cover {
|
||||
width: 100%;
|
||||
aspect-ratio: 1 / 1;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.album-info {
|
||||
padding: 0.5rem;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.album-title {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.album-artist {
|
||||
font-size: 0.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
/* Prevent anchor links from appearing blue */
|
||||
|
||||
@@ -29,18 +29,16 @@ document.addEventListener('DOMContentLoaded', () => {
|
||||
});
|
||||
|
||||
function renderAlbum(album) {
|
||||
// Hide loading and error messages.
|
||||
document.getElementById('loading').classList.add('hidden');
|
||||
document.getElementById('error').classList.add('hidden');
|
||||
|
||||
const baseUrl = window.location.origin;
|
||||
|
||||
// Album header info with embedded links
|
||||
|
||||
// Album name becomes a link to the album page.
|
||||
// Set album header info.
|
||||
document.getElementById('album-name').innerHTML =
|
||||
`<a href="${baseUrl}/album/${album.id}">${album.name}</a>`;
|
||||
|
||||
// Album artists become links to their artist pages.
|
||||
document.getElementById('album-artist').innerHTML =
|
||||
`By ${album.artists.map(artist => `<a href="${baseUrl}/artist/${artist.id}">${artist.name}</a>`).join(', ')}`;
|
||||
|
||||
@@ -54,19 +52,19 @@ function renderAlbum(album) {
|
||||
const image = album.images[0]?.url || 'placeholder.jpg';
|
||||
document.getElementById('album-image').src = image;
|
||||
|
||||
// Home Button using SVG icon
|
||||
// Create (if needed) the Home Button.
|
||||
let homeButton = document.getElementById('homeButton');
|
||||
if (!homeButton) {
|
||||
homeButton = document.createElement('button');
|
||||
homeButton.id = 'homeButton';
|
||||
homeButton.className = 'home-btn';
|
||||
|
||||
// Create an image element for the home icon.
|
||||
const homeIcon = document.createElement('img');
|
||||
homeIcon.src = '/static/images/home.svg';
|
||||
homeIcon.alt = 'Home';
|
||||
homeButton.appendChild(homeIcon);
|
||||
|
||||
// Insert as first child of album-header.
|
||||
const headerContainer = document.getElementById('album-header');
|
||||
headerContainer.insertBefore(homeButton, headerContainer.firstChild);
|
||||
}
|
||||
@@ -74,7 +72,7 @@ function renderAlbum(album) {
|
||||
window.location.href = window.location.origin;
|
||||
});
|
||||
|
||||
// Download Album Button
|
||||
// Create (if needed) the Download Album Button.
|
||||
let downloadAlbumBtn = document.getElementById('downloadAlbumBtn');
|
||||
if (!downloadAlbumBtn) {
|
||||
downloadAlbumBtn = document.createElement('button');
|
||||
@@ -85,6 +83,7 @@ function renderAlbum(album) {
|
||||
}
|
||||
|
||||
downloadAlbumBtn.addEventListener('click', () => {
|
||||
// Remove any other download buttons (keeping the full-album button in place).
|
||||
document.querySelectorAll('.download-btn').forEach(btn => {
|
||||
if (btn.id !== 'downloadAlbumBtn') btn.remove();
|
||||
});
|
||||
@@ -92,15 +91,17 @@ function renderAlbum(album) {
|
||||
downloadAlbumBtn.disabled = true;
|
||||
downloadAlbumBtn.textContent = 'Queueing...';
|
||||
|
||||
downloadWholeAlbum(album).then(() => {
|
||||
downloadAlbumBtn.textContent = 'Queued!';
|
||||
}).catch(err => {
|
||||
showError('Failed to queue album download: ' + err.message);
|
||||
downloadAlbumBtn.disabled = false;
|
||||
});
|
||||
downloadWholeAlbum(album)
|
||||
.then(() => {
|
||||
downloadAlbumBtn.textContent = 'Queued!';
|
||||
})
|
||||
.catch(err => {
|
||||
showError('Failed to queue album download: ' + err.message);
|
||||
downloadAlbumBtn.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
// Render tracks
|
||||
// Render each track.
|
||||
const tracksList = document.getElementById('tracks-list');
|
||||
tracksList.innerHTML = '';
|
||||
|
||||
@@ -108,36 +109,54 @@ function renderAlbum(album) {
|
||||
const trackElement = document.createElement('div');
|
||||
trackElement.className = 'track';
|
||||
trackElement.innerHTML = `
|
||||
<div class="track-number">${index + 1}</div>
|
||||
<div class="track-info">
|
||||
<div class="track-name">
|
||||
<a href="${baseUrl}/track/${track.id}">${track.name}</a>
|
||||
<div class="track-number">${index + 1}</div>
|
||||
<div class="track-info">
|
||||
<div class="track-name">
|
||||
<a href="${baseUrl}/track/${track.id}">${track.name}</a>
|
||||
</div>
|
||||
<div class="track-artist">
|
||||
${track.artists.map(a => `<a href="${baseUrl}/artist/${a.id}">${a.name}</a>`).join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
<div class="track-artist">
|
||||
${track.artists.map(a => `<a href="${baseUrl}/artist/${a.id}">${a.name}</a>`).join(', ')}
|
||||
</div>
|
||||
</div>
|
||||
<div class="track-duration">${msToTime(track.duration_ms)}</div>
|
||||
<button class="download-btn download-btn--circle"
|
||||
data-url="${track.external_urls.spotify}"
|
||||
data-type="track"
|
||||
data-name="${track.name}"
|
||||
title="Download">
|
||||
<img src="/static/images/download.svg" alt="Download">
|
||||
</button>
|
||||
`;
|
||||
|
||||
<div class="track-duration">${msToTime(track.duration_ms)}</div>
|
||||
<button class="download-btn download-btn--circle"
|
||||
data-url="${track.external_urls.spotify}"
|
||||
data-type="track"
|
||||
data-name="${track.name}"
|
||||
title="Download">
|
||||
<img src="/static/images/download.svg" alt="Download">
|
||||
</button>
|
||||
`;
|
||||
tracksList.appendChild(trackElement);
|
||||
});
|
||||
|
||||
// Reveal header and track list.
|
||||
document.getElementById('album-header').classList.remove('hidden');
|
||||
document.getElementById('tracks-container').classList.remove('hidden');
|
||||
attachDownloadListeners();
|
||||
|
||||
// If on a small screen, re-arrange the action buttons.
|
||||
if (window.innerWidth <= 480) {
|
||||
let actionsContainer = document.getElementById('album-actions');
|
||||
if (!actionsContainer) {
|
||||
actionsContainer = document.createElement('div');
|
||||
actionsContainer.id = 'album-actions';
|
||||
document.getElementById('album-header').appendChild(actionsContainer);
|
||||
}
|
||||
// Append in the desired order: Home, Download, then Queue Toggle (if exists).
|
||||
actionsContainer.innerHTML = ''; // Clear any previous content
|
||||
actionsContainer.appendChild(document.getElementById('homeButton'));
|
||||
actionsContainer.appendChild(document.getElementById('downloadAlbumBtn'));
|
||||
const queueToggle = document.querySelector('.queue-toggle');
|
||||
if (queueToggle) {
|
||||
actionsContainer.appendChild(queueToggle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadWholeAlbum(album) {
|
||||
const url = album.external_urls.spotify;
|
||||
startDownload(url, 'album', { name: album.name });
|
||||
return startDownload(url, 'album', { name: album.name });
|
||||
}
|
||||
|
||||
function msToTime(duration) {
|
||||
@@ -160,19 +179,14 @@ function attachDownloadListeners() {
|
||||
const url = e.currentTarget.dataset.url;
|
||||
const type = e.currentTarget.dataset.type;
|
||||
const name = e.currentTarget.dataset.name || extractName(url);
|
||||
const albumType = e.currentTarget.dataset.albumType;
|
||||
|
||||
// Remove the button after click
|
||||
// Remove the button immediately after click.
|
||||
e.currentTarget.remove();
|
||||
|
||||
// Start the download for this track.
|
||||
startDownload(url, type, { name }, albumType);
|
||||
startDownload(url, type, { name });
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function startDownload(url, type, item, albumType) {
|
||||
// Retrieve configuration (if any) from localStorage
|
||||
const config = JSON.parse(localStorage.getItem('activeConfig')) || {};
|
||||
const {
|
||||
fallback = false,
|
||||
@@ -186,17 +200,14 @@ async function startDownload(url, type, item, albumType) {
|
||||
const service = url.includes('open.spotify.com') ? 'spotify' : 'deezer';
|
||||
let apiUrl = '';
|
||||
|
||||
// Build API URL based on the download type.
|
||||
if (type === 'album') {
|
||||
apiUrl = `/api/album/download?service=${service}&url=${encodeURIComponent(url)}`;
|
||||
} else if (type === 'artist') {
|
||||
apiUrl = `/api/artist/download?service=${service}&artist_url=${encodeURIComponent(url)}&album_type=${encodeURIComponent(albumType || 'album,single,compilation')}`;
|
||||
} else {
|
||||
// Default is track download.
|
||||
apiUrl = `/api/${type}/download?service=${service}&url=${encodeURIComponent(url)}`;
|
||||
}
|
||||
|
||||
// Append account and quality details.
|
||||
if (fallback && service === 'spotify') {
|
||||
apiUrl += `&main=${deezer}&fallback=${spotify}`;
|
||||
apiUrl += `&quality=${deezerQuality}&fall_quality=${spotifyQuality}`;
|
||||
@@ -212,9 +223,12 @@ async function startDownload(url, type, item, albumType) {
|
||||
try {
|
||||
const response = await fetch(apiUrl);
|
||||
const data = await response.json();
|
||||
// Add the download to the queue using the working queue implementation.
|
||||
downloadQueue.addDownload(item, type, data.prg_file);
|
||||
} catch (error) {
|
||||
showError('Download failed: ' + error.message);
|
||||
}
|
||||
}
|
||||
|
||||
function extractName(url) {
|
||||
return url;
|
||||
}
|
||||
|
||||
@@ -85,12 +85,14 @@ function renderArtist(artistData, artistId) {
|
||||
downloadArtistBtn.disabled = true;
|
||||
downloadArtistBtn.textContent = 'Queueing...';
|
||||
|
||||
downloadWholeArtist(artistData).then(() => {
|
||||
downloadArtistBtn.textContent = 'Queued!';
|
||||
}).catch(err => {
|
||||
showError('Failed to queue artist download: ' + err.message);
|
||||
downloadArtistBtn.disabled = false;
|
||||
});
|
||||
downloadWholeArtist(artistData)
|
||||
.then(() => {
|
||||
downloadArtistBtn.textContent = 'Queued!';
|
||||
})
|
||||
.catch(err => {
|
||||
showError('Failed to queue artist download: ' + err.message);
|
||||
downloadArtistBtn.disabled = false;
|
||||
});
|
||||
});
|
||||
|
||||
// Group albums by album type.
|
||||
@@ -128,24 +130,20 @@ function renderArtist(artistData, artistId) {
|
||||
// Container for individual albums in this group.
|
||||
const albumsContainer = document.createElement('div');
|
||||
albumsContainer.className = 'albums-list';
|
||||
albums.forEach((album, index) => {
|
||||
albums.forEach(album => {
|
||||
const albumElement = document.createElement('div');
|
||||
albumElement.className = 'track'; // reusing styling from the playlist view
|
||||
|
||||
// Use an <a> around the album image and name.
|
||||
// Build a unified album card markup that works for both desktop and mobile.
|
||||
albumElement.className = 'album-card';
|
||||
albumElement.innerHTML = `
|
||||
<div class="track-number">${index + 1}</div>
|
||||
<a href="/album/${album.id}" class="album-link">
|
||||
<img class="track-image" src="${album.images[1]?.url || album.images[0]?.url || 'placeholder.jpg'}"
|
||||
<img src="${album.images[1]?.url || album.images[0]?.url || 'placeholder.jpg'}"
|
||||
alt="Album cover"
|
||||
style="width: 64px; height: 64px; border-radius: 4px; margin-right: 1rem;">
|
||||
class="album-cover">
|
||||
</a>
|
||||
<div class="track-info">
|
||||
<a href="/album/${album.id}" class="track-name">${album.name}</a>
|
||||
<div class="track-artist"></div>
|
||||
<div class="album-info">
|
||||
<div class="album-title">${album.name}</div>
|
||||
<div class="album-artist">${album.artists.map(a => a.name).join(', ')}</div>
|
||||
</div>
|
||||
<div class="track-album">${album.release_date}</div>
|
||||
<div class="track-duration">${album.total_tracks} tracks</div>
|
||||
<button class="download-btn download-btn--circle"
|
||||
data-url="${album.external_urls.spotify}"
|
||||
data-type="album"
|
||||
|
||||
Reference in New Issue
Block a user