debounced saving on settings page for all drop-down, tick boxes, input boxes and sliders.
This commit is contained in:
parent
8cf0950d3b
commit
1d50ece62c
2 changed files with 52 additions and 13 deletions
|
|
@ -1542,14 +1542,39 @@ async function copyAddress(address, cryptoName) {
|
|||
// SETTINGS FUNCTIONALITY
|
||||
// ===============================
|
||||
|
||||
let settingsAutoSaveTimer = null;
|
||||
|
||||
function debouncedAutoSaveSettings() {
|
||||
if (settingsAutoSaveTimer) clearTimeout(settingsAutoSaveTimer);
|
||||
settingsAutoSaveTimer = setTimeout(() => saveSettings(true), 2000);
|
||||
}
|
||||
|
||||
function handleManualSaveClick() {
|
||||
if (settingsAutoSaveTimer) clearTimeout(settingsAutoSaveTimer);
|
||||
saveSettings(false);
|
||||
}
|
||||
|
||||
function initializeSettings() {
|
||||
// This function is called when the settings page is loaded.
|
||||
// It attaches event listeners to all interactive elements on the page.
|
||||
|
||||
// Main save button
|
||||
// Main save button (manual save, non-quiet)
|
||||
// Uses named function reference so addEventListener deduplicates across repeated calls
|
||||
const saveButton = document.getElementById('save-settings');
|
||||
if (saveButton) {
|
||||
saveButton.addEventListener('click', saveSettings);
|
||||
saveButton.addEventListener('click', handleManualSaveClick);
|
||||
}
|
||||
|
||||
// Debounced auto-save on all settings inputs
|
||||
// Uses named function reference (debouncedAutoSaveSettings) so addEventListener deduplicates
|
||||
const settingsPage = document.getElementById('settings-page');
|
||||
if (settingsPage) {
|
||||
settingsPage.querySelectorAll('input[type="text"], input[type="url"], input[type="password"], input[type="number"], input[type="range"]').forEach(input => {
|
||||
input.addEventListener('input', debouncedAutoSaveSettings);
|
||||
});
|
||||
settingsPage.querySelectorAll('input[type="checkbox"], select').forEach(input => {
|
||||
input.addEventListener('change', debouncedAutoSaveSettings);
|
||||
});
|
||||
}
|
||||
|
||||
// Server toggle buttons
|
||||
|
|
@ -1592,7 +1617,7 @@ function resetFileOrganizationTemplates() {
|
|||
document.getElementById('template-single-path').value = defaults.single;
|
||||
document.getElementById('template-playlist-path').value = defaults.playlist;
|
||||
|
||||
showToast('Templates reset to defaults. Click "Save Settings" to apply.', 'success');
|
||||
debouncedAutoSaveSettings();
|
||||
}
|
||||
|
||||
function validateFileOrganizationTemplates() {
|
||||
|
|
@ -1886,6 +1911,9 @@ function toggleServer(serverType) {
|
|||
loadJellyfinUsers();
|
||||
loadJellyfinMusicLibraries();
|
||||
}
|
||||
|
||||
// Auto-save after server toggle change
|
||||
debouncedAutoSaveSettings();
|
||||
}
|
||||
|
||||
function updateDownloadSourceUI() {
|
||||
|
|
@ -2112,11 +2140,11 @@ async function saveQualityProfile() {
|
|||
// END QUALITY PROFILE FUNCTIONS
|
||||
// ===============================
|
||||
|
||||
async function saveSettings() {
|
||||
async function saveSettings(quiet = false) {
|
||||
// Validate file organization templates before saving
|
||||
const validationErrors = validateFileOrganizationTemplates();
|
||||
if (validationErrors.length > 0) {
|
||||
showToast('Template validation failed: ' + validationErrors.join(', '), 'error');
|
||||
if (!quiet) showToast('Template validation failed: ' + validationErrors.join(', '), 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2197,7 +2225,7 @@ async function saveSettings() {
|
|||
};
|
||||
|
||||
try {
|
||||
showLoadingOverlay('Saving settings...');
|
||||
if (!quiet) showLoadingOverlay('Saving settings...');
|
||||
|
||||
// Save main settings
|
||||
const response = await fetch(API.settings, {
|
||||
|
|
@ -2228,8 +2256,7 @@ async function saveSettings() {
|
|||
}
|
||||
|
||||
if (result.success && qualityProfileSaved && lookbackSaved) {
|
||||
showToast('Settings saved successfully', 'success');
|
||||
// Trigger immediate status update
|
||||
showToast(quiet ? 'Settings auto-saved' : 'Settings saved successfully', 'success');
|
||||
setTimeout(updateServiceStatus, 1000);
|
||||
} else if (result.success && qualityProfileSaved && !lookbackSaved) {
|
||||
showToast('Settings saved, but discovery lookback period failed to save', 'warning');
|
||||
|
|
@ -2244,7 +2271,7 @@ async function saveSettings() {
|
|||
console.error('Error saving settings:', error);
|
||||
showToast('Failed to save settings', 'error');
|
||||
} finally {
|
||||
hideLoadingOverlay();
|
||||
if (!quiet) hideLoadingOverlay();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8246,8 +8246,15 @@ body {
|
|||
}
|
||||
|
||||
@keyframes batchBarSlideIn {
|
||||
from { opacity: 0; transform: translateY(-8px); }
|
||||
to { opacity: 1; transform: translateY(0); }
|
||||
from {
|
||||
opacity: 0;
|
||||
transform: translateY(-8px);
|
||||
}
|
||||
|
||||
to {
|
||||
opacity: 1;
|
||||
transform: translateY(0);
|
||||
}
|
||||
}
|
||||
|
||||
.watchlist-batch-count {
|
||||
|
|
@ -8301,12 +8308,12 @@ body {
|
|||
background: rgba(255, 255, 255, 0.06);
|
||||
}
|
||||
|
||||
.watchlist-checkbox-wrapper input:checked + .watchlist-checkbox-custom {
|
||||
.watchlist-checkbox-wrapper input:checked+.watchlist-checkbox-custom {
|
||||
background: rgba(29, 185, 84, 0.3);
|
||||
border-color: #1db954;
|
||||
}
|
||||
|
||||
.watchlist-checkbox-wrapper input:checked + .watchlist-checkbox-custom::after {
|
||||
.watchlist-checkbox-wrapper input:checked+.watchlist-checkbox-custom::after {
|
||||
content: '✓';
|
||||
color: #1db954;
|
||||
font-size: 13px;
|
||||
|
|
@ -13212,6 +13219,11 @@ body {
|
|||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
#artist-hero-section #artist-detail-image {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.artist-detail-image {
|
||||
width: 200px;
|
||||
height: 200px;
|
||||
|
|
|
|||
Loading…
Reference in a new issue