Add download progress bar on card thumbnails
Replaces pulse-only state with a visible progress bar animation:
- Indeterminate bar slides across the bottom of card thumbnails during download
- markCardCacheState dynamically adds/removes the bar element
- renderCard includes the bar for newly rendered downloading cards
- Now-playing button already showed '⏳ Saving…' state
Files:
- frontend/app.js: dl-progress in renderCard, markCardCacheState dynamic bar
- frontend/styles.css: .dl-progress, .dl-bar with dlSlide animation
This commit is contained in:
@@ -18,7 +18,7 @@ bottom as they come up.
|
||||
- [x] Empty-state designs for empty playlists and empty history (match the new hero).
|
||||
- [x] Loading skeletons for search results instead of a bare "Searching…".
|
||||
- [x] Keyboard-shortcut help overlay (press `?`), listing space / arrows / f / m.
|
||||
- [ ] Download/preload progress indicator on cards (percent or a bar, not just a pulse).
|
||||
- [x] Download/preload progress indicator on cards (percent or a bar, not just a pulse).
|
||||
- [ ] Remember and restore the last playback position per video.
|
||||
- [ ] Toast queue (stack multiple toasts instead of replacing).
|
||||
|
||||
|
||||
@@ -172,6 +172,16 @@ function markCardCacheState(id, state) {
|
||||
document.querySelectorAll(`.card[data-id="${CSS.escape(id)}"]`).forEach((c) => {
|
||||
c.classList.toggle('cached', state === 'cached');
|
||||
c.classList.toggle('downloading', state === 'downloading');
|
||||
const thumb = c.querySelector('.thumb');
|
||||
if (state === 'downloading' && !thumb.querySelector('.dl-progress')) {
|
||||
const bar = document.createElement('div');
|
||||
bar.className = 'dl-progress';
|
||||
bar.innerHTML = '<div class="dl-bar"></div>';
|
||||
thumb.appendChild(bar);
|
||||
} else if (state !== 'downloading') {
|
||||
const bar = thumb.querySelector('.dl-progress');
|
||||
if (bar) bar.remove();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -802,13 +812,16 @@ async function renderSettings() {
|
||||
|
||||
function renderCard(v, index, list) {
|
||||
const card = document.createElement('div');
|
||||
card.className = 'card' + (cachedIds.has(v.id) ? ' cached' : '') + (downloading.has(v.id) ? ' downloading' : '');
|
||||
const isCached = cachedIds.has(v.id);
|
||||
const isDownloading = downloading.has(v.id);
|
||||
card.className = 'card' + (isCached ? ' cached' : '') + (isDownloading ? ' downloading' : '');
|
||||
card.dataset.id = v.id;
|
||||
card.innerHTML = `
|
||||
<div class="thumb">
|
||||
<img loading="lazy" src="${v.thumbnail || ''}" alt="" />
|
||||
${v.duration ? `<span class="dur">${fmtTime(v.duration)}</span>` : ''}
|
||||
<span class="saved-badge" title="Saved offline">⬇</span>
|
||||
<span class="saved-badge" title="${isDownloading ? 'Downloading…' : 'Saved offline'}">${isDownloading ? '' : '⬇'}</span>
|
||||
${isDownloading ? '<div class="dl-progress"><div class="dl-bar"></div></div>' : ''}
|
||||
</div>
|
||||
<div class="card-info">
|
||||
<div class="card-title"></div>
|
||||
|
||||
@@ -773,6 +773,27 @@ input[type="range"]::-webkit-slider-thumb:hover { transform: scale(1.25); }
|
||||
.card.downloading .saved-badge::before { content: "⏳"; }
|
||||
.card.downloading .saved-badge { font-size: 0; }
|
||||
.card.downloading .saved-badge::before { font-size: 10px; }
|
||||
|
||||
/* Download progress bar on card thumb */
|
||||
.dl-progress {
|
||||
position: absolute;
|
||||
bottom: 0; left: 0; right: 0;
|
||||
height: 3px;
|
||||
background: rgba(0,0,0,0.5);
|
||||
overflow: hidden;
|
||||
}
|
||||
.dl-bar {
|
||||
height: 100%;
|
||||
width: 30%;
|
||||
background: linear-gradient(90deg, var(--accent-deep), var(--accent-bright));
|
||||
border-radius: 0 2px 2px 0;
|
||||
animation: dlSlide 1.2s ease-in-out infinite;
|
||||
}
|
||||
@keyframes dlSlide {
|
||||
0% { transform: translateX(-100%); width: 30%; }
|
||||
50% { width: 45%; }
|
||||
100% { transform: translateX(400%); width: 30%; }
|
||||
}
|
||||
@keyframes pulse { 0%,100% { opacity: 1; } 50% { opacity: 0.5; } }
|
||||
|
||||
/* ===================== Settings page ===================== */
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Reference in New Issue
Block a user