413 lines
22 KiB
HTML
413 lines
22 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
<head>
|
|
<meta charset="UTF-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
<title>Configuration - Spotizerr</title>
|
|
<!-- Add the new base.css first -->
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/main/base.css') }}" />
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/config/config.css') }}" />
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/main/icons.css') }}">
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='css/queue/queue.css') }}">
|
|
</head>
|
|
<body>
|
|
<div class="app-container">
|
|
<div class="config-container">
|
|
<header class="config-header">
|
|
<h1 class="header-title">Configuration</h1>
|
|
<span class="version-text">Set on build</span>
|
|
</header>
|
|
|
|
<div class="account-config card">
|
|
<h2 class="section-title">Download Settings</h2>
|
|
<!-- Default service selection - new element -->
|
|
<div class="config-item">
|
|
<label>Default Service:</label>
|
|
<select id="defaultServiceSelect" class="form-select">
|
|
<option value="spotify">Spotify</option>
|
|
</select>
|
|
<div class="setting-description">
|
|
The default service to use for downloads when not explicitly specified
|
|
</div>
|
|
</div>
|
|
<!-- Your account config section remains unchanged -->
|
|
<div class="config-item spotify-specific">
|
|
<label>Active Spotify Account:</label>
|
|
<select id="spotifyAccountSelect" class="form-select"></select>
|
|
<div id="spotifyAccountMessage" style="display: none; color: #888; margin-top: 5px;"></div>
|
|
</div>
|
|
<div class="config-item spotify-specific">
|
|
<label>Spotify Quality:</label>
|
|
<select id="spotifyQualitySelect" class="form-select">
|
|
<option value="NORMAL">OGG 96</option>
|
|
<option value="HIGH">OGG 160</option>
|
|
<option value="VERY_HIGH">OGG 320 (premium)</option>
|
|
</select>
|
|
</div>
|
|
<div class="config-item deezer-specific">
|
|
<label>Active Deezer Account:</label>
|
|
<select id="deezerAccountSelect" class="form-select"></select>
|
|
<div id="deezerAccountMessage" style="display: none; color: #888; margin-top: 5px;"></div>
|
|
</div>
|
|
<div class="config-item deezer-specific">
|
|
<label>Deezer Quality:</label>
|
|
<select id="deezerQualitySelect" class="form-select">
|
|
<option value="MP3_128">MP3 128</option>
|
|
<option value="MP3_320">MP3 320 (sometimes premium)</option>
|
|
<option value="FLAC">FLAC (premium)</option>
|
|
</select>
|
|
</div>
|
|
<!-- Explicit Filter Status -->
|
|
<div class="config-item">
|
|
<label>Explicit Content Filter:</label>
|
|
<div class="env-controlled-setting">
|
|
<span id="explicitFilterStatus" class="env-controlled-value">Loading...</span>
|
|
<div class="env-controlled-badge">ENV</div>
|
|
</div>
|
|
<div class="setting-description">
|
|
Filter explicit content. Controlled by environment variable EXPLICIT_FILTER.
|
|
</div>
|
|
</div>
|
|
<div class="config-item">
|
|
<label>Download Fallback:</label>
|
|
<label class="switch">
|
|
<input type="checkbox" id="fallbackToggle" />
|
|
<span class="slider"></span>
|
|
</label>
|
|
</div>
|
|
<div class="config-item">
|
|
<label>Real time downloading:</label>
|
|
<label class="switch">
|
|
<input type="checkbox" id="realTimeToggle" />
|
|
<span class="slider"></span>
|
|
</label>
|
|
</div>
|
|
<div class="config-item">
|
|
<label for="maxConcurrentDownloads">Max Concurrent Downloads:</label>
|
|
<input type="number" id="maxConcurrentDownloads" min="1" value="3" class="form-input">
|
|
</div>
|
|
|
|
<!-- New Conversion Options -->
|
|
<h2 class="section-title">Conversion Settings</h2>
|
|
<div class="config-item">
|
|
<label for="convertToSelect">Convert To Format:</label>
|
|
<select id="convertToSelect" class="form-select">
|
|
<option value="">No Conversion</option>
|
|
<option value="MP3">MP3</option>
|
|
<option value="AAC">AAC</option>
|
|
<option value="OGG">OGG</option>
|
|
<option value="OPUS">OPUS</option>
|
|
<option value="FLAC">FLAC</option>
|
|
<option value="WAV">WAV</option>
|
|
<option value="ALAC">ALAC</option>
|
|
</select>
|
|
<div class="setting-description">
|
|
Select a format to convert downloaded files to. "No Conversion" keeps the original format.
|
|
</div>
|
|
</div>
|
|
<div class="config-item">
|
|
<label for="bitrateSelect">Bitrate:</label>
|
|
<select id="bitrateSelect" class="form-select" disabled>
|
|
<!-- Options will be populated by JavaScript -->
|
|
<option value="">N/A</option>
|
|
</select>
|
|
<div class="setting-description">
|
|
Select the bitrate for the chosen format. Only applicable for lossy formats.
|
|
</div>
|
|
</div>
|
|
|
|
<!-- New Retry Options -->
|
|
<h2 class="section-title">Retry Options</h2>
|
|
<div class="config-item">
|
|
<label for="maxRetries">Max Retry Attempts:</label>
|
|
<input type="number" id="maxRetries" min="0" max="10" value="3" class="form-input">
|
|
</div>
|
|
<div class="config-item">
|
|
<label for="retryDelaySeconds">Initial Retry Delay (seconds):</label>
|
|
<input type="number" id="retryDelaySeconds" min="1" value="5" class="form-input">
|
|
</div>
|
|
<div class="config-item">
|
|
<label for="retryDelayIncrease">Retry Delay Increase (seconds):</label>
|
|
<input type="number" id="retryDelayIncrease" min="0" value="5" class="form-input">
|
|
<div class="setting-description">
|
|
The amount of additional delay to add for each retry attempt
|
|
</div>
|
|
</div>
|
|
<!-- New Formatting Options -->
|
|
<h2 class="section-title">Formatting Options</h2>
|
|
<div class="config-item">
|
|
<label>Custom Directory Format:</label>
|
|
<input
|
|
type="text"
|
|
id="customDirFormat"
|
|
placeholder="e.g. %artist%/%album%"
|
|
class="form-input"
|
|
/>
|
|
<div class="format-help">
|
|
<select id="dirFormatHelp" class="format-selector">
|
|
<option value="">-- Select placeholder --</option>
|
|
<optgroup label="Common">
|
|
<option value="%music%">%music% - Track title</option>
|
|
<option value="%artist%">%artist% - Track artist. If multiple artists, use %artist_1%, %artist_2%, etc. to select a specific one.</option>
|
|
<option value="%album%">%album% - Album name</option>
|
|
<option value="%ar_album%">%ar_album% - Album artist. If multiple album artists, use %ar_album_1%, %ar_album_2%, etc. to select a specific one.</option>
|
|
<option value="%tracknum%">%tracknum% - Track number</option>
|
|
<option value="%year%">%year% - Year of release</option>
|
|
</optgroup>
|
|
<optgroup label="Additional">
|
|
<option value="%discnum%">%discnum% - Disc number</option>
|
|
<option value="%date%">%date% - Release date</option>
|
|
<option value="%genre%">%genre% - Music genre</option>
|
|
<option value="%isrc%">%isrc% - International Standard Recording Code</option>
|
|
<option value="%explicit%">%explicit% - Explicit content flag</option>
|
|
<option value="%duration%">%duration% - Track duration (seconds)</option>
|
|
</optgroup>
|
|
<optgroup label="Metadata">
|
|
<option value="%publisher%">%publisher% - Publisher information</option>
|
|
<option value="%composer%">%composer% - Track composer</option>
|
|
<option value="%copyright%">%copyright% - Copyright information</option>
|
|
<option value="%author%">%author% - Author information</option>
|
|
<option value="%lyricist%">%lyricist% - Lyricist information</option>
|
|
<option value="%version%">%version% - Version information</option>
|
|
<option value="%comment%">%comment% - Comment field</option>
|
|
</optgroup>
|
|
<optgroup label="Other">
|
|
<option value="%encodedby%">%encodedby% - Encoded by information</option>
|
|
<option value="%language%">%language% - Language information</option>
|
|
<option value="%lyrics%">%lyrics% - Track lyrics</option>
|
|
<option value="%mood%">%mood% - Mood information</option>
|
|
<option value="%rating%">%rating% - Track rating</option>
|
|
<option value="%website%">%website% - Website information</option>
|
|
</optgroup>
|
|
<optgroup label="ReplayGain">
|
|
<option value="%replaygain_album_gain%">%replaygain_album_gain% - Album gain</option>
|
|
<option value="%replaygain_album_peak%">%replaygain_album_peak% - Album peak</option>
|
|
<option value="%replaygain_track_gain%">%replaygain_track_gain% - Track gain</option>
|
|
<option value="%replaygain_track_peak%">%replaygain_track_peak% - Track peak</option>
|
|
</optgroup>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
<div class="config-item">
|
|
<label>Custom Track Format:</label>
|
|
<input
|
|
type="text"
|
|
id="customTrackFormat"
|
|
placeholder="e.g. %tracknum% - %music%"
|
|
class="form-input"
|
|
/>
|
|
<div class="format-help">
|
|
<select id="trackFormatHelp" class="format-selector">
|
|
<option value="">-- Select placeholder --</option>
|
|
<optgroup label="Common">
|
|
<option value="%music%">%music% - Track title</option>
|
|
<option value="%artist%">%artist% - Track artist. If multiple artists, use %artist_1%, %artist_2%, etc. to select a specific one.</option>
|
|
<option value="%album%">%album% - Album name</option>
|
|
<option value="%ar_album%">%ar_album% - Album artist. If multiple album artists, use %ar_album_1%, %ar_album_2%, etc. to select a specific one.</option>
|
|
<option value="%tracknum%">%tracknum% - Track number</option>
|
|
<option value="%year%">%year% - Year of release</option>
|
|
</optgroup>
|
|
<optgroup label="Additional">
|
|
<option value="%discnum%">%discnum% - Disc number</option>
|
|
<option value="%date%">%date% - Release date</option>
|
|
<option value="%genre%">%genre% - Music genre</option>
|
|
<option value="%isrc%">%isrc% - International Standard Recording Code</option>
|
|
<option value="%explicit%">%explicit% - Explicit content flag</option>
|
|
<option value="%duration%">%duration% - Track duration (seconds)</option>
|
|
</optgroup>
|
|
<optgroup label="Metadata">
|
|
<option value="%publisher%">%publisher% - Publisher information</option>
|
|
<option value="%composer%">%composer% - Track composer</option>
|
|
<option value="%copyright%">%copyright% - Copyright information</option>
|
|
<option value="%author%">%author% - Author information</option>
|
|
<option value="%lyricist%">%lyricist% - Lyricist information</option>
|
|
<option value="%version%">%version% - Version information</option>
|
|
<option value="%comment%">%comment% - Comment field</option>
|
|
</optgroup>
|
|
<optgroup label="Other">
|
|
<option value="%encodedby%">%encodedby% - Encoded by information</option>
|
|
<option value="%language%">%language% - Language information</option>
|
|
<option value="%lyrics%">%lyrics% - Track lyrics</option>
|
|
<option value="%mood%">%mood% - Mood information</option>
|
|
<option value="%rating%">%rating% - Track rating</option>
|
|
<option value="%website%">%website% - Website information</option>
|
|
<option value="%quality%">%quality% - Quality of the track</option>
|
|
</optgroup>
|
|
<optgroup label="ReplayGain">
|
|
<option value="%replaygain_album_gain%">%replaygain_album_gain% - Album gain</option>
|
|
<option value="%replaygain_album_peak%">%replaygain_album_peak% - Album peak</option>
|
|
<option value="%replaygain_track_gain%">%replaygain_track_gain% - Track gain</option>
|
|
<option value="%replaygain_track_peak%">%replaygain_track_peak% - Track peak</option>
|
|
</optgroup>
|
|
</select>
|
|
</div>
|
|
<div class="setting-description">
|
|
Note that these placeholder depend on the metadata of the track, if one entry is not available in a track, the placeholder will be replaced with an empty string.
|
|
</div>
|
|
</div>
|
|
<!-- New Track Number Padding Toggle -->
|
|
<div class="config-item">
|
|
<label>Track Number Padding:</label>
|
|
<label class="switch">
|
|
<input type="checkbox" id="tracknumPaddingToggle" />
|
|
<span class="slider"></span>
|
|
</label>
|
|
<div class="setting-description">
|
|
When enabled: "01. Track" - When disabled: "1. Track"
|
|
</div>
|
|
</div>
|
|
<!-- New Save Cover Art Toggle -->
|
|
<div class="config-item">
|
|
<label>Save Cover Art:</label>
|
|
<label class="switch">
|
|
<input type="checkbox" id="saveCoverToggle" />
|
|
<span class="slider"></span>
|
|
</label>
|
|
<div class="setting-description">
|
|
When enabled, cover art will saved as cover.jpg in the same directory as the track.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="watch-options-config card">
|
|
<h2 class="section-title">Watch Options</h2>
|
|
<div class="config-item">
|
|
<label>Enable Watch Feature:</label>
|
|
<label class="switch">
|
|
<input type="checkbox" id="watchEnabledToggle" />
|
|
<span class="slider"></span>
|
|
</label>
|
|
<div class="setting-description">
|
|
Enable or disable the entire watch feature (monitoring playlists and artists for new content).
|
|
</div>
|
|
</div>
|
|
<div id="watchEnabledWarning" class="config-item urgent-warning-message" style="display: none;">
|
|
<svg class="warning-icon" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="currentColor" width="24px" height="24px"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"/></svg>
|
|
Warning: Enable "Real time downloading" in the Download Settings to avoid rate-limiting issues. If you don't, you WILL (pretty much immediately) encounter API rate limits, and the watch feature WILL break.
|
|
</div>
|
|
<div class="config-item">
|
|
<label for="watchedArtistAlbumGroup">Artist Page - Album Groups to Watch:</label>
|
|
<div id="watchedArtistAlbumGroupChecklist" class="checklist-container">
|
|
<div class="checklist-item">
|
|
<input type="checkbox" id="albumGroup-album" name="watchedArtistAlbumGroup" value="album">
|
|
<label for="albumGroup-album">Album</label>
|
|
</div>
|
|
<div class="checklist-item">
|
|
<input type="checkbox" id="albumGroup-single" name="watchedArtistAlbumGroup" value="single">
|
|
<label for="albumGroup-single">Single</label>
|
|
</div>
|
|
<div class="checklist-item">
|
|
<input type="checkbox" id="albumGroup-compilation" name="watchedArtistAlbumGroup" value="compilation">
|
|
<label for="albumGroup-compilation">Compilation</label>
|
|
</div>
|
|
<div class="checklist-item">
|
|
<input type="checkbox" id="albumGroup-appears_on" name="watchedArtistAlbumGroup" value="appears_on">
|
|
<label for="albumGroup-appears_on">Appears On</label>
|
|
</div>
|
|
</div>
|
|
<div class="setting-description">
|
|
Select which album groups to monitor on watched artist pages.
|
|
</div>
|
|
</div>
|
|
<div class="config-item">
|
|
<label for="watchPollIntervalSeconds">Watch Poll Interval (seconds):</label>
|
|
<input type="number" id="watchPollIntervalSeconds" min="60" value="3600" class="form-input">
|
|
<div class="setting-description">
|
|
How often to check watched items for updates (e.g., new playlist tracks, new artist albums).
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="master-accounts-config-section">
|
|
<h2 class="section-title">Accounts configuration</h2>
|
|
|
|
<!-- Global Spotify API Credentials Card: MOVED HERE -->
|
|
<div class="global-api-keys-config card"> <!-- Changed class to global-api-keys-config -->
|
|
<h2 class="section-title">Global Spotify API Credentials</h2>
|
|
<div class="config-item">
|
|
<label for="globalSpotifyClientId">Client ID:</label>
|
|
<input type="text" id="globalSpotifyClientId" class="form-input" placeholder="Enter your Spotify Client ID">
|
|
</div>
|
|
<div class="config-item">
|
|
<label for="globalSpotifyClientSecret">Client Secret:</label>
|
|
<input type="password" id="globalSpotifyClientSecret" class="form-input" placeholder="Enter your Spotify Client Secret">
|
|
</div>
|
|
<div class="config-item">
|
|
<button id="saveSpotifyApiConfigBtn" class="btn btn-primary">Save</button>
|
|
</div>
|
|
<div id="spotifyApiConfigStatus" class="status-message" style="margin-top: 10px;"></div>
|
|
</div>
|
|
<!-- End Global Spotify API Credentials Card -->
|
|
|
|
<div class="accounts-section">
|
|
<div class="service-tabs">
|
|
<button class="tab-button active" data-service="spotify">Spotify</button>
|
|
<button class="tab-button" data-service="deezer">Deezer</button>
|
|
</div>
|
|
|
|
<!-- Wrapper for the list and the add button -->
|
|
<div class="credentials-list-wrapper card">
|
|
<div class="credentials-list-items">
|
|
<!-- Dynamic credential items will be rendered here by JavaScript -->
|
|
<!-- "No credentials" message will also be rendered here -->
|
|
</div>
|
|
<div class="add-account-item">
|
|
<button id="showAddAccountFormBtn" class="btn-add-account-styled" type="button">
|
|
<img src="{{ url_for('static', filename='images/plus-circle.svg') }}" alt="Add" /> Add New Account
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="credentials-form card">
|
|
<h2 id="formTitle" class="section-title">Add New Spotify Account</h2>
|
|
<form id="credentialForm">
|
|
<div id="serviceFields"></div>
|
|
<!-- Region Hints START -->
|
|
<div id="spotifyRegionHint" class="setting-description" style="display:none; margin-left: 10px; margin-top: -5px; margin-bottom:15px; font-size: 0.9em;">
|
|
<small>Region not matching your account may lead to issues. Check it <a href="https://www.spotify.com/mx/account/profile/" target="_blank" rel="noopener noreferrer">here</a>.</small>
|
|
</div>
|
|
<div id="deezerRegionHint" class="setting-description" style="display:none; margin-left: 10px; margin-top: -5px; margin-bottom:15px; font-size: 0.9em;">
|
|
<small>Region not matching your account may lead to issues. Check it <a href="https://www.deezer.com/account/country_selector" target="_blank" rel="noopener noreferrer">here</a>.</small>
|
|
</div>
|
|
<!-- Region Hints END -->
|
|
<div id="searchFields" style="display: none;"></div>
|
|
<button type="submit" id="submitCredentialBtn" class="btn btn-primary save-btn">Save Account</button>
|
|
<button type="button" id="cancelAddAccountBtn" class="btn btn-secondary cancel-btn btn-cancel-icon" style="margin-left: 10px;" title="Cancel">
|
|
<img src="{{ url_for('static', filename='images/cross.svg') }}" alt="Cancel" />
|
|
</button>
|
|
</form>
|
|
<div id="configSuccess" class="success"></div>
|
|
<div id="configError" class="error"></div>
|
|
</div>
|
|
</div>
|
|
</div> <!-- End of accounts-section -->
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Fixed floating buttons for back and queue -->
|
|
<a href="/history" class="btn-icon history-nav-btn floating-icon settings-icon" aria-label="Download History" title="Go to Download History">
|
|
<img src="{{ url_for('static', filename='images/history.svg') }}" alt="History" onerror="handleImageError(this)"/>
|
|
</a>
|
|
<a href="/" class="back-button floating-icon settings-icon" aria-label="Back to app">
|
|
<img src="{{ url_for('static', filename='images/arrow-left.svg') }}" alt="Back" />
|
|
</a>
|
|
|
|
<a id="watchlistButton" href="/watchlist" class="btn-icon watchlist-icon floating-icon hidden" aria-label="Watchlist" title="Go to Watchlist">
|
|
<img src="{{ url_for('static', filename='images/binoculars.svg') }}" alt="Watchlist" onerror="handleImageError(this)"/>
|
|
</a>
|
|
|
|
<button
|
|
id="queueIcon"
|
|
class="btn-icon queue-icon floating-icon"
|
|
aria-label="Download queue"
|
|
aria-controls="downloadQueue"
|
|
aria-expanded="false"
|
|
>
|
|
<img src="{{ url_for('static', filename='images/queue.svg') }}" alt="Queue" />
|
|
</button>
|
|
|
|
<!-- Load config.js as a module so you can import queue.js -->
|
|
<script type="module" src="{{ url_for('static', filename='js/config.js') }}"></script>
|
|
</body>
|
|
</html>
|