diff options
Diffstat (limited to 'ext/js')
-rw-r--r-- | ext/js/pages/settings/backup-controller.js | 130 |
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; + } + } } |