updater: add 'ignoreDigest' to force-update on manage page
* saveStyle: retain only known properties in sections[] and normalize their order * remove styleDigest on import * shorten detailed status names in updater * don't autohide update status message
This commit is contained in:
parent
32ae088c03
commit
7677f0dece
|
@ -323,7 +323,7 @@
|
|||
"description": "Checkbox to show only locally edited styles"
|
||||
},
|
||||
"manageOnlyUpdates": {
|
||||
"message": "Only with updates",
|
||||
"message": "Only with updates or problems",
|
||||
"description": "Checkbox to show only styles that have updates after check-all-styles-for-updates was performed"
|
||||
},
|
||||
"manageNewUI": {
|
||||
|
@ -592,7 +592,7 @@
|
|||
"description": "Text that displays when an update check skipped updating the style to avoid losing possible local modifications"
|
||||
},
|
||||
"updateCheckManualUpdateHint": {
|
||||
"message": "Do a one-time manual update on its userstyles.org page (your edits will be lost)",
|
||||
"message": "To force an update (and lose your edits) update each style individually.",
|
||||
"description": "Additional text displayed when an update check skipped updating the style to avoid losing local modifications"
|
||||
},
|
||||
"updateCheckSucceededNoUpdate": {
|
||||
|
@ -600,7 +600,11 @@
|
|||
"description": "Text that displays when an update check completed and no update is available"
|
||||
},
|
||||
"updateAllCheckSucceededNoUpdate": {
|
||||
"message": "All styles are up to date.",
|
||||
"message": "No updates found.",
|
||||
"description": "Text that displays when an update all check completed and no updates are available"
|
||||
},
|
||||
"updateAllCheckSucceededSomeEdited": {
|
||||
"message": "Some updatable styles weren't checked to avoid losing possible local edits.",
|
||||
"description": "Text that displays when an update all check completed and no updates are available"
|
||||
},
|
||||
"updateCompleted": {
|
||||
|
|
|
@ -294,7 +294,7 @@ summary {
|
|||
cursor: pointer;
|
||||
}
|
||||
|
||||
.update-problem .check-update svg {
|
||||
.newUI .update-problem .check-update svg {
|
||||
fill: #ef6969;
|
||||
}
|
||||
|
||||
|
@ -500,6 +500,10 @@ input[id^="manage.newUI"] {
|
|||
opacity: .35;
|
||||
}
|
||||
|
||||
#update-all-no-updates[data-skipped-edited="true"]:after {
|
||||
content: " __MSG_updateAllCheckSucceededSomeEdited__ __MSG_updateCheckManualUpdateHint__";
|
||||
}
|
||||
|
||||
/* highlight updated/added styles */
|
||||
.highlight {
|
||||
animation: highlight 10s cubic-bezier(0,.82,.47,.98);
|
||||
|
|
16
manage.html
16
manage.html
|
@ -135,18 +135,26 @@
|
|||
<fieldset>
|
||||
<legend id="filters" i18n-text="manageFilters"></legend>
|
||||
<label>
|
||||
<input id="manage.onlyEnabled" type="checkbox" data-filter=".disabled">
|
||||
<input id="manage.onlyEnabled" type="checkbox"
|
||||
data-filter=".enabled"
|
||||
data-filter-hide=".disabled">
|
||||
<span i18n-text="manageOnlyEnabled"></span>
|
||||
</label>
|
||||
<label>
|
||||
<input id="manage.onlyEdited" type="checkbox" data-filter=".updatable">
|
||||
<input id="manage.onlyEdited" type="checkbox"
|
||||
data-filter=":not(.updatable)"
|
||||
data-filter-hide=".updatable">
|
||||
<span i18n-text="manageOnlyEdited"></span>
|
||||
</label>
|
||||
<label id="onlyUpdates" class="hidden">
|
||||
<input type="checkbox" data-filter=":not(.can-update)">
|
||||
<input type="checkbox"
|
||||
data-filter=".can-update, .update-problem"
|
||||
data-filter-hide=":not(.updatable), .update-done, .no-update:not(.update-problem)">
|
||||
<span i18n-text="manageOnlyUpdates"></span>
|
||||
</label>
|
||||
<input id="search" type="search" i18n-placeholder="searchStyles" data-filter=".not-matching">
|
||||
<input id="search" type="search" i18n-placeholder="searchStyles"
|
||||
data-filter=":not(.not-matching)"
|
||||
data-filter-hide=".not-matching">
|
||||
</fieldset>
|
||||
<p>
|
||||
<button id="check-all-updates" i18n-text="checkAllUpdates"><span id="update-progress"></span></button>
|
||||
|
|
81
manage.js
81
manage.js
|
@ -365,10 +365,15 @@ Object.assign(handleEvent, {
|
|||
el.lastValue = value;
|
||||
}
|
||||
const enabledFilters = $$('#header [data-filter]').filter(el => getValue(el));
|
||||
const buildFilter = hide =>
|
||||
[...enabledFilters.map(el =>
|
||||
el.dataset[hide ? 'filterHide' : 'filter']
|
||||
.split(/,\s*/)
|
||||
.map(s => '.entry' + (hide ? '' : '.hidden') + s))
|
||||
].join(',');
|
||||
Object.assign(filtersSelector, {
|
||||
hide: enabledFilters.map(el => '.entry:not(.hidden)' + el.dataset.filter).join(','),
|
||||
unhide: '.entry.hidden' + enabledFilters.map(el =>
|
||||
(':not(' + el.dataset.filter + ')').replace(/^:not\(:not\((.+?)\)\)$/, '$1')).join(''),
|
||||
hide: buildFilter(true),
|
||||
unhide: buildFilter(false),
|
||||
});
|
||||
reapplyFilter();
|
||||
},
|
||||
|
@ -505,12 +510,13 @@ function checkUpdateAll() {
|
|||
|
||||
let total = 0;
|
||||
let checked = 0;
|
||||
let skippedEdited = 0;
|
||||
let updated = 0;
|
||||
|
||||
$$('.updatable:not(.can-update)').map(el => checkUpdate(el, {single: false}));
|
||||
BG.updater.checkAllStyles(observe, {save: false}).then(done);
|
||||
$$('.updatable:not(.can-update):not(.update-problem)').map(el => checkUpdate(el, {single: false}));
|
||||
BG.updater.checkAllStyles({observer, save: false});
|
||||
|
||||
function observe(state, value, details) {
|
||||
function observer(state, value, details) {
|
||||
switch (state) {
|
||||
case BG.updater.COUNT:
|
||||
total = value;
|
||||
|
@ -524,37 +530,41 @@ function checkUpdateAll() {
|
|||
// fallthrough
|
||||
case BG.updater.SKIPPED:
|
||||
checked++;
|
||||
if (details == BG.updater.EDITED || details == BG.updater.MAYBE_EDITED) {
|
||||
skippedEdited++;
|
||||
}
|
||||
reportUpdateState(state, value, details);
|
||||
break;
|
||||
case BG.updater.DONE:
|
||||
$('#check-all-updates').disabled = false;
|
||||
$('#apply-all-updates').disabled = false;
|
||||
renderUpdatesOnlyFilter({check: updated + skippedEdited > 0});
|
||||
if (!updated) {
|
||||
$('#update-all-no-updates').dataset.skippedEdited = skippedEdited > 0;
|
||||
$('#update-all-no-updates').classList.remove('hidden');
|
||||
}
|
||||
return;
|
||||
}
|
||||
const progress = $('#update-progress');
|
||||
const maxWidth = progress.parentElement.clientWidth;
|
||||
progress.style.width = Math.round(checked / total * maxWidth) + 'px';
|
||||
}
|
||||
|
||||
function done() {
|
||||
$('#check-all-updates').disabled = false;
|
||||
$('#apply-all-updates').disabled = false;
|
||||
renderUpdatesOnlyFilter({check: updated > 0});
|
||||
if (!updated) {
|
||||
$('#update-all-no-updates').classList.remove('hidden');
|
||||
setTimeout(() => {
|
||||
$('#update-all-no-updates').classList.add('hidden');
|
||||
}, 10e3);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function checkUpdate(element, {single = true} = {}) {
|
||||
$('.update-note', element).textContent = t('checkingForUpdate');
|
||||
$('.check-update', element).title = '';
|
||||
element.classList.remove('checking-update', 'no-update', 'update-problem');
|
||||
element.classList.add('checking-update');
|
||||
function checkUpdate(entry, {single = true} = {}) {
|
||||
$('.update-note', entry).textContent = t('checkingForUpdate');
|
||||
$('.check-update', entry).title = '';
|
||||
if (single) {
|
||||
const style = BG.cachedStyles.byId.get(element.styleId);
|
||||
BG.updater.checkStyle(style, reportUpdateState, {save: false});
|
||||
BG.updater.checkStyle({
|
||||
save: false,
|
||||
ignoreDigest: entry.classList.contains('update-problem'),
|
||||
style: BG.cachedStyles.byId.get(entry.styleId),
|
||||
observer: reportUpdateState,
|
||||
});
|
||||
}
|
||||
entry.classList.remove('checking-update', 'no-update', 'update-problem');
|
||||
entry.classList.add('checking-update');
|
||||
}
|
||||
|
||||
|
||||
|
@ -569,18 +579,19 @@ function reportUpdateState(state, style, details) {
|
|||
$('#onlyUpdates').classList.remove('hidden');
|
||||
break;
|
||||
case BG.updater.SKIPPED: {
|
||||
if (entry.classList.contains('can-update')) {
|
||||
break;
|
||||
}
|
||||
if (!details) {
|
||||
details = t('updateCheckFailServerUnreachable');
|
||||
} else if (typeof details == 'number') {
|
||||
details = t('updateCheckFailBadResponseCode', [details]);
|
||||
} else if (details == BG.updater.SKIPPED_EDITED) {
|
||||
} else if (details == BG.updater.EDITED) {
|
||||
details = t('updateCheckSkippedLocallyEdited') + '\n' + t('updateCheckManualUpdateHint');
|
||||
} else if (details == BG.updater.SKIPPED_MAYBE_EDITED) {
|
||||
} else if (details == BG.updater.MAYBE_EDITED) {
|
||||
details = t('updateCheckSkippedMaybeLocallyEdited') + '\n' + t('updateCheckManualUpdateHint');
|
||||
}
|
||||
const same =
|
||||
details == BG.updater.SKIPPED_SAME_MD5 ||
|
||||
details == BG.updater.SKIPPED_SAME_CODE;
|
||||
const same = details == BG.updater.SAME_MD5 || details == BG.updater.SAME_CODE;
|
||||
const message = same ? t('updateCheckSucceededNoUpdate') : details;
|
||||
entry.classList.add('no-update');
|
||||
entry.classList.toggle('update-problem', !same);
|
||||
|
@ -588,7 +599,7 @@ function reportUpdateState(state, style, details) {
|
|||
$('.check-update', entry).title = newUI.enabled ? message : '';
|
||||
if (!$('#check-all-updates').disabled) {
|
||||
// this is a single update job so we can decide whether to hide the filter
|
||||
$('#onlyUpdates').classList.toggle('hidden', !$('.can-update'));
|
||||
renderUpdatesOnlyFilter({show: $('.can-update, .update-problem')});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -600,10 +611,10 @@ function reportUpdateState(state, style, details) {
|
|||
|
||||
function renderUpdatesOnlyFilter({show, check} = {}) {
|
||||
const numUpdatable = $$('.can-update').length;
|
||||
const canUpdate = numUpdatable > 0;
|
||||
const mightUpdate = numUpdatable > 0 || $('.update-problem');
|
||||
const checkbox = $('#onlyUpdates input');
|
||||
show = show !== undefined ? show : canUpdate;
|
||||
check = check !== undefined ? show && check : checkbox.checked && canUpdate;
|
||||
show = show !== undefined ? show : mightUpdate;
|
||||
check = check !== undefined ? show && check : checkbox.checked && mightUpdate;
|
||||
|
||||
$('#onlyUpdates').classList.toggle('hidden', !show);
|
||||
checkbox.checked = check;
|
||||
|
@ -611,7 +622,7 @@ function renderUpdatesOnlyFilter({show, check} = {}) {
|
|||
|
||||
const btnApply = $('#apply-all-updates');
|
||||
if (!btnApply.matches('.hidden')) {
|
||||
if (canUpdate) {
|
||||
if (numUpdatable > 0) {
|
||||
btnApply.dataset.value = numUpdatable;
|
||||
} else {
|
||||
btnApply.classList.add('hidden');
|
||||
|
|
|
@ -41,16 +41,14 @@ function checkUpdates() {
|
|||
let total = 0;
|
||||
let checked = 0;
|
||||
let updated = 0;
|
||||
const installed = $('#updates-installed');
|
||||
const progress = $('#update-progress');
|
||||
const maxWidth = progress.parentElement.clientWidth;
|
||||
progress.style.width = 0;
|
||||
installed.dataset.value = '';
|
||||
document.body.classList.add('update-in-progress');
|
||||
BG.updater.checkAllStyles((state, value) => {
|
||||
const maxWidth = $('#update-progress').parentElement.clientWidth;
|
||||
BG.updater.checkAllStyles({observer});
|
||||
|
||||
function observer(state, value) {
|
||||
switch (state) {
|
||||
case BG.updater.COUNT:
|
||||
total = value;
|
||||
document.body.classList.add('update-in-progress');
|
||||
break;
|
||||
case BG.updater.UPDATED:
|
||||
updated++;
|
||||
|
@ -58,10 +56,11 @@ function checkUpdates() {
|
|||
case BG.updater.SKIPPED:
|
||||
checked++;
|
||||
break;
|
||||
}
|
||||
progress.style.width = Math.round(checked / total * maxWidth) + 'px';
|
||||
installed.dataset.value = updated || '';
|
||||
}).then(() => {
|
||||
case BG.updater.DONE:
|
||||
document.body.classList.remove('update-in-progress');
|
||||
});
|
||||
return;
|
||||
}
|
||||
$('#update-progress').style.width = Math.round(checked / total * maxWidth) + 'px';
|
||||
$('#updates-installed').dataset.value = updated || '';
|
||||
}
|
||||
}
|
||||
|
|
56
storage.js
56
storage.js
|
@ -218,7 +218,7 @@ function saveStyle(style) {
|
|||
const tx = db.transaction(['styles'], 'readwrite');
|
||||
const os = tx.objectStore('styles');
|
||||
|
||||
const id = style.id !== undefined && style.id !== null ? Number(style.id) : null;
|
||||
const id = style.id == '0' ? 0 : Number(style.id) || null;
|
||||
const reason = style.reason;
|
||||
const notify = style.notify !== false;
|
||||
delete style.method;
|
||||
|
@ -227,15 +227,16 @@ function saveStyle(style) {
|
|||
if (!style.name) {
|
||||
delete style.name;
|
||||
}
|
||||
let existed, codeIsUpdated;
|
||||
|
||||
if (id !== null) {
|
||||
// Update or create
|
||||
style.id = id;
|
||||
os.get(id).onsuccess = eventGet => {
|
||||
const existed = Boolean(eventGet.target.result);
|
||||
const oldStyle = Object.assign({}, eventGet.target.result);
|
||||
const codeIsUpdated = 'sections' in style && !styleSectionsEqual(style, oldStyle);
|
||||
write(Object.assign(oldStyle, style), {reason, existed, codeIsUpdated});
|
||||
const oldStyle = eventGet.target.result;
|
||||
existed = Boolean(oldStyle);
|
||||
codeIsUpdated = !existed || style.sections && !styleSectionsEqual(style, oldStyle);
|
||||
write(Object.assign({}, oldStyle, style));
|
||||
};
|
||||
} else {
|
||||
// Create
|
||||
|
@ -247,18 +248,11 @@ function saveStyle(style) {
|
|||
md5Url: null,
|
||||
url: null,
|
||||
originalMd5: null,
|
||||
}, style), {reason});
|
||||
}, style));
|
||||
}
|
||||
|
||||
function write(style, {reason, existed, codeIsUpdated} = {}) {
|
||||
style.sections = (style.sections || []).map(section =>
|
||||
Object.assign({
|
||||
urls: [],
|
||||
urlPrefixes: [],
|
||||
domains: [],
|
||||
regexps: [],
|
||||
}, section)
|
||||
);
|
||||
function write(style) {
|
||||
style.sections = normalizeStyleSections(style);
|
||||
os.put(style).onsuccess = event => {
|
||||
style.id = style.id || event.target.result;
|
||||
invalidateCache(existed ? {updated: style} : {added: style});
|
||||
|
@ -271,6 +265,8 @@ function saveStyle(style) {
|
|||
}
|
||||
if (reason == 'update') {
|
||||
updateStyleDigest(style);
|
||||
} else if (reason == 'import') {
|
||||
chrome.storage.local.remove(DIGEST_KEY_PREFIX + style.id, ignoreChromeError);
|
||||
}
|
||||
resolve(style);
|
||||
};
|
||||
|
@ -308,10 +304,14 @@ function getApplicableSections({style, matchUrl, strictRegexp = true, stopOnFirs
|
|||
for (const section of style.sections) {
|
||||
const {urls, domains, urlPrefixes, regexps, code} = section;
|
||||
if ((!urls.length && !urlPrefixes.length && !domains.length && !regexps.length
|
||||
|| urls.length && urls.indexOf(matchUrl) >= 0
|
||||
|| urlPrefixes.length && arraySomeIsPrefix(urlPrefixes, matchUrl)
|
||||
|| domains.length && arraySomeIn(cachedStyles.urlDomains.get(matchUrl) || getDomains(matchUrl), domains)
|
||||
|| regexps.length && arraySomeMatches(regexps, matchUrl, strictRegexp)
|
||||
|| urls.length
|
||||
&& urls.indexOf(matchUrl) >= 0
|
||||
|| urlPrefixes.length
|
||||
&& arraySomeIsPrefix(urlPrefixes, matchUrl)
|
||||
|| domains.length
|
||||
&& arraySomeIn(cachedStyles.urlDomains.get(matchUrl) || getDomains(matchUrl), domains)
|
||||
|| regexps.length
|
||||
&& arraySomeMatches(regexps, matchUrl, strictRegexp)
|
||||
) && !styleCodeEmpty(code)) {
|
||||
sections.push(section);
|
||||
if (stopOnFirst) {
|
||||
|
@ -534,6 +534,18 @@ function getDomains(url) {
|
|||
}
|
||||
|
||||
|
||||
function normalizeStyleSections({sections}) {
|
||||
// retain known properties in an arbitrarily predefined order
|
||||
return (sections || []).map(section => ({
|
||||
code: section.code || '',
|
||||
urls: section.urls || [],
|
||||
urlPrefixes: section.urlPrefixes || [],
|
||||
domains: section.domains || [],
|
||||
regexps: section.regexps || [],
|
||||
}));
|
||||
}
|
||||
|
||||
|
||||
function getStyleDigests(style) {
|
||||
return Promise.all([
|
||||
chromeLocal.getValue(DIGEST_KEY_PREFIX + style.id),
|
||||
|
@ -548,9 +560,11 @@ function updateStyleDigest(style) {
|
|||
}
|
||||
|
||||
|
||||
function calcStyleDigest({sections}) {
|
||||
const text = new TextEncoder('utf-8').encode(JSON.stringify(sections));
|
||||
function calcStyleDigest(style) {
|
||||
const jsonString = JSON.stringify(normalizeStyleSections(style));
|
||||
const text = new TextEncoder('utf-8').encode(jsonString);
|
||||
return crypto.subtle.digest('SHA-1', text).then(hex);
|
||||
|
||||
function hex(buffer) {
|
||||
const parts = [];
|
||||
const PAD8 = '00000000';
|
||||
|
|
65
update.js
65
update.js
|
@ -1,4 +1,5 @@
|
|||
/* globals getStyles, saveStyle, styleSectionsEqual, getStyleDigests, updateStyleDigest */
|
||||
/* global getStyles, saveStyle, styleSectionsEqual */
|
||||
/* global getStyleDigests, updateStyleDigest */
|
||||
'use strict';
|
||||
|
||||
// eslint-disable-next-line no-var
|
||||
|
@ -7,55 +8,71 @@ var updater = {
|
|||
COUNT: 'count',
|
||||
UPDATED: 'updated',
|
||||
SKIPPED: 'skipped',
|
||||
SKIPPED_EDITED: 'locally edited',
|
||||
SKIPPED_MAYBE_EDITED: 'maybe locally edited',
|
||||
SKIPPED_SAME_MD5: 'up-to-date: MD5 is unchanged',
|
||||
SKIPPED_SAME_CODE: 'up-to-date: code sections are unchanged',
|
||||
SKIPPED_ERROR_MD5: 'error: MD5 is invalid',
|
||||
SKIPPED_ERROR_JSON: 'error: JSON is invalid',
|
||||
DONE: 'done',
|
||||
|
||||
// details for SKIPPED status
|
||||
EDITED: 'locally edited',
|
||||
MAYBE_EDITED: 'maybe locally edited',
|
||||
SAME_MD5: 'up-to-date: MD5 is unchanged',
|
||||
SAME_CODE: 'up-to-date: code sections are unchanged',
|
||||
ERROR_MD5: 'error: MD5 is invalid',
|
||||
ERROR_JSON: 'error: JSON is invalid',
|
||||
|
||||
lastUpdateTime: parseInt(localStorage.lastUpdateTime) || Date.now(),
|
||||
|
||||
checkAllStyles(observe = () => {}, {save = true} = {}) {
|
||||
checkAllStyles({observer = () => {}, save = true, ignoreDigest} = {}) {
|
||||
updater.resetInterval();
|
||||
return new Promise(resolve => {
|
||||
getStyles({}, styles => {
|
||||
styles = styles.filter(style => style.updateUrl);
|
||||
observe(updater.COUNT, styles.length);
|
||||
observer(updater.COUNT, styles.length);
|
||||
Promise.all(styles.map(style =>
|
||||
updater.checkStyle(style, observe, {save})
|
||||
updater.checkStyle({style, observer, save, ignoreDigest})
|
||||
)).then(() => {
|
||||
observe(updater.DONE);
|
||||
observer(updater.DONE);
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
checkStyle(style, observe = () => {}, {save = true} = {}) {
|
||||
checkStyle({style, observer = () => {}, save = true, ignoreDigest}) {
|
||||
let hasDigest;
|
||||
/*
|
||||
Original style digests are calculated in these cases:
|
||||
* style is installed or updated from server
|
||||
* style is checked for an update and its code is equal to the server code
|
||||
|
||||
Update check proceeds in these cases:
|
||||
* style has the original digest and it's equal to the current digest
|
||||
* [ignoreDigest: true] style doesn't yet have the original digest but we ignore it
|
||||
* [ignoreDigest: none/false] style doesn't yet have the original digest
|
||||
so we compare the code to the server code and if it's the same we save the digest,
|
||||
otherwise we skip the style and report MAYBE_EDITED status
|
||||
|
||||
'ignoreDigest' option is set on the second manual individual update check on the manage page.
|
||||
*/
|
||||
return getStyleDigests(style)
|
||||
.then(fetchMd5IfNotEdited)
|
||||
.then(fetchCodeIfMd5Changed)
|
||||
.then(saveIfUpdated)
|
||||
.then(saved => observe(updater.UPDATED, saved))
|
||||
.catch(err => observe(updater.SKIPPED, style, err));
|
||||
.then(saved => observer(updater.UPDATED, saved))
|
||||
.catch(err => observer(updater.SKIPPED, style, err));
|
||||
|
||||
function fetchMd5IfNotEdited([originalDigest, current]) {
|
||||
hasDigest = Boolean(originalDigest);
|
||||
if (hasDigest && originalDigest != current) {
|
||||
return Promise.reject(updater.SKIPPED_EDITED);
|
||||
if (hasDigest && !ignoreDigest && originalDigest != current) {
|
||||
return Promise.reject(updater.EDITED);
|
||||
}
|
||||
return download(style.md5Url);
|
||||
}
|
||||
|
||||
function fetchCodeIfMd5Changed(md5) {
|
||||
if (!md5 || md5.length != 32) {
|
||||
return Promise.reject(updater.SKIPPED_ERROR_MD5);
|
||||
return Promise.reject(updater.ERROR_MD5);
|
||||
}
|
||||
if (md5 == style.originalMd5 && hasDigest) {
|
||||
return Promise.reject(updater.SKIPPED_SAME_MD5);
|
||||
return Promise.reject(updater.SAME_MD5);
|
||||
}
|
||||
return download(style.updateUrl);
|
||||
}
|
||||
|
@ -63,16 +80,16 @@ var updater = {
|
|||
function saveIfUpdated(text) {
|
||||
const json = tryJSONparse(text);
|
||||
if (!styleJSONseemsValid(json)) {
|
||||
return Promise.reject(updater.SKIPPED_ERROR_JSON);
|
||||
return Promise.reject(updater.ERROR_JSON);
|
||||
}
|
||||
json.id = style.id;
|
||||
if (styleSectionsEqual(json, style)) {
|
||||
if (!hasDigest) {
|
||||
// JSONs may have different order of items even if sections are effectively equal
|
||||
// so we'll update the digest anyway
|
||||
updateStyleDigest(json);
|
||||
}
|
||||
return Promise.reject(updater.SKIPPED_SAME_CODE);
|
||||
} else if (!hasDigest) {
|
||||
return Promise.reject(updater.SKIPPED_MAYBE_EDITED);
|
||||
return Promise.reject(updater.SAME_CODE);
|
||||
} else if (!hasDigest && !ignoreDigest) {
|
||||
return Promise.reject(updater.MAYBE_EDITED);
|
||||
}
|
||||
return !save ? json :
|
||||
saveStyle(Object.assign(json, {
|
||||
|
|
Loading…
Reference in New Issue
Block a user