Add $discnum to template variable list, validation, and docs

$discnum was functional but missing from the settings hint text,
template validation whitelist, and docs page. Users would see an
"invalid variable" error when trying to use it.

Also fixes wishlist auto-processing toast spam — was firing every 2s
instead of once per auto-processing run.
pull/253/head
Broque Thomas 2 months ago
parent 54b6c8f65f
commit d61a779b0e

@ -4818,7 +4818,7 @@
<input type="text" id="template-album-path"
placeholder="$albumartist/$albumartist - $album/$track - $title">
<small class="settings-hint">Variables: $albumartist, $artist, $artistletter, $album, $albumtype,
$title, $track, $disc, $year, $quality (filename only)</small>
$title, $track, $disc (01), $discnum (1), $year, $quality (filename only)</small>
</div>
<div class="form-group">

@ -766,7 +766,7 @@ const DOCS_SECTIONS = [
<li><strong>AcoustID Fingerprint Verification</strong> &mdash; If AcoustID is configured, the downloaded file is fingerprinted and compared against the expected track. Title and artist are fuzzy-matched (title &ge; 70% similarity, artist &ge; 60%). Files that fail verification are <strong>quarantined</strong> instead of added to your library. <em>Note: AcoustID is skipped for streaming sources (Tidal, Qobuz, Deezer, HiFi) since files are downloaded by exact track ID. However, streaming search results are still verified by artist and title matching before download to prevent wrong-track matches (e.g. same title, different artist).</em></li>
<li><strong>Metadata Tagging</strong> &mdash; The file is tagged with official metadata: title, artist, album artist, album, track number, disc number, year, genre, and composer. Tags are written using Mutagen (supports MP3, FLAC, OGG, M4A).</li>
<li><strong>Cover Art Embedding</strong> &mdash; Album artwork is downloaded from the metadata source and embedded directly into the audio file.</li>
<li><strong>File Organization</strong> &mdash; The file is renamed and moved to your transfer path following customizable templates. Separate templates for albums, singles, and playlists are configured in Settings. Available variables include <code>$artist</code>, <code>$album</code>, <code>$title</code>, <code>$track</code>, <code>$year</code>, <code>$quality</code>, and <code>$albumtype</code> (resolves to Album, Single, EP, or Compilation). For <strong>multi-disc albums</strong>, a <code>Disc N/</code> subfolder is automatically created when the album has more than one disc (or use <code>$disc</code> in your template for manual control).</li>
<li><strong>File Organization</strong> &mdash; The file is renamed and moved to your transfer path following customizable templates. Separate templates for albums, singles, and playlists are configured in Settings. Available variables include <code>$artist</code>, <code>$album</code>, <code>$title</code>, <code>$track</code>, <code>$year</code>, <code>$quality</code>, and <code>$albumtype</code> (resolves to Album, Single, EP, or Compilation). For <strong>multi-disc albums</strong>, a <code>Disc N/</code> subfolder is automatically created when the album has more than one disc (or use <code>$disc</code> for zero-padded "01" or <code>$discnum</code> for unpadded "1" in your template for manual control).</li>
<li><strong>Lyrics (LRC)</strong> &mdash; Synced lyrics are fetched from the LRClib API and saved as <code>.lrc</code> sidecar files alongside the audio file. Compatible media players (foobar2000, MusicBee, Plex, etc.) will display time-synced lyrics automatically. Falls back to plain-text lyrics if synced versions aren't available.</li>
<li><strong>Lossy Copy</strong> &mdash; If enabled in settings, a lower-bitrate copy is created alongside the original (useful for mobile device syncing).</li>
<li><strong>Media Server Scan</strong> &mdash; Your media server (Plex/Jellyfin) is notified to scan for the new file. Navidrome auto-detects changes.</li>

@ -3362,15 +3362,19 @@ function updateMediaScanFromData(data) {
}
}
let _wishlistAutoProcessingNotified = false;
function updateWishlistStatsFromData(data) {
// Auto-processing detection: close modal and notify
// Auto-processing detection: close modal and notify (once only)
if (data.is_auto_processing) {
if (typeof closeWishlistOverviewModal === 'function') {
if (!_wishlistAutoProcessingNotified && typeof closeWishlistOverviewModal === 'function') {
closeWishlistOverviewModal();
showToast('Wishlist auto-processing started. View progress in Download Manager.', 'info');
_wishlistAutoProcessingNotified = true;
}
return;
}
// Reset flag when auto-processing ends
_wishlistAutoProcessingNotified = false;
// Store latest stats for countdown timer refresh
_lastWishlistStats = data;
}
@ -5361,7 +5365,7 @@ function validateFileOrganizationTemplates() {
// Valid variables for each template type
const validVars = {
album: ['$artist', '$albumartist', '$artistletter', '$album', '$albumtype', '$title', '$track', '$disc', '$year', '$quality'],
album: ['$artist', '$albumartist', '$artistletter', '$album', '$albumtype', '$title', '$track', '$disc', '$discnum', '$year', '$quality'],
single: ['$artist', '$albumartist', '$artistletter', '$album', '$albumtype', '$title', '$year', '$quality'],
playlist: ['$artist', '$artistletter', '$playlist', '$title', '$year', '$quality']
};
@ -12891,8 +12895,11 @@ function startWishlistCountdownTimer(currentCycle, initialSeconds) {
if (socketConnected && _lastWishlistStats) {
const data = _lastWishlistStats;
if (data.is_auto_processing) {
closeWishlistOverviewModal();
showToast('Wishlist auto-processing started. View progress in Download Manager.', 'info');
if (!_wishlistAutoProcessingNotified) {
closeWishlistOverviewModal();
showToast('Wishlist auto-processing started. View progress in Download Manager.', 'info');
_wishlistAutoProcessingNotified = true;
}
return;
}
if (remainingSeconds <= 0) {
@ -12908,11 +12915,14 @@ function startWishlistCountdownTimer(currentCycle, initialSeconds) {
const response = await fetch('/api/wishlist/stats');
const data = await response.json();
// AUTO-CLOSE DETECTION: If auto-processing started, close modal and notify user
// AUTO-CLOSE DETECTION: If auto-processing started, close modal and notify user (once)
if (data.is_auto_processing) {
console.log('🤖 [Wishlist] Auto-processing detected, closing overview modal');
closeWishlistOverviewModal();
showToast('Wishlist auto-processing started. View progress in Download Manager.', 'info');
if (!_wishlistAutoProcessingNotified) {
console.log('🤖 [Wishlist] Auto-processing detected, closing overview modal');
closeWishlistOverviewModal();
showToast('Wishlist auto-processing started. View progress in Download Manager.', 'info');
_wishlistAutoProcessingNotified = true;
}
return; // Exit interval
}

Loading…
Cancel
Save