Fix: parallel import

This commit is contained in:
eight 2018-10-13 13:50:03 +08:00
parent 4d06435486
commit f08faea149
5 changed files with 36 additions and 45 deletions

View File

@ -19,6 +19,7 @@ window.API_METHODS = Object.assign(window.API_METHODS || {}, {
importStyle: styleManager.importStyle, importStyle: styleManager.importStyle,
styleExists: styleManager.styleExists, styleExists: styleManager.styleExists,
getStyle: styleManager.get, getStyle: styleManager.get,
getAllStyles: styleManager.getAllStyles, // used by importer
getTabUrlPrefix() { getTabUrlPrefix() {
return this.sender.tab.url.match(/^([\w-]+:\/+[^/#]+)/)[1]; return this.sender.tab.url.match(/^([\w-]+:\/+[^/#]+)/)[1];

View File

@ -56,8 +56,12 @@ const styleManager = (() => {
port = null; port = null;
if (id) { if (id) {
const style = styles.get(id); const style = styles.get(id);
if (!style) {
// maybe deleted
return;
}
style.preview = null; style.preview = null;
broadcastStyleUpdated(style.data, 'editPreview'); broadcastStyleUpdated(style.data, 'editPreviewEnd');
} }
}); });
}); });
@ -128,7 +132,7 @@ const styleManager = (() => {
function importStyle(data) { function importStyle(data) {
// FIXME: is it a good idea to save the data directly? // FIXME: is it a good idea to save the data directly?
return saveStyle(data) return saveStyle(data)
.then(newData => handleSave(newData)); .then(newData => handleSave(newData, 'import'));
} }
function installStyle(data) { function installStyle(data) {

View File

@ -56,19 +56,14 @@ function importFromFile({fileTypeFilter, file} = {}) {
} }
function importFromString(jsonString, oldStyles) { function importFromString(jsonString) {
if (!oldStyles) {
return API.getStylesInfo().then(styles => importFromString(jsonString, styles));
}
const json = tryJSONparse(jsonString); const json = tryJSONparse(jsonString);
if (!Array.isArray(json)) { if (!Array.isArray(json)) {
return Promise.reject(new Error('the backup is not a valid JSON file')); return Promise.reject(new Error('the backup is not a valid JSON file'));
} }
const oldStylesById = new Map( let oldStyles;
oldStyles.map(style => [style.id, style])); let oldStylesById;
const oldStylesByName = json.length && new Map( let oldStylesByName;
oldStyles.map(style => [style.name.trim(), style]));
const stats = { const stats = {
added: {names: [], ids: [], legend: 'importReportLegendAdded'}, added: {names: [], ids: [], legend: 'importReportLegendAdded'},
unchanged: {names: [], ids: [], legend: 'importReportLegendIdentical'}, unchanged: {names: [], ids: [], legend: 'importReportLegendIdentical'},
@ -78,27 +73,25 @@ function importFromString(jsonString, oldStyles) {
invalid: {names: [], legend: 'importReportLegendInvalid'}, invalid: {names: [], legend: 'importReportLegendInvalid'},
}; };
let index = 0; return API.getAllStyles().then(styles => {
let lastRenderTime = performance.now(); // make a copy of the current database, that may be used when we want to
const renderQueue = []; // undo
const RENDER_NAP_TIME_MAX = 1000; // ms oldStyles = styles;
const RENDER_QUEUE_MAX = 50; // number of styles oldStylesById = new Map(
return proceed(); oldStyles.map(style => [style.id, style]));
oldStylesByName = json.length && new Map(
function proceed() { oldStyles.map(style => [style.name.trim(), style]));
while (index < json.length) { return Promise.all(json.map((item, i) => {
const item = json[index++]; const info = analyze(item, i);
const info = analyze(item); if (info) {
if (!info) {
continue;
}
return API.importStyle(item) return API.importStyle(item)
.then(style => account({style, info})); .then(style => updateStats(style, info));
}
return done();
} }
}));
})
.then(done);
function analyze(item) { function analyze(item, index) {
if (typeof item !== 'object' || if (typeof item !== 'object' ||
!item || !item ||
!item.name || !item.name ||
@ -142,18 +135,6 @@ function importFromString(jsonString, oldStyles) {
.some(field => oldStyle[field] && oldStyle[field] === newStyle[field]); .some(field => oldStyle[field] && oldStyle[field] === newStyle[field]);
} }
function account({style, info}) {
renderQueue.push(style);
if (performance.now() - lastRenderTime > RENDER_NAP_TIME_MAX
|| renderQueue.length > RENDER_QUEUE_MAX) {
setTimeout(scrollElementIntoView, 0, $('#style-' + renderQueue.pop().id));
renderQueue.length = 0;
lastRenderTime = performance.now();
}
updateStats(style, info);
return proceed();
}
function updateStats(style, {oldStyle, metaEqual, codeEqual}) { function updateStats(style, {oldStyle, metaEqual, codeEqual}) {
if (!oldStyle) { if (!oldStyle) {
stats.added.names.push(style.name); stats.added.names.push(style.name);

View File

@ -48,7 +48,8 @@ function onRuntimeMessage(msg) {
switch (msg.method) { switch (msg.method) {
case 'styleUpdated': case 'styleUpdated':
case 'styleAdded': case 'styleAdded':
handleUpdate(msg.style, msg); API.getStylesInfo({id: msg.style.id})
.then(([style]) => handleUpdate(style, msg));
break; break;
case 'styleDeleted': case 'styleDeleted':
handleDelete(msg.style.id); handleDelete(msg.style.id);
@ -521,7 +522,7 @@ function handleUpdate(style, {reason, method} = {}) {
if (reason === 'editPreview') return; if (reason === 'editPreview') return;
// the style was toggled and refreshAllTabs() sent a mini-notification, // the style was toggled and refreshAllTabs() sent a mini-notification,
// but we've already processed 'styleUpdated' sent directly from notifyAllTabs() // but we've already processed 'styleUpdated' sent directly from notifyAllTabs()
if (!style.sections) return; // if (!style.sections) return;
let entry; let entry;
let oldEntry = $(ENTRY_ID_PREFIX + style.id); let oldEntry = $(ENTRY_ID_PREFIX + style.id);
if (oldEntry && method === 'styleUpdated') { if (oldEntry && method === 'styleUpdated') {

View File

@ -29,6 +29,10 @@ getActiveTab()
onDOMready().then(initPopup), onDOMready().then(initPopup),
])) ]))
.then(([results]) => { .then(([results]) => {
if (!results) {
// unsupported URL;
return;
}
showStyles(results.map(r => Object.assign(r.data, r))); showStyles(results.map(r => Object.assign(r.data, r)));
}) })
.catch(console.error); .catch(console.error);