manage: reuse BG.updater

This commit is contained in:
tophf 2017-04-21 15:33:28 +03:00
parent fc7793453c
commit 9617d571f8
2 changed files with 75 additions and 115 deletions

175
manage.js
View File

@ -484,138 +484,97 @@ function applyUpdateAll() {
function checkUpdateAll() { function checkUpdateAll() {
const btnCheck = $('#check-all-updates'); $('#check-all-updates').disabled = true;
const btnApply = $('#apply-all-updates'); $('#apply-all-updates').classList.add('hidden');
const noUpdates = $('#update-all-no-updates'); $('#update-all-no-updates').classList.add('hidden');
const progress = $('#update-progress');
btnCheck.disabled = true; let total = 0;
btnApply.classList.add('hidden');
noUpdates.classList.add('hidden');
const maxWidth = progress.parentElement.clientWidth;
const queue = $$('.updatable:not(.can-update)').map(checkUpdate);
const total = queue.length;
let updatesFound = false;
let checked = 0; let checked = 0;
processQueue(); let updated = 0;
BG.updater.resetInterval();
function processQueue(status) { $$('.updatable:not(.can-update)').map(el => checkUpdate(el, {single: false}));
if (status === true) { BG.updater.checkAllStyles(observe, {save: false}).then(done);
updatesFound = true;
btnApply.disabled = true; function observe(state, value, details) {
btnApply.classList.remove('hidden'); switch (state) {
renderUpdatesOnlyFilter({check: true}); case BG.updater.COUNT:
total = value;
break;
case BG.updater.UPDATED:
if (++updated == 1) {
$('#apply-all-updates').disabled = true;
$('#apply-all-updates').classList.remove('hidden');
}
$('#apply-all-updates').dataset.value = updated;
// fallthrough
case BG.updater.SKIPPED:
checked++;
reportUpdateState(state, value, details);
break;
} }
if (checked < total) { const progress = $('#update-progress');
queue[checked++].then(status => { const maxWidth = progress.parentElement.clientWidth;
progress.style.width = Math.round(checked / total * maxWidth) + 'px'; progress.style.width = Math.round(checked / total * maxWidth) + 'px';
setTimeout(processQueue, 0, status); }
});
return; function done() {
} $('#check-all-updates').disabled = false;
btnCheck.disabled = false; $('#apply-all-updates').disabled = false;
btnApply.disabled = false; renderUpdatesOnlyFilter({check: updated > 0});
if (!updatesFound) { if (!updated) {
noUpdates.classList.remove('hidden'); $('#update-all-no-updates').classList.remove('hidden');
setTimeout(() => { setTimeout(() => {
noUpdates.classList.add('hidden'); $('#update-all-no-updates').classList.add('hidden');
}, 10e3); }, 10e3);
} }
} }
} }
function checkUpdate(element) { function checkUpdate(element, {single = true} = {}) {
$('.update-note', element).textContent = t('checkingForUpdate'); $('.update-note', element).textContent = t('checkingForUpdate');
$('.check-update', element).title = ''; $('.check-update', element).title = '';
element.classList.remove('checking-update', 'no-update', 'update-problem'); element.classList.remove('checking-update', 'no-update', 'update-problem');
element.classList.add('checking-update'); element.classList.add('checking-update');
return new Updater(element).run(); // eslint-disable-line no-use-before-define if (single) {
const style = BG.cachedStyles.byId.get(element.styleId);
BG.updater.checkStyle(style, reportUpdateState, {save: false});
}
} }
class Updater { function reportUpdateState(state, style, details) {
constructor(element) { const entry = $('#style-' + style.id);
const style = BG.cachedStyles.byId.get(element.styleId); entry.classList.remove('checking-update');
Object.assign(this, { switch (state) {
element, case BG.updater.UPDATED:
id: style.id, entry.classList.add('can-update');
url: style.updateUrl, entry.updatedCode = style;
md5Url: style.md5Url, $('.update-note', entry).textContent = '';
md5: style.originalMd5,
});
}
run() {
return this.md5Url && this.md5
? this.checkMd5()
: this.checkFullCode();
}
checkMd5() {
return download(this.md5Url).then(
md5 => (md5.length == 32
? this.decideOnMd5(md5 != this.md5)
: this.onFailure(-1)),
status => this.onFailure(status));
}
decideOnMd5(md5changed) {
if (md5changed) {
return this.checkFullCode({forceUpdate: true});
}
this.display();
}
checkFullCode({forceUpdate = false} = {}) {
return download(this.url).then(
text => this.handleJson(forceUpdate, JSON.parse(text)),
status => this.onFailure(status));
}
handleJson(forceUpdate, json) {
return getStylesSafe({id: this.id}).then(([style]) => {
const needsUpdate = forceUpdate || !BG.styleSectionsEqual(style, json);
this.display({json: needsUpdate && json});
return needsUpdate;
});
}
onFailure(status) {
this.display({
message: status == 0
? t('updateCheckFailServerUnreachable')
: t('updateCheckFailBadResponseCode', [status]),
});
}
display({json, message} = {}) {
// json on success
// message on failure
// none on update not needed
this.element.classList.remove('checking-update');
if (json) {
this.element.classList.add('can-update');
this.element.updatedCode = json;
$('.update-note', this.element).textContent = '';
$('#onlyUpdates').classList.remove('hidden'); $('#onlyUpdates').classList.remove('hidden');
} else { break;
this.element.classList.add('no-update'); case BG.updater.SKIPPED: {
this.element.classList.toggle('update-problem', Boolean(message)); if (!details) {
$('.update-note', this.element).textContent = message || t('updateCheckSucceededNoUpdate'); details = t('updateCheckFailServerUnreachable');
if (newUI.enabled) { } else if (typeof details == 'number') {
$('.check-update', this.element).title = message; details = t('updateCheckFailBadResponseCode', [details]);
} }
// don't hide if check-all is running const same =
details == BG.updater.SKIPPED_SAME_MD5 ||
details == BG.updater.SKIPPED_SAME_CODE;
const message = same ? t('updateCheckSucceededNoUpdate') : details;
entry.classList.add('no-update');
entry.classList.toggle('update-problem', !same);
$('.update-note', entry).textContent = message;
$('.check-update', entry).title = newUI.enabled ? message : '';
if (!$('#check-all-updates').disabled) { 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')); $('#onlyUpdates').classList.toggle('hidden', !$('.can-update'));
} }
} }
if (filtersSelector.hide) { }
filterAndAppend({entry: this.element}); if (filtersSelector.hide) {
} filterAndAppend({entry});
} }
} }

