debounced saving on settings page for all drop-down, tick boxes, input boxes and sliders.

pull/153/head
Broque Thomas 3 months ago
parent 8cf0950d3b
commit 1d50ece62c

@ -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…
Cancel
Save