diff --git a/BACKLOG.md b/BACKLOG.md index a90bc06..9bb8cea 100644 --- a/BACKLOG.md +++ b/BACKLOG.md @@ -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). diff --git a/frontend/app.js b/frontend/app.js index d4aa902..e3ee74d 100644 --- a/frontend/app.js +++ b/frontend/app.js @@ -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 = '
'; + 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 = `
${v.duration ? `${fmtTime(v.duration)}` : ''} - + ${isDownloading ? '' : '⬇'} + ${isDownloading ? '
' : ''}
diff --git a/frontend/styles.css b/frontend/styles.css index c1f3aef..2426a50 100644 --- a/frontend/styles.css +++ b/frontend/styles.css @@ -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 ===================== */ diff --git a/releases/YT Player_1.0.0_x64-setup.exe b/releases/YT Player_1.0.0_x64-setup.exe index 4f5be60..3529ba8 100755 Binary files a/releases/YT Player_1.0.0_x64-setup.exe and b/releases/YT Player_1.0.0_x64-setup.exe differ diff --git a/releases/YT Player_1.0.0_x64_en-US.msi b/releases/YT Player_1.0.0_x64_en-US.msi index daaabf5..5c64f05 100755 Binary files a/releases/YT Player_1.0.0_x64_en-US.msi and b/releases/YT Player_1.0.0_x64_en-US.msi differ diff --git a/releases/ytplayer.exe b/releases/ytplayer.exe index e431aca..e8d40bb 100644 Binary files a/releases/ytplayer.exe and b/releases/ytplayer.exe differ