fix: auto-populate artist sort map on album page — no Artists page visit needed

ensureArtistSortMap() fetches getArtists once per session (cached) and
populates _artistSortMap automatically. Called at start of loadAlbumDetail
when showRomaji is on, so artist sort names are always available.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-06-08 23:07:02 +02:00
1 parent 6851c37e15
commit 9e6e81bc22
2 files changed
+19 -2

No files matched your search

+17 -1
View File
@@ -95,6 +95,7 @@ let _artistRomajiMap = null; // Map<artistId, artistRomaji> — kuromoji backend
let _artistSortMap = null; // Map<artistId, sortName> — Navidrome sort tag (preferred) let _artistSortMap = null; // Map<artistId, sortName> — Navidrome sort tag (preferred)
let _albumRomajiMap = null; // Map<albumName(JP), albumRomaji> — for album cards without song ID let _albumRomajiMap = null; // Map<albumName(JP), albumRomaji> — for album cards without song ID
let _romajiIndexFetch = null; // in-flight promise dedup let _romajiIndexFetch = null; // in-flight promise dedup
let _artistSortFetch = null; // in-flight dedup for ensureArtistSortMap
function _buildRomajiMap(idx) { function _buildRomajiMap(idx) {
const m = new Map(); const m = new Map();
@@ -122,7 +123,22 @@ export async function fetchRomajiIndex() {
return _romajiIndexFetch; return _romajiIndexFetch;
} }
export function invalidateRomajiIndex() { _romajiIndex = null; _romajiMap = null; _artistRomajiMap = null; _artistSortMap = null; _albumRomajiMap = null; } export function invalidateRomajiIndex() { _romajiIndex = null; _romajiMap = null; _artistRomajiMap = null; _artistSortMap = null; _albumRomajiMap = null; _artistSortFetch = null; }
// Ensures _artistSortMap is populated from getArtists (cached — one network call per session).
// Safe to call from anywhere; deduplicates concurrent calls automatically.
export async function ensureArtistSortMap() {
if (_artistSortMap) return;
if (_artistSortFetch) return _artistSortFetch;
_artistSortFetch = apiCached('getArtists')
.then(r => {
const all = (r?.artists?.index || []).flatMap(i => i.artist || []);
cacheArtistSortNames(all);
_artistSortFetch = null;
})
.catch(() => { _artistSortFetch = null; });
return _artistSortFetch;
}
// Populate _artistSortMap from Navidrome artist objects (OpenSubsonic sortName field). // Populate _artistSortMap from Navidrome artist objects (OpenSubsonic sortName field).
// Called whenever getArtists or getArtist data is loaded so dispArtistById can use it. // Called whenever getArtists or getArtist data is loaded so dispArtistById can use it.
+2 -1
View File
@@ -1,6 +1,6 @@
import { S } from '../state.js'; import { S } from '../state.js';
import { esc, toast } from '../utils.js'; import { esc, toast } from '../utils.js';
import { api, coverUrl, itunesSearch, itunesLookupAlbum, itunesLookupArtistSongs, itunesLookupArtistAlbums, fetchRomajiIndex, dispArtistById, dispAlbumName, cacheArtistSortNames } from '../api.js'; import { api, coverUrl, itunesSearch, itunesLookupAlbum, itunesLookupArtistSongs, itunesLookupArtistAlbums, fetchRomajiIndex, dispArtistById, dispAlbumName, cacheArtistSortNames, ensureArtistSortMap } from '../api.js';
import { makeCard, makeAlbumCard, makeGlobalTrackItem, makeSongItem } from '../ui/components.js'; import { makeCard, makeAlbumCard, makeGlobalTrackItem, makeSongItem } from '../ui/components.js';
import { playQueue, dlSongLocal, toggleStar, parseArtists } from '../player/player.js'; import { playQueue, dlSongLocal, toggleStar, parseArtists } from '../player/player.js';
import { showCtxMenu, openDlModal } from '../ui/ui.js'; import { showCtxMenu, openDlModal } from '../ui/ui.js';
@@ -378,6 +378,7 @@ export async function loadItunesAlbumDetail(album) {
// ─── ALBUM DETAIL ─── // ─── ALBUM DETAIL ───
export async function loadAlbumDetail(album) { export async function loadAlbumDetail(album) {
if (S.cfg.showRomaji) await ensureArtistSortMap().catch(() => {});
document.getElementById('album-back-btn').onclick = () => document.getElementById('album-back-btn').onclick = () =>
album._fromArtist ? navigate('artist-detail', album._fromArtist) : navigate('albums'); album._fromArtist ? navigate('artist-detail', album._fromArtist) : navigate('albums');
document.getElementById('album-detail-name').textContent = dispAlbumName(album); document.getElementById('album-detail-name').textContent = dispAlbumName(album);