feat: artist in filename, hide album=title subtitle, remove title hover

Naming convention (download + edit-metadata):
  Before: {01 - }Title.ext
  After:  {01 - }Artist1, Artist2 - Title.ext
- ytdlp.js: builds fileBase with artist prefix; findExistingTrack checks
  both new and old format so existing files aren't re-downloaded
- metadata.js: findExistingTrack accepts optional safeArtist param
- novasonic-server.js: file rename on title edit now includes artist
  (falls back to Navidrome's stored artist if not provided in body)

Song list subtitle: hide album name when album === title (singles where
the album is named after the track appear to duplicate the title)

Player bar: removed .player-title:hover underline/colour effect

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
HoneyandClaude Sonnet 4.6 committed 2026-05-23 22:33:35 +02:00
1 parent 2dd3d7c7e5
commit 7ba5b8ce9a
5 files changed
+26 -17

No files matched your search

+9 -6
View File
@@ -604,7 +604,8 @@ app.post('/api/edit-metadata', async (req, res) => {
const ndApi = `${ndUrl}/rest/getSong?id=${songId}&u=${encodeURIComponent(user)}&t=${token}&s=${salt}&v=1.16.1&c=novasonic&f=json`;
const ndRes = await fetch(ndApi, { signal: AbortSignal.timeout(8000) });
const ndData = await ndRes.json();
filePath = ndData?.['subsonic-response']?.song?.path;
const ndSong = ndData?.['subsonic-response']?.song;
filePath = ndSong?.path;
if (!filePath) return res.status(404).json({ error: 'Song not found in Navidrome' });
} catch (e) {
return res.status(502).json({ error: `Navidrome lookup failed: ${e.message}` });
@@ -687,12 +688,14 @@ app.post('/api/edit-metadata', async (req, res) => {
// ── Post-save: rename file and/or move to correct artist/album folder ──
let currentFile = filePath;
// 1. Rename file if title changed — convention: {01 - }?{sanitized title}.ext
// 1. Rename file if title changed — convention: {01 - }?{Artist} - {Title}.ext
if (title) {
const safeTitle = sanitize(title);
const prefix = trackNum ? String(trackNum).padStart(2, '0') + ' - ' : '';
const newName = `${prefix}${safeTitle}${fileExt}`;
const newPath = path.join(path.dirname(currentFile), newName);
const safeTitle = sanitize(title);
const fileArtist = (artist || ndSong?.artist || '').replace(/;/g, ',');
const safeArtistPart = fileArtist ? sanitize(fileArtist) + ' - ' : '';
const prefix = trackNum ? String(trackNum).padStart(2, '0') + ' - ' : '';
const newName = `${prefix}${safeArtistPart}${safeTitle}${fileExt}`;
const newPath = path.join(path.dirname(currentFile), newName);
if (newPath !== currentFile && !fs.existsSync(newPath)) {
try { fs.renameSync(currentFile, newPath); currentFile = newPath; }
catch (e) { console.error('[edit-metadata] file rename:', e.message); }