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,
styleExists: styleManager.styleExists,
getStyle: styleManager.get,
getAllStyles: styleManager.getAllStyles, // used by importer
getTabUrlPrefix() {
return this.sender.tab.url.match(/^([\w-]+:\/+[^/#]+)/)[1];

View File

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

View File

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

View File

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

View File

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