summaryrefslogtreecommitdiff
path: root/ext/js/pages
diff options
context:
space:
mode:
authortoasted-nutbread <toasted-nutbread@users.noreply.github.com>2021-03-02 20:27:51 -0500
committerGitHub <noreply@github.com>2021-03-02 20:27:51 -0500
commit4208595293a18c2cd95064caf77db786c2902ac8 (patch)
treebff87aa2eb501ad5cd11bdf70b2048edb662ffa2 /ext/js/pages
parent571b865ae5207acb8e58a5ee38e4ed900194f7fb (diff)
Persistent storage controller (#1478)
* Add PersistentStorageController * Update DictionaryController * Update DictionaryImportController * Update when storage stats are updated
Diffstat (limited to 'ext/js/pages')
-rw-r--r--ext/js/pages/settings/dictionary-controller.js10
-rw-r--r--ext/js/pages/settings/dictionary-import-controller.js15
-rw-r--r--ext/js/pages/settings/main.js10
-rw-r--r--ext/js/pages/settings/persistent-storage-controller.js94
-rw-r--r--ext/js/pages/settings/settings-main.js10
-rw-r--r--ext/js/pages/settings/storage-controller.js97
-rw-r--r--ext/js/pages/welcome-main.js4
7 files changed, 142 insertions, 98 deletions
diff --git a/ext/js/pages/settings/dictionary-controller.js b/ext/js/pages/settings/dictionary-controller.js
index e12017f2..17abfa13 100644
--- a/ext/js/pages/settings/dictionary-controller.js
+++ b/ext/js/pages/settings/dictionary-controller.js
@@ -190,10 +190,9 @@ class DictionaryEntry {
}
class DictionaryController {
- constructor(settingsController, modalController, storageController, statusFooter) {
+ constructor(settingsController, modalController, statusFooter) {
this._settingsController = settingsController;
this._modalController = modalController;
- this._storageController = storageController;
this._statusFooter = statusFooter;
this._dictionaries = null;
this._dictionaryEntries = [];
@@ -436,7 +435,6 @@ class DictionaryController {
const index = this._dictionaryEntries.findIndex((entry) => entry.dictionaryTitle === dictionaryTitle);
if (index < 0) { return; }
- const storageController = this._storageController;
const statusFooter = this._statusFooter;
const {node} = this._dictionaryEntries[index];
const progressSelector = '.dictionary-delete-progress';
@@ -483,7 +481,7 @@ class DictionaryController {
if (statusFooter !== null) { statusFooter.setTaskActive(progressSelector, false); }
this._setButtonsEnabled(true);
this._isDeleting = false;
- if (storageController !== null) { storageController.updateStats(); }
+ this._triggerStorageChanged();
}
}
@@ -547,6 +545,10 @@ class DictionaryController {
}
}
+ _triggerStorageChanged() {
+ yomichan.trigger('storageChanged');
+ }
+
static createDefaultDictionarySettings() {
return {
enabled: false,
diff --git a/ext/js/pages/settings/dictionary-import-controller.js b/ext/js/pages/settings/dictionary-import-controller.js
index 1389b7f0..ce724263 100644
--- a/ext/js/pages/settings/dictionary-import-controller.js
+++ b/ext/js/pages/settings/dictionary-import-controller.js
@@ -22,10 +22,9 @@
*/
class DictionaryImportController {
- constructor(settingsController, modalController, storageController, statusFooter) {
+ constructor(settingsController, modalController, statusFooter) {
this._settingsController = settingsController;
this._modalController = modalController;
- this._storageController = storageController;
this._statusFooter = statusFooter;
this._modifying = false;
this._purgeButton = null;
@@ -92,7 +91,6 @@ class DictionaryImportController {
if (this._modifying) { return; }
const purgeNotification = this._purgeNotification;
- const storageController = this._storageController;
const prevention = this._preventPageExit();
try {
@@ -114,7 +112,7 @@ class DictionaryImportController {
if (purgeNotification !== null) { purgeNotification.hidden = true; }
this._setSpinnerVisible(false);
this._setModifying(false);
- if (storageController !== null) { storageController.updateStats(); }
+ this._triggerStorageChanged();
}
}
@@ -122,7 +120,6 @@ class DictionaryImportController {
if (this._modifying) { return; }
const statusFooter = this._statusFooter;
- const storageController = this._storageController;
const importInfo = document.querySelector('#dictionary-import-info');
const progressSelector = '.dictionary-import-progress';
const progressContainers = [
@@ -156,7 +153,7 @@ class DictionaryImportController {
const statusString = `${percent.toFixed(0)}%`;
for (const progressBar of progressBars) { progressBar.style.width = cssString; }
for (const label of statusLabels) { label.textContent = statusString; }
- if (storageController !== null) { storageController.updateStats(); }
+ this._triggerStorageChanged();
};
const fileCount = files.length;
@@ -186,7 +183,7 @@ class DictionaryImportController {
}
this._setSpinnerVisible(false);
this._setModifying(false);
- if (storageController !== null) { storageController.updateStats(); }
+ this._triggerStorageChanged();
}
}
@@ -342,4 +339,8 @@ class DictionaryImportController {
}
return errors;
}
+
+ _triggerStorageChanged() {
+ yomichan.trigger('storageChanged');
+ }
}
diff --git a/ext/js/pages/settings/main.js b/ext/js/pages/settings/main.js
index 9785ee0e..3ccf2dd6 100644
--- a/ext/js/pages/settings/main.js
+++ b/ext/js/pages/settings/main.js
@@ -25,6 +25,7 @@
* GenericSettingController
* ModalController
* PermissionsToggleController
+ * PersistentStorageController
* PopupPreviewController
* ProfileController
* ScanInputsController
@@ -63,7 +64,10 @@ async function setupEnvironmentInfo() {
const settingsController = new SettingsController(optionsFull.profileCurrent);
settingsController.prepare();
- const storageController = new StorageController();
+ const persistentStorageController = new PersistentStorageController();
+ persistentStorageController.prepare();
+
+ const storageController = new StorageController(persistentStorageController);
storageController.prepare();
const genericSettingController = new GenericSettingController(settingsController);
@@ -81,10 +85,10 @@ async function setupEnvironmentInfo() {
const profileController = new ProfileController(settingsController, modalController);
profileController.prepare();
- const dictionaryController = new DictionaryController(settingsController, modalController, storageController, null);
+ const dictionaryController = new DictionaryController(settingsController, modalController, null);
dictionaryController.prepare();
- const dictionaryImportController = new DictionaryImportController(settingsController, modalController, storageController, null);
+ const dictionaryImportController = new DictionaryImportController(settingsController, modalController, null);
dictionaryImportController.prepare();
const ankiController = new AnkiController(settingsController);
diff --git a/ext/js/pages/settings/persistent-storage-controller.js b/ext/js/pages/settings/persistent-storage-controller.js
new file mode 100644
index 00000000..e46dbe87
--- /dev/null
+++ b/ext/js/pages/settings/persistent-storage-controller.js
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2021 Yomichan Authors
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+class PersistentStorageController {
+ constructor() {
+ this._persistentStorageCheckbox = false;
+ }
+
+ async prepare() {
+ this._persistentStorageCheckbox = document.querySelector('#storage-persistent-checkbox');
+ this._persistentStorageCheckbox.addEventListener('change', this._onPersistentStorageCheckboxChange.bind(this), false);
+
+ const button = document.querySelector('#storage-persistent-button');
+ if (button !== null) {
+ button.hidden = false;
+ button.addEventListener('click', this._onPersistStorageButtonClick.bind(this), false);
+ }
+
+ if (!this._isPersistentStorageSupported()) { return; }
+
+ const info = document.querySelector('#storage-persistent-info');
+ if (info !== null) { info.hidden = false; }
+
+ const isStoragePeristent = await this.isStoragePeristent();
+ this._updateCheckbox(isStoragePeristent);
+ }
+
+ async isStoragePeristent() {
+ try {
+ return await navigator.storage.persisted();
+ } catch (e) {
+ // NOP
+ }
+ return false;
+ }
+
+ // Private
+
+ _onPersistentStorageCheckboxChange(e) {
+ const node = e.currentTarget;
+ if (node.checked) {
+ node.checked = false;
+ this._attemptPersistStorage();
+ } else {
+ node.checked = true;
+ }
+ }
+
+ _onPersistStorageButtonClick() {
+ const {checked} = this._persistentStorageCheckbox;
+ if (checked) { return; }
+ this._persistentStorageCheckbox.checked = !checked;
+ this._persistentStorageCheckbox.dispatchEvent(new Event('change'));
+ }
+
+ async _attemptPersistStorage() {
+ let isStoragePeristent = false;
+ try {
+ isStoragePeristent = await navigator.storage.persist();
+ } catch (e) {
+ // NOP
+ }
+
+ this._updateCheckbox(isStoragePeristent);
+
+ const node = document.querySelector('#storage-persistent-fail-warning');
+ if (node !== null) { node.hidden = isStoragePeristent; }
+
+ yomichan.trigger('storageChanged');
+ }
+
+ _isPersistentStorageSupported() {
+ return isObject(navigator.storage) && typeof navigator.storage.persist === 'function';
+ }
+
+ _updateCheckbox(isStoragePeristent) {
+ this._persistentStorageCheckbox.checked = isStoragePeristent;
+ this._persistentStorageCheckbox.readOnly = isStoragePeristent;
+ }
+}
diff --git a/ext/js/pages/settings/settings-main.js b/ext/js/pages/settings/settings-main.js
index 273142cd..3618836c 100644
--- a/ext/js/pages/settings/settings-main.js
+++ b/ext/js/pages/settings/settings-main.js
@@ -30,6 +30,7 @@
* ModalController
* NestedPopupsController
* PermissionsToggleController
+ * PersistentStorageController
* PopupPreviewController
* PopupWindowController
* ProfileController
@@ -79,13 +80,16 @@ async function setupGenericSettingsController(genericSettingController) {
const settingsController = new SettingsController(optionsFull.profileCurrent);
settingsController.prepare();
- const storageController = new StorageController();
+ const persistentStorageController = new PersistentStorageController();
+ persistentStorageController.prepare();
+
+ const storageController = new StorageController(persistentStorageController);
storageController.prepare();
- const dictionaryController = new DictionaryController(settingsController, modalController, storageController, statusFooter);
+ const dictionaryController = new DictionaryController(settingsController, modalController, statusFooter);
dictionaryController.prepare();
- const dictionaryImportController = new DictionaryImportController(settingsController, modalController, storageController, statusFooter);
+ const dictionaryImportController = new DictionaryImportController(settingsController, modalController, statusFooter);
dictionaryImportController.prepare();
const genericSettingController = new GenericSettingController(settingsController);
diff --git a/ext/js/pages/settings/storage-controller.js b/ext/js/pages/settings/storage-controller.js
index c27c8690..d92ecff0 100644
--- a/ext/js/pages/settings/storage-controller.js
+++ b/ext/js/pages/settings/storage-controller.js
@@ -16,11 +16,11 @@
*/
class StorageController {
- constructor() {
+ constructor(persistentStorageController) {
+ this._persistentStorageController = persistentStorageController;
this._mostRecentStorageEstimate = null;
this._storageEstimateFailed = false;
this._isUpdating = false;
- this._persistentStorageCheckbox = false;
this._storageUsageNode = null;
this._storageQuotaNode = null;
this._storageUseFiniteNodes = null;
@@ -30,7 +30,6 @@ class StorageController {
}
prepare() {
- this._persistentStorageCheckbox = document.querySelector('#storage-persistent-checkbox');
this._storageUsageNodes = document.querySelectorAll('.storage-usage');
this._storageQuotaNodes = document.querySelectorAll('.storage-quota');
this._storageUseFiniteNodes = document.querySelectorAll('.storage-use-finite');
@@ -38,13 +37,23 @@ class StorageController {
this._storageUseValidNodes = document.querySelectorAll('.storage-use-valid');
this._storageUseInvalidNodes = document.querySelectorAll('.storage-use-invalid');
- this._preparePersistentStorage();
- this.updateStats();
- this._persistentStorageCheckbox.addEventListener('change', this._onPersistentStorageCheckboxChange.bind(this), false);
- document.querySelector('#storage-refresh').addEventListener('click', this.updateStats.bind(this), false);
+ document.querySelector('#storage-refresh').addEventListener('click', this._onStorageRefreshButtonClick.bind(this), false);
+ yomichan.on('storageChanged', this._onStorageChanged.bind(this));
+
+ this._updateStats();
+ }
+
+ // Private
+
+ _onStorageRefreshButtonClick() {
+ this._updateStats();
}
- async updateStats() {
+ _onStorageChanged() {
+ this._updateStats();
+ }
+
+ async _updateStats() {
if (this._isUpdating) { return; }
try {
@@ -54,7 +63,7 @@ class StorageController {
const valid = (estimate !== null);
// Firefox reports usage as 0 when persistent storage is enabled.
- const finite = valid && (estimate.usage > 0 || !(await this._isStoragePeristent()));
+ const finite = valid && (estimate.usage > 0 || !(await this._persistentStorageController.isStoragePeristent()));
if (finite) {
for (const node of this._storageUsageNodes) {
node.textContent = this._bytesToLabeledString(estimate.usage);
@@ -77,61 +86,6 @@ class StorageController {
// Private
- async _preparePersistentStorage() {
- if (!(navigator.storage && navigator.storage.persist)) {
- // Not supported
- return;
- }
-
- const info = document.querySelector('#storage-persistent-info');
- if (info !== null) { info.hidden = false; }
-
- const isStoragePeristent = await this._isStoragePeristent();
- this._updateCheckbox(isStoragePeristent);
-
- const button = document.querySelector('#storage-persistent-button');
- if (button !== null) {
- button.hidden = false;
- button.addEventListener('click', this._onPersistStorageButtonClick.bind(this), false);
- }
- }
-
- _onPersistentStorageCheckboxChange(e) {
- const node = e.currentTarget;
- if (!node.checked) {
- node.checked = true;
- return;
- }
- this._attemptPersistStorage();
- }
-
- _onPersistStorageButtonClick() {
- const {checked} = this._persistentStorageCheckbox;
- if (checked) { return; }
- this._persistentStorageCheckbox.checked = !checked;
- this._persistentStorageCheckbox.dispatchEvent(new Event('change'));
- }
-
- async _attemptPersistStorage() {
- if (await this._isStoragePeristent()) { return; }
-
- let isStoragePeristent = false;
- try {
- isStoragePeristent = await navigator.storage.persist();
- } catch (e) {
- // NOP
- }
-
- this._updateCheckbox(isStoragePeristent);
-
- if (isStoragePeristent) {
- this.updateStats();
- } else {
- const node = document.querySelector('#storage-persistent-fail-warning');
- if (node !== null) { node.hidden = false; }
- }
- }
-
async _storageEstimate() {
if (this._storageEstimateFailed && this._mostRecentStorageEstimate === null) {
return null;
@@ -159,21 +113,6 @@ class StorageController {
return `${label}${labels[labelIndex]}`;
}
- async _isStoragePeristent() {
- try {
- return await navigator.storage.persisted();
- } catch (e) {
- // NOP
- }
- return false;
- }
-
- _updateCheckbox(isStoragePeristent) {
- const checkbox = this._persistentStorageCheckbox;
- checkbox.checked = isStoragePeristent;
- checkbox.readOnly = isStoragePeristent;
- }
-
_setElementsVisible(elements, visible) {
visible = !visible;
for (const element of elements) {
diff --git a/ext/js/pages/welcome-main.js b/ext/js/pages/welcome-main.js
index 27d0af6a..90067282 100644
--- a/ext/js/pages/welcome-main.js
+++ b/ext/js/pages/welcome-main.js
@@ -62,10 +62,10 @@ async function setupGenericSettingsController(genericSettingController) {
const settingsController = new SettingsController(optionsFull.profileCurrent);
settingsController.prepare();
- const dictionaryController = new DictionaryController(settingsController, modalController, null, statusFooter);
+ const dictionaryController = new DictionaryController(settingsController, modalController, statusFooter);
dictionaryController.prepare();
- const dictionaryImportController = new DictionaryImportController(settingsController, modalController, null, statusFooter);
+ const dictionaryImportController = new DictionaryImportController(settingsController, modalController, statusFooter);
dictionaryImportController.prepare();
const genericSettingController = new GenericSettingController(settingsController);