Storage controller refactor (#905)

* Use hidden instead of storage-hidden class

* Refactor storage events

* Make ID more generic

* Update how persistent storage is activated

* Add null checks

* Update HTML/ID

* Disallow disabling persistent storage

* Refactoring

* Update more IDs

* Disable multiple simultaneous stats updates

* Store node references

* Move undefined assignment
This commit is contained in:
toasted-nutbread 2020-10-10 16:54:52 -04:00 committed by GitHub
parent 3174f3c657
commit 199dd7d763
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 98 additions and 48 deletions

View File

@ -16,7 +16,7 @@
*/
.storage-hidden {
.help-block[hidden] {
display: none;
}

View File

@ -20,15 +20,35 @@ class StorageController {
this._mostRecentStorageEstimate = null;
this._storageEstimateFailed = false;
this._isUpdating = false;
this._persistentStorageCheckbox = false;
this._storageUsageNode = null;
this._storageQuotaNode = null;
this._storageUseFiniteNode = null;
this._storageUseInfiniteNode = null;
this._storageUseUndefinedNode = null;
this._storageUseNode = null;
this._storageErrorNode = null;
}
prepare() {
this._persistentStorageCheckbox = document.querySelector('#storage-persistent-checkbox');
this._storageUsageNode = document.querySelector('#storage-usage');
this._storageQuotaNode = document.querySelector('#storage-quota');
this._storageUseFiniteNode = document.querySelector('#storage-use-finite');
this._storageUseInfiniteNode = document.querySelector('#storage-use-infinite');
this._storageUseUndefinedNode = document.querySelector('#storage-use-undefined');
this._storageUseNode = document.querySelector('#storage-use');
this._storageErrorNode = document.querySelector('#storage-error');
this._preparePersistentStorage();
this.updateStats();
this._persistentStorageCheckbox.addEventListener('change', this._onPersistentStorageCheckboxChange.bind(this), false);
document.querySelector('#storage-refresh').addEventListener('click', this.updateStats.bind(this), false);
}
async updateStats() {
if (this._isUpdating) { return; }
try {
this._isUpdating = true;
@ -39,15 +59,16 @@ class StorageController {
// Firefox reports usage as 0 when persistent storage is enabled.
const finite = (estimate.usage > 0 || !(await this._isStoragePeristent()));
if (finite) {
document.querySelector('#storage-usage').textContent = this._bytesToLabeledString(estimate.usage);
document.querySelector('#storage-quota').textContent = this._bytesToLabeledString(estimate.quota);
this._storageUsageNode.textContent = this._bytesToLabeledString(estimate.usage);
this._storageQuotaNode.textContent = this._bytesToLabeledString(estimate.quota);
}
document.querySelector('#storage-use-finite').classList.toggle('storage-hidden', !finite);
document.querySelector('#storage-use-infinite').classList.toggle('storage-hidden', finite);
this._storageUseFiniteNode.hidden = !finite;
this._storageUseInfiniteNode.hidden = finite;
}
document.querySelector('#storage-use').classList.toggle('storage-hidden', !valid);
document.querySelector('#storage-error').classList.toggle('storage-hidden', valid);
if (this._storageUseUndefinedNode !== null) { this._storageUseUndefinedNode.hidden = !valid; }
if (this._storageUseNode !== null) { this._storageUseNode.hidden = !valid; }
if (this._storageErrorNode !== null) { this._storageErrorNode.hidden = valid; }
return valid;
} finally {
@ -63,35 +84,53 @@ class StorageController {
return;
}
const info = document.querySelector('#storage-persist-info');
const button = document.querySelector('#storage-persist-button');
const checkbox = document.querySelector('#storage-persist-button-checkbox');
const info = document.querySelector('#storage-persistent-info');
if (info !== null) { info.hidden = false; }
info.classList.remove('storage-hidden');
button.classList.remove('storage-hidden');
const isStoragePeristent = await this._isStoragePeristent();
this._updateCheckbox(isStoragePeristent);
let persisted = await this._isStoragePeristent();
checkbox.checked = persisted;
const button = document.querySelector('#storage-persistent-button');
if (button !== null) {
button.hidden = false;
button.addEventListener('click', this._onPersistStorageButtonClick.bind(this), false);
}
}
button.addEventListener('click', async () => {
if (persisted) {
return;
}
let result = false;
try {
result = await navigator.storage.persist();
} catch (e) {
// NOP
}
_onPersistentStorageCheckboxChange(e) {
const node = e.currentTarget;
if (!node.checked) {
node.checked = true;
return;
}
this._attemptPersistStorage();
}
if (result) {
persisted = true;
checkbox.checked = true;
this.updateStats();
} else {
document.querySelector('.storage-persist-fail-warning').classList.remove('storage-hidden');
}
}, false);
_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() {
@ -128,4 +167,10 @@ class StorageController {
}
return false;
}
_updateCheckbox(isStoragePeristent) {
const checkbox = this._persistentStorageCheckbox;
checkbox.checked = isStoragePeristent;
checkbox.readOnly = isStoragePeristent;
}
}

View File

@ -796,7 +796,7 @@
<h3>Storage</h3>
</div>
<div id="storage-persist-info" class="storage-hidden">
<div id="storage-persistent-info" hidden>
<p class="help-block">
Web browsers may sometimes clear stored data if the device is running low on storage space.
This can result in the stored dictionary data being deleted unexpectedly, causing Yomichan to stop working for no apparent reason.
@ -804,16 +804,19 @@
</p>
</div>
<div id="storage-use" class="storage-hidden">
<p class="help-block storage-hidden" id="storage-use-finite">
<div id="storage-use" hidden>
<p class="help-block" id="storage-use-undefined">
Yomichan is using an indeterminate amount of storage.
</p>
<p class="help-block" id="storage-use-finite" hidden>
Yomichan is using approximately <strong id="storage-usage"></strong> of <strong id="storage-quota"></strong>.
</p>
<p class="help-block storage-hidden" id="storage-use-infinite">
<p class="help-block" id="storage-use-infinite" hidden>
Yomichan is permitted <strong>unlimited storage</strong>.
</p>
</div>
<div id="storage-error" class="storage-hidden">
<div id="storage-error" hidden>
<p class="help-block">
Could not detect how much storage Yomichan is using.
</p>
@ -832,22 +835,24 @@
<div>
<button class="btn btn-default" id="storage-refresh"><span class="btn-inner-middle">Refresh</span></button>
<button class="btn btn-default storage-hidden ignore-form-changes" id="storage-persist-button"><span class="storage-button-inner"><input type="checkbox" class="btn-inner-middle storage-button-checkbox" id="storage-persist-button-checkbox" readonly /><span class="btn-inner-middle">Persistent Storage</span></span></button>
<button class="btn btn-default ignore-form-changes" id="storage-persistent-button" hidden><span class="storage-button-inner"><input type="checkbox" class="btn-inner-middle storage-button-checkbox" id="storage-persistent-checkbox" readonly /><span class="btn-inner-middle">Persistent Storage</span></span></button>
</div>
<p></p>
<div data-show-for-browser="firefox-mobile"><div class="alert alert-warning storage-persist-fail-warning storage-hidden">
<p>It may not be possible to enable Persistent Storage on Firefox for Android.</p>
</div></div>
<div id="storage-persistent-fail-warning" hidden>
<div data-show-for-browser="firefox-mobile"><div class="alert alert-warning">
<p>It may not be possible to enable Persistent Storage on Firefox for Android.</p>
</div></div>
<div data-show-for-browser="chrome"><div class="alert alert-warning storage-persist-fail-warning storage-hidden">
<p>
It may not be possible to enable Persistent Storage on Chrome-based browsers.
However, the Yomichan extension has permission for unlimited storage which should
prevent Chrome from deleting data.<sup><a href="https://bugs.chromium.org/p/chromium/issues/detail?id=680392#c15" target="_blank" rel="noopener">[1]</a></sup>
</p>
</div></div>
<div data-show-for-browser="chrome"><div class="alert alert-warning">
<p>
It may not be possible to enable Persistent Storage on Chrome-based browsers.
However, the Yomichan extension has permission for unlimited storage which should
prevent Chrome from deleting data.<sup><a href="https://bugs.chromium.org/p/chromium/issues/detail?id=680392#c15" target="_blank" rel="noopener">[1]</a></sup>
</p>
</div></div>
</div>
</div>
<div>