diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index ce3c38f..bf36fb4 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,6 +19,7 @@ jobs: uses: actions/checkout@v4 with: fetch-depth: 1 + ref: ${{ github.head_ref || github.ref }} - name: Setup Bun uses: oven-sh/setup-bun@v1 @@ -55,7 +56,6 @@ jobs: commit_message: 'style: auto-fix linting issues' commit_user_name: 'github-actions[bot]' commit_user_email: 'github-actions[bot]@users.noreply.github.com' - only_if_changed: true - name: Run HTML Lint run: bun run lint:html diff --git a/js/events.js b/js/events.js index be7c97d..d660f6b 100644 --- a/js/events.js +++ b/js/events.js @@ -1458,10 +1458,12 @@ export async function handleTrackAction( const layout = localStorage.getItem('libraryLikedTracksView') || 'list'; const tempDiv = document.createElement('div'); if (layout === 'grid') { - tracksContainer.className = 'card-grid'; + tracksContainer.classList.remove('track-list'); + tracksContainer.classList.add('card-grid'); tempDiv.innerHTML = ui.createTrackCardHTML(item); } else { - tracksContainer.className = 'track-list'; + tracksContainer.classList.remove('card-grid'); + tracksContainer.classList.add('track-list'); const index = tracksContainer.children.length; tempDiv.innerHTML = ui.createTrackItemHTML(item, index, true, false, false, true); } @@ -1470,7 +1472,7 @@ export async function handleTrackAction( if (newEl) { tracksContainer.appendChild(newEl); trackDataStore.set(newEl, item); - ui.updateLikeState(newEl, item.type === 'video' ? 'video' : 'track', item.id); + ui.updateLikeState(newEl, 'track', item.id); const likedToolbar = document.getElementById('library-liked-tracks-toolbar'); if (likedToolbar) likedToolbar.style.display = 'flex'; const shuffleBtn = document.getElementById('shuffle-liked-tracks-btn'); diff --git a/js/ui.js b/js/ui.js index 30102eb..10fa97a 100644 --- a/js/ui.js +++ b/js/ui.js @@ -738,13 +738,18 @@ export class UIRenderer { videoCoverCandidate && (typeof videoCoverCandidate === 'string' || typeof videoCoverCandidate === 'number') ? this.api.getVideoCoverUrl(videoCoverCandidate) : null; - const cover = video.image || video.cover; + const coverFallback = video.image || video.cover; + const coverPrimitive = + coverFallback != null && + (typeof coverFallback === 'string' || typeof coverFallback === 'number') + ? coverFallback + : null; let imageHTML; if (videoCoverUrl) { imageHTML = `${escapeHtml(video.title)}`; - } else if (cover) { - imageHTML = this.getCoverHTML(cover, escapeHtml(video.title)); + } else if (coverPrimitive) { + imageHTML = this.getCoverHTML(coverPrimitive, escapeHtml(video.title)); } else { imageHTML = `
${SVG_PLAY(48, { style: 'opacity: 0.7;' })}
`; } @@ -843,18 +848,20 @@ export class UIRenderer { const oldListener = clearBtn._clearListener; if (oldListener) clearBtn.removeEventListener('click', oldListener); - // Toggle visibility based on input value + const oldToggle = inputElement._searchClearToggleListener; + if (oldToggle) inputElement.removeEventListener('input', oldToggle); + const toggleVisibility = () => { clearBtn.style.display = inputElement.value.trim() ? 'flex' : 'none'; }; - // Clear input on click const clearListener = () => { inputElement.value = ''; inputElement.dispatchEvent(new Event('input')); inputElement.focus(); }; + inputElement._searchClearToggleListener = toggleVisibility; inputElement.addEventListener('input', toggleVisibility); clearBtn._clearListener = clearListener; clearBtn.addEventListener('click', clearListener); @@ -1718,6 +1725,7 @@ export class UIRenderer { } showPage(pageId) { + const previousPage = this.currentPage; this.currentPage = pageId; document.querySelectorAll('.page').forEach((page) => { page.classList.toggle('active', page.id === `page-${pageId}`); @@ -1730,7 +1738,10 @@ export class UIRenderer { ); }); - document.querySelector('.main-content').scrollTop = 0; + const mainContent = document.querySelector('.main-content'); + if (mainContent && previousPage !== pageId) { + mainContent.scrollTop = 0; + } // Clear artist context when navigating away from artist page if (pageId !== 'artist') { @@ -1809,7 +1820,8 @@ export class UIRenderer { if (viewGridBtn) viewGridBtn.classList.toggle('active', likedViewLayout === 'grid'); if (likedViewLayout === 'grid') { - tracksContainer.className = 'card-grid'; + tracksContainer.classList.remove('track-list'); + tracksContainer.classList.add('card-grid'); tracksContainer.innerHTML = likedTracks.map((t) => this.createTrackCardHTML(t)).join(''); likedTracks.forEach((track) => { const el = tracksContainer.querySelector(`[data-track-id="${track.id}"]`); @@ -1820,7 +1832,8 @@ export class UIRenderer { } }); } else { - tracksContainer.className = 'track-list'; + tracksContainer.classList.remove('card-grid'); + tracksContainer.classList.add('track-list'); this.renderListWithTracks(tracksContainer, likedTracks, true, false, false, true); } this.setupLibraryLikedTracksSearch(tracksContainer); @@ -1828,7 +1841,8 @@ export class UIRenderer { if (likedToolbar) likedToolbar.style.display = 'none'; if (shuffleBtn) shuffleBtn.style.display = 'none'; if (downloadBtn) downloadBtn.style.display = 'none'; - tracksContainer.className = 'track-list'; + tracksContainer.classList.remove('card-grid'); + tracksContainer.classList.add('track-list'); tracksContainer.innerHTML = createPlaceholder('No liked tracks yet.'); } diff --git a/styles.css b/styles.css index a0faf14..60522dc 100644 --- a/styles.css +++ b/styles.css @@ -2419,7 +2419,7 @@ body.multi-select-mode .track-item:hover { } .track-row-like-btn.active { - color: var(--highlight); + color: #ef4444; } .track-item-duration {