Merge pull request #26 from JulienMaille/fav-lib

many ui small improvements
This commit is contained in:
Julien 2025-12-27 14:13:59 +01:00 committed by GitHub
commit a85262a25a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 88 additions and 38 deletions

View file

@ -137,14 +137,14 @@
<h2 class="section-title">Recent Albums</h2> <h2 class="section-title">Recent Albums</h2>
<div class="card-grid" id="home-recent-albums"></div> <div class="card-grid" id="home-recent-albums"></div>
</section> </section>
<section class="content-section">
<h2 class="section-title">Recent Playlists</h2>
<div class="card-grid" id="home-recent-playlists"></div>
</section>
<section class="content-section"> <section class="content-section">
<h2 class="section-title">Recent Artists</h2> <h2 class="section-title">Recent Artists</h2>
<div class="card-grid" id="home-recent-artists"></div> <div class="card-grid" id="home-recent-artists"></div>
</section> </section>
<section class="content-section">
<h2 class="section-title">Recent Playlists</h2>
<div class="card-grid" id="home-recent-playlists"></div>
</section>
</div> </div>
<div id="page-search" class="page"> <div id="page-search" class="page">
@ -172,7 +172,7 @@
<div id="page-library" class="page"> <div id="page-library" class="page">
<h2 class="section-title">Your Library</h2> <h2 class="section-title">Your Library</h2>
<div class="search-tabs"> <div class="search-tabs">
<button class="search-tab active" data-tab="tracks">Liked Songs</button> <button class="search-tab active" data-tab="tracks">Liked Tracks</button>
<button class="search-tab" data-tab="albums">Albums</button> <button class="search-tab" data-tab="albums">Albums</button>
<button class="search-tab" data-tab="artists">Artists</button> <button class="search-tab" data-tab="artists">Artists</button>
<button class="search-tab" data-tab="playlists">Playlists</button> <button class="search-tab" data-tab="playlists">Playlists</button>

View file

@ -354,7 +354,7 @@ export async function handleTrackAction(action, item, player, api, lyricsManager
const container = itemEl.parentElement; const container = itemEl.parentElement;
itemEl.remove(); itemEl.remove();
if (container && container.children.length === 0) { if (container && container.children.length === 0) {
const msg = type === 'track' ? 'No liked songs yet.' : `No liked ${type}s yet.`; const msg = type === 'track' ? 'No liked tracks yet.' : `No liked ${type}s yet.`;
container.innerHTML = `<div class="placeholder-text">${msg}</div>`; container.innerHTML = `<div class="placeholder-text">${msg}</div>`;
} }
} else if (added && !itemEl && ui && type === 'track') { } else if (added && !itemEl && ui && type === 'track') {
@ -427,7 +427,14 @@ export function initializeTrackInteractions(player, api, mainContent, contextMen
e.stopPropagation(); e.stopPropagation();
const trackItem = menuBtn.closest('.track-item'); const trackItem = menuBtn.closest('.track-item');
if (trackItem && !trackItem.dataset.queueIndex) { if (trackItem && !trackItem.dataset.queueIndex) {
contextTrack = trackDataStore.get(trackItem); const clickedTrack = trackDataStore.get(trackItem);
if (contextMenu.style.display === 'block' && contextTrack && clickedTrack && contextTrack.id === clickedTrack.id) {
contextMenu.style.display = 'none';
return;
}
contextTrack = clickedTrack;
if (contextTrack) { if (contextTrack) {
await updateContextMenuLikeState(contextMenu, contextTrack); await updateContextMenuLikeState(contextMenu, contextTrack);
const rect = menuBtn.getBoundingClientRect(); const rect = menuBtn.getBoundingClientRect();

View file

@ -454,31 +454,16 @@ export class UIRenderer {
async renderLibraryPage() { async renderLibraryPage() {
this.showPage('library'); this.showPage('library');
const playlistsContainer = document.getElementById('library-playlists-container');
const tracksContainer = document.getElementById('library-tracks-container'); const tracksContainer = document.getElementById('library-tracks-container');
const albumsContainer = document.getElementById('library-albums-container'); const albumsContainer = document.getElementById('library-albums-container');
const artistsContainer = document.getElementById('library-artists-container'); const artistsContainer = document.getElementById('library-artists-container');
const playlistsContainer = document.getElementById('library-playlists-container');
// Render Favorites
const likedPlaylists = await db.getFavorites('playlist');
if (likedPlaylists.length) {
playlistsContainer.innerHTML = likedPlaylists.map(p => this.createPlaylistCardHTML(p)).join('');
likedPlaylists.forEach(playlist => {
const el = playlistsContainer.querySelector(`[data-playlist-id="${playlist.uuid}"]`);
if (el) {
trackDataStore.set(el, playlist);
this.updateLikeState(el, 'playlist', playlist.uuid);
}
});
} else {
playlistsContainer.innerHTML = createPlaceholder('No liked playlists yet.');
}
const likedTracks = await db.getFavorites('track'); const likedTracks = await db.getFavorites('track');
if (likedTracks.length) { if (likedTracks.length) {
this.renderListWithTracks(tracksContainer, likedTracks, true); this.renderListWithTracks(tracksContainer, likedTracks, true);
} else { } else {
tracksContainer.innerHTML = createPlaceholder('No liked songs yet.'); tracksContainer.innerHTML = createPlaceholder('No liked tracks yet.');
} }
const likedAlbums = await db.getFavorites('album'); const likedAlbums = await db.getFavorites('album');
@ -508,6 +493,20 @@ export class UIRenderer {
} else { } else {
artistsContainer.innerHTML = createPlaceholder('No liked artists yet.'); artistsContainer.innerHTML = createPlaceholder('No liked artists yet.');
} }
const likedPlaylists = await db.getFavorites('playlist');
if (likedPlaylists.length) {
playlistsContainer.innerHTML = likedPlaylists.map(p => this.createPlaylistCardHTML(p)).join('');
likedPlaylists.forEach(playlist => {
const el = playlistsContainer.querySelector(`[data-playlist-id="${playlist.uuid}"]`);
if (el) {
trackDataStore.set(el, playlist);
this.updateLikeState(el, 'playlist', playlist.uuid);
}
});
} else {
playlistsContainer.innerHTML = createPlaceholder('No liked playlists yet.');
}
} }
async renderHomePage() { async renderHomePage() {
@ -528,7 +527,7 @@ export class UIRenderer {
} }
}); });
} else { } else {
albumsContainer.innerHTML = createPlaceholder("You haven't viewed any albums yet. Search for music to get started!"); albumsContainer.innerHTML = createPlaceholder("You haven't viewed any albums yet.");
} }
if (recents.artists.length) { if (recents.artists.length) {
@ -541,7 +540,7 @@ export class UIRenderer {
} }
}); });
} else { } else {
artistsContainer.innerHTML = createPlaceholder("You haven't viewed any artists yet. Search for music to get started!"); artistsContainer.innerHTML = createPlaceholder("You haven't viewed any artists yet.");
} }
if (playlistsContainer) { if (playlistsContainer) {
@ -555,7 +554,7 @@ export class UIRenderer {
} }
}); });
} else { } else {
playlistsContainer.innerHTML = createPlaceholder("You haven't viewed any playlists yet. Search for music to get started!"); playlistsContainer.innerHTML = createPlaceholder("You haven't viewed any playlists yet.");
} }
} }
} }

