usercss config: skip and warn about mismatching vars on saving
This commit is contained in:
parent
fad03fb7c9
commit
c31495c283
|
@ -973,6 +973,9 @@
|
|||
"usercssReplaceTemplateConfirmation": {
|
||||
"message": "Replace the default template for new Usercss styles with the current code?"
|
||||
},
|
||||
"usercssConfigIncomplete": {
|
||||
"message": "The style was updated or deleted after the configuration dialog was shown. These variables were not saved to avoid corrupting the style's metadata:"
|
||||
},
|
||||
"versionInvalidOlder": {
|
||||
"message": "The version is older than the installed style.",
|
||||
"description": "Displayed when the version of style is older than the installed one"
|
||||
|
|
|
@ -2,9 +2,15 @@
|
|||
'use strict';
|
||||
|
||||
function configDialog(style) {
|
||||
const form = buildConfigForm();
|
||||
const varsHash = deepCopy(style.usercssData.vars) || {};
|
||||
const varNames = Object.keys(varsHash);
|
||||
const vars = varNames.map(name => varsHash[name]);
|
||||
const elements = [];
|
||||
const colorpicker = window.colorpicker();
|
||||
|
||||
buildConfigForm();
|
||||
renderValues();
|
||||
|
||||
return messageBox({
|
||||
title: `${style.name} v${style.usercssData.version}`,
|
||||
className: 'config-dialog',
|
||||
|
@ -19,31 +25,67 @@ function configDialog(style) {
|
|||
}),
|
||||
$element({
|
||||
className: 'config-body',
|
||||
appendChild: form.elements
|
||||
appendChild: elements
|
||||
})
|
||||
],
|
||||
buttons: [
|
||||
t('confirmSave'),
|
||||
{
|
||||
textContent: t('confirmDefault'),
|
||||
onclick: form.useDefault
|
||||
onclick: useDefault
|
||||
},
|
||||
t('confirmCancel')
|
||||
]
|
||||
}).then(({button, enter}) => {
|
||||
}).then(({button, esc}) => {
|
||||
if (button !== 1) {
|
||||
colorpicker.hide();
|
||||
}
|
||||
if (button === 0 || enter) {
|
||||
return form.getVars();
|
||||
if (button > 0 || esc || !vars.length || !vars.some(va => va.dirty)) {
|
||||
return;
|
||||
}
|
||||
style.reason = 'config';
|
||||
const styleVars = style.usercssData.vars;
|
||||
const bgStyle = BG.cachedStyles.byId.get(style.id);
|
||||
const bgVars = bgStyle && (bgStyle.usercssData || {}).vars || {};
|
||||
const invalid = [];
|
||||
let numValid = 0;
|
||||
for (const va of vars) {
|
||||
const bgva = bgVars[va.name];
|
||||
let error;
|
||||
if (!bgva) {
|
||||
error = `${va.name}: deleted`;
|
||||
} else
|
||||
if (bgva.type !== va.type) {
|
||||
error = `${va.name}: type '${va.type}' != '${bgva.type}'`;
|
||||
} else
|
||||
if ((va.type === 'select' || va.type === 'dropdown') &&
|
||||
bgva.options.every(o => o.name !== va.value)) {
|
||||
error = `${va.name}: '${va.value}' not in the updated '${va.type}' list`;
|
||||
} else if (!va.dirty) {
|
||||
continue;
|
||||
} else {
|
||||
styleVars[va.name].value = va.value;
|
||||
numValid++;
|
||||
continue;
|
||||
}
|
||||
invalid.push(error);
|
||||
delete styleVars[va.name];
|
||||
}
|
||||
if (invalid.length) {
|
||||
messageBox.alert([
|
||||
$element({textContent: t('usercssConfigIncomplete'), style: 'max-width: 34em'}),
|
||||
$element({
|
||||
tag: 'ol',
|
||||
style: 'text-align: left; font-weight: bold;',
|
||||
appendChild: invalid.map(s => $element({tag: 'li', textContent: s})),
|
||||
}),
|
||||
]);
|
||||
}
|
||||
return numValid && BG.usercssHelper.save(style);
|
||||
});
|
||||
|
||||
function buildConfigForm() {
|
||||
const labels = [];
|
||||
const vars = deepCopy(style.usercssData.vars);
|
||||
for (const key of Object.keys(vars)) {
|
||||
const va = vars[key];
|
||||
for (const va of vars) {
|
||||
let appendChild;
|
||||
switch (va.type) {
|
||||
case 'color':
|
||||
|
@ -52,7 +94,7 @@ function configDialog(style) {
|
|||
appendChild: va.inputColor = $element({
|
||||
va,
|
||||
className: 'color-swatch',
|
||||
onclick: onColorClicked,
|
||||
onclick: showColorpicker,
|
||||
})
|
||||
})];
|
||||
break;
|
||||
|
@ -97,22 +139,26 @@ function configDialog(style) {
|
|||
appendChild = [va.input];
|
||||
break;
|
||||
}
|
||||
appendChild.unshift($element({tag: 'span', appendChild: va.label}));
|
||||
labels.push($element({
|
||||
elements.push($element({
|
||||
tag: 'label',
|
||||
className: `config-${va.type}`,
|
||||
appendChild
|
||||
appendChild: [
|
||||
$element({tag: 'span', appendChild: va.label}),
|
||||
...appendChild,
|
||||
],
|
||||
}));
|
||||
}
|
||||
drawValues();
|
||||
}
|
||||
|
||||
function drawValues() {
|
||||
for (const key of Object.keys(vars)) {
|
||||
const va = vars[key];
|
||||
function renderValues() {
|
||||
for (const va of vars) {
|
||||
const useDefault = va.value === null || va.value === undefined;
|
||||
const value = useDefault ? va.default : va.value;
|
||||
if (va.type === 'color') {
|
||||
va.inputColor.style.backgroundColor = value;
|
||||
if (colorpicker.options.va === va) {
|
||||
colorpicker.setColor(value);
|
||||
}
|
||||
} else if (va.type === 'checkbox') {
|
||||
va.input.checked = Number(value);
|
||||
} else {
|
||||
|
@ -122,46 +168,40 @@ function configDialog(style) {
|
|||
}
|
||||
|
||||
function useDefault() {
|
||||
for (const key of Object.keys(vars)) {
|
||||
const va = vars[key];
|
||||
va.dirty = va.value !== null && va.value !== undefined && va.value !== va.default;
|
||||
for (const va of vars) {
|
||||
const hasValue = va.value !== null && va.value !== undefined;
|
||||
va.dirty = hasValue && va.value !== va.default;
|
||||
va.value = null;
|
||||
}
|
||||
drawValues();
|
||||
renderValues();
|
||||
}
|
||||
|
||||
function getVars() {
|
||||
return vars;
|
||||
}
|
||||
|
||||
function onColorClicked() {
|
||||
function showColorpicker() {
|
||||
window.removeEventListener('keydown', messageBox.listeners.key, true);
|
||||
const box = $('#message-box-contents');
|
||||
colorpicker.show({
|
||||
va: this.va,
|
||||
color: this.va.value || this.va.default,
|
||||
top: this.getBoundingClientRect().bottom - 5,
|
||||
left: box.getBoundingClientRect().left - 360,
|
||||
hideDelay: 1e6,
|
||||
guessBrightness: box,
|
||||
callback: newColor => {
|
||||
if (newColor) {
|
||||
this.va.dirty = true;
|
||||
this.va.value = newColor;
|
||||
this.style.backgroundColor = newColor;
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (!$('.colorpicker-popup')) {
|
||||
window.addEventListener('keydown', messageBox.listeners.key, true);
|
||||
}
|
||||
});
|
||||
},
|
||||
callback: onColorChanged,
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
elements: labels,
|
||||
useDefault,
|
||||
getVars
|
||||
};
|
||||
function onColorChanged(newColor) {
|
||||
if (newColor) {
|
||||
this.va.dirty = true;
|
||||
this.va.value = newColor;
|
||||
this.va.inputColor.style.backgroundColor = newColor;
|
||||
}
|
||||
debounce(restoreEscInDialog);
|
||||
}
|
||||
|
||||
function restoreEscInDialog() {
|
||||
if (!$('.colorpicker-popup') && messageBox.element) {
|
||||
window.addEventListener('keydown', messageBox.listeners.key, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -194,7 +194,7 @@ function createStyleElement({style, name}) {
|
|||
if (style.updateUrl && newUI.enabled) {
|
||||
$('.actions', entry).appendChild(template.updaterIcons.cloneNode(true));
|
||||
}
|
||||
if (shouldShowConfig() && newUI.enabled) {
|
||||
if (style.usercssData && Object.keys(style.usercssData.vars).length > 0 && newUI.enabled) {
|
||||
$('.actions', entry).appendChild(template.configureIcon.cloneNode(true));
|
||||
}
|
||||
|
||||
|
@ -203,10 +203,6 @@ function createStyleElement({style, name}) {
|
|||
createStyleTargetsElement({entry, style, postponeFavicons: name});
|
||||
|
||||
return entry;
|
||||
|
||||
function shouldShowConfig() {
|
||||
return style.usercssData && Object.keys(style.usercssData.vars).length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -287,24 +283,6 @@ Object.assign(handleEvent, {
|
|||
'.configure-usercss': 'config'
|
||||
},
|
||||
|
||||
config(event, {styleMeta: style}) {
|
||||
configDialog(style).then(vars => {
|
||||
if (!vars) {
|
||||
return;
|
||||
}
|
||||
const keys = Object.keys(vars).filter(k => vars[k].dirty);
|
||||
if (!keys.length) {
|
||||
return;
|
||||
}
|
||||
style.reason = 'config';
|
||||
for (const key of keys) {
|
||||
style.usercssData.vars[key].value = vars[key].value;
|
||||
}
|
||||
onBackgroundReady()
|
||||
.then(() => BG.usercssHelper.save(style));
|
||||
});
|
||||
},
|
||||
|
||||
entryClicked(event) {
|
||||
const target = event.target;
|
||||
const entry = target.closest('.entry');
|
||||
|
@ -407,6 +385,10 @@ Object.assign(handleEvent, {
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
config(event, {styleMeta}) {
|
||||
configDialog(styleMeta);
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user