Files
tv/web/js/settings.js
T
2026-08-26 20:39:37 -05:00

156 lines
5.3 KiB
JavaScript

/*
SETTINGS — source provider toggles, API server base URL, local data.
*/
(function () {
'use strict';
SR.app.initChrome();
const providerList = document.getElementById('providerList');
const providersStatus = document.getElementById('providersStatus');
const apiBaseInput = document.getElementById('apiBaseInput');
const connStatus = document.getElementById('connStatus');
const dataStatus = document.getElementById('dataStatus');
/* ---- nav --------------------------------------------------------------------- */
const navlinks = Array.from(document.querySelectorAll('.settings__navlink'));
navlinks.forEach((link) => {
link.addEventListener('click', (e) => {
e.preventDefault();
const target = document.querySelector(link.getAttribute('href'));
if (target) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
navlinks.forEach((l) => l.classList.toggle('is-active', l === link));
history.replaceState(null, '', link.getAttribute('href'));
});
});
/* ---- sources ------------------------------------------------------------------- */
let allProviders = [];
let serverEnabled = [];
const boxes = new Map(); // provider name -> checkbox
function setStatus(el, message, kind) {
el.textContent = message || '';
el.className =
kind === 'ok' ? 'settings__status settings__status--ok'
: kind === 'err' ? 'settings__status settings__status--err'
: 'settings__status';
}
function currentMap() {
const map = {};
for (const [name, box] of boxes) map[name] = box.checked;
return map;
}
function persist(map, message) {
SR.config.setProviders(map);
if (message) setStatus(providersStatus, message);
}
function renderProviders() {
providerList.replaceChildren();
boxes.clear();
const overrides = SR.config.getProviders();
const enabled = SR.config.enabledProviders(allProviders, serverEnabled);
for (const name of allProviders) {
const checked = enabled.includes(name);
const label = document.createElement('label');
label.className = 'provider';
const input = document.createElement('input');
input.type = 'checkbox';
input.checked = !!checked;
const nameEl = document.createElement('span');
nameEl.className = 'provider__name';
nameEl.textContent = name;
label.append(input, nameEl);
input.addEventListener('change', () =>
persist(currentMap(), input.checked ? `${name} enabled` : `${name} disabled`));
boxes.set(name, input);
providerList.appendChild(label);
}
const on = boxes.size ? Array.from(boxes.values()).filter((b) => b.checked).length : 0;
const source = overrides ? 'your selection' : 'default sources';
let host;
try { host = new URL(SR.config.getBase()).host; } catch (e) { host = SR.config.getBase(); }
setStatus(providersStatus, `${on} of ${allProviders.length} enabled — ${source} · ${host}`);
}
function resetProviders(message) {
SR.config.clearProviders();
renderProviders();
if (message) setStatus(providersStatus, message);
}
document.getElementById('allOn').addEventListener('click', () => {
if (!boxes.size) return;
for (const box of boxes.values()) box.checked = true;
persist(currentMap(), 'All sources enabled');
});
document.getElementById('allOff').addEventListener('click', () => {
if (!boxes.size) return;
for (const box of boxes.values()) box.checked = false;
persist(currentMap(), 'All sources disabled');
});
document.getElementById('providersReset').addEventListener('click', () =>
resetProviders('Using default sources'));
async function initSources() {
try {
const data = await SR.api.providers();
allProviders = data.all || [];
serverEnabled = data.enabled || [];
renderProviders();
} catch (e) {
setStatus(providersStatus, `Could not load the provider list: ${e.message}`, 'err');
}
}
/* ---- server ----------------------------------------------------------------------- */
apiBaseInput.value = SR.config.getBase();
async function testConnection() {
try {
const data = await SR.api.providers();
setStatus(connStatus, `Connected — ${data.all ? data.all.length : 0} provider(s) known.`, 'ok');
return true;
} catch (e) {
setStatus(connStatus, `Not reachable: ${e.message}`, 'err');
return false;
}
}
document.getElementById('apiBaseSave').addEventListener('click', async () => {
SR.config.setBase(apiBaseInput.value);
apiBaseInput.value = SR.config.getBase();
SR.app.initChrome(); // refresh the footer label
if (await testConnection()) SR.app.toast('API base URL saved');
});
document.getElementById('apiBaseReset').addEventListener('click', async () => {
SR.config.clearBase();
apiBaseInput.value = SR.config.getBase();
SR.app.initChrome();
await testConnection();
});
/* ---- data ---------------------------------------------------------------------------- */
document.getElementById('clearHistory').addEventListener('click', () => {
SR.storage.clear();
setStatus(dataStatus, 'Continue-watching history cleared.');
});
document.getElementById('resetProviders').addEventListener('click', () => {
resetProviders('');
setStatus(dataStatus, 'Source toggles reset to default sources.');
});
initSources();
})();