Fix: refactor import-export
This commit is contained in:
		
							parent
							
								
									86ea846a89
								
							
						
					
					
						commit
						c55675912e
					
				|  | @ -1,11 +1,10 @@ | ||||||
| /* global messageBox handleUpdate handleDelete styleSectionsEqual getOwnTab API | /* global messageBox styleSectionsEqual getOwnTab API | ||||||
|   tryJSONparse scrollElementIntoView $ $$ API $create t animateElement */ |   tryJSONparse scrollElementIntoView $ $$ API $create t animateElement */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| const STYLISH_DUMP_FILE_EXT = '.txt'; | const STYLISH_DUMP_FILE_EXT = '.txt'; | ||||||
| const STYLUS_BACKUP_FILE_EXT = '.json'; | const STYLUS_BACKUP_FILE_EXT = '.json'; | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| function importFromFile({fileTypeFilter, file} = {}) { | function importFromFile({fileTypeFilter, file} = {}) { | ||||||
|   return new Promise(resolve => { |   return new Promise(resolve => { | ||||||
|     const fileInput = document.createElement('input'); |     const fileInput = document.createElement('input'); | ||||||
|  | @ -61,9 +60,9 @@ function importFromString(jsonString, oldStyles) { | ||||||
|   if (!oldStyles) { |   if (!oldStyles) { | ||||||
|     return API.getStylesInfo().then(styles => importFromString(jsonString, styles)); |     return API.getStylesInfo().then(styles => importFromString(jsonString, styles)); | ||||||
|   } |   } | ||||||
|   const json = tryJSONparse(jsonString) || []; |   const json = tryJSONparse(jsonString); | ||||||
|   if (typeof json.slice !== 'function') { |   if (!Array.isArray(json)) { | ||||||
|     json.length = 0; |     return Promise.reject(new Error('the backup is not a valid JSON file')); | ||||||
|   } |   } | ||||||
|   const oldStylesById = new Map( |   const oldStylesById = new Map( | ||||||
|     oldStyles.map(style => [style.id, style])); |     oldStyles.map(style => [style.id, style])); | ||||||
|  | @ -84,24 +83,19 @@ function importFromString(jsonString, oldStyles) { | ||||||
|   const renderQueue = []; |   const renderQueue = []; | ||||||
|   const RENDER_NAP_TIME_MAX = 1000; // ms
 |   const RENDER_NAP_TIME_MAX = 1000; // ms
 | ||||||
|   const RENDER_QUEUE_MAX = 50; // number of styles
 |   const RENDER_QUEUE_MAX = 50; // number of styles
 | ||||||
|   const SAVE_OPTIONS = {reason: 'import', notify: false}; |   return proceed(); | ||||||
| 
 | 
 | ||||||
|   return new Promise(proceed); |   function proceed() { | ||||||
| 
 |  | ||||||
|   function proceed(resolve) { |  | ||||||
|     while (index < json.length) { |     while (index < json.length) { | ||||||
|       const item = json[index++]; |       const item = json[index++]; | ||||||
|       const info = analyze(item); |       const info = analyze(item); | ||||||
|       if (info) { |       if (!info) { | ||||||
|         // using saveStyle directly since json was parsed in background page context
 |         continue; | ||||||
|         // FIXME: rewrite importStyle
 |  | ||||||
|         return API.saveStyle(Object.assign(item, SAVE_OPTIONS)) |  | ||||||
|           .then(style => account({style, info, resolve})); |  | ||||||
|       } |       } | ||||||
|  |       return API.importStyle(item) | ||||||
|  |         .then(style => account({style, info})); | ||||||
|     } |     } | ||||||
|     renderQueue.forEach(style => handleUpdate(style, {reason: 'import'})); |     return done(); | ||||||
|     renderQueue.length = 0; |  | ||||||
|     done(resolve); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   function analyze(item) { |   function analyze(item) { | ||||||
|  | @ -148,17 +142,19 @@ function importFromString(jsonString, oldStyles) { | ||||||
|         .some(field => oldStyle[field] && oldStyle[field] === newStyle[field]); |         .some(field => oldStyle[field] && oldStyle[field] === newStyle[field]); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   function account({style, info, resolve}) { |   function account({style, info}) { | ||||||
|     renderQueue.push(style); |     renderQueue.push(style); | ||||||
|     if (performance.now() - lastRenderTime > RENDER_NAP_TIME_MAX |     if (performance.now() - lastRenderTime > RENDER_NAP_TIME_MAX | ||||||
|     || renderQueue.length > RENDER_QUEUE_MAX) { |     || renderQueue.length > RENDER_QUEUE_MAX) { | ||||||
|       renderQueue.forEach(style => handleUpdate(style, {reason: 'import'})); |  | ||||||
|       setTimeout(scrollElementIntoView, 0, $('#style-' + renderQueue.pop().id)); |       setTimeout(scrollElementIntoView, 0, $('#style-' + renderQueue.pop().id)); | ||||||
|       renderQueue.length = 0; |       renderQueue.length = 0; | ||||||
|       lastRenderTime = performance.now(); |       lastRenderTime = performance.now(); | ||||||
|     } |     } | ||||||
|     setTimeout(proceed, 0, resolve); |     updateStats(style, info); | ||||||
|     const {oldStyle, metaEqual, codeEqual} = info; |     return proceed(); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function updateStats(style, {oldStyle, metaEqual, codeEqual}) { | ||||||
|     if (!oldStyle) { |     if (!oldStyle) { | ||||||
|       stats.added.names.push(style.name); |       stats.added.names.push(style.name); | ||||||
|       stats.added.ids.push(style.id); |       stats.added.ids.push(style.id); | ||||||
|  | @ -178,42 +174,41 @@ function importFromString(jsonString, oldStyles) { | ||||||
|     stats.metaOnly.ids.push(style.id); |     stats.metaOnly.ids.push(style.id); | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   function done(resolve) { |   function done() { | ||||||
|     const numChanged = stats.metaAndCode.names.length + |     const numChanged = stats.metaAndCode.names.length + | ||||||
|       stats.metaOnly.names.length + |       stats.metaOnly.names.length + | ||||||
|       stats.codeOnly.names.length + |       stats.codeOnly.names.length + | ||||||
|       stats.added.names.length; |       stats.added.names.length; | ||||||
|     Promise.resolve(numChanged && API.refreshAllTabs()).then(() => { |     const report = Object.keys(stats) | ||||||
|       const report = Object.keys(stats) |       .filter(kind => stats[kind].names.length) | ||||||
|         .filter(kind => stats[kind].names.length) |       .map(kind => { | ||||||
|         .map(kind => { |         const {ids, names, legend} = stats[kind]; | ||||||
|           const {ids, names, legend} = stats[kind]; |         const listItemsWithId = (name, i) => | ||||||
|           const listItemsWithId = (name, i) => |           $create('div', {dataset: {id: ids[i]}}, name); | ||||||
|             $create('div', {dataset: {id: ids[i]}}, name); |         const listItems = name => | ||||||
|           const listItems = name => |           $create('div', name); | ||||||
|             $create('div', name); |         const block = | ||||||
|           const block = |           $create('details', {dataset: {id: kind}}, [ | ||||||
|             $create('details', {dataset: {id: kind}}, [ |             $create('summary', | ||||||
|               $create('summary', |               $create('b', names.length + ' ' + t(legend))), | ||||||
|                 $create('b', names.length + ' ' + t(legend))), |             $create('small', | ||||||
|               $create('small', |               names.map(ids ? listItemsWithId : listItems)), | ||||||
|                 names.map(ids ? listItemsWithId : listItems)), |           ]); | ||||||
|             ]); |         return block; | ||||||
|           return block; |       }); | ||||||
|         }); |     scrollTo(0, 0); | ||||||
|       scrollTo(0, 0); |     messageBox({ | ||||||
|       messageBox({ |       title: t('importReportTitle'), | ||||||
|         title: t('importReportTitle'), |       contents: report.length ? report : t('importReportUnchanged'), | ||||||
|         contents: report.length ? report : t('importReportUnchanged'), |       buttons: [t('confirmClose'), numChanged && t('undo')], | ||||||
|         buttons: [t('confirmClose'), numChanged && t('undo')], |       onshow: bindClick, | ||||||
|         onshow:  bindClick, |     }) | ||||||
|       }).then(({button}) => { |       .then(({button}) => { | ||||||
|         if (button === 1) { |         if (button === 1) { | ||||||
|           undo(); |           undo(); | ||||||
|         } |         } | ||||||
|       }); |       }); | ||||||
|       resolve(numChanged); |     return Promise.resolve(numChanged); | ||||||
|     }); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   function undo() { |   function undo() { | ||||||
|  | @ -224,28 +219,20 @@ function importFromString(jsonString, oldStyles) { | ||||||
|       ...stats.added.ids, |       ...stats.added.ids, | ||||||
|     ]; |     ]; | ||||||
|     let tasks = Promise.resolve(); |     let tasks = Promise.resolve(); | ||||||
|     let tasksUI = Promise.resolve(); |  | ||||||
|     for (const id of newIds) { |     for (const id of newIds) { | ||||||
|       tasks = tasks.then(() => API.deleteStyle(id)); |       tasks = tasks.then(() => API.deleteStyle(id)); | ||||||
|       tasksUI = tasksUI.then(() => handleDelete(id)); |  | ||||||
|       const oldStyle = oldStylesById.get(id); |       const oldStyle = oldStylesById.get(id); | ||||||
|       if (oldStyle) { |       if (oldStyle) { | ||||||
|         Object.assign(oldStyle, SAVE_OPTIONS); |         tasks = tasks.then(() => API.importStyle(oldStyle)); | ||||||
|         // FIXME: import undo
 |  | ||||||
|         // tasks = tasks.then(() => API.saveStyle(oldStyle));
 |  | ||||||
|         tasksUI = tasksUI.then(() => handleUpdate(oldStyle, {reason: 'import'})); |  | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|     // taskUI is superfast and updates style list only in this page,
 |     // taskUI is superfast and updates style list only in this page,
 | ||||||
|     // which should account for 99.99999999% of cases, supposedly
 |     // which should account for 99.99999999% of cases, supposedly
 | ||||||
|     return tasks |     return tasks.then(() => messageBox({ | ||||||
|       .then(tasksUI) |       title: t('importReportUndoneTitle'), | ||||||
|       .then(API.refreshAllTabs) |       contents: newIds.length + ' ' + t('importReportUndone'), | ||||||
|       .then(() => messageBox({ |       buttons: [t('confirmClose')], | ||||||
|         title: t('importReportUndoneTitle'), |     })); | ||||||
|         contents: newIds.length + ' ' + t('importReportUndone'), |  | ||||||
|         buttons: [t('confirmClose')], |  | ||||||
|       })); |  | ||||||
|   } |   } | ||||||
| 
 | 
 | ||||||
|   function bindClick() { |   function bindClick() { | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user