浏览代码

fix sync with new storage

Gerald 8 年之前
父节点
当前提交
21c35f315e

+ 26 - 17
src/background/app.js

@@ -3,13 +3,19 @@ import 'src/common/browser';
 import { i18n, defaultImage, object } from 'src/common';
 import * as sync from './sync';
 import {
-  cache, vmdb,
+  cache,
   getRequestId, httpRequest, abortRequest, confirmInstall,
   newScript, parseMeta,
   setClipboard, checkUpdate,
   getOption, setOption, hookOptions, getAllOptions,
   initialize,
 } from './utils';
+import {
+  getScripts, removeScript, getData, getScriptsByURL,
+  updateScriptInfo, setValues, getExportData, getScriptCode,
+  getScriptByIds, moveScript, vacuum, parseScript, getScript,
+  normalizePosition,
+} from './utils/db';
 
 const VM_VER = browser.runtime.getManifest().version;
 
@@ -32,7 +38,7 @@ function broadcast(data) {
 
 function checkUpdateAll() {
   setOption('lastUpdate', Date.now());
-  vmdb.getScripts()
+  getScripts()
   .then(scripts => {
     const toUpdate = scripts.filter(item => object.get(item, 'config.shouldUpdate'));
     return Promise.all(toUpdate.map(checkUpdate));
@@ -61,11 +67,11 @@ const commands = {
     return newScript();
   },
   RemoveScript(id) {
-    return vmdb.removeScript(id)
+    return removeScript(id)
     .then(() => { sync.sync(); });
   },
   GetData() {
-    return vmdb.getData().then(data => {
+    return getData().then(data => {
       data.sync = sync.getStates();
       data.version = VM_VER;
       return data;
@@ -83,11 +89,11 @@ const commands = {
       }
     });
     return data.isApplied ? (
-      vmdb.getScriptsByURL(url).then(res => Object.assign(data, res))
+      getScriptsByURL(url).then(res => Object.assign(data, res))
     ) : data;
   },
   UpdateScriptInfo({ id, config }) {
-    return vmdb.updateScriptInfo(id, {
+    return updateScriptInfo(id, {
       config,
       custom: {
         modified: Date.now(),
@@ -97,12 +103,15 @@ const commands = {
       sync.sync();
       browser.runtime.sendMessage({
         cmd: 'UpdateScript',
-        data: script,
+        data: {
+          where: { id: script.props.id },
+          update: script,
+        },
       });
     });
   },
   SetValue({ where, values }) {
-    return vmdb.setValues(where, values)
+    return setValues(where, values)
     .then(data => {
       broadcast({
         cmd: 'UpdateValues',
@@ -111,28 +120,28 @@ const commands = {
     });
   },
   ExportZip({ ids, values }) {
-    return vmdb.getExportData(ids, values);
+    return getExportData(ids, values);
   },
   GetScriptCode(id) {
-    return vmdb.getScriptCode(id);
+    return getScriptCode(id);
   },
   GetMetas(ids) {
-    return vmdb.getScriptByIds(ids);
+    return getScriptByIds(ids);
   },
   Move({ id, offset }) {
-    return vmdb.moveScript(id, offset)
+    return moveScript(id, offset)
     .then(() => { sync.sync(); });
   },
-  Vacuum: vmdb.vacuum,
+  Vacuum: vacuum,
   ParseScript(data) {
-    return vmdb.parseScript(data).then(res => {
+    return parseScript(data).then(res => {
       browser.runtime.sendMessage(res);
       sync.sync();
       return res.data;
     });
   },
   CheckUpdate(id) {
-    vmdb.getScript({ id }).then(checkUpdate)
+    getScript({ id }).then(checkUpdate)
     .then(updated => {
       if (updated) sync.sync();
     });
@@ -195,11 +204,11 @@ const commands = {
   },
   ConfirmInstall: confirmInstall,
   CheckScript({ name, namespace }) {
-    return vmdb.getScript({ meta: { name, namespace } })
+    return getScript({ meta: { name, namespace } })
     .then(script => (script ? script.meta.version : null));
   },
   CheckPosition() {
-    return vmdb.normalizePosition();
+    return normalizePosition();
   },
 };
 

+ 61 - 46
src/background/sync/base.js

@@ -1,10 +1,6 @@
-import { debounce, normalizeKeys, request, noop } from 'src/common';
-import {
-  getEventEmitter, vmdb,
-  getOption, setOption, hookOptions,
-} from '../utils';
-
-const { getScriptsByIndex, parseScript, removeScript, checkPosition } = vmdb;
+import { debounce, normalizeKeys, request, noop, object } from 'src/common';
+import { getEventEmitter, getOption, setOption, hookOptions } from '../utils';
+import { getScripts, getScriptCode, parseScript, removeScript, normalizePosition } from '../utils/db';
 
 const serviceNames = [];
 const services = {};
@@ -22,6 +18,11 @@ export function getURI(name) {
   return decodeURIComponent(name.slice(3));
 }
 
+function getLocalData() {
+  return getScripts()
+  .then(scripts => scripts.filter(script => !script.config.removed));
+}
+
 function initConfig() {
   function get(key, def) {
     const keys = normalizeKeys(key);
@@ -289,7 +290,7 @@ export const BaseService = serviceFactory({
     .then(remoteMeta => Promise.all([
       remoteMeta,
       this.list(),
-      getScriptsByIndex('position'),
+      getLocalData(),
     ]))
     .then(([remoteMeta, remoteData, localData]) => {
       const remoteMetaInfo = remoteMeta.info || {};
@@ -322,19 +323,20 @@ export const BaseService = serviceFactory({
         return info;
       }, {});
       localData.forEach(item => {
-        const remoteInfo = remoteMeta.info[item.uri];
+        const { props: { uri, position }, custom: { modified } } = item;
+        const remoteInfo = remoteMeta.info[uri];
         if (remoteInfo) {
-          if (firstSync || !item.custom.modified || remoteInfo.modified > item.custom.modified) {
-            const remoteItem = remoteItemMap[item.uri];
+          if (firstSync || !modified || remoteInfo.modified > modified) {
+            const remoteItem = remoteItemMap[uri];
             getRemote.push(remoteItem);
-          } else if (remoteInfo.modified < item.custom.modified) {
+          } else if (remoteInfo.modified < modified) {
             putRemote.push(item);
-          } else if (remoteInfo.position !== item.position) {
-            remoteInfo.position = item.position;
+          } else if (remoteInfo.position !== position) {
+            remoteInfo.position = position;
             remoteChanged = true;
           }
-          delete remoteItemMap[item.uri];
-        } else if (firstSync || !outdated || item.custom.modified > remoteTimestamp) {
+          delete remoteItemMap[uri];
+        } else if (firstSync || !outdated || modified > remoteTimestamp) {
           putRemote.push(item);
         } else {
           delLocal.push(item);
@@ -353,44 +355,55 @@ export const BaseService = serviceFactory({
           this.log('Download script:', item.uri);
           return this.get(getFilename(item.uri))
           .then(raw => {
-            const data = { more: {} };
+            const data = {};
             try {
               const obj = JSON.parse(raw);
-              if (obj.version === 1) {
+              if (obj.version === 2) {
+                data.code = obj.code;
+                data.config = obj.config;
+                data.custom = obj.custom;
+              } else if (obj.version === 1) {
                 data.code = obj.code;
-                if (obj.more) data.more = obj.more;
+                if (obj.more) {
+                  data.custom = obj.more.custom;
+                  data.config = object.purify({
+                    enabled: obj.more.enabled,
+                    shouldUpdate: obj.more.update,
+                  });
+                }
               }
             } catch (e) {
               data.code = raw;
             }
             const remoteInfo = remoteMeta.info[item.uri];
-            const { modified, position } = remoteInfo;
+            const { modified } = remoteInfo;
             data.modified = modified;
-            if (position) data.more.position = position;
-            if (!getOption('syncScriptStatus') && data.more) {
-              delete data.more.enabled;
+            const position = +remoteInfo.position;
+            if (position) data.position = position;
+            if (!getOption('syncScriptStatus') && data.config) {
+              delete data.config.enabled;
             }
             return parseScript(data)
             .then(res => { browser.runtime.sendMessage(res); });
           });
         }),
-        ...putRemote.map(item => {
-          this.log('Upload script:', item.uri);
-          const data = JSON.stringify({
-            version: 1,
-            code: item.code,
-            more: {
-              custom: item.custom,
-              enabled: item.enabled,
-              update: item.update,
-            },
+        ...putRemote.map(script => {
+          this.log('Upload script:', script.props.uri);
+          return getScriptCode(script.props.id)
+          .then(code => {
+            const data = JSON.stringify({
+              version: 2,
+              code,
+              custom: script.custom,
+              config: script.config,
+            });
+            remoteMeta.info[script.props.uri] = {
+              modified: script.custom.modified,
+              position: script.props.position,
+            };
+            remoteChanged = true;
+            return this.put(getFilename(script.props.uri), data);
           });
-          remoteMeta.info[item.uri] = {
-            modified: item.custom.modified,
-            position: item.position,
-          };
-          remoteChanged = true;
-          return this.put(getFilename(item.uri), data);
         }),
         ...delRemote.map(item => {
           this.log('Remove remote script:', item.uri);
@@ -398,17 +411,19 @@ export const BaseService = serviceFactory({
           remoteChanged = true;
           return this.remove(getFilename(item.uri));
         }),
-        ...delLocal.map(item => {
-          this.log('Remove local script:', item.uri);
-          return removeScript(item.id);
+        ...delLocal.map(script => {
+          this.log('Remove local script:', script.props.uri);
+          return removeScript(script.props.id);
         }),
       ];
-      promiseQueue.push(Promise.all(promiseQueue).then(() => checkPosition()).then(changed => {
+      promiseQueue.push(Promise.all(promiseQueue).then(() => normalizePosition()).then(changed => {
         if (!changed) return;
         remoteChanged = true;
-        return getScriptsByIndex('position', null, null, item => {
-          const remoteInfo = remoteMeta.info[item.uri];
-          if (remoteInfo) remoteInfo.position = item.position;
+        return getScripts().then(scripts => {
+          scripts.forEach(script => {
+            const remoteInfo = remoteMeta.info[script.props.uri];
+            if (remoteInfo) remoteInfo.position = script.props.position;
+          });
         });
       }));
       promiseQueue.push(Promise.all(promiseQueue).then(() => {

+ 5 - 1
src/background/utils/db.js

@@ -306,7 +306,8 @@ export function normalizePosition() {
     }
   });
   store.storeInfo.position = store.scripts.length;
-  return storage.script.dump(updates);
+  const { length } = updates;
+  return length ? storage.script.dump(updates).then(() => length) : Promise.resolve();
 }
 
 export function getScript(where) {
@@ -540,11 +541,14 @@ export function parseScript(data) {
     }
     if (isRemote(data.url)) script.custom.lastInstallURL = data.url;
     object.set(script, 'props.lastModified', data.modified || Date.now());
+    const position = +data.position;
+    if (position) object.set(script, 'props.position', position);
     return saveScript(script, code).then(() => script);
   })
   .then(script => {
     fetchScriptResources(script, data);
     Object.assign(result.data.update, script);
+    result.data.where = { id: script.props.id };
     return result;
   });
 }

+ 0 - 1
src/background/utils/index.js

@@ -7,7 +7,6 @@ export getEventEmitter from './events';
 export * from './script';
 export * from './options';
 export * from './requests';
-export * as vmdb from './db';
 export * from './search';
 export { initialize } from './init';
 

+ 13 - 0
src/common/index.js

@@ -42,6 +42,19 @@ export const object = {
     } else {
       sub[lastKey] = val;
     }
+    return root;
+  },
+  purify(obj) {
+    // Remove keys with undefined values
+    if (Array.isArray(obj)) {
+      obj.forEach(object.purify);
+    } else if (obj && typeof obj === 'object') {
+      Object.keys(obj).forEach(key => {
+        const type = typeof obj[key];
+        if (type === 'undefined') delete obj[key];
+        else object.purify(obj[key]);
+      });
+    }
     return obj;
   },
 };

+ 4 - 4
src/options/app.js

@@ -75,10 +75,10 @@ function initMain() {
     UpdateSync(data) {
       store.sync = data;
     },
-    AddScript(data) {
-      data.message = '';
-      initSearch(data);
-      store.scripts.push(data);
+    AddScript({ update }) {
+      update.message = '';
+      initSearch(update);
+      store.scripts.push(update);
     },
     UpdateScript(data) {
       if (!data) return;

+ 3 - 3
src/options/views/tab-settings/vm-import.vue

@@ -79,11 +79,11 @@ function getVMFile(entry, vmFile) {
         const more = vm.scripts[entry.filename.slice(0, -8)];
         if (more) {
           data.custom = more.custom;
-          data.config = more.config;
+          data.config = more.config || {};
           data.position = more.position;
           // Import data from older version
-          if ('enabled' in more) object.set(data, ['config', 'enabled'], more.enabled);
-          if ('update' in more) object.set(data, ['config', 'shouldUpdate'], more.update);
+          if ('enabled' in more) data.config.enabled = more.enabled;
+          if ('update' in more) data.config.shouldUpdate = more.update;
         }
       }
       sendMessage({