fix: iTunes Japanese artist lookup + sort tag editing in info modal

- views.js: skip ASCII word-match when artist name is non-ASCII so Japanese
  artists (e.g. ヨルシカ) resolve correctly to an iTunes artist ID
- index.html + styles.css: collapsible Sort-Tags section in edit modal
- ui.js: pre-fill sort fields from romaji index; include in save body
- novasonic-server.js: accept manual titleSort/artistSort/albumArtistSort/albumSort
  overrides; fall back to auto-computed romaji when not provided

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-25 19:49:47 +02:00
1 parent 1c0d3eb4cc
commit 5dda1a7101
5 files changed
+54 -22

No files matched your search

+12 -7
View File
@@ -615,7 +615,8 @@ app.get('/api/musicbrainz/lookup', async (req, res) => {
// ─── METADATA EDIT ───────────────────────────────────────────────────────────
app.post('/api/edit-metadata', async (req, res) => {
const { ndUrl, user, pass, songId, title, artist, albumArtist, album, year, trackNum, totalTracks,
discNum, discTotal, genre, artworkBase64, artworkMime, artworkUrl: newArtworkUrl } = req.body;
discNum, discTotal, genre, artworkBase64, artworkMime, artworkUrl: newArtworkUrl,
titleSort, artistSort, albumArtistSort, albumSort } = req.body;
if (!ndUrl || !user || !pass || !songId) return res.status(400).json({ error: 'ndUrl, user, pass, songId required' });
// Normalize artist separators — accept •, ·, ;, , and rejoin canonically
@@ -698,12 +699,16 @@ app.post('/api/edit-metadata', async (req, res) => {
const resolvedAlbumArtist = normalAlbumArtist || (normalArtist ? normalArtist.split(';')[0].trim() : null);
if (resolvedAlbumArtist) ffArgs.push('-metadata', `album_artist=${resolvedAlbumArtist}`);
if (album) ffArgs.push('-metadata', `album=${album}`);
// Sort tags: romaji versions for apps that use them for sorting / display
if (romajiTitle && romajiTitle !== title) ffArgs.push('-metadata', `TITLESORT=${romajiTitle}`);
if (romajiArtist && romajiArtist !== normalArtist) ffArgs.push('-metadata', `ARTISTSORT=${romajiArtist}`);
const resolvedRomajiAA = romajiAlbumArtist || (romajiArtist ? romajiArtist.split(';')[0].trim() : null);
if (resolvedRomajiAA && resolvedRomajiAA !== resolvedAlbumArtist) ffArgs.push('-metadata', `ALBUMARTISTSORT=${resolvedRomajiAA}`);
if (romajiAlbum && romajiAlbum !== album) ffArgs.push('-metadata', `ALBUMSORT=${romajiAlbum}`);
// Sort tags: manual override from frontend > auto-computed romaji
const effectiveTitleSort = titleSort !== undefined ? titleSort : (romajiTitle !== title ? romajiTitle : null);
const effectiveArtistSort = artistSort !== undefined ? artistSort : (romajiArtist !== normalArtist ? romajiArtist : null);
const resolvedRomajiAA = romajiAlbumArtist || (romajiArtist ? romajiArtist.split(';')[0].trim() : null);
const effectiveAlbumArtistSort = albumArtistSort !== undefined ? albumArtistSort : (resolvedRomajiAA !== resolvedAlbumArtist ? resolvedRomajiAA : null);
const effectiveAlbumSort = albumSort !== undefined ? albumSort : (romajiAlbum !== album ? romajiAlbum : null);
if (effectiveTitleSort) ffArgs.push('-metadata', `TITLESORT=${effectiveTitleSort}`);
if (effectiveArtistSort) ffArgs.push('-metadata', `ARTISTSORT=${effectiveArtistSort}`);
if (effectiveAlbumArtistSort) ffArgs.push('-metadata', `ALBUMARTISTSORT=${effectiveAlbumArtistSort}`);
if (effectiveAlbumSort) ffArgs.push('-metadata', `ALBUMSORT=${effectiveAlbumSort}`);
if (year) ffArgs.push('-metadata', `date=${year}`);
if (trackNum) ffArgs.push('-metadata', `track=${totalTracks ? `${trackNum}/${totalTracks}` : String(trackNum)}`);
if (totalTracks) ffArgs.push('-metadata', `totaltracks=${String(totalTracks)}`);