'use strict'; // Cross-browser API namespace (see background.js). No-op in Firefox. if (typeof browser === 'undefined' || browser == null) { var browser = (typeof chrome !== 'undefined' ? chrome : {}); } const $ = (sel) => document.querySelector(sel); const MASTER_KEY = 'enabled'; const PROFILES_KEY = 'profiles'; let editingProfileId = null; // ---- Master toggle ---- async function loadMaster() { const { enabled } = await browser.storage.local.get(MASTER_KEY); $('#masterToggle').checked = enabled !== false; $('#masterLabel').textContent = enabled === false ? 'Disabled' : 'Enabled'; } $('#masterToggle').addEventListener('change', async (e) => { await browser.storage.local.set({ [MASTER_KEY]: e.target.checked }); $('#masterLabel').textContent = e.target.checked ? 'Enabled' : 'Disabled'; }); // ---- PDF settings: truncate long course descriptions (default ON) ---- async function loadPdfSettings() { const s = await browser.storage.local.get(['truncateDescription', 'showYearLevel', 'customYearLevel', 'yearMode']); $('#truncateToggle').checked = s.truncateDescription !== false; $('#showYearToggle').checked = s.showYearLevel !== false; $('#customYear').value = s.customYearLevel || ''; $('#yearMode').value = s.yearMode || 'auto'; } $('#truncateToggle').addEventListener('change', async (e) => { await browser.storage.local.set({ truncateDescription: e.target.checked }); }); $('#showYearToggle').addEventListener('change', async (e) => { await browser.storage.local.set({ showYearLevel: e.target.checked }); }); $('#yearMode').addEventListener('change', async (e) => { await browser.storage.local.set({ yearMode: e.target.value }); }); $('#customYear').addEventListener('change', async (e) => { await browser.storage.local.set({ customYearLevel: e.target.value.trim() }); }); // ---- Profiles ---- async function getProfiles() { const { profiles } = await browser.storage.local.get(PROFILES_KEY); return profiles || []; } async function saveProfiles(profiles) { await browser.storage.local.set({ [PROFILES_KEY]: profiles }); } function renderProfiles(profiles) { const list = $('#profileList'); list.innerHTML = ''; for (const p of profiles) { const li = document.createElement('li'); const name = document.createElement('div'); name.className = 'name'; name.innerHTML = '' + escapeHtml(p.name) + '
' + escapeHtml(p.username) + ''; const toggle = document.createElement('input'); toggle.type = 'checkbox'; toggle.checked = !!p.enabled; toggle.title = 'Enable/disable'; toggle.addEventListener('change', async () => { if (toggle.checked) { profiles.forEach((x) => { x.enabled = x.id === p.id; }); } else { p.enabled = false; } await saveProfiles(profiles); renderProfiles(await getProfiles()); }); const edit = document.createElement('button'); edit.className = 'btn'; edit.textContent = 'Edit'; edit.addEventListener('click', () => openProfileForm(p)); const del = document.createElement('button'); del.className = 'btn'; del.textContent = 'Delete'; del.addEventListener('click', async () => { await saveProfiles(profiles.filter((x) => x.id !== p.id)); renderProfiles(await getProfiles()); }); li.append(toggle, name, edit, del); list.appendChild(li); } } function escapeHtml(s) { return String(s).replace(/[&<>"']/g, (c) => ({ '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' }[c])); } function openProfileForm(p) { editingProfileId = p ? p.id : null; $('#pName').value = p ? p.name : ''; $('#pUsername').value = p ? p.username : ''; $('#pPassword').value = p ? p.password : ''; $('#pEnabled').checked = p ? !!p.enabled : true; $('#profileForm').hidden = false; } $('#addProfile').addEventListener('click', () => openProfileForm(null)); $('#cancelProfile').addEventListener('click', () => { $('#profileForm').hidden = true; }); $('#saveProfile').addEventListener('click', async () => { const profiles = await getProfiles(); const data = { id: editingProfileId || Date.now().toString(), name: $('#pName').value.trim(), username: $('#pUsername').value.trim(), password: $('#pPassword').value, enabled: $('#pEnabled').checked }; if (!data.name || !data.username) return; if (editingProfileId) { const i = profiles.findIndex((x) => x.id === editingProfileId); if (i >= 0) profiles[i] = data; } else { profiles.push(data); } await saveProfiles(profiles); $('#profileForm').hidden = true; renderProfiles(profiles); }); // ---- Init ---- (async function init() { await loadMaster(); await loadPdfSettings(); renderProfiles(await getProfiles()); })();