diff --git a/backend/novasonic-server.js b/backend/novasonic-server.js index 352ca17..057d1f2 100644 --- a/backend/novasonic-server.js +++ b/backend/novasonic-server.js @@ -684,15 +684,52 @@ app.post('/api/edit-metadata', async (req, res) => { fs.renameSync(tmpFile, filePath); if (artFile) try { fs.unlinkSync(artFile); } catch {} - // Rename album folder if album changed and folder name matches old album dir - if (album) { - const dir = path.dirname(filePath); - const newDirName = sanitize(album); - if (path.basename(dir) !== newDirName) { - const newDir = path.join(path.dirname(dir), newDirName); - if (!fs.existsSync(newDir)) { - try { fs.renameSync(dir, newDir); } catch (e) { console.error('[edit-metadata] folder rename:', e.message); } + // ── 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 + 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); + if (newPath !== currentFile && !fs.existsSync(newPath)) { + try { fs.renameSync(currentFile, newPath); currentFile = newPath; } + catch (e) { console.error('[edit-metadata] file rename:', e.message); } + } + } + + // 2. Move to new artist/album folder when albumArtist or album changed + const oldAlbumDir = path.dirname(currentFile); + const oldArtistDir = path.dirname(oldAlbumDir); + const newAlbumName = album ? sanitize(album) : path.basename(oldAlbumDir); + const newArtistName = albumArtist ? sanitize(albumArtist.split(/[,;]/)[0].trim()) : path.basename(oldArtistDir); + const newDir = path.join(CONFIG.musicPath, newArtistName, newAlbumName); + + if (newDir !== oldAlbumDir) { + try { + fs.mkdirSync(newDir, { recursive: true }); + const destFile = path.join(newDir, path.basename(currentFile)); + if (!fs.existsSync(destFile)) { + fs.renameSync(currentFile, destFile); + currentFile = destFile; } + // Remove old album dir if now empty, then old artist dir if also empty + const oldAlbumLeft = fs.readdirSync(oldAlbumDir).filter(f => !f.startsWith('.')); + if (oldAlbumLeft.length === 0) { + try { fs.rmdirSync(oldAlbumDir); } catch {} + try { + const oldArtistLeft = fs.readdirSync(oldArtistDir).filter(f => !f.startsWith('.')); + if (oldArtistLeft.length === 0) fs.rmdirSync(oldArtistDir); + } catch {} + } + } catch (e) { console.error('[edit-metadata] move:', e.message); } + } else if (album && path.basename(oldAlbumDir) !== sanitize(album)) { + // Only album name changed (no artist move) — rename album folder in place + const renamedDir = path.join(oldArtistDir, sanitize(album)); + if (!fs.existsSync(renamedDir)) { + try { fs.renameSync(oldAlbumDir, renamedDir); } + catch (e) { console.error('[edit-metadata] folder rename:', e.message); } } }