Explorar el Código

feat: update position on import

Gerald hace 8 años
padre
commit
2d050d7770

+ 15 - 34
src/background/utils/db.js

@@ -2,11 +2,16 @@ import Promise from 'sync-promise-lite';
 import { i18n, request } from 'src/common';
 import { getNameURI, getScriptInfo, isRemote, parseMeta, newScript } from './script';
 import { testScript, testBlacklist } from './tester';
+import {
+  initialize as initPosition,
+  check as checkPosition,
+  get as getPosition,
+  update as updatePosition,
+} from './position';
 
 let db;
-let position;
 
-export const initialized = openDatabase().then(initPosition);
+export const initialized = openDatabase().then(() => initPosition(db));
 
 function openDatabase() {
   return new Promise((resolve, reject) => {
@@ -41,18 +46,6 @@ function openDatabase() {
   });
 }
 
-function initPosition() {
-  position = 0;
-  const os = db.transaction('scripts', 'readwrite').objectStore('scripts');
-  return new Promise(resolve => {
-    os.index('position').openCursor(null, 'prev').onsuccess = e => {
-      const { result } = e.target;
-      if (result) position = result.key;
-      resolve();
-    };
-  });
-}
-
 export function getScript(id, cTx) {
   const tx = cTx || db.transaction('scripts');
   const os = tx.objectStore('scripts');
@@ -272,10 +265,8 @@ function saveRequire(uri, code, cTx) {
 export function saveScript(script, cTx) {
   script.enabled = script.enabled ? 1 : 0;
   script.update = script.update ? 1 : 0;
-  if (!script.position) {
-    position += 1;
-    script.position = position;
-  }
+  if (!script.position) script.position = getPosition();
+  updatePosition(script.position);
   const tx = cTx || db.transaction('scripts', 'readwrite');
   const os = tx.objectStore('scripts');
   return new Promise((resolve, reject) => {
@@ -376,9 +367,9 @@ export function getExportData(ids, withValues) {
 
 export function vacuum() {
   const tx = db.transaction(['scripts', 'require', 'cache', 'values'], 'readwrite');
+  checkPosition();
   return loadScripts()
   .then(data => Promise.all([
-    vacuumPosition(data.ids),
     vacuumCache('require', data.require),
     vacuumCache('cache', data.cache),
     vacuumCache('values', data.values),
@@ -404,22 +395,8 @@ export function vacuum() {
       });
       if (isRemote(script.meta.icon)) data.cache[script.meta.icon] = 1;
       data.values[script.uri] = 1;
-      return script.id;
     })
-    .then(ids => {
-      data.ids = ids;
-      return data;
-    });
-  }
-  function vacuumPosition(ids) {
-    const os = tx.objectStore('scripts');
-    return ids.reduce((res, id, i) => res.then(() => new Promise(resolve => {
-      os.get(id).onsuccess = e => {
-        const { result } = e.target;
-        result.position = i + 1;
-        os.put(result).onsuccess = () => resolve();
-      };
-    })), Promise.resolve());
+    .then(() => data);
   }
   function vacuumCache(dbName, dict) {
     const os = tx.objectStore(dbName);
@@ -509,6 +486,7 @@ export function parseScript(data) {
       image.src = url;
     }));
   }
+  let needCheckPosition;
   return queryScript(data.id, meta, tx)
   .then(result => {
     let script;
@@ -517,9 +495,11 @@ export function parseScript(data) {
       script = result;
     } else {
       script = newScript();
+      script.position = getPosition();
       res.cmd = 'AddScript';
       res.data.message = i18n('msgInstalled');
     }
+    needCheckPosition = data.more && data.more.position !== script.position;
     updateProps(script, data.more);
     updateProps(script.custom, data.custom);
     script.meta = meta;
@@ -534,6 +514,7 @@ export function parseScript(data) {
     return saveScript(script, tx);
   })
   .then(script => {
+    if (needCheckPosition) checkPosition(script.position);
     Object.assign(res.data, getScriptInfo(script));
     return res;
   });

+ 74 - 0
src/background/utils/position.js

@@ -0,0 +1,74 @@
+import { debounce } from 'src/common';
+
+let position;
+let start = -1;
+let debouncedCheck;
+
+export function initialize(db) {
+  position = 0;
+  const os = db.transaction('scripts', 'readwrite').objectStore('scripts');
+  debouncedCheck = debounce(initCheck(db), 300);
+  return new Promise(resolve => {
+    os.index('position').openCursor(null, 'prev').onsuccess = e => {
+      const { result } = e.target;
+      if (result) position = result.key;
+      resolve();
+    };
+  });
+}
+
+function initCheck(db) {
+  return function doCheck() {
+    const tx = db.transaction('scripts', 'readwrite');
+    const os = tx.objectStore('scripts');
+    let offset = Math.max(1, start);
+    start = -1;
+    const updates = [];
+    return new Promise(resolve => {
+      os.index('position').openCursor(start).onsuccess = e => {
+        const cursor = e.target.result;
+        if (cursor) {
+          const { value } = cursor;
+          if (value.position !== offset) updates.push({ id: value.id, position: offset });
+          if (position < offset) position = offset;
+          offset += 1;
+          cursor.continue();
+        } else {
+          resolve();
+        }
+      };
+    })
+    .then(updatePosition)
+    .then(() => {
+      browser.runtime.sendMessage({
+        cmd: 'ScriptsUpdated',
+      });
+    });
+    function updatePosition() {
+      const item = updates.shift();
+      if (item) {
+        return new Promise(resolve => {
+          os.get(item.id).onsuccess = e => {
+            const { result } = e.target;
+            result.position = item.position;
+            os.put(result).onsuccess = () => { resolve(); };
+          };
+        })
+        .then(updatePosition);
+      }
+    }
+  };
+}
+
+export function check(startOffset = 0) {
+  if (start < 0 || start > startOffset) start = startOffset;
+  if (debouncedCheck) debouncedCheck();
+}
+
+export function get() {
+  return position + 1;
+}
+
+export function update(pos) {
+  if (position < pos) position = pos;
+}

+ 7 - 2
src/options/app.js

@@ -72,8 +72,7 @@ function loadHash() {
   }
 }
 
-function initMain() {
-  store.loading = true;
+function loadData() {
   sendMessage({ cmd: 'GetData' })
   .then((data) => {
     [
@@ -87,7 +86,13 @@ function initMain() {
     // features.reset(data.version);
     features.reset('sync');
   });
+}
+
+function initMain() {
+  store.loading = true;
+  loadData();
   Object.assign(handlers, {
+    ScriptsUpdated: loadData,
     UpdateSync(data) {
       store.sync = data;
     },

+ 1 - 1
src/options/views/tab-settings/vm-export.vue

@@ -114,7 +114,7 @@ function exportData(selectedIds) {
         names[name] += 1;
         name = `${name}_${names[name]}`;
       } else names[name] = 1;
-      vm.scripts[name] = ['id', 'custom', 'enabled', 'update']
+      vm.scripts[name] = ['custom', 'enabled', 'update', 'position']
       .reduce((res, key) => {
         res[key] = script[key];
         return res;