mirror of
https://github.com/Psychotoxical/psysonic.git
synced 2026-07-21 23:05:46 +00:00
feat(home): Lossless Albums rail + dedicated page + sidebar nav (#506)
* wip(home): Lossless rail + dedicated /lossless-albums page Rail under Home > mostPlayed and a dedicated infinite-scroll page that list albums whose tracks are tagged in lossless containers. Walks Navidrome's native /api/song?_sort=bit_depth&_order=DESC, dedupes by albumId on the way down, stops when the song stream crosses into lossy (bitDepth==0) or the server runs out of rows. _filters has no operators on quality columns, so a sort + walk is the only path; equality on sample_rate / bit_depth probes returned empty (verified). The page paginates through the song-cursor with an in-flight ref so overlapping IntersectionObserver fires don't double-add albums, plus a cancelled flag so React StrictMode's double-mount doesn't apply two parallel result sets in dev. Suffix allowlist excludes ambiguous wrappers — m4a/m4b can be ALAC *or* AAC and Navidrome's response carries an empty codec field, so we can't tell them apart; same story for wma. Allowlist is flac, wav, aiff/aif, dsf/dff, ape, wv, shn, tta — containers that are only lossless. ALAC-in-m4a setups will miss out, acceptable trade-off without a reliable codec field. Status: WIP. Settings home-customizer label and en.ts strings landed, no other locales yet, no quality badge on AlbumCards across the rest of the app, no CHANGELOG. Branch was 'feat/home-hires-rail' during the earlier hi-res-only iteration before the lossless broadening. * wip(home): Lossless page header parity + streaming + sidebar nav Page header now mirrors All Albums: selection mode with three action buttons (Enqueue Selected, Add Offline, Download ZIPs) wired to the same handlers Albums.tsx uses, selection-counter title swap, and the perfFlags.disableMainstageStickyHeader respect path. Filters were intentionally skipped — the rail is sorted by bit_depth, mixing client- side filters with server-driven pagination would produce gaps. Loading feels noticeably faster: ndListLosslessAlbumsPage takes an optional onProgress callback that fires once per internal fetch with the entries discovered in that fetch, so the page can stream new albums into state instead of waiting on the whole loadMore. Page-side budget dropped from 5×200 to 2×100 songs per loadMore (~1 MB worst case vs 5 MB before), since the rail's catch-em-all pass is wrong for infinite-scroll UX. Subtitle under the page title primes the user that this is slower than other album pages because Psysonic walks the song catalog by quality (Navidrome ignores _fields, so per-song responses ship with lyrics + tags + participants whether we want them or not). Sidebar nav entry registered under 'losslessAlbums' with a Gem icon, defaults to visible:false (matches composers / folderBrowser / deviceSync — niche browsing modes). Existing users get the entry appended at the end of their persisted sidebar list automatically via the onRehydrateStorage merge that sidebarStore already runs for new DEFAULT_SIDEBAR_ITEMS. i18n: full coverage across all 8 locales for sidebar.losslessAlbums, home.losslessAlbums, losslessAlbums.empty, losslessAlbums.unsupported and the new losslessAlbums.slowFetchHint subtitle. ru/zh are machine-translation quality, flagged for a polish pass. * feat(home): default Lossless sidebar entry to visible Flips the DEFAULT_SIDEBAR_ITEMS entry for `losslessAlbums` from false to true. Existing installs keep whatever the user has in persisted storage; fresh installs see the entry in the sidebar from the start. Earlier wip commit defaulted it off (matched composers / folderBrowser / deviceSync as a niche browse mode), but the rail + page do show something useful for any library with at least one FLAC/WAV/etc. album, so off-by-default just hid the feature. * docs: changelog entry for PR #506 Logs the Lossless Albums rail + page + sidebar entry in v1.46.0 "## Added". * docs(settings): contributor entry for PR #506 Adds the Lossless Albums rail/page bullet to Psychotoxical's contributions list.
This commit is contained in:
committed by
GitHub
parent
a41e3a624a
commit
bd56177e2c
@@ -25,6 +25,7 @@ export const deTranslation = {
|
||||
tracks: 'Titel',
|
||||
playlists: 'Playlists',
|
||||
mostPlayed: 'Meistgehört',
|
||||
losslessAlbums: 'Lossless',
|
||||
radio: 'Internetradio',
|
||||
folderBrowser: 'Ordner-Browser',
|
||||
deviceSync: 'Gerätesync',
|
||||
@@ -41,6 +42,7 @@ export const deTranslation = {
|
||||
recent: 'Zuletzt hinzugefügt',
|
||||
mostPlayed: 'Meistgehört',
|
||||
recentlyPlayed: 'Kürzlich gespielt',
|
||||
losslessAlbums: 'Lossless-Alben',
|
||||
discover: 'Entdecken',
|
||||
discoverSongs: 'Titel entdecken',
|
||||
loadMore: 'Mehr laden',
|
||||
@@ -1513,6 +1515,11 @@ export const deTranslation = {
|
||||
filterCompilations: 'Sampler-Künstler ausblenden (Various Artists, Soundtracks usw.)',
|
||||
filterCompilationsShort: 'Sampler ausblenden',
|
||||
},
|
||||
losslessAlbums: {
|
||||
empty: 'Noch keine Lossless-Alben in dieser Bibliothek.',
|
||||
unsupported: 'Dieser Server liefert keine Metadaten, mit denen sich Lossless-Alben erkennen lassen.',
|
||||
slowFetchHint: 'Lädt langsamer als andere Album-Seiten — Psysonic geht den gesamten Songkatalog nach Qualität durch.',
|
||||
},
|
||||
radio: {
|
||||
title: 'Internetradio',
|
||||
empty: 'Keine Radiosender konfiguriert.',
|
||||
|
||||
@@ -27,6 +27,7 @@ export const enTranslation = {
|
||||
playlists: 'Playlists',
|
||||
smartPlaylists: 'Smart Playlists',
|
||||
mostPlayed: 'Most Played',
|
||||
losslessAlbums: 'Lossless',
|
||||
radio: 'Internet Radio',
|
||||
folderBrowser: 'Folder Browser',
|
||||
deviceSync: 'Device Sync',
|
||||
@@ -43,6 +44,7 @@ export const enTranslation = {
|
||||
recent: 'Recently Added',
|
||||
mostPlayed: 'Most Played',
|
||||
recentlyPlayed: 'Recently Played',
|
||||
losslessAlbums: 'Lossless Albums',
|
||||
discover: 'Discover',
|
||||
discoverSongs: 'Discover Songs',
|
||||
loadMore: 'Load More',
|
||||
@@ -1519,6 +1521,11 @@ export const enTranslation = {
|
||||
filterCompilations: 'Hide compilation artists (Various Artists, Soundtracks, etc.)',
|
||||
filterCompilationsShort: 'Hide compilations',
|
||||
},
|
||||
losslessAlbums: {
|
||||
empty: 'No lossless albums in this library yet.',
|
||||
unsupported: 'This server does not expose the metadata needed to find lossless albums.',
|
||||
slowFetchHint: 'Loads slower than other album pages — Psysonic walks the full song catalog by quality.',
|
||||
},
|
||||
radio: {
|
||||
title: 'Internet Radio',
|
||||
empty: 'No radio stations configured.',
|
||||
|
||||
@@ -26,6 +26,7 @@ export const esTranslation = {
|
||||
tracks: 'Canciones',
|
||||
playlists: 'Listas de Reproducción',
|
||||
mostPlayed: 'Más Reproducidos',
|
||||
losslessAlbums: 'Sin Pérdidas',
|
||||
radio: 'Radio por Internet',
|
||||
folderBrowser: 'Explorar Carpetas',
|
||||
deviceSync: 'Sincronizar dispositivo',
|
||||
@@ -42,6 +43,7 @@ export const esTranslation = {
|
||||
recent: 'Agregados Recientemente',
|
||||
mostPlayed: 'Más Reproducidos',
|
||||
recentlyPlayed: 'Reproducidos Recientemente',
|
||||
losslessAlbums: 'Álbumes sin Pérdidas',
|
||||
discover: 'Descubrir',
|
||||
discoverSongs: 'Descubrir canciones',
|
||||
loadMore: 'Cargar Más',
|
||||
@@ -1478,6 +1480,11 @@ export const esTranslation = {
|
||||
filterCompilations: 'Ocultar artistas de compilaciones (Various Artists, Soundtracks, etc.)',
|
||||
filterCompilationsShort: 'Ocultar compilaciones',
|
||||
},
|
||||
losslessAlbums: {
|
||||
empty: 'Aún no hay álbumes sin pérdidas en esta biblioteca.',
|
||||
unsupported: 'Este servidor no expone los metadatos necesarios para encontrar álbumes sin pérdidas.',
|
||||
slowFetchHint: 'Carga más lento que otras páginas de álbumes — Psysonic recorre todo el catálogo de canciones por calidad.',
|
||||
},
|
||||
radio: {
|
||||
title: 'Radio por Internet',
|
||||
empty: 'No hay estaciones de radio configuradas.',
|
||||
|
||||
@@ -25,6 +25,7 @@ export const frTranslation = {
|
||||
tracks: 'Titres',
|
||||
playlists: 'Playlists',
|
||||
mostPlayed: 'Les plus joués',
|
||||
losslessAlbums: 'Lossless',
|
||||
radio: 'Radio Internet',
|
||||
folderBrowser: 'Explorateur de dossiers',
|
||||
deviceSync: 'Sync appareil',
|
||||
@@ -41,6 +42,7 @@ export const frTranslation = {
|
||||
recent: 'Ajoutés récemment',
|
||||
mostPlayed: 'Les plus écoutés',
|
||||
recentlyPlayed: 'Récemment écoutés',
|
||||
losslessAlbums: 'Albums lossless',
|
||||
discover: 'Découvrir',
|
||||
discoverSongs: 'Découvrir des titres',
|
||||
loadMore: 'Charger plus',
|
||||
@@ -1473,6 +1475,11 @@ export const frTranslation = {
|
||||
filterCompilations: 'Masquer les artistes de compilations (Various Artists, Soundtracks, etc.)',
|
||||
filterCompilationsShort: 'Masquer les compilations',
|
||||
},
|
||||
losslessAlbums: {
|
||||
empty: 'Aucun album lossless dans cette bibliothèque pour l\'instant.',
|
||||
unsupported: 'Ce serveur n\'expose pas les métadonnées nécessaires pour trouver des albums lossless.',
|
||||
slowFetchHint: 'Chargement plus lent que les autres pages d\'albums — Psysonic parcourt tout le catalogue par qualité.',
|
||||
},
|
||||
radio: {
|
||||
title: 'Radio Internet',
|
||||
empty: 'Aucune station radio configurée.',
|
||||
|
||||
@@ -25,6 +25,7 @@ export const nbTranslation = {
|
||||
tracks: 'Spor',
|
||||
playlists: 'Spillelister',
|
||||
mostPlayed: 'Mest spilt',
|
||||
losslessAlbums: 'Lossless',
|
||||
radio: 'Internettradio',
|
||||
folderBrowser: 'Mappeleser',
|
||||
deviceSync: 'Enhetssynk',
|
||||
@@ -41,6 +42,7 @@ export const nbTranslation = {
|
||||
recent: 'Nylig lagt til',
|
||||
mostPlayed: 'Mest spilt',
|
||||
recentlyPlayed: 'Nylig spilt',
|
||||
losslessAlbums: 'Lossless-album',
|
||||
discover: 'Oppdag',
|
||||
discoverSongs: 'Oppdag spor',
|
||||
loadMore: 'Last inn flere',
|
||||
@@ -1431,6 +1433,11 @@ export const nbTranslation = {
|
||||
filterCompilations: 'Skjul kompilasjonsartister (Various Artists, Soundtracks, etc.)',
|
||||
filterCompilationsShort: 'Skjul kompilasjoner',
|
||||
},
|
||||
losslessAlbums: {
|
||||
empty: 'Ingen lossless-album i dette biblioteket ennå.',
|
||||
unsupported: 'Denne serveren eksponerer ikke metadata som trengs for å finne lossless-album.',
|
||||
slowFetchHint: 'Lastes saktere enn andre albumsider — Psysonic går gjennom hele sangkatalogen etter kvalitet.',
|
||||
},
|
||||
smartPlaylists: {
|
||||
sectionBasic: '1. Grunnleggende',
|
||||
sectionGenres: '2. Sjanger',
|
||||
|
||||
@@ -25,6 +25,7 @@ export const nlTranslation = {
|
||||
tracks: 'Nummers',
|
||||
playlists: 'Playlists',
|
||||
mostPlayed: 'Meest gespeeld',
|
||||
losslessAlbums: 'Lossless',
|
||||
radio: 'Internetradio',
|
||||
folderBrowser: 'Mappenverkenner',
|
||||
deviceSync: 'Apparaatsync',
|
||||
@@ -41,6 +42,7 @@ export const nlTranslation = {
|
||||
recent: 'Recent toegevoegd',
|
||||
mostPlayed: 'Meest gespeeld',
|
||||
recentlyPlayed: 'Recent afgespeeld',
|
||||
losslessAlbums: 'Lossless-albums',
|
||||
discover: 'Ontdekken',
|
||||
discoverSongs: 'Nummers ontdekken',
|
||||
loadMore: 'Meer laden',
|
||||
@@ -1472,6 +1474,11 @@ export const nlTranslation = {
|
||||
filterCompilations: 'Compilatie-artiesten verbergen (Various Artists, Soundtracks, etc.)',
|
||||
filterCompilationsShort: 'Compilaties verbergen',
|
||||
},
|
||||
losslessAlbums: {
|
||||
empty: 'Nog geen lossless-albums in deze bibliotheek.',
|
||||
unsupported: 'Deze server biedt geen metadata om lossless-albums te vinden.',
|
||||
slowFetchHint: 'Laadt langzamer dan andere albumpagina\'s — Psysonic doorloopt de volledige songcatalogus op kwaliteit.',
|
||||
},
|
||||
radio: {
|
||||
title: 'Internetradio',
|
||||
empty: 'Geen radiostations geconfigureerd.',
|
||||
|
||||
@@ -27,6 +27,7 @@ export const ruTranslation = {
|
||||
playlists: 'Плейлисты',
|
||||
smartPlaylists: 'Смарт-плейлисты',
|
||||
mostPlayed: 'Популярное',
|
||||
losslessAlbums: 'Lossless',
|
||||
radio: 'Онлайн-радио',
|
||||
folderBrowser: 'Браузер папок',
|
||||
deviceSync: 'Синхронизация устройства',
|
||||
@@ -43,6 +44,7 @@ export const ruTranslation = {
|
||||
recent: 'Недавно добавлено',
|
||||
mostPlayed: 'Популярное',
|
||||
recentlyPlayed: 'Недавно проиграно',
|
||||
losslessAlbums: 'Lossless-альбомы',
|
||||
discover: 'Обзор',
|
||||
discoverSongs: 'Открыть треки',
|
||||
loadMore: 'Ещё',
|
||||
@@ -1536,6 +1538,11 @@ export const ruTranslation = {
|
||||
filterCompilations: 'Скрыть исполнителей сборников (Various Artists, Soundtracks и др.)',
|
||||
filterCompilationsShort: 'Скрыть сборники',
|
||||
},
|
||||
losslessAlbums: {
|
||||
empty: 'В этой библиотеке пока нет lossless-альбомов.',
|
||||
unsupported: 'Этот сервер не предоставляет метаданные, необходимые для поиска lossless-альбомов.',
|
||||
slowFetchHint: 'Загружается медленнее других страниц альбомов — Psysonic проходит весь каталог песен по качеству.',
|
||||
},
|
||||
radio: {
|
||||
title: 'Онлайн-радио',
|
||||
empty: 'Радиостанции не настроены.',
|
||||
|
||||
@@ -25,6 +25,7 @@ export const zhTranslation = {
|
||||
tracks: '曲目',
|
||||
playlists: '播放列表',
|
||||
mostPlayed: '最常播放',
|
||||
losslessAlbums: '无损',
|
||||
radio: '网络电台',
|
||||
folderBrowser: '文件夹浏览器',
|
||||
deviceSync: '设备同步',
|
||||
@@ -41,6 +42,7 @@ export const zhTranslation = {
|
||||
recent: '最近添加',
|
||||
mostPlayed: '最常播放',
|
||||
recentlyPlayed: '最近播放',
|
||||
losslessAlbums: '无损专辑',
|
||||
discover: '发现',
|
||||
discoverSongs: '发现曲目',
|
||||
loadMore: '加载更多',
|
||||
@@ -1465,6 +1467,11 @@ export const zhTranslation = {
|
||||
filterCompilations: '隐藏合辑艺术家(Various Artists、原声带等)',
|
||||
filterCompilationsShort: '隐藏合辑',
|
||||
},
|
||||
losslessAlbums: {
|
||||
empty: '此媒体库中还没有无损专辑。',
|
||||
unsupported: '此服务器未公开查找无损专辑所需的元数据。',
|
||||
slowFetchHint: '加载比其他专辑页面慢 — Psysonic 按音质遍历整个歌曲目录。',
|
||||
},
|
||||
radio: {
|
||||
title: '网络电台',
|
||||
empty: '未配置任何电台。',
|
||||
|
||||
Reference in New Issue
Block a user