diff --git a/CHANGELOG.md b/CHANGELOG.md index 159aff4..bfc215b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## 0.0.3 - 2025-03-10 + +- Automatically load presets from the YTPTube instance. +- Once the preset is selected, update the default preset in the extension options. + ## 0.0.1 - 2025-03-08 - Initial release version diff --git a/src/options.js b/src/options.js index 104f015..87b6ffc 100644 --- a/src/options.js +++ b/src/options.js @@ -2,9 +2,8 @@ const str_keys = ["instance_url", "preset", "template", "folder", "username", "password"] -const $ = s => document.querySelector(s) - if (typeof chrome === 'undefined') { + // noinspection JSUnusedLocalSymbols let chrome = browser } @@ -25,7 +24,7 @@ document.getElementById("ytptube_options").addEventListener("submit", (e) => { let showContextMenu = document.querySelector("#showContextMenu").checked; - let data = {} + let data = {presets: {presets: ['default'], last_updated: 0}} str_keys.forEach(key => data[key] = document.querySelector(`#${key}`).value) data["showContextMenu"] = showContextMenu diff --git a/src/popup.html b/src/popup.html index 02b6429..52cee1f 100644 --- a/src/popup.html +++ b/src/popup.html @@ -11,6 +11,10 @@ margin: 1em; } + body { + font-size: 100%; + } + @media (prefers-color-scheme: dark) { body { color: white; @@ -35,10 +39,17 @@
+
+ + + Select preset to use with the URL. +
- The URL to send to YTPTube instance
+ The URL to send to YTPTube instance
diff --git a/src/popup.js b/src/popup.js index 0bf1bd7..5f070b9 100644 --- a/src/popup.js +++ b/src/popup.js @@ -6,6 +6,11 @@ if (typeof chrome === 'undefined') { let chrome = browser } +const getOption = async (key, default_data) => { + let item = await chrome.storage.sync.get(key); + return item[key] ?? default_data; +} + const notify = message => chrome.notifications.create({ "type": "basic", "iconUrl": chrome.runtime.getURL("icons/icon-128.png"), @@ -34,6 +39,37 @@ addEventListener('DOMContentLoaded', async _ => { } $('#user_url').value = url || '' + + const defaultPreset = await getOption("preset") + + const cache = await getOption('presets', { + presets: [], + last_updated: 0 + }) + + if (Date.now() - cache.last_updated > 1000 * 60 * 60) { + cache.presets = await getPresets() + cache.last_updated = Date.now() + await chrome.storage.sync.set({presets: cache}) + } + + const s = $('#preset') + + // -- remove existing options + while (s.firstChild) { + s.removeChild(s.lastChild); + } + + cache.presets.forEach(p => { + let option = document.createElement('option'); + option.value = p; + option.text = p; + // -- set the default preset + if (p === defaultPreset) { + option.selected = true; + } + s.appendChild(option); + }) }) $('#go-to-options').addEventListener('click', function () { @@ -42,4 +78,38 @@ $('#go-to-options').addEventListener('click', function () { } else { window.open(chrome.runtime.getURL('options.html')); } -}); \ No newline at end of file +}); + +$('#preset').addEventListener('change', async e => await chrome.storage.sync.set({preset: e.target.value})) + +const getPresets = async () => { + let presets = [] + + const instanceUrl = await getOption("instance_url"); + if (!instanceUrl) { + presets.push('YTPTube instance url not configured.'); + return presets + } + + let headers = {}; + + const auth_username = await getOption('username'); + const auth_password = await getOption('password'); + if (auth_username && auth_password) { + headers['Authorization'] = 'Basic ' + btoa(`${auth_username}:${auth_password}`); + } + + const url = new URL(instanceUrl); + url.pathname = '/api/presets'; + url.search = 'filter=name'; + + const req = await fetch(url, {method: 'GET', headers: {...headers, 'Accept': 'application/json'}}); + if (200 !== req.status) { + presets.push('Error fetching presets from YTPTube.'); + return presets + } + + (await req.json()).forEach(preset => presets.push(preset.name)) + + return presets +}; \ No newline at end of file