progress
This commit is contained in:
parent
bb6be656e0
commit
a78732fb08
2 changed files with 381 additions and 38 deletions
|
|
@ -992,26 +992,69 @@ function displayDownloadsResults(results) {
|
||||||
|
|
||||||
if (isAlbum) {
|
if (isAlbum) {
|
||||||
const trackCount = result.tracks ? result.tracks.length : 0;
|
const trackCount = result.tracks ? result.tracks.length : 0;
|
||||||
|
const totalSize = result.total_size ? `${(result.total_size / 1024 / 1024).toFixed(1)} MB` : 'Unknown size';
|
||||||
|
|
||||||
|
// Generate individual track items
|
||||||
|
let trackListHtml = '';
|
||||||
|
if (result.tracks && result.tracks.length > 0) {
|
||||||
|
result.tracks.forEach((track, trackIndex) => {
|
||||||
|
const trackSize = track.size ? `${(track.size / 1024 / 1024).toFixed(1)} MB` : 'Unknown size';
|
||||||
|
const trackBitrate = track.bitrate ? `${track.bitrate}kbps` : '';
|
||||||
|
trackListHtml += `
|
||||||
|
<div class="track-item">
|
||||||
|
<div class="track-item-info">
|
||||||
|
<div class="track-item-title">${escapeHtml(track.title || `Track ${trackIndex + 1}`)}</div>
|
||||||
|
<div class="track-item-details">
|
||||||
|
${track.track_number ? `${track.track_number}. ` : ''}${escapeHtml(track.artist || result.artist || 'Unknown Artist')} • ${trackSize} • ${escapeHtml(track.quality || 'Unknown')} ${trackBitrate}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="track-item-actions">
|
||||||
|
<button onclick="downloadAlbumTrack(${index}, ${trackIndex})" class="track-download-btn">⬇</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
html += `
|
html += `
|
||||||
<div class="search-result-item album-result">
|
<div class="album-result-card" data-album-index="${index}">
|
||||||
<div class="result-info">
|
<div class="album-card-header" onclick="toggleAlbumExpansion(${index})">
|
||||||
<strong>🎵 ${escapeHtml(result.album_title || result.title || 'Unknown Album')}</strong><br>
|
<div class="album-expand-indicator">▶</div>
|
||||||
<span>by ${escapeHtml(result.artist || 'Unknown Artist')}</span><br>
|
<div class="album-icon">💿</div>
|
||||||
<small>${trackCount} tracks • ${escapeHtml(result.quality || 'Mixed')}</small>
|
<div class="album-info">
|
||||||
|
<div class="album-title">${escapeHtml(result.album_title || result.title || 'Unknown Album')}</div>
|
||||||
|
<div class="album-artist">by ${escapeHtml(result.artist || 'Unknown Artist')}</div>
|
||||||
|
<div class="album-details">
|
||||||
|
${trackCount} tracks • ${totalSize} • ${escapeHtml(result.quality || 'Mixed')}
|
||||||
|
</div>
|
||||||
|
<div class="album-uploader">Shared by ${escapeHtml(result.username || 'Unknown')}</div>
|
||||||
|
</div>
|
||||||
|
<div class="album-actions" onclick="event.stopPropagation()">
|
||||||
|
<button onclick="downloadAlbum(${index})" class="album-download-btn">⬇ Download Album</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="album-track-list" style="display: none;">
|
||||||
|
${trackListHtml}
|
||||||
</div>
|
</div>
|
||||||
<button onclick="downloadAlbum(${index})" class="download-btn">⬇ Download Album</button>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
const sizeText = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : 'Unknown size';
|
const sizeText = result.size ? `${(result.size / 1024 / 1024).toFixed(1)} MB` : 'Unknown size';
|
||||||
|
const bitrateText = result.bitrate ? `${result.bitrate}kbps` : '';
|
||||||
html += `
|
html += `
|
||||||
<div class="search-result-item track-result">
|
<div class="track-result-card">
|
||||||
<div class="result-info">
|
<div class="track-icon">🎵</div>
|
||||||
<strong>${escapeHtml(result.title || 'Unknown Title')}</strong><br>
|
<div class="track-info">
|
||||||
<span>by ${escapeHtml(result.artist || 'Unknown Artist')}</span><br>
|
<div class="track-title">${escapeHtml(result.title || 'Unknown Title')}</div>
|
||||||
<small>${sizeText} • ${escapeHtml(result.quality || 'Unknown')} ${result.bitrate ? `${result.bitrate}kbps` : ''}</small>
|
<div class="track-artist">by ${escapeHtml(result.artist || 'Unknown Artist')}</div>
|
||||||
|
<div class="track-details">
|
||||||
|
${sizeText} • ${escapeHtml(result.quality || 'Unknown')} ${bitrateText}
|
||||||
|
</div>
|
||||||
|
<div class="track-uploader">Shared by ${escapeHtml(result.username || 'Unknown')}</div>
|
||||||
|
</div>
|
||||||
|
<div class="track-actions">
|
||||||
|
<button onclick="downloadTrack(${index})" class="track-download-btn">⬇ Download</button>
|
||||||
</div>
|
</div>
|
||||||
<button onclick="downloadTrack(${index})" class="download-btn">⬇ Download</button>
|
|
||||||
</div>
|
</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
@ -1074,6 +1117,55 @@ async function downloadAlbum(index) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function toggleAlbumExpansion(albumIndex) {
|
||||||
|
const albumCard = document.querySelector(`[data-album-index="${albumIndex}"]`);
|
||||||
|
if (!albumCard) return;
|
||||||
|
|
||||||
|
const trackList = albumCard.querySelector('.album-track-list');
|
||||||
|
const indicator = albumCard.querySelector('.album-expand-indicator');
|
||||||
|
|
||||||
|
if (trackList.style.display === 'none' || !trackList.style.display) {
|
||||||
|
// Expand
|
||||||
|
trackList.style.display = 'block';
|
||||||
|
indicator.textContent = '▼';
|
||||||
|
albumCard.classList.add('expanded');
|
||||||
|
} else {
|
||||||
|
// Collapse
|
||||||
|
trackList.style.display = 'none';
|
||||||
|
indicator.textContent = '▶';
|
||||||
|
albumCard.classList.remove('expanded');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function downloadAlbumTrack(albumIndex, trackIndex) {
|
||||||
|
const results = window.currentSearchResults;
|
||||||
|
if (!results || !results[albumIndex] || !results[albumIndex].tracks || !results[albumIndex].tracks[trackIndex]) return;
|
||||||
|
|
||||||
|
const track = results[albumIndex].tracks[trackIndex];
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await fetch('/api/download', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({
|
||||||
|
...track,
|
||||||
|
result_type: 'track'
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.success) {
|
||||||
|
showToast(`Download started: ${track.title}`, 'success');
|
||||||
|
} else {
|
||||||
|
showToast(`Track download failed: ${data.error}`, 'error');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Track download error:', error);
|
||||||
|
showToast('Failed to start track download', 'error');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function loadArtistsData() {
|
async function loadArtistsData() {
|
||||||
try {
|
try {
|
||||||
const response = await fetch(API.artists);
|
const response = await fetch(API.artists);
|
||||||
|
|
@ -1426,3 +1518,5 @@ window.startStream = startStream;
|
||||||
window.startDownload = startDownload;
|
window.startDownload = startDownload;
|
||||||
window.downloadTrack = downloadTrack;
|
window.downloadTrack = downloadTrack;
|
||||||
window.downloadAlbum = downloadAlbum;
|
window.downloadAlbum = downloadAlbum;
|
||||||
|
window.toggleAlbumExpansion = toggleAlbumExpansion;
|
||||||
|
window.downloadAlbumTrack = downloadAlbumTrack;
|
||||||
|
|
@ -2008,34 +2008,283 @@ body {
|
||||||
animation: modalFadeIn 0.3s ease-out;
|
animation: modalFadeIn 0.3s ease-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Simple Downloads Results Styling */
|
/* GUI-Matching Search Results Styling */
|
||||||
.search-result-item {
|
|
||||||
background: rgba(255, 255, 255, 0.02);
|
/* Single Track Card (SearchResultItem) */
|
||||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
.track-result-card {
|
||||||
border-radius: 8px;
|
background: linear-gradient(to bottom,
|
||||||
padding: 12px;
|
rgba(48, 48, 52, 0.95),
|
||||||
margin-bottom: 8px;
|
rgba(38, 38, 42, 0.98));
|
||||||
|
border-radius: 18px;
|
||||||
|
border: 1px solid rgba(70, 70, 76, 0.5);
|
||||||
|
margin: 8px 4px;
|
||||||
|
padding: 16px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
}
|
gap: 16px;
|
||||||
|
|
||||||
.search-result-item .result-info {
|
|
||||||
flex: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
.search-result-item .download-btn {
|
|
||||||
background: rgba(29, 185, 84, 0.1);
|
|
||||||
color: #1ed760;
|
|
||||||
border: 1px solid rgba(29, 185, 84, 0.3);
|
|
||||||
padding: 8px 16px;
|
|
||||||
border-radius: 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
font-size: 12px;
|
|
||||||
transition: all 0.2s ease;
|
transition: all 0.2s ease;
|
||||||
}
|
}
|
||||||
|
|
||||||
.search-result-item .download-btn:hover {
|
.track-result-card:hover {
|
||||||
background: rgba(29, 185, 84, 0.2);
|
background: linear-gradient(to bottom,
|
||||||
border-color: rgba(29, 185, 84, 0.5);
|
rgba(55, 55, 60, 0.98),
|
||||||
|
rgba(45, 45, 50, 1.0));
|
||||||
|
border: 1px solid rgba(29, 185, 84, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-icon {
|
||||||
|
background: linear-gradient(to bottom right,
|
||||||
|
rgba(29, 185, 84, 0.3),
|
||||||
|
rgba(24, 156, 71, 0.2));
|
||||||
|
border-radius: 22px;
|
||||||
|
border: 2px solid rgba(29, 185, 84, 0.4);
|
||||||
|
font-size: 18px;
|
||||||
|
color: rgba(29, 185, 84, 1.0);
|
||||||
|
width: 44px;
|
||||||
|
height: 44px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-info {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-title {
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-artist {
|
||||||
|
font-size: 12px;
|
||||||
|
color: #b3b3b3;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-details {
|
||||||
|
font-size: 10px;
|
||||||
|
color: #888888;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-uploader {
|
||||||
|
font-size: 10px;
|
||||||
|
color: rgba(29, 185, 84, 1.0);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-actions {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-download-btn {
|
||||||
|
background: linear-gradient(to bottom,
|
||||||
|
rgba(29, 185, 84, 0.95),
|
||||||
|
rgba(24, 156, 71, 0.9));
|
||||||
|
border: 2px solid rgba(29, 185, 84, 0.3);
|
||||||
|
border-radius: 23px;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 14px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 8px 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-download-btn:hover {
|
||||||
|
background: linear-gradient(to bottom,
|
||||||
|
rgba(30, 215, 96, 1.0),
|
||||||
|
rgba(25, 180, 80, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Album Card (AlbumResultItem) */
|
||||||
|
.album-result-card {
|
||||||
|
background: linear-gradient(to bottom,
|
||||||
|
rgba(52, 52, 58, 0.95),
|
||||||
|
rgba(42, 42, 48, 0.98));
|
||||||
|
border-radius: 20px;
|
||||||
|
border: 1px solid rgba(75, 75, 82, 0.5);
|
||||||
|
margin: 8px 4px;
|
||||||
|
padding: 18px;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-result-card:hover {
|
||||||
|
border: 1px solid rgba(29, 185, 84, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-card-header {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-icon {
|
||||||
|
font-size: 28px;
|
||||||
|
background: linear-gradient(to bottom right,
|
||||||
|
rgba(29, 185, 84, 0.2),
|
||||||
|
rgba(24, 156, 71, 0.15));
|
||||||
|
border-radius: 28px;
|
||||||
|
border: 2px solid rgba(29, 185, 84, 0.4);
|
||||||
|
width: 56px;
|
||||||
|
height: 56px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
color: rgba(29, 185, 84, 1.0);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-info {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-title {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-artist {
|
||||||
|
font-size: 13px;
|
||||||
|
color: #b3b3b3;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-details {
|
||||||
|
font-size: 11px;
|
||||||
|
color: #888888;
|
||||||
|
margin-bottom: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-uploader {
|
||||||
|
font-size: 11px;
|
||||||
|
color: rgba(29, 185, 84, 1.0);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-actions {
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-download-btn {
|
||||||
|
background: linear-gradient(to bottom,
|
||||||
|
rgba(29, 185, 84, 0.95),
|
||||||
|
rgba(24, 156, 71, 0.9));
|
||||||
|
border: 2px solid rgba(29, 185, 84, 0.3);
|
||||||
|
border-radius: 23px;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 15px;
|
||||||
|
font-weight: bold;
|
||||||
|
padding: 10px 20px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-download-btn:hover {
|
||||||
|
background: linear-gradient(to bottom,
|
||||||
|
rgba(30, 215, 96, 1.0),
|
||||||
|
rgba(25, 180, 80, 1.0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Album Expansion Functionality */
|
||||||
|
.album-card-header {
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-expand-indicator {
|
||||||
|
position: absolute;
|
||||||
|
left: -12px;
|
||||||
|
top: 50%;
|
||||||
|
transform: translateY(-50%);
|
||||||
|
font-size: 12px;
|
||||||
|
color: rgba(29, 185, 84, 0.8);
|
||||||
|
transition: transform 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.album-result-card.expanded .album-expand-indicator {
|
||||||
|
transform: translateY(-50%) rotate(90deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Track List within Albums */
|
||||||
|
.album-track-list {
|
||||||
|
margin-top: 12px;
|
||||||
|
padding-top: 12px;
|
||||||
|
border-top: 1px solid rgba(75, 75, 82, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Individual Track Items (TrackItem) */
|
||||||
|
.track-item {
|
||||||
|
background: rgba(40, 40, 40, 0.5);
|
||||||
|
border-radius: 8px;
|
||||||
|
border: 1px solid rgba(60, 60, 60, 0.3);
|
||||||
|
padding: 10px;
|
||||||
|
margin-bottom: 6px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-item:hover {
|
||||||
|
background: rgba(50, 50, 50, 0.7);
|
||||||
|
border: 1px solid rgba(29, 185, 84, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-item-info {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-item-title {
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
color: #ffffff;
|
||||||
|
margin-bottom: 2px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-item-details {
|
||||||
|
font-size: 10px;
|
||||||
|
color: #888888;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-item-actions {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-download-btn {
|
||||||
|
background: linear-gradient(to bottom,
|
||||||
|
rgba(29, 185, 84, 0.8),
|
||||||
|
rgba(24, 156, 71, 0.7));
|
||||||
|
border: 1px solid rgba(29, 185, 84, 0.4);
|
||||||
|
border-radius: 50%;
|
||||||
|
color: #000000;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all 0.2s ease;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.track-download-btn:hover {
|
||||||
|
background: linear-gradient(to bottom,
|
||||||
|
rgba(30, 215, 96, 0.9),
|
||||||
|
rgba(25, 180, 80, 0.8));
|
||||||
|
border-color: rgba(29, 185, 84, 0.6);
|
||||||
}
|
}
|
||||||
Loading…
Reference in a new issue