aboutsummaryrefslogtreecommitdiff
path: root/ext/js/pages/settings/backup-controller.js
diff options
context:
space:
mode:
authorDarius Jahandarie <djahandarie@gmail.com>2023-08-15 23:57:37 +0900
committerGitHub <noreply@github.com>2023-08-15 23:57:37 +0900
commit83be1d6312b5741f732243e3315a1f98c12dc184 (patch)
tree797652c9b6b8d637e0dbbbd0cb2cdeb26c248ca8 /ext/js/pages/settings/backup-controller.js
parentc4378974f1bea94947cbe6278b1d1593cfe653d9 (diff)
parent7bad83e01cb4bb65dd544de127224ba453b8e4eb (diff)
Merge pull request #187 from infi-personal/master
Add support for exporting and importing dictionaries database.
Diffstat (limited to 'ext/js/pages/settings/backup-controller.js')
-rw-r--r--ext/js/pages/settings/backup-controller.js130
1 files changed, 130 insertions, 0 deletions
diff --git a/ext/js/pages/settings/backup-controller.js b/ext/js/pages/settings/backup-controller.js
index b4de01bf..bd089fb1 100644
--- a/ext/js/pages/settings/backup-controller.js
+++ b/ext/js/pages/settings/backup-controller.js
@@ -18,6 +18,7 @@
/* global
* ArrayBufferUtil
+ * Dexie
* DictionaryController
* OptionsUtil
*/
@@ -33,6 +34,10 @@ class BackupController {
this._settingsImportErrorModal = null;
this._settingsImportWarningModal = null;
this._optionsUtil = null;
+
+ this._dictionariesDatabaseName = 'dict';
+ this._settingsExportDatabaseToken = null;
+
try {
this._optionsUtil = new OptionsUtil();
} catch (e) {
@@ -56,6 +61,10 @@ class BackupController {
this._addNodeEventListener('#settings-import-file', 'change', this._onSettingsImportFileChange.bind(this), false);
this._addNodeEventListener('#settings-reset-button', 'click', this._onSettingsResetClick.bind(this), false);
this._addNodeEventListener('#settings-reset-confirm-button', 'click', this._onSettingsResetConfirmClick.bind(this), false);
+
+ this._addNodeEventListener('#settings-export-db-button', 'click', this._onSettingsExportDatabaseClick.bind(this), false);
+ this._addNodeEventListener('#settings-import-db-button', 'click', this._onSettingsImportDatabaseClick.bind(this), false);
+ this._addNodeEventListener('#settings-import-db', 'change', this._onSettingsImportDatabaseChange.bind(this), false);
}
// Private
@@ -413,4 +422,125 @@ class BackupController {
log.error(e);
}
}
+
+ // Exporting Dictionaries Database
+
+ _databaseExportImportErrorMessage(message, isWarning=false) {
+ const errorMessageContainer = document.querySelector('#db-ops-error-report');
+ errorMessageContainer.style.display = 'block';
+ errorMessageContainer.textContent = message;
+
+ if (isWarning) { // Hide after 5 seconds (5000 milliseconds)
+ errorMessageContainer.style.color = '#FFC40C';
+ setTimeout(function _hideWarningMessage() {
+ errorMessageContainer.style.display = 'none';
+ errorMessageContainer.style.color = '#8B0000';
+ }, 5000);
+ }
+ }
+
+ _databaseExportProgressCallback({totalRows, completedRows, done}) {
+ console.log(`Progress: ${completedRows} of ${totalRows} rows completed`);
+ const messageContainer = document.querySelector('#db-ops-progress-report');
+ messageContainer.style.display = 'block';
+ messageContainer.textContent = `Export Progress: ${completedRows} of ${totalRows} rows completed`;
+
+ if (done) {
+ console.log('Done exporting.');
+ messageContainer.style.display = 'none';
+ }
+ }
+
+ async _exportDatabase(databaseName) {
+ const db = await new Dexie(databaseName).open();
+ const blob = await db.export({progressCallback: this._databaseExportProgressCallback});
+ await db.close();
+ return blob;
+ }
+
+ async _onSettingsExportDatabaseClick() {
+ if (this._settingsExportDatabaseToken !== null) {
+ // An existing import or export is in progress.
+ this._databaseExportImportErrorMessage('An export or import operation is already in progress. Please wait till it is over.', true);
+ return;
+ }
+
+ const errorMessageContainer = document.querySelector('#db-ops-error-report');
+ errorMessageContainer.style.display = 'none';
+
+ const date = new Date(Date.now());
+ const pageExitPrevention = this._settingsController.preventPageExit();
+ try {
+ const token = {};
+ this._settingsExportDatabaseToken = token;
+ const fileName = `yomitan-dictionaries-${this._getSettingsExportDateString(date, '-', '-', '-', 6)}.json`;
+ const data = await this._exportDatabase(this._dictionariesDatabaseName);
+ const blob = new Blob([data], {type: 'application/json'});
+ this._saveBlob(blob, fileName);
+ } catch (error) {
+ console.log(error);
+ this._databaseExportImportErrorMessage('Errors encountered while exporting. Please try again. Restart the browser if it continues to fail.');
+ } finally {
+ pageExitPrevention.end();
+ this._settingsExportDatabaseToken = null;
+ }
+ }
+
+ // Importing Dictionaries Database
+
+ _databaseImportProgressCallback({totalRows, completedRows, done}) {
+ console.log(`Progress: ${completedRows} of ${totalRows} rows completed`);
+ const messageContainer = document.querySelector('#db-ops-progress-report');
+ messageContainer.style.display = 'block';
+ messageContainer.style.color = '#4169e1';
+ messageContainer.textContent = `Import Progress: ${completedRows} of ${totalRows} rows completed`;
+
+ if (done) {
+ console.log('Done importing.');
+ messageContainer.style.color = '#006633';
+ messageContainer.textContent = 'Done importing. You will need to re-enable the dictionaries and refresh afterward. If you run into issues, please restart the browser. If it continues to fail, reinstall Yomitan and import dictionaries one-by-one.';
+ }
+ }
+
+ async _importDatabase(databaseName, file) {
+ await yomichan.api.purgeDatabase();
+ await Dexie.import(file, {progressCallback: this._databaseImportProgressCallback});
+ yomichan.api.triggerDatabaseUpdated('dictionary', 'import');
+ yomichan.trigger('storageChanged');
+ }
+
+ _onSettingsImportDatabaseClick() {
+ document.querySelector('#settings-import-db').click();
+ }
+
+ async _onSettingsImportDatabaseChange(e) {
+ if (this._settingsExportDatabaseToken !== null) {
+ // An existing import or export is in progress.
+ this._databaseExportImportErrorMessage('An export or import operation is already in progress. Please wait till it is over.', true);
+ return;
+ }
+
+ const errorMessageContainer = document.querySelector('#db-ops-error-report');
+ errorMessageContainer.style.display = 'none';
+
+ const files = e.target.files;
+ if (files.length === 0) { return; }
+
+ const pageExitPrevention = this._settingsController.preventPageExit();
+ const file = files[0];
+ e.target.value = null;
+ try {
+ const token = {};
+ this._settingsExportDatabaseToken = token;
+ await this._importDatabase(this._dictionariesDatabaseName, file);
+ } catch (error) {
+ console.log(error);
+ const messageContainer = document.querySelector('#db-ops-progress-report');
+ messageContainer.style.color = 'red';
+ this._databaseExportImportErrorMessage('Encountered errors when importing. Please restart the browser and try again. If it continues to fail, reinstall Yomitan and import dictionaries one-by-one.');
+ } finally {
+ pageExitPrevention.end();
+ this._settingsExportDatabaseToken = null;
+ }
+ }
}