/** * AniWorld - Main Config Module * * Handles main configuration (directory, connection) and config management * (backup, export, validate, reset). * * Dependencies: constants.js, api-client.js, ui-utils.js */ var AniWorld = window.AniWorld || {}; AniWorld.MainConfig = (function() { 'use strict'; const API = AniWorld.Constants.API; /** * Save main configuration */ async function save() { try { const animeDirectory = document.getElementById('anime-directory-input').value.trim(); const appName = document.getElementById('app-name-input').value.trim(); const dataDir = document.getElementById('data-dir-input').value.trim(); if (!animeDirectory) { AniWorld.UI.showToast('Please enter an anime directory path', 'error'); return; } // Get current config const currentConfig = await loadCurrentConfig(); if (!currentConfig) { AniWorld.UI.showToast('Failed to load current configuration', 'error'); return; } // Update fields if (appName) currentConfig.name = appName; if (dataDir) currentConfig.data_dir = dataDir; if (!currentConfig.other) currentConfig.other = {}; currentConfig.other.anime_directory = animeDirectory; // Save updated config const response = await AniWorld.ApiClient.put(AniWorld.Constants.API.CONFIG, currentConfig); if (!response) return; const data = await response.json(); AniWorld.UI.showToast('Main configuration saved successfully', 'success'); await refreshStatus(); } catch (error) { console.error('Error saving main config:', error); AniWorld.UI.showToast('Failed to save main configuration', 'error'); } } /** * Load current configuration from API */ async function loadCurrentConfig() { try { const response = await AniWorld.ApiClient.get(AniWorld.Constants.API.CONFIG); if (!response) return null; return await response.json(); } catch (error) { console.error('Error loading config:', error); return null; } } /** * Reset main configuration */ function reset() { if (confirm('Are you sure you want to reset the main configuration? This will clear the anime directory.')) { document.getElementById('anime-directory-input').value = ''; document.getElementById('series-count-input').value = '0'; AniWorld.UI.showToast('Main configuration reset', 'info'); } } /** * Test network connection */ async function testConnection() { try { AniWorld.UI.showToast('Testing connection...', 'info'); const response = await AniWorld.ApiClient.get(API.DIAGNOSTICS_NETWORK); if (!response) return; const data = await response.json(); if (data.status === 'success') { const networkStatus = data.data; const connectionDiv = document.getElementById('connection-status-display'); const statusIndicator = connectionDiv.querySelector('.status-indicator'); const statusText = connectionDiv.querySelector('.status-text'); if (networkStatus.aniworld_reachable) { statusIndicator.className = 'status-indicator connected'; statusText.textContent = 'Connected'; AniWorld.UI.showToast('Connection test successful', 'success'); } else { statusIndicator.className = 'status-indicator disconnected'; statusText.textContent = 'Disconnected'; AniWorld.UI.showToast('Connection test failed', 'error'); } } else { AniWorld.UI.showToast('Connection test failed', 'error'); } } catch (error) { console.error('Error testing connection:', error); AniWorld.UI.showToast('Connection test failed', 'error'); } } /** * Browse for directory */ function browseDirectory() { const currentPath = document.getElementById('anime-directory-input').value; const newPath = prompt('Enter the anime directory path:', currentPath); if (newPath !== null && newPath.trim() !== '') { document.getElementById('anime-directory-input').value = newPath.trim(); } } /** * Refresh status display */ async function refreshStatus() { try { // Load full configuration const config = await loadCurrentConfig(); if (!config) return; // Populate general settings document.getElementById('app-name-input').value = config.name || 'Aniworld'; document.getElementById('data-dir-input').value = config.data_dir || 'data'; document.getElementById('anime-directory-input').value = config.other?.anime_directory || ''; // Populate scheduler settings document.getElementById('scheduled-rescan-enabled').checked = config.scheduler?.enabled || false; document.getElementById('scheduled-rescan-interval').value = config.scheduler?.interval_minutes || 60; // Populate logging settings document.getElementById('log-level').value = config.logging?.level || 'INFO'; document.getElementById('log-file').value = config.logging?.file || ''; document.getElementById('log-max-bytes').value = config.logging?.max_bytes || ''; document.getElementById('log-backup-count').value = config.logging?.backup_count || 3; // Populate backup settings document.getElementById('backup-enabled').checked = config.backup?.enabled || false; document.getElementById('backup-path').value = config.backup?.path || 'data/backups'; document.getElementById('backup-keep-days').value = config.backup?.keep_days || 30; // Populate NFO settings document.getElementById('tmdb-api-key').value = config.nfo?.tmdb_api_key || ''; document.getElementById('nfo-auto-create').checked = config.nfo?.auto_create || false; document.getElementById('nfo-update-on-scan').checked = config.nfo?.update_on_scan || false; document.getElementById('nfo-download-poster').checked = config.nfo?.download_poster !== false; document.getElementById('nfo-download-logo').checked = config.nfo?.download_logo !== false; document.getElementById('nfo-download-fanart').checked = config.nfo?.download_fanart !== false; document.getElementById('nfo-image-size').value = config.nfo?.image_size || 'original'; // Get series count from status endpoint const statusResponse = await AniWorld.ApiClient.get(API.ANIME_STATUS); if (statusResponse) { const statusData = await statusResponse.json(); document.getElementById('series-count-input').value = statusData.series_count || '0'; } } catch (error) { console.error('Error refreshing status:', error); } } /** * Create configuration backup */ async function createBackup() { const backupName = prompt('Enter backup name (optional):'); try { const response = await AniWorld.ApiClient.request(API.CONFIG_BACKUP, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: backupName || '' }) }); if (!response) return; const data = await response.json(); if (data.success) { AniWorld.UI.showToast('Backup created: ' + data.filename, 'success'); } else { AniWorld.UI.showToast('Failed to create backup: ' + data.error, 'error'); } } catch (error) { console.error('Error creating backup:', error); AniWorld.UI.showToast('Failed to create backup', 'error'); } } /** * View configuration backups */ async function viewBackups() { try { const response = await AniWorld.ApiClient.get(API.CONFIG_BACKUPS); if (!response) return; const data = await response.json(); if (data.success) { showBackupsModal(data.backups); } else { AniWorld.UI.showToast('Failed to load backups: ' + data.error, 'error'); } } catch (error) { console.error('Error loading backups:', error); AniWorld.UI.showToast('Failed to load backups', 'error'); } } /** * Show backups modal */ function showBackupsModal(backups) { // Implementation for showing backups modal console.log('Backups:', backups); AniWorld.UI.showToast('Found ' + backups.length + ' backup(s)', 'info'); } /** * Export configuration */ function exportConfig() { AniWorld.UI.showToast('Export configuration feature coming soon', 'info'); } /** * Validate configuration */ async function validateConfig() { try { const response = await AniWorld.ApiClient.request(API.CONFIG_VALIDATE, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({}) }); if (!response) return; const data = await response.json(); if (data.success) { showValidationResults(data.validation); } else { AniWorld.UI.showToast('Validation failed: ' + data.error, 'error'); } } catch (error) { console.error('Error validating config:', error); AniWorld.UI.showToast('Failed to validate configuration', 'error'); } } /** * Show validation results */ function showValidationResults(validation) { const container = document.getElementById('validation-results'); container.innerHTML = ''; container.classList.remove('hidden'); if (validation.valid) { const success = document.createElement('div'); success.className = 'validation-success'; success.innerHTML = ' Configuration is valid!'; container.appendChild(success); } else { const header = document.createElement('div'); header.innerHTML = 'Validation Issues Found:'; container.appendChild(header); } // Show errors validation.errors.forEach(function(error) { const errorDiv = document.createElement('div'); errorDiv.className = 'validation-error'; errorDiv.innerHTML = ' Error: ' + error; container.appendChild(errorDiv); }); // Show warnings validation.warnings.forEach(function(warning) { const warningDiv = document.createElement('div'); warningDiv.className = 'validation-warning'; warningDiv.innerHTML = ' Warning: ' + warning; container.appendChild(warningDiv); }); } /** * Reset all configuration to defaults */ async function resetAllConfig() { if (!confirm('Are you sure you want to reset all configuration to defaults? This cannot be undone (except by restoring a backup).')) { return; } try { const response = await AniWorld.ApiClient.request(API.CONFIG_RESET, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ preserve_security: true }) }); if (!response) return; const data = await response.json(); if (data.success) { AniWorld.UI.showToast('Configuration reset to defaults', 'success'); // Notify caller to reload config modal return true; } else { AniWorld.UI.showToast('Failed to reset config: ' + data.error, 'error'); return false; } } catch (error) { console.error('Error resetting config:', error); AniWorld.UI.showToast('Failed to reset configuration', 'error'); return false; } } /** * Save backup configuration */ async function saveBackupConfig() { try { const config = await loadCurrentConfig(); if (!config) { AniWorld.UI.showToast('Failed to load current configuration', 'error'); return; } // Update backup settings config.backup = { enabled: document.getElementById('backup-enabled').checked, path: document.getElementById('backup-path').value.trim(), keep_days: parseInt(document.getElementById('backup-keep-days').value) || 30 }; // Save updated config const response = await AniWorld.ApiClient.put(AniWorld.Constants.API.CONFIG, config); if (!response) return; AniWorld.UI.showToast('Backup configuration saved successfully', 'success'); } catch (error) { console.error('Error saving backup config:', error); AniWorld.UI.showToast('Failed to save backup configuration', 'error'); } } // Public API return { save: save, reset: reset, testConnection: testConnection, browseDirectory: browseDirectory, refreshStatus: refreshStatus, createBackup: createBackup, viewBackups: viewBackups, exportConfig: exportConfig, validateConfig: validateConfig, resetAllConfig: resetAllConfig, saveBackupConfig: saveBackupConfig }; })();