'use strict'; import { err, log } from './logger.js'; import { dom, qs } from './querySelector.js'; let cfg = {}; const { ael, make, isNull, isEmpty } = userjs; const i18n$ = (txt) => webext.i18n.getMessage(txt); const iconSVG = { cfg: { viewBox: '0 0 24 24', html: '' }, close: { viewBox: '0 0 24 24', html: '' }, filter: { viewBox: '0 0 24 24', html: '' }, fsClose: { viewBox: '0 0 24 24', html: ' ' }, fsOpen: { viewBox: '0 0 24 24', html: ' ' }, fullscreen: { viewBox: '0 0 96 96', html: '' }, gf: { viewBox: '0 0 510.4 510.4', html: '' }, gh: { viewBox: '0 0 16 16', html: '' }, hide: { viewBox: '0 0 24 24', html: ' ' }, install: { viewBox: '0 0 16 16', html: '' }, issue: { viewBox: '0 0 24 24', html: '' }, nav: { viewBox: '0 0 24 24', html: ' ' }, plus: { viewBox: '0 0 24 24', html: '' }, search: { viewBox: '0 0 24 24', html: '' }, verified: { viewBox: '0 0 56 56', fill: 'currentColor', stroke: 'currentColor', html: '' }, load(type, container) { const xmlns = 'http://www.w3.org/2000/svg'; const svgElem = document.createElementNS(xmlns, 'svg'); for (const [k, v] of Object.entries(iconSVG[type])) { if (k === 'html') { continue; } svgElem.setAttributeNS(null, k, v); } if (typeof iconSVG[type].html === 'string') { svgElem.innerHTML = iconSVG[type].html; } if (container) { container.appendChild(svgElem); return svgElem; } return svgElem.outerHTML; } }; const renderTheme = (theme) => { theme = theme || cfg.theme; if (isEmpty(theme)) { return; } // if (theme === defcfg.theme) { // return; // } const sty = qs('mujs-root').style; for (const [k, v] of Object.entries(theme)) { const str = `--mujs-${k}`; const prop = sty.getPropertyValue(str); if (isEmpty(v)) { theme[k] = prop; } if (prop === v) { continue; } sty.removeProperty(str); sty.setProperty(str, v); } }; const cfgpage = qs('form'); const cfgMap = new Map(); //#region Make Config const makecfg = () => { const exBtn = make('mu-js', 'mujs-sty-flex'); const exportCFG = make('mujs-btn', 'mujs-export', { textContent: i18n$('export_config'), dataset: { command: 'export-cfg' } }); const importCFG = make('mujs-btn', 'mujs-import', { textContent: i18n$('import_config'), dataset: { command: 'import-cfg' } }); const exportTheme = make('mujs-btn', 'mujs-export', { textContent: i18n$('export_theme'), dataset: { command: 'export-theme' } }); const importTheme = make('mujs-btn', 'mujs-import', { textContent: i18n$('import_theme'), dataset: { command: 'import-theme' } }); exBtn.append(importCFG, importTheme, exportCFG, exportTheme); cfgpage.append(exBtn); const makerow = (desc, type = null, nm, attrs = {}) => { desc = desc ?? i18n$('no_license'); nm = nm ?? i18n$('no_license'); const sec = make('mujs-section', 'mujs-cfg-section', { style: nm === 'cache' ? 'display: none;' : '' }); const lb = make('label'); const divDesc = make('mu-js', 'mujs-cfg-desc', { textContent: desc }); lb.append(divDesc); sec.append(lb); cfgpage.append(sec); if (isNull(type)) { return lb; } const inp = make('input', 'mujs-cfg-input', { type, dataset: { name: nm }, ...attrs }); if (!cfgMap.has(nm)) { cfgMap.set(nm, inp); } if (type === 'checkbox') { const inlab = make('mu-js', 'mujs-inlab'); const la = make('label', '', { onclick() { inp.dispatchEvent(new MouseEvent('click')); } }); inlab.append(inp, la); lb.append(inlab); if (nm.includes('-')) { return inp; } if (/(greasy|sleazy)fork|openuserjs|gi(thub|st)/gi.test(nm)) { for (const i of cfg.engines) { if (i.name !== nm) continue; inp.checked = i.enabled; inp.dataset.engine = i.name; ael(inp, 'change', (evt) => { // MUJS.unsaved = true; // MUJS.rebuild = true; i.enabled = evt.target.checked; userjs.hermes.send('Save', { prop: 'engines', value: cfg.engines }); }); } } else { inp.checked = cfg[nm]; ael(inp, 'change', (evt) => { // MUJS.unsaved = true; // if (/filterlang/i.test(nm)) { // MUJS.rebuild = true; // } cfg[nm] = evt.target.checked; userjs.hermes.send('Save', { prop: nm, value: cfg[nm] }); }); } } else { lb.append(inp); } return inp; }; makerow('Sync with GM', 'checkbox', 'cache'); makerow(i18n$('redirect'), 'checkbox', 'sleazyredirect'); makerow(i18n$('filter'), 'checkbox', 'filterlang'); makerow(i18n$('preview_code'), 'checkbox', 'codePreview'); for (const inp of [ makerow('Recommend author', 'checkbox', 'recommend-author'), makerow('Recommend scripts', 'checkbox', 'recommend-others') ]) { const nm = inp.dataset.name === 'recommend-author' ? 'author' : 'others'; inp.checked = cfg.recommend[nm]; ael(inp, 'change', (evt) => { // MUJS.unsaved = true; cfg.recommend[nm] = evt.target.checked; userjs.hermes.send('Save', { prop: 'recommend', value: cfg.recommend }); }); } makerow('Greasy Fork', 'checkbox', 'greasyfork'); makerow('Sleazy Fork', 'checkbox', 'sleazyfork'); makerow('Open UserJS', 'checkbox', 'openuserjs'); makerow('GitHub API', 'checkbox', 'github'); const ghAPI = cfg.engines.find((c) => c.name === 'github'); const ghToken = makerow('GitHub API (Token)', 'text', 'github', { defaultValue: '', value: ghAPI.token ?? '', placeholder: 'Paste Access Token' // onchange(evt) { // MUJS.unsaved = true; // MUJS.rebuild = true; // if (isNull(legacyMsg)) { // ghAPI.token = evt.target.value; // } // } }); ghToken.dataset.engine = 'github-token'; cfgMap.set('github-token', ghToken); makerow(`${i18n$('dtime')} (ms)`, 'number', 'time', { defaultValue: 10000, value: cfg.time, min: 0, step: 500, onbeforeinput(evt) { if (evt.target.validity.badInput) { dom.cl.add(evt.target, 'mujs-invalid'); dom.prop(savebtn, 'disabled', true); } else { dom.cl.remove(evt.target, 'mujs-invalid'); dom.prop(savebtn, 'disabled', false); } }, oninput(evt) { // MUJS.unsaved = true; const t = evt.target; if (t.validity.badInput || (t.validity.rangeUnderflow && t.value !== '-1')) { dom.cl.add(t, 'mujs-invalid'); dom.prop(savebtn, 'disabled', true); } else { dom.cl.remove(t, 'mujs-invalid'); dom.prop(savebtn, 'disabled', false); cfg.time = isEmpty(t.value) ? cfg.time : parseFloat(t.value); } } }); const cbtn = make('mu-js', 'mujs-sty-flex'); const savebtn = make('mujs-btn', 'save', { textContent: i18n$('save'), dataset: { command: 'save' }, disabled: false }); const resetbtn = make('mujs-btn', 'reset', { textContent: i18n$('reset'), dataset: { command: 'reset' } }); const blacklist = make('textarea', '', { dataset: { name: 'blacklist' }, rows: '10', autocomplete: false, spellcheck: false, wrap: 'soft', value: JSON.stringify(cfg.blacklist, null, ' '), oninput(evt) { let isvalid = true; try { cfg.blacklist = JSON.parse(evt.target.value); isvalid = true; } catch (ex) { err(ex); isvalid = false; } finally { if (isvalid) { dom.cl.remove(evt.target, 'mujs-invalid'); dom.prop(savebtn, 'disabled', false); } else { dom.cl.add(evt.target, 'mujs-invalid'); dom.prop(savebtn, 'disabled', true); } } } }); const theme = make('textarea', '', { dataset: { name: 'theme' }, rows: '10', autocomplete: false, spellcheck: false, wrap: 'soft', value: JSON.stringify(cfg.theme, null, ' '), oninput(evt) { let isvalid = true; try { cfg.theme = JSON.parse(evt.target.value); isvalid = true; renderTheme(JSON.parse(evt.target.value)); } catch (ex) { err(ex); isvalid = false; } finally { if (isvalid) { dom.cl.remove(evt.target, 'mujs-invalid'); dom.prop(savebtn, 'disabled', false); } else { dom.cl.add(evt.target, 'mujs-invalid'); dom.prop(savebtn, 'disabled', true); } } } }); cfgMap.set('blacklist', blacklist); cfgMap.set('theme', theme); cbtn.append(resetbtn, savebtn); cfgpage.append(blacklist, theme, cbtn); }; //#endregion userjs.hermes.getPort().onMessage.addListener((root = {}) => { const m = root.msg; // log('Settings', root); if (root.channel === 'Config' && isEmpty(cfg)) { cfg = m.cfg || cfg; makecfg(); } });