mirror of
https://github.com/plexguide/Huntarr.io.git
synced 2026-04-20 11:06:53 -04:00
484 lines
35 KiB
JavaScript
484 lines
35 KiB
JavaScript
(function() {
|
|
window.SettingsForms = window.SettingsForms || {};
|
|
|
|
window.SettingsForms.generateGeneralForm = function(container, settings = {}) {
|
|
if (!settings || typeof settings !== "object") {
|
|
settings = {};
|
|
}
|
|
|
|
container.setAttribute("data-app-type", "general");
|
|
|
|
// Build timezone options
|
|
const timezoneOptions = (() => {
|
|
const predefinedTimezones = [
|
|
"UTC", "America/New_York", "America/Chicago", "America/Denver", "America/Los_Angeles", "Pacific/Honolulu",
|
|
"America/Toronto", "America/Vancouver", "America/Sao_Paulo", "America/Argentina/Buenos_Aires", "America/Mexico_City",
|
|
"America/Phoenix", "America/Anchorage", "America/Halifax", "America/St_Johns", "America/Lima", "America/Bogota",
|
|
"America/Caracas", "America/Santiago", "America/La_Paz",
|
|
"Europe/London", "Europe/Paris", "Europe/Berlin", "Europe/Amsterdam", "Europe/Rome", "Europe/Madrid",
|
|
"Europe/Stockholm", "Europe/Zurich", "Europe/Vienna", "Europe/Prague", "Europe/Warsaw", "Europe/Budapest",
|
|
"Europe/Bucharest", "Europe/Sofia", "Europe/Athens", "Europe/Helsinki", "Europe/Oslo", "Europe/Copenhagen",
|
|
"Europe/Brussels", "Europe/Lisbon", "Europe/Dublin", "Europe/Moscow", "Europe/Kiev", "Europe/Minsk",
|
|
"Europe/Riga", "Europe/Tallinn", "Europe/Vilnius",
|
|
"Africa/Cairo", "Africa/Lagos", "Africa/Nairobi", "Africa/Casablanca", "Africa/Johannesburg",
|
|
"Asia/Dubai", "Asia/Qatar", "Asia/Kuwait", "Asia/Riyadh", "Asia/Tehran", "Asia/Tashkent", "Asia/Almaty",
|
|
"Asia/Tokyo", "Asia/Seoul", "Asia/Shanghai", "Asia/Hong_Kong", "Asia/Singapore", "Asia/Bangkok", "Asia/Kolkata",
|
|
"Asia/Karachi", "Asia/Jakarta", "Asia/Manila", "Asia/Kuala_Lumpur", "Asia/Taipei", "Asia/Yekaterinburg",
|
|
"Australia/Sydney", "Australia/Melbourne", "Australia/Brisbane", "Australia/Adelaide", "Australia/Perth",
|
|
"Pacific/Auckland", "Pacific/Fiji", "Pacific/Guam"
|
|
];
|
|
let custom = "";
|
|
const ct = settings.timezone;
|
|
if (ct && !predefinedTimezones.includes(ct)) {
|
|
custom = `<option value="${ct}" selected>${ct} (Custom from Environment)</option>`;
|
|
}
|
|
const labels = {
|
|
"UTC": "UTC (Coordinated Universal Time)",
|
|
"America/New_York": "Eastern Time (America/New_York)", "America/Chicago": "Central Time (America/Chicago)",
|
|
"America/Denver": "Mountain Time (America/Denver)", "America/Los_Angeles": "Pacific Time (America/Los_Angeles)",
|
|
"Pacific/Honolulu": "Hawaii Time (Pacific/Honolulu)", "America/Toronto": "Eastern Canada (America/Toronto)",
|
|
"America/Vancouver": "Pacific Canada (America/Vancouver)", "America/Sao_Paulo": "Brazil (America/Sao_Paulo)",
|
|
"America/Argentina/Buenos_Aires": "Argentina (America/Argentina/Buenos_Aires)", "America/Mexico_City": "Mexico (America/Mexico_City)",
|
|
"America/Phoenix": "Arizona (America/Phoenix)", "America/Anchorage": "Alaska (America/Anchorage)",
|
|
"America/Halifax": "Atlantic Canada (America/Halifax)", "America/St_Johns": "Newfoundland (America/St_Johns)",
|
|
"America/Lima": "Peru (America/Lima)", "America/Bogota": "Colombia (America/Bogota)",
|
|
"America/Caracas": "Venezuela (America/Caracas)", "America/Santiago": "Chile (America/Santiago)",
|
|
"America/La_Paz": "Bolivia (America/La_Paz)", "Europe/London": "UK Time (Europe/London)",
|
|
"Europe/Paris": "Central Europe (Europe/Paris)", "Europe/Berlin": "Germany (Europe/Berlin)",
|
|
"Europe/Amsterdam": "Netherlands (Europe/Amsterdam)", "Europe/Rome": "Italy (Europe/Rome)",
|
|
"Europe/Madrid": "Spain (Europe/Madrid)", "Europe/Stockholm": "Sweden (Europe/Stockholm)",
|
|
"Europe/Zurich": "Switzerland (Europe/Zurich)", "Europe/Vienna": "Austria (Europe/Vienna)",
|
|
"Europe/Prague": "Czech Republic (Europe/Prague)", "Europe/Warsaw": "Poland (Europe/Warsaw)",
|
|
"Europe/Budapest": "Hungary (Europe/Budapest)", "Europe/Bucharest": "Romania (Europe/Bucharest)",
|
|
"Europe/Sofia": "Bulgaria (Europe/Sofia)", "Europe/Athens": "Greece (Europe/Athens)",
|
|
"Europe/Helsinki": "Finland (Europe/Helsinki)", "Europe/Oslo": "Norway (Europe/Oslo)",
|
|
"Europe/Copenhagen": "Denmark (Europe/Copenhagen)", "Europe/Brussels": "Belgium (Europe/Brussels)",
|
|
"Europe/Lisbon": "Portugal (Europe/Lisbon)", "Europe/Dublin": "Ireland (Europe/Dublin)",
|
|
"Europe/Moscow": "Russia Moscow (Europe/Moscow)", "Europe/Kiev": "Ukraine (Europe/Kiev)",
|
|
"Europe/Minsk": "Belarus (Europe/Minsk)", "Europe/Riga": "Latvia (Europe/Riga)",
|
|
"Europe/Tallinn": "Estonia (Europe/Tallinn)", "Europe/Vilnius": "Lithuania (Europe/Vilnius)",
|
|
"Africa/Cairo": "Egypt (Africa/Cairo)", "Africa/Lagos": "Nigeria (Africa/Lagos)",
|
|
"Africa/Nairobi": "Kenya (Africa/Nairobi)", "Africa/Casablanca": "Morocco (Africa/Casablanca)",
|
|
"Africa/Johannesburg": "South Africa (Africa/Johannesburg)", "Asia/Dubai": "UAE (Asia/Dubai)",
|
|
"Asia/Qatar": "Qatar (Asia/Qatar)", "Asia/Kuwait": "Kuwait (Asia/Kuwait)",
|
|
"Asia/Riyadh": "Saudi Arabia (Asia/Riyadh)", "Asia/Tehran": "Iran (Asia/Tehran)",
|
|
"Asia/Tashkent": "Uzbekistan (Asia/Tashkent)", "Asia/Almaty": "Kazakhstan (Asia/Almaty)",
|
|
"Asia/Tokyo": "Japan (Asia/Tokyo)", "Asia/Seoul": "South Korea (Asia/Seoul)",
|
|
"Asia/Shanghai": "China (Asia/Shanghai)", "Asia/Hong_Kong": "Hong Kong (Asia/Hong_Kong)",
|
|
"Asia/Singapore": "Singapore (Asia/Singapore)", "Asia/Bangkok": "Thailand (Asia/Bangkok)",
|
|
"Asia/Kolkata": "India (Asia/Kolkata)", "Asia/Karachi": "Pakistan (Asia/Karachi)",
|
|
"Asia/Jakarta": "Indonesia (Asia/Jakarta)", "Asia/Manila": "Philippines (Asia/Manila)",
|
|
"Asia/Kuala_Lumpur": "Malaysia (Asia/Kuala_Lumpur)", "Asia/Taipei": "Taiwan (Asia/Taipei)",
|
|
"Asia/Yekaterinburg": "Russia Yekaterinburg (Asia/Yekaterinburg)",
|
|
"Australia/Sydney": "Australia East (Australia/Sydney)", "Australia/Melbourne": "Australia Melbourne (Australia/Melbourne)",
|
|
"Australia/Brisbane": "Australia Brisbane (Australia/Brisbane)", "Australia/Adelaide": "Australia Adelaide (Australia/Adelaide)",
|
|
"Australia/Perth": "Australia West (Australia/Perth)", "Pacific/Auckland": "New Zealand (Pacific/Auckland)",
|
|
"Pacific/Fiji": "Fiji (Pacific/Fiji)", "Pacific/Guam": "Guam (Pacific/Guam)"
|
|
};
|
|
return custom + predefinedTimezones.map(tz =>
|
|
`<option value="${tz}" ${settings.timezone === tz || (tz === "UTC" && !settings.timezone) ? "selected" : ""}>${labels[tz] || tz}</option>`
|
|
).join("\n");
|
|
})();
|
|
|
|
container.innerHTML = `
|
|
<!-- Two-column grid (header is in template) -->
|
|
<div class="mset-grid">
|
|
|
|
<!-- System Settings card -->
|
|
<div class="mset-card">
|
|
<div class="mset-card-header">
|
|
<div class="mset-card-icon mset-icon-blue"><i class="fas fa-globe"></i></div>
|
|
<h3>System Settings</h3>
|
|
</div>
|
|
<div class="mset-card-body">
|
|
<div class="setting-item">
|
|
<label for="timezone">Timezone:</label>
|
|
<select id="timezone" name="timezone" class="mset-select">${timezoneOptions}</select>
|
|
<p class="setting-help">Set your timezone for accurate time display in logs and scheduling. Changes are applied immediately.</p>
|
|
</div>
|
|
<div class="setting-item" style="margin-top: 15px;">
|
|
<label for="tmdb_image_cache_days">TMDB Image Cache:</label>
|
|
<select id="tmdb_image_cache_days" class="mset-select">
|
|
<option value="0" ${settings.tmdb_image_cache_days === 0 ? "selected" : ""}>Disabled (Always Load)</option>
|
|
<option value="1" ${settings.tmdb_image_cache_days === 1 ? "selected" : ""}>1 Day</option>
|
|
<option value="7" ${settings.tmdb_image_cache_days === 7 ? "selected" : ""}>7 Days</option>
|
|
<option value="30" ${(settings.tmdb_image_cache_days === 30 || settings.tmdb_image_cache_days === undefined) ? "selected" : ""}>30 Days</option>
|
|
</select>
|
|
<p class="setting-help">Cache TMDB images to reduce load times and API usage. Missing images will still attempt to load.</p>
|
|
</div>
|
|
<div class="setting-item flex-row" style="margin-top: 15px;" id="show_trending_setting_item">
|
|
<label for="show_trending">Show Smart Hunt on Home:</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="show_trending" ${settings.show_trending !== false ? "checked" : ""}>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
<p class="setting-help">Display the Smart Hunt carousel on the Home page. Configure mix settings in Requestarr > Smart Hunt.</p>
|
|
<div class="setting-item flex-row" style="margin-top: 15px;">
|
|
<label for="show_nzb_hunt_on_home">Show NZB Hunt on Home:</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="show_nzb_hunt_on_home" ${settings.show_nzb_hunt_on_home === true ? "checked" : ""}>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
<p class="setting-help">Display the NZB Hunt status bar on the Home page with live speed, connections, and ETA when servers are configured.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Huntarr Operations card -->
|
|
<div class="mset-card">
|
|
<div class="mset-card-header">
|
|
<div class="mset-card-icon mset-icon-blue"><i class="fas fa-cogs"></i></div>
|
|
<h3>Huntarr Operations</h3>
|
|
</div>
|
|
<div class="mset-card-body">
|
|
<div class="setting-item flex-row">
|
|
<label for="disable_requests">Disable Requests:</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="disable_requests" ${settings.enable_requestarr === false ? "checked" : ""}>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
<p class="setting-help">When enabled, the Requests section (Discover, TV Shows, Movies, etc.) is fully off—no UI, logging, or background work. Saves compute.</p>
|
|
<div class="setting-item flex-row" style="margin-top: 15px;">
|
|
<label for="disable_media_hunt">Disable Media Hunt & NZB Hunt:</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="disable_media_hunt" ${settings.enable_media_hunt === false ? "checked" : ""}>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
<p class="setting-help">When enabled, Media Hunt, NZB Hunt, and Index Master are fully off—no UI, logging, or background work. Saves compute.</p>
|
|
<div class="setting-item flex-row" style="margin-top: 15px;">
|
|
<label for="disable_third_party_apps">Disable 3rd Party Apps:</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="disable_third_party_apps" ${settings.enable_third_party_apps === false ? "checked" : ""}>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
<p class="setting-help">When enabled, 3rd Party Apps (Sonarr, Radarr, etc.) are fully off—no UI, logging, or hunt cycles. Saves compute.</p>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Security & Networking card -->
|
|
<div class="mset-card">
|
|
<div class="mset-card-header">
|
|
<div class="mset-card-icon mset-icon-amber"><i class="fas fa-shield-alt"></i></div>
|
|
<h3>Security & Networking</h3>
|
|
</div>
|
|
<div class="mset-card-body">
|
|
<div class="setting-item">
|
|
<label for="auth_mode">Authentication Mode:</label>
|
|
<select id="auth_mode" name="auth_mode" class="mset-select">
|
|
<option value="login" ${settings.auth_mode === "login" || (!settings.auth_mode && !settings.local_access_bypass && !settings.proxy_auth_bypass) ? "selected" : ""}>Login Mode</option>
|
|
<option value="local_bypass" ${settings.auth_mode === "local_bypass" || (!settings.auth_mode && settings.local_access_bypass === true && !settings.proxy_auth_bypass) ? "selected" : ""}>Local Bypass Mode</option>
|
|
<option value="no_login" ${settings.auth_mode === "no_login" || (!settings.auth_mode && settings.proxy_auth_bypass === true) ? "selected" : ""}>No Login Mode</option>
|
|
</select>
|
|
<p class="setting-help">Login Mode: Standard login. Local Bypass: No login on local network. No Login: Completely open (use behind proxy).</p>
|
|
</div>
|
|
<div class="setting-item flex-row">
|
|
<label for="ssl_verify">Enable SSL Verify:</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="ssl_verify" ${settings.ssl_verify === true ? "checked" : ""}>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
<p class="setting-help">Disable SSL certificate verification when using self-signed certificates.</p>
|
|
<div class="setting-item" style="margin-top: 15px; border-top: 1px solid rgba(148, 163, 184, 0.08); padding-top: 15px;">
|
|
<label for="frame_ancestors">Iframe Embedding:</label>
|
|
<select id="frame_ancestors" class="mset-select">
|
|
<option value="'self'" ${!settings.frame_ancestors || settings.frame_ancestors === "'self'" ? "selected" : ""}>Disabled (Same Origin Only)</option>
|
|
<option value="*" ${settings.frame_ancestors === "*" ? "selected" : ""}>Allow All Origins</option>
|
|
<option value="custom" ${settings.frame_ancestors && settings.frame_ancestors !== "'self'" && settings.frame_ancestors !== "*" ? "selected" : ""}>Custom Origins</option>
|
|
</select>
|
|
<input type="text" id="frame_ancestors_custom" class="mset-input" placeholder="'self' https://organizr.local https://homepage.local" value="${settings.frame_ancestors && settings.frame_ancestors !== "'self'" && settings.frame_ancestors !== "*" ? settings.frame_ancestors : ""}" style="margin-top: 8px; display: ${settings.frame_ancestors && settings.frame_ancestors !== "'self'" && settings.frame_ancestors !== "*" ? "block" : "none"};">
|
|
<p class="setting-help">Allow Huntarr to be embedded in iframes (e.g. Organizr, Homepage). Custom origins use CSP frame-ancestors syntax.</p>
|
|
</div>
|
|
<div style="margin-top: 18px; border-top: 1px solid rgba(148, 163, 184, 0.08); padding-top: 15px;">
|
|
<div class="setting-item flex-row">
|
|
<label for="proxy_enabled">Use Proxy:</label>
|
|
<label class="toggle-switch">
|
|
<input type="checkbox" id="proxy_enabled" ${settings.proxy_enabled === true ? "checked" : ""}>
|
|
<span class="toggle-slider"></span>
|
|
</label>
|
|
</div>
|
|
<p class="setting-help">Route outbound HTTP requests through a proxy server (HTTP, SOCKS4, or SOCKS5).</p>
|
|
<div id="proxy-fields" style="display: ${settings.proxy_enabled ? "block" : "none"}; margin-top: 12px;">
|
|
<div class="setting-item">
|
|
<label for="proxy_type">Proxy Type:</label>
|
|
<select id="proxy_type" class="mset-select">
|
|
<option value="http" ${(settings.proxy_type || "http") === "http" ? "selected" : ""}>HTTP(S)</option>
|
|
<option value="socks4" ${settings.proxy_type === "socks4" ? "selected" : ""}>SOCKS4</option>
|
|
<option value="socks5" ${settings.proxy_type === "socks5" ? "selected" : ""}>SOCKS5 (Tor supported)</option>
|
|
</select>
|
|
</div>
|
|
<div class="setting-item">
|
|
<label for="proxy_hostname">Hostname:</label>
|
|
<input type="text" id="proxy_hostname" value="${settings.proxy_hostname || ""}" placeholder="proxy.example.com" class="mset-input">
|
|
</div>
|
|
<div class="setting-item">
|
|
<label for="proxy_port">Port:</label>
|
|
<input type="number" id="proxy_port" value="${settings.proxy_port || 8080}" min="1" max="65535" class="mset-input" style="max-width: 120px;">
|
|
</div>
|
|
<div class="setting-item">
|
|
<label for="proxy_username">Username:</label>
|
|
<input type="text" id="proxy_username" value="${settings.proxy_username || ""}" placeholder="Optional" class="mset-input" autocomplete="off">
|
|
</div>
|
|
<div class="setting-item">
|
|
<label for="proxy_password">Password:</label>
|
|
<input type="password" id="proxy_password" value="${settings.proxy_password || ""}" placeholder="Optional" class="mset-input" autocomplete="off">
|
|
</div>
|
|
<div class="setting-item">
|
|
<label for="proxy_ignored_addresses">Bypassed Addresses:</label>
|
|
<input type="text" id="proxy_ignored_addresses" value="${settings.proxy_ignored_addresses || ""}" placeholder="localhost, 192.168.*, *.local" class="mset-input">
|
|
<p class="setting-help">Comma-separated list of domains/IPs that bypass the proxy. Wildcards (*) supported.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- Advanced Settings card -->
|
|
<div class="mset-card">
|
|
<div class="mset-card-header">
|
|
<div class="mset-card-icon mset-icon-purple"><i class="fas fa-terminal"></i></div>
|
|
<h3>Advanced Settings</h3>
|
|
</div>
|
|
<div class="mset-card-body">
|
|
<div class="setting-item" style="margin-top: 15px; border-top: 1px solid rgba(148, 163, 184, 0.08); padding-top: 15px;">
|
|
<label for="base_url">Base URL:</label>
|
|
<input type="text" id="base_url" value="${settings.base_url || ""}" placeholder="/huntarr" class="mset-input">
|
|
<p class="setting-help">Base URL path for reverse proxy. Requires restart.</p>
|
|
</div>
|
|
<div class="setting-item">
|
|
<label for="dev_key">Huntarr Dev Key:${settings.dev_mode === true ? ' <i class="fas fa-check-circle" style="color: #22c55e; margin-left: 5px;" title="Dev Mode Active"></i>' : ''}</label>
|
|
<input type="password" id="dev_key" value="${settings.dev_key || ""}" placeholder="Enter dev key" class="mset-input">
|
|
<p class="setting-help">Enter development key to enable dev mode.</p>
|
|
</div>
|
|
<div class="setting-item" style="margin-top: 15px;">
|
|
<label for="web_server_threads">Web Server Threads:</label>
|
|
<select id="web_server_threads" class="mset-select">
|
|
<option value="8" ${settings.web_server_threads === 8 ? "selected" : ""}>8 (Light)</option>
|
|
<option value="16" ${settings.web_server_threads === 16 ? "selected" : ""}>16 (Moderate)</option>
|
|
<option value="32" ${(settings.web_server_threads === 32 || !settings.web_server_threads) ? "selected" : ""}>32 (Default)</option>
|
|
<option value="48" ${settings.web_server_threads === 48 ? "selected" : ""}>48 (Heavy)</option>
|
|
<option value="64" ${settings.web_server_threads === 64 ? "selected" : ""}>64 (High Load)</option>
|
|
<option value="96" ${settings.web_server_threads === 96 ? "selected" : ""}>96 (Maximum)</option>
|
|
</select>
|
|
<p class="setting-help">Number of web server worker threads for handling concurrent requests. Increase if using many apps/instances. Requires restart.</p>
|
|
</div>
|
|
<div class="setting-item" style="margin-top: 15px; border-top: 1px solid rgba(148, 163, 184, 0.08); padding-top: 15px;">
|
|
<label>Reset Media Hunt Wizard:</label>
|
|
<button type="button" id="reset-media-hunt-wizard-btn" class="mset-btn-secondary" style="margin-top: 6px; padding: 7px 16px; background: rgba(239, 68, 68, 0.08); border: 1px solid rgba(239, 68, 68, 0.25); border-radius: 6px; color: #f87171; font-size: 0.85rem; cursor: pointer; transition: all 0.15s;">
|
|
<i class="fas fa-redo"></i> Reset Wizard
|
|
</button>
|
|
<p class="setting-help">Re-show the Media Hunt setup wizard on next visit. Useful if you skipped the wizard and want to run it again.</p>
|
|
</div>
|
|
<div class="setting-item" style="margin-top: 15px; border-top: 1px solid rgba(148, 163, 184, 0.08); padding-top: 15px;">
|
|
<label>Reset Welcome Message:</label>
|
|
<button type="button" id="reset-welcome-message-btn" class="mset-btn-secondary" style="margin-top: 6px; padding: 7px 16px; background: rgba(239, 68, 68, 0.08); border: 1px solid rgba(239, 68, 68, 0.25); border-radius: 6px; color: #f87171; font-size: 0.85rem; cursor: pointer; transition: all 0.15s;">
|
|
<i class="fas fa-envelope-open"></i> Reset Welcome
|
|
</button>
|
|
<p class="setting-help">Re-show the welcome message on the Home page. Useful for testing or if you want to see the welcome message again.</p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
</div>
|
|
`;
|
|
|
|
// Proxy toggle: show/hide proxy fields
|
|
var proxyToggle = container.querySelector('#proxy_enabled');
|
|
var proxyFields = container.querySelector('#proxy-fields');
|
|
if (proxyToggle && proxyFields) {
|
|
proxyToggle.addEventListener('change', function() {
|
|
proxyFields.style.display = proxyToggle.checked ? 'block' : 'none';
|
|
});
|
|
}
|
|
|
|
// Frame ancestors: show/hide custom input
|
|
var frameSelect = container.querySelector('#frame_ancestors');
|
|
var frameCustom = container.querySelector('#frame_ancestors_custom');
|
|
if (frameSelect && frameCustom) {
|
|
frameSelect.addEventListener('change', function() {
|
|
frameCustom.style.display = frameSelect.value === 'custom' ? 'block' : 'none';
|
|
});
|
|
}
|
|
|
|
// Reset Media Hunt Wizard button
|
|
var resetWizardBtn = container.querySelector('#reset-media-hunt-wizard-btn');
|
|
if (resetWizardBtn) {
|
|
resetWizardBtn.addEventListener('click', function() {
|
|
if (window.HuntarrConfirm && window.HuntarrConfirm.show) {
|
|
window.HuntarrConfirm.show({
|
|
title: 'Reset Media Hunt Wizard',
|
|
message: 'This will re-show the Media Hunt setup wizard on your next visit to Media Hunt. Continue?',
|
|
confirmLabel: 'Reset',
|
|
cancelLabel: 'Cancel',
|
|
onConfirm: function() {
|
|
// Update in-memory prefs
|
|
if (window.huntarrUI && window.huntarrUI.originalSettings && window.huntarrUI.originalSettings.general) {
|
|
var prefs = window.huntarrUI.originalSettings.general.ui_preferences || {};
|
|
prefs['media-hunt-wizard-completed'] = false;
|
|
window.huntarrUI.originalSettings.general.ui_preferences = prefs;
|
|
}
|
|
// Save directly to server (don't rely on setUIPreference chaining)
|
|
HuntarrUtils.fetchWithTimeout('./api/settings/general', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ ui_preferences: { 'media-hunt-wizard-completed': false } })
|
|
}).then(function() {
|
|
if (window.HuntarrToast) window.HuntarrToast.success('Media Hunt wizard has been reset. It will show on your next visit to Media Hunt.');
|
|
}).catch(function(err) {
|
|
console.error('[ResetWizard] Failed to save:', err);
|
|
if (window.HuntarrToast) window.HuntarrToast.error('Failed to save wizard reset.');
|
|
});
|
|
// Set a force-show flag so the wizard appears even if all steps are done
|
|
try { sessionStorage.setItem('setup-wizard-force-show', '1'); } catch (e) {}
|
|
}
|
|
});
|
|
} else {
|
|
if (confirm('Reset the Media Hunt wizard? It will show again on your next visit.')) {
|
|
if (window.huntarrUI && window.huntarrUI.originalSettings && window.huntarrUI.originalSettings.general) {
|
|
var prefs = window.huntarrUI.originalSettings.general.ui_preferences || {};
|
|
prefs['media-hunt-wizard-completed'] = false;
|
|
window.huntarrUI.originalSettings.general.ui_preferences = prefs;
|
|
}
|
|
HuntarrUtils.fetchWithTimeout('./api/settings/general', {
|
|
method: 'POST',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ ui_preferences: { 'media-hunt-wizard-completed': false } })
|
|
}).catch(function(err) { console.error('[ResetWizard] Failed to save:', err); });
|
|
try { sessionStorage.setItem('setup-wizard-force-show', '1'); } catch (e) {}
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Reset Welcome Message button
|
|
var resetWelcomeBtn = container.querySelector('#reset-welcome-message-btn');
|
|
if (resetWelcomeBtn) {
|
|
resetWelcomeBtn.addEventListener('click', function() {
|
|
if (window.HuntarrConfirm && window.HuntarrConfirm.show) {
|
|
window.HuntarrConfirm.show({
|
|
title: 'Reset Welcome Message',
|
|
message: 'This will re-show the welcome message the next time you visit the Home page. Continue?',
|
|
confirmLabel: 'Reset',
|
|
cancelLabel: 'Cancel',
|
|
onConfirm: function() {
|
|
HuntarrUtils.setUIPreference('welcome-dismissed', false);
|
|
if (window.HuntarrToast) window.HuntarrToast.success('Welcome message has been reset. It will show on your next visit to Home.');
|
|
}
|
|
});
|
|
} else {
|
|
if (confirm('Reset the welcome message? It will show again on your next Home page visit.')) {
|
|
HuntarrUtils.setUIPreference('welcome-dismissed', false);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
// Frame ancestors dropdown: show/hide custom input
|
|
var frameSelect = container.querySelector('#frame_ancestors');
|
|
var frameCustom = container.querySelector('#frame_ancestors_custom');
|
|
if (frameSelect && frameCustom) {
|
|
frameSelect.addEventListener('change', function() {
|
|
frameCustom.style.display = frameSelect.value === 'custom' ? 'block' : 'none';
|
|
if (frameSelect.value !== 'custom') frameCustom.value = '';
|
|
});
|
|
}
|
|
|
|
if (window.SettingsForms.setupSettingsManualSave) {
|
|
window.SettingsForms.setupSettingsManualSave(container, settings);
|
|
}
|
|
};
|
|
|
|
window.SettingsForms.setupSettingsManualSave = function(container, originalSettings = {}) {
|
|
let saveButton = container.querySelector("#settings-save-button");
|
|
if (!saveButton) saveButton = document.getElementById("settings-save-button");
|
|
if (!saveButton) return;
|
|
|
|
saveButton.style.display = '';
|
|
saveButton.disabled = true;
|
|
saveButton.classList.remove("mset-save-active");
|
|
|
|
let hasChanges = false;
|
|
window.settingsUnsavedChanges = false;
|
|
if (window.SettingsForms.removeUnsavedChangesWarning) {
|
|
window.SettingsForms.removeUnsavedChangesWarning();
|
|
}
|
|
|
|
const getLiveSaveButton = () => container.querySelector("#settings-save-button") || document.getElementById("settings-save-button");
|
|
const updateSaveButtonState = (changesDetected) => {
|
|
hasChanges = changesDetected;
|
|
window.settingsUnsavedChanges = changesDetected;
|
|
const btn = getLiveSaveButton();
|
|
if (!btn) return;
|
|
if (hasChanges) {
|
|
btn.disabled = false;
|
|
btn.classList.add("mset-save-active");
|
|
if (window.SettingsForms.addUnsavedChangesWarning) {
|
|
window.SettingsForms.addUnsavedChangesWarning();
|
|
}
|
|
} else {
|
|
btn.disabled = true;
|
|
btn.classList.remove("mset-save-active");
|
|
if (window.SettingsForms.removeUnsavedChangesWarning) {
|
|
window.SettingsForms.removeUnsavedChangesWarning();
|
|
}
|
|
}
|
|
};
|
|
|
|
container.addEventListener('input', () => updateSaveButtonState(true));
|
|
container.addEventListener('change', () => updateSaveButtonState(true));
|
|
|
|
const newSaveButton = saveButton.cloneNode(true);
|
|
saveButton.parentNode.replaceChild(newSaveButton, saveButton);
|
|
|
|
newSaveButton.addEventListener("click", () => {
|
|
if (!hasChanges) return;
|
|
const liveBtn = getLiveSaveButton();
|
|
if (liveBtn) {
|
|
liveBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i> Saving...';
|
|
liveBtn.disabled = true;
|
|
}
|
|
|
|
const settings = window.SettingsForms.getFormSettings(container, "general");
|
|
window.SettingsForms.saveAppSettings("general", settings, "Settings saved successfully", { section: "main" })
|
|
.then(function() {
|
|
if (window.huntarrUI) {
|
|
window.huntarrUI._enableRequestarr = settings.enable_requestarr !== false;
|
|
window.huntarrUI._enableMediaHunt = settings.enable_media_hunt !== false;
|
|
window.huntarrUI._enableThirdPartyApps = settings.enable_third_party_apps !== false;
|
|
}
|
|
// Update sidebar visibility immediately from saved settings (don't rely on async fetch)
|
|
var requestsGroup = document.getElementById('nav-group-requests');
|
|
var mediaHuntGroup = document.getElementById('nav-group-media-hunt');
|
|
var nzbHuntGroup = document.getElementById('nzb-hunt-sidebar-group');
|
|
var appsGroup = document.getElementById('nav-group-apps');
|
|
var appsLabel = document.getElementById('nav-group-apps-label');
|
|
if (requestsGroup) requestsGroup.style.display = (settings.enable_requestarr === false) ? 'none' : '';
|
|
if (mediaHuntGroup) mediaHuntGroup.style.display = (settings.enable_media_hunt === false) ? 'none' : '';
|
|
if (nzbHuntGroup) nzbHuntGroup.style.display = (settings.enable_media_hunt === false) ? 'none' : '';
|
|
if (appsGroup) appsGroup.style.display = (settings.enable_third_party_apps === false) ? 'none' : '';
|
|
if (appsLabel) appsLabel.style.display = (settings.enable_media_hunt === false && settings.enable_third_party_apps === false) ? 'none' : '';
|
|
if (typeof window.applyFeatureFlags === 'function') window.applyFeatureFlags();
|
|
if (window.HomeRequestarr && typeof window.HomeRequestarr.applyTrendingVisibility === 'function') {
|
|
window.HomeRequestarr.applyTrendingVisibility();
|
|
}
|
|
if (window.huntarrUI && window.huntarrUI.currentSection === 'home') {
|
|
if (window.HuntarrStats && typeof window.HuntarrStats.loadMediaStats === 'function') {
|
|
window.HuntarrStats.loadMediaStats(true);
|
|
}
|
|
if (window.HuntarrIndexerHuntHome && typeof window.HuntarrIndexerHuntHome.load === 'function') {
|
|
window.HuntarrIndexerHuntHome.load();
|
|
}
|
|
}
|
|
}).catch(function() {});
|
|
|
|
if (liveBtn) liveBtn.innerHTML = '<i class="fas fa-save"></i> Save';
|
|
updateSaveButtonState(false);
|
|
});
|
|
};
|
|
})();
|