View file

@ -530,8 +530,8 @@ body.has-page-background .track-item:hover {
.card-like-btn { .card-like-btn {
position: absolute; position: absolute;
top: 0.5rem; top: 2%;
right: 0.5rem; right: 2%;
background: rgba(0, 0, 0, 0.25) !important; background: rgba(0, 0, 0, 0.25) !important;
backdrop-filter: blur(8px); backdrop-filter: blur(8px);
-webkit-backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
@ -947,6 +947,20 @@ body.has-page-background .track-item:hover {
flex-shrink: 0; flex-shrink: 0;
} }
#like-album-btn,
#like-playlist-btn,
#like-artist-btn {
width: auto;
height: auto;
padding: 0.875rem;
display: flex;
align-items: center;
justify-content: center;
border-radius: 50%;
flex-shrink: 0;
aspect-ratio: 1/1;
}
.btn-secondary { .btn-secondary {
padding: 0.5rem 1rem; padding: 0.5rem 1rem;
background-color: var(--secondary); background-color: var(--secondary);
@ -1379,6 +1393,7 @@ input:checked + .slider::before {
filter: var(--cover-filter); filter: var(--cover-filter);
z-index: -1; z-index: -1;
background-image: var(--bg-image); background-image: var(--bg-image);
transition: background-image var(--transition);
} }
.fullscreen-cover-content { .fullscreen-cover-content {
@ -2296,13 +2311,33 @@ input:checked + .slider::before {
.detail-header-actions { .detail-header-actions {
width: auto; width: auto;
margin-top: 0.5em; margin-top: 0.5em;
display: flex;
align-items: center;
gap: 0.5rem;
} }
.detail-header-actions .btn-primary { .detail-header-actions .btn-primary {
width: auto; width: 40px;
padding: 0.5rem; height: 40px;
padding: 0;
border-radius: 50%; border-radius: 50%;
aspect-ratio: 1/1; display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}
#like-album-btn,
#like-playlist-btn,
#like-artist-btn {
width: 40px;
height: 40px;
padding: 0;
border-radius: 50%;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
} }
.detail-header-actions .btn-primary span { .detail-header-actions .btn-primary span {
@ -2669,6 +2704,11 @@ input:checked + .slider::before {
} }
@media (hover: none) and (pointer: coarse) { @media (hover: none) and (pointer: coarse) {
.main-content {
padding: var(--spacing-sm);
grid-area: main;
}
.progress-bar, .progress-bar,
.volume-bar { .volume-bar {
height: 8px; height: 8px;
@ -2688,20 +2728,23 @@ input:checked + .slider::before {
box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3); box-shadow: 0 2px 6px rgba(0, 0, 0, 0.3);
} }
.track-item, button {
.queue-track-item { min-height: 36px;
padding: var(--spacing-md) var(--spacing-sm); min-width: 36px;
} }
button { .track-item {
min-height: 44px; grid-template-columns: 32px 1fr 40px 36px;
min-width: 44px;
} }
.player-controls .buttons button { .player-controls .buttons button {
min-height: 36px; min-height: 36px;
min-width: 36px; min-width: 36px;
} }
.card-like-btn {
opacity: 1;
}
} }
@supports (padding-top: env(safe-area-inset-top)) { @supports (padding-top: env(safe-area-inset-top)) {
@ -3161,3 +3204,4 @@ input:checked + .slider::before {
padding-top: max(1.5rem, env(titlebar-area-height, 0)); padding-top: max(1.5rem, env(titlebar-area-height, 0));
} }
} }