summaryrefslogtreecommitdiff
path: root/ext/bg/js/database.js
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2019-11-02 16:21:06 -0400
committertoasted-nutbread <toasted-nutbread@users.noreply.github.com>2019-11-07 20:30:55 -0500
commite091c7ebe2f6780b6a88df313c9f20170a8e5c1c (patch)
tree54eaeb00c11fa591321dc4d6a934fd449cd4c5d3 /ext/bg/js/database.js
parente355b839142a8bab0edc446c7da08256ad5b938c (diff)
Add support for deleting individual dictionaries
Diffstat (limited to 'ext/bg/js/database.js')
-rw-r--r--ext/bg/js/database.js104
1 files changed, 104 insertions, 0 deletions
diff --git a/ext/bg/js/database.js b/ext/bg/js/database.js
index fc0af049..dc2198ac 100644
--- a/ext/bg/js/database.js
+++ b/ext/bg/js/database.js
@@ -56,6 +56,42 @@ class Database {
await this.prepare();
}
+ async deleteDictionary(dictionaryName, onProgress, progressSettings) {
+ this.validate();
+
+ const targets = [
+ ['dictionaries', 'title'],
+ ['kanji', 'dictionary'],
+ ['kanjiMeta', 'dictionary'],
+ ['terms', 'dictionary'],
+ ['termMeta', 'dictionary'],
+ ['tagMeta', 'dictionary']
+ ];
+ const promises = [];
+ const progressData = {
+ count: 0,
+ processed: 0,
+ storeCount: targets.length,
+ storesProcesed: 0
+ };
+ let progressRate = (typeof progressSettings === 'object' && progressSettings !== null ? progressSettings.rate : 0);
+ if (typeof progressRate !== 'number' || progressRate <= 0) {
+ progressRate = 1000;
+ }
+
+ const db = this.db.backendDB();
+
+ for (const [objectStoreName, index] of targets) {
+ const dbTransaction = db.transaction([objectStoreName], 'readwrite');
+ const dbObjectStore = dbTransaction.objectStore(objectStoreName);
+ const dbIndex = dbObjectStore.index(index);
+ const only = IDBKeyRange.only(dictionaryName);
+ promises.push(Database.deleteValues(dbObjectStore, dbIndex, only, onProgress, progressData, progressRate));
+ }
+
+ await Promise.all(promises);
+ }
+
async findTermsBulk(termList, titles) {
this.validate();
@@ -612,4 +648,72 @@ class Database {
request.onsuccess = (e) => resolve(e.target.result);
});
}
+
+ static getAllKeys(dbIndex, query) {
+ const fn = typeof dbIndex.getAllKeys === 'function' ? Database.getAllKeysFast : Database.getAllKeysUsingCursor;
+ return fn(dbIndex, query);
+ }
+
+ static getAllKeysFast(dbIndex, query) {
+ return new Promise((resolve, reject) => {
+ const request = dbIndex.getAllKeys(query);
+ request.onerror = (e) => reject(e);
+ request.onsuccess = (e) => resolve(e.target.result);
+ });
+ }
+
+ static getAllKeysUsingCursor(dbIndex, query) {
+ return new Promise((resolve, reject) => {
+ const primaryKeys = [];
+ const request = dbIndex.openKeyCursor(query, 'next');
+ request.onerror = (e) => reject(e);
+ request.onsuccess = (e) => {
+ const cursor = e.target.result;
+ if (cursor) {
+ primaryKeys.push(cursor.primaryKey);
+ cursor.continue();
+ } else {
+ resolve(primaryKeys);
+ }
+ };
+ });
+ }
+
+ static async deleteValues(dbObjectStore, dbIndex, query, onProgress, progressData, progressRate) {
+ const hasProgress = (typeof onProgress === 'function');
+ const count = await Database.getCount(dbIndex, query);
+ ++progressData.storesProcesed;
+ progressData.count += count;
+ if (hasProgress) {
+ onProgress(progressData);
+ }
+
+ const onValueDeleted = (
+ hasProgress ?
+ () => {
+ const p = ++progressData.processed;
+ if ((p % progressRate) === 0 || p === progressData.count) {
+ onProgress(progressData);
+ }
+ } :
+ () => {}
+ );
+
+ const promises = [];
+ const primaryKeys = await Database.getAllKeys(dbIndex, query);
+ for (const key of primaryKeys) {
+ const promise = Database.deleteValue(dbObjectStore, key).then(onValueDeleted);
+ promises.push(promise);
+ }
+
+ await Promise.all(promises);
+ }
+
+ static deleteValue(dbObjectStore, key) {
+ return new Promise((resolve, reject) => {
+ const request = dbObjectStore.delete(key);
+ request.onerror = (e) => reject(e);
+ request.onsuccess = () => resolve();
+ });
+ }
}