add per-style setting for autoupdate checks
This commit is contained in:
parent
f041f2265a
commit
ce9e74e2a0
|
@ -63,7 +63,7 @@ const updateMan = (() => {
|
||||||
checkingAll = true;
|
checkingAll = true;
|
||||||
const port = observe && chrome.runtime.connect({name: 'updater'});
|
const port = observe && chrome.runtime.connect({name: 'updater'});
|
||||||
const styles = (await API.styles.getAll())
|
const styles = (await API.styles.getAll())
|
||||||
.filter(style => style.updateUrl);
|
.filter(style => style.updateUrl && style.updatable !== false);
|
||||||
if (port) port.postMessage({count: styles.length});
|
if (port) port.postMessage({count: styles.length});
|
||||||
log('');
|
log('');
|
||||||
log(`${save ? 'Scheduled' : 'Manual'} update check for ${styles.length} styles`);
|
log(`${save ? 'Scheduled' : 'Manual'} update check for ${styles.length} styles`);
|
||||||
|
|
|
@ -23,10 +23,13 @@
|
||||||
.style-settings input[type=radio] {
|
.style-settings input[type=radio] {
|
||||||
margin-left: -.5em; /* compensate for label's 16px margin in edit.css */
|
margin-left: -.5em; /* compensate for label's 16px margin in edit.css */
|
||||||
}
|
}
|
||||||
.style-settings input[type=text],
|
.style-settings input:disabled ~ label {
|
||||||
.style-settings input[type=number],
|
opacity: .5;
|
||||||
.style-settings select,
|
}
|
||||||
.style-settings textarea {
|
.style-settings .rel {
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
.style-settings .w100 {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin-top: .25em;
|
margin-top: .25em;
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
<div>
|
<div>
|
||||||
<fieldset class="style-settings can-close-on-esc">
|
<fieldset class="style-settings can-close-on-esc">
|
||||||
<label i18n-text="styleUpdateUrlLabel">
|
<div class="rel">
|
||||||
<input id="ss-update-url" type="text">
|
<input id="ss-updatable" type="checkbox">
|
||||||
</label>
|
<svg class="svg-icon checked"><use xlink:href="#svg-icon-checked"/></svg>
|
||||||
|
<label i18n-text="installUpdateFromLabel" for="ss-updatable"></label>
|
||||||
|
<input id="ss-update-url" type="url" class="w100" i18n-placeholder="styleUpdateUrlLabel">
|
||||||
|
</div>
|
||||||
<div id="ss-scheme">
|
<div id="ss-scheme">
|
||||||
<div i18n-text="installPreferSchemeLabel"></div>
|
<div i18n-text="installPreferSchemeLabel"></div>
|
||||||
<label i18n-text-append="installPreferSchemeNone">
|
<label i18n-text-append="installPreferSchemeNone">
|
||||||
|
@ -16,11 +19,11 @@
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<label i18n-text="styleIncludeLabel">
|
<label i18n-text="styleIncludeLabel">
|
||||||
<textarea id="ss-inclusions" spellcheck="false"
|
<textarea id="ss-inclusions" spellcheck="false" class="w100"
|
||||||
placeholder="*://site1.com/* *://site2.com/*"></textarea>
|
placeholder="*://site1.com/* *://site2.com/*"></textarea>
|
||||||
</label>
|
</label>
|
||||||
<label i18n-text="styleExcludeLabel">
|
<label i18n-text="styleExcludeLabel">
|
||||||
<textarea id="ss-exclusions" spellcheck="false"
|
<textarea id="ss-exclusions" spellcheck="false" class="w100"
|
||||||
placeholder="*://site1.com/* *://site2.com/*"></textarea>
|
placeholder="*://site1.com/* *://site2.com/*"></textarea>
|
||||||
</label>
|
</label>
|
||||||
</fieldset>
|
</fieldset>
|
||||||
|
|
|
@ -1,26 +1,32 @@
|
||||||
/* global $ $$ moveFocus setupLivePrefs */// dom.js
|
/* global $ moveFocus setupLivePrefs */// dom.js
|
||||||
/* global API */// msg.js
|
/* global API */// msg.js
|
||||||
/* global editor */
|
/* global editor */
|
||||||
/* global helpPopup */// util.js
|
/* global helpPopup */// util.js
|
||||||
/* global t */// localization.js
|
/* global t */// localization.js
|
||||||
/* global debounce */// toolbox.js
|
/* global debounce tryURL */// toolbox.js
|
||||||
/* exported StyleSettings */
|
/* exported StyleSettings */
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
async function StyleSettings() {
|
async function StyleSettings() {
|
||||||
const AUTOSAVE_DELAY = 500; // same as config-dialog.js
|
const AUTOSAVE_DELAY = 500; // same as config-dialog.js
|
||||||
const SS_ID = 'styleSettings';
|
const SS_ID = 'styleSettings';
|
||||||
|
const PASS = val => val;
|
||||||
await t.fetchTemplate('/edit/settings.html', SS_ID);
|
await t.fetchTemplate('/edit/settings.html', SS_ID);
|
||||||
const {style} = editor;
|
const {style} = editor;
|
||||||
const ui = t.template[SS_ID].cloneNode(true);
|
const ui = t.template[SS_ID].cloneNode(true);
|
||||||
const elAuto = $('#config\\.autosave', ui);
|
const elAuto = $('#config\\.autosave', ui);
|
||||||
const elSave = $('#ss-save', ui);
|
const elSave = $('#ss-save', ui);
|
||||||
|
const elUpd = $('#ss-updatable', ui);
|
||||||
const pendingSetters = new Map();
|
const pendingSetters = new Map();
|
||||||
const updaters = [
|
const updaters = [
|
||||||
initInput('#ss-update-url', () => style.updateUrl || '',
|
initCheckbox(elUpd, 'updatable', tryURL(style.updateUrl).href),
|
||||||
val => API.styles.config(style.id, 'updateUrl', val)),
|
initInput('#ss-update-url', 'updateUrl', '', {
|
||||||
initRadio('ss-scheme', () => style.preferScheme || 'none',
|
validate(el) {
|
||||||
val => API.styles.config(style.id, 'preferScheme', val)),
|
elUpd.disabled = !el.value || !el.validity.valid;
|
||||||
|
return el.validity.valid;
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
initRadio('ss-scheme', 'preferScheme', 'none'),
|
||||||
initArea('inclusions'),
|
initArea('inclusions'),
|
||||||
initArea('exclusions'),
|
initArea('exclusions'),
|
||||||
];
|
];
|
||||||
|
@ -43,51 +49,67 @@ async function StyleSettings() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function initArea(type) {
|
function initArea(type) {
|
||||||
const selector = `#ss-${type}`;
|
return initInput(`#ss-${type}`, type, [], {
|
||||||
const el = $(selector, ui);
|
get: textToList,
|
||||||
el.oninput = () => {
|
set: list => list.join('\n'),
|
||||||
|
validate(el) {
|
||||||
const val = el.value;
|
const val = el.value;
|
||||||
el.rows = val.match(/^/gm).length + !val.endsWith('\n');
|
el.rows = val.match(/^/gm).length + !val.endsWith('\n');
|
||||||
};
|
|
||||||
return initInput(selector,
|
|
||||||
() => {
|
|
||||||
const list = style[type] || [];
|
|
||||||
const text = list.join('\n');
|
|
||||||
el.rows = (list.length || 1) + 1;
|
|
||||||
return text;
|
|
||||||
},
|
},
|
||||||
val => API.styles.config(style.id, type, textToList(val))
|
});
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function initInput(selector, getter, setter) {
|
function initCheckbox(el, key, defVal) {
|
||||||
const el = $(selector, ui);
|
return initInput(el, key, Boolean(defVal), {dom: 'checked'});
|
||||||
el.oninput = () => autosave(el, setter);
|
}
|
||||||
|
|
||||||
|
function initInput(el, key, defVal, {
|
||||||
|
dom = 'value', // DOM property name
|
||||||
|
get = PASS, // transformer function(val) after getting DOM value
|
||||||
|
set = PASS, // transformer function(val) before setting DOM value
|
||||||
|
validate = PASS, // function(el) - return `false` to prevent saving
|
||||||
|
} = {}) {
|
||||||
|
if (typeof el === 'string') {
|
||||||
|
el = $(el, ui);
|
||||||
|
}
|
||||||
|
el.oninput = () => {
|
||||||
|
if (validate(el) !== false) {
|
||||||
|
autosave(el, {dom, get, key});
|
||||||
|
}
|
||||||
|
};
|
||||||
return () => {
|
return () => {
|
||||||
const val = getter();
|
let val = style[key];
|
||||||
|
val = set(val != null ? val : defVal);
|
||||||
// Skipping if unchanged to preserve the Undo history of the input
|
// Skipping if unchanged to preserve the Undo history of the input
|
||||||
if (el.value !== val) el.value = val;
|
if (el[dom] !== val) el[dom] = val;
|
||||||
|
validate(el);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function initRadio(name, getter, setter) {
|
function initRadio(name, key, defVal) {
|
||||||
for (const el of $$(`[name="${name}"]`, ui)) {
|
$(`#${name}`, ui).oninput = e => {
|
||||||
el.onchange = () => {
|
if (e.target.checked) {
|
||||||
if (el.checked) autosave(el, setter);
|
autosave(e.target, {key});
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
};
|
||||||
return () => {
|
return () => {
|
||||||
$(`[name="${name}"][value="${getter()}"]`, ui).checked = true;
|
const val = style[key] || defVal;
|
||||||
|
const el = $(`[name="${name}"][value="${val}"]`, ui);
|
||||||
|
el.checked = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
function save() {
|
function save() {
|
||||||
pendingSetters.forEach((fn, el) => fn(el.value));
|
pendingSetters.forEach(saveValue);
|
||||||
pendingSetters.clear();
|
pendingSetters.clear();
|
||||||
helpPopup.div.classList.remove('dirty');
|
helpPopup.div.classList.remove('dirty');
|
||||||
elSave.disabled = true;
|
elSave.disabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function saveValue({dom = 'value', get = PASS, key}, el) {
|
||||||
|
return API.styles.config(style.id, key, get(el[dom]));
|
||||||
|
}
|
||||||
|
|
||||||
function textToList(text) {
|
function textToList(text) {
|
||||||
return text.split(/\n/).map(s => s.trim()).filter(Boolean);
|
return text.split(/\n/).map(s => s.trim()).filter(Boolean);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user