show .config-error on failure to save

This commit is contained in:
tophf 2017-12-08 01:08:25 +03:00
parent 99cce55a8e
commit 3318db1999
2 changed files with 69 additions and 18 deletions

View File

@ -102,6 +102,29 @@
display: inline-flex; display: inline-flex;
} }
#message-box-buttons {
position: relative;
}
.config-error {
position: absolute;
z-index: 99;
left: 0;
right: 0;
bottom: -1rem;
padding: 0 .75rem;
line-height: 24px;
height: 24px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
background-color: red;
color: white;
font-weight: bold;
text-shadow: 0.5px 0.5px 6px #400;
animation: fadein .5s;
}
.cm-colorview::before, .cm-colorview::before,
.color-swatch { .color-swatch {
width: var(--onoffswitch-width) !important; width: var(--onoffswitch-width) !important;
@ -124,3 +147,12 @@
border: none !important; border: none !important;
box-shadow: 3px 3px 50px rgba(0,0,0,.5) !important; box-shadow: 3px 3px 50px rgba(0,0,0,.5) !important;
} }
@keyframes fadein {
from {
opacity: 0;
}
to {
opacity: 1;
}
}

View File

@ -2,6 +2,7 @@
'use strict'; 'use strict';
function configDialog(style) { function configDialog(style) {
const AUTOSAVE_DELAY = 500;
const data = style.usercssData; const data = style.usercssData;
const varsHash = deepCopy(data.vars) || {}; const varsHash = deepCopy(data.vars) || {};
const varNames = Object.keys(varsHash); const varNames = Object.keys(varsHash);
@ -77,7 +78,7 @@ function configDialog(style) {
if (va) { if (va) {
va.dirty = varsInitial[va.name] !== (isDefault(va) ? va.default : va.value); va.dirty = varsInitial[va.name] !== (isDefault(va) ? va.default : va.value);
if (prefs.get('config.autosave')) { if (prefs.get('config.autosave')) {
debounce(save); debounce(save, 0, {anyChangeIsDirty: true});
} else { } else {
target.closest('label').classList.toggle('dirty', va.dirty); target.closest('label').classList.toggle('dirty', va.dirty);
updateButtons(); updateButtons();
@ -92,8 +93,9 @@ function configDialog(style) {
buttons.close.textContent = t(someDirty ? 'confirmCancel' : 'confirmClose'); buttons.close.textContent = t(someDirty ? 'confirmCancel' : 'confirmClose');
} }
function save() { function save({anyChangeIsDirty = false} = {}) {
if (!vars.length || !vars.some(va => va.dirty)) { if (!vars.length ||
!vars.some(va => va.dirty || anyChangeIsDirty && va.value !== va.savedValue)) {
return; return;
} }
style.enabled = true; style.enabled = true;
@ -117,10 +119,11 @@ function configDialog(style) {
!isDefault(va) && !isDefault(va) &&
bgva.options.every(o => o.name !== va.value)) { bgva.options.every(o => o.name !== va.value)) {
error = `'${va.value}' not in the updated '${va.type}' list`; error = `'${va.value}' not in the updated '${va.type}' list`;
} else if (!va.dirty) { } else if (!va.dirty && (!anyChangeIsDirty || va.value === va.savedValue)) {
continue; continue;
} else { } else {
styleVars[va.name].value = va.value; styleVars[va.name].value = va.value;
va.savedValue = va.value;
numValid++; numValid++;
continue; continue;
} }
@ -147,8 +150,13 @@ function configDialog(style) {
varsInitial = getInitialValues(deepCopy(saved.usercssData.vars)); varsInitial = getInitialValues(deepCopy(saved.usercssData.vars));
vars.forEach(va => onchange({target: va.input})); vars.forEach(va => onchange({target: va.input}));
updateButtons(); updateButtons();
$.remove('.config-error');
}) })
.catch(errors => onhide() + messageBox.alert(Array.isArray(errors) ? errors.join('\n') : errors)); .catch(errors => {
const el = $('.config-error', messageBox.element) ||
$('#message-box-buttons').insertAdjacentElement('afterbegin', $create('.config-error'));
el.textContent = el.title = Array.isArray(errors) ? errors.join('\n') : errors;
});
} }
function useDefault() { function useDefault() {
@ -184,9 +192,7 @@ function configDialog(style) {
va.input = $create('input.slider', { va.input = $create('input.slider', {
va, va,
type: 'checkbox', type: 'checkbox',
onchange() { onchange: updateVarOnChange,
va.value = va.input.checked ? '1' : '0';
},
}), }),
$create('span'), $create('span'),
]), ]),
@ -201,9 +207,7 @@ function configDialog(style) {
$create('.select-resizer', [ $create('.select-resizer', [
va.input = $create('select', { va.input = $create('select', {
va, va,
onchange() { onchange: updateVarOnChange,
va.value = this.value;
}
}, },
va.options.map(o => va.options.map(o =>
$create('option', {value: o.name}, o.label))), $create('option', {value: o.name}, o.label))),
@ -218,10 +222,8 @@ function configDialog(style) {
va.input = $create('input', { va.input = $create('input', {
va, va,
type: 'text', type: 'text',
oninput() { onchange: updateVarOnChange,
va.value = this.value; oninput: updateVarOnInput,
this.dispatchEvent(new Event('change', {bubbles: true}));
},
}), }),
]; ];
break; break;
@ -234,6 +236,18 @@ function configDialog(style) {
} }
} }
function updateVarOnChange() {
this.va.value = this.value;
}
function updateVarOnInput(event, debounced = false) {
if (debounced) {
event.target.dispatchEvent(new Event('change', {bubbles: true}));
} else {
debounce(updateVarOnInput, AUTOSAVE_DELAY, event, true);
}
}
function renderValues() { function renderValues() {
for (const va of vars) { for (const va of vars) {
const value = isDefault(va) ? va.default : va.value; const value = isDefault(va) ? va.default : va.value;
@ -287,13 +301,18 @@ function configDialog(style) {
const colorpicker = document.body.appendChild( const colorpicker = document.body.appendChild(
$create('.colorpicker-popup', {style: 'display: none!important'})); $create('.colorpicker-popup', {style: 'display: none!important'}));
const PADDING = 50;
const MIN_WIDTH = parseFloat(getComputedStyle(colorpicker).width) || 350; const MIN_WIDTH = parseFloat(getComputedStyle(colorpicker).width) || 350;
const MIN_HEIGHT = 250; const MIN_HEIGHT = 250 + PADDING;
colorpicker.remove(); colorpicker.remove();
width = Math.max(Math.min(width / 0.9 + 2, 800), MIN_WIDTH); width = constrain(MIN_WIDTH, 800, width + PADDING);
height = Math.max(Math.min(height / 0.9 + 2, 600), MIN_HEIGHT); height = constrain(MIN_HEIGHT, 600, height + PADDING);
document.body.style.setProperty('min-width', width + 'px', 'important'); document.body.style.setProperty('min-width', width + 'px', 'important');
document.body.style.setProperty('min-height', height + 'px', 'important'); document.body.style.setProperty('min-height', height + 'px', 'important');
} }
function constrain(min, max, value) {
return value < min ? min : value > max ? max : value;
}
} }