View File

@ -15,17 +15,14 @@ var updater = {
lastUpdateTime: parseInt(localStorage.lastUpdateTime) || Date.now(), lastUpdateTime: parseInt(localStorage.lastUpdateTime) || Date.now(),
checkAllStyles(observe = () => {}) { checkAllStyles(observe = () => {}, {save = true} = {}) {
updater.resetInterval(); updater.resetInterval();
return new Promise(resolve => { return new Promise(resolve => {
getStyles({}, styles => { getStyles({}, styles => {
styles = styles.filter(style => style.updateUrl); styles = styles.filter(style => style.updateUrl);
observe(updater.COUNT, styles.length); observe(updater.COUNT, styles.length);
Promise.all(styles.map(style => Promise.all(styles.map(style =>
updater.checkStyle(style) updater.checkStyle(style, observe, {save})
.then(saveStyle)
.then(saved => observe(updater.UPDATED, saved))
.catch(err => observe(updater.SKIPPED, style, err))
)).then(() => { )).then(() => {
observe(updater.DONE); observe(updater.DONE);
resolve(); resolve();
@ -34,7 +31,7 @@ var updater = {
}); });
}, },
checkStyle(style) { checkStyle(style, observe = () => {}, {save = true} = {}) {
return download(style.md5Url) return download(style.md5Url)
.then(md5 => .then(md5 =>
!md5 || md5.length != 32 ? Promise.reject(updater.SKIPPED_ERROR_MD5) : !md5 || md5.length != 32 ? Promise.reject(updater.SKIPPED_ERROR_MD5) :
@ -49,7 +46,11 @@ var updater = {
Object.assign(json, { Object.assign(json, {
id: style.id, id: style.id,
name: null, name: null,
})); reason: 'update',
}))
.then(json => save ? saveStyle(json) : json)
.then(saved => observe(updater.UPDATED, saved))
.catch(err => observe(updater.SKIPPED, style, err));
}, },
styleJSONseemsValid(json) { styleJSONseemsValid(json) {