diff options
| author | toasted-nutbread <toasted-nutbread@users.noreply.github.com> | 2021-02-14 23:10:01 -0500 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-02-14 23:10:01 -0500 | 
| commit | 450912c1098b0ec4c0ec29b7aec8b47143cfd6fc (patch) | |
| tree | 6aae6ab69e037915faf7681991952113ad6d6094 /ext/js/pages/settings/storage-controller.js | |
| parent | d6332d2bc723f9aa60f2c886564bef49a6b91b84 (diff) | |
Move js/settings (#1397)
* Move js/settings to js/pages/settings
* Fix script ordering
Diffstat (limited to 'ext/js/pages/settings/storage-controller.js')
| -rw-r--r-- | ext/js/pages/settings/storage-controller.js | 183 | 
1 files changed, 183 insertions, 0 deletions
diff --git a/ext/js/pages/settings/storage-controller.js b/ext/js/pages/settings/storage-controller.js new file mode 100644 index 00000000..c27c8690 --- /dev/null +++ b/ext/js/pages/settings/storage-controller.js @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2019-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 StorageController { +    constructor() { +        this._mostRecentStorageEstimate = null; +        this._storageEstimateFailed = false; +        this._isUpdating = false; +        this._persistentStorageCheckbox = false; +        this._storageUsageNode = null; +        this._storageQuotaNode = null; +        this._storageUseFiniteNodes = null; +        this._storageUseInfiniteNodes = null; +        this._storageUseValidNodes = null; +        this._storageUseInvalidNodes = null; +    } + +    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'); +        this._storageUseInfiniteNodes = document.querySelectorAll('.storage-use-infinite'); +        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); +    } + +    async updateStats() { +        if (this._isUpdating) { return; } + +        try { +            this._isUpdating = true; + +            const estimate = await this._storageEstimate(); +            const valid = (estimate !== null); + +            // Firefox reports usage as 0 when persistent storage is enabled. +            const finite = valid && (estimate.usage > 0 || !(await this._isStoragePeristent())); +            if (finite) { +                for (const node of this._storageUsageNodes) { +                    node.textContent = this._bytesToLabeledString(estimate.usage); +                } +                for (const node of this._storageQuotaNodes) { +                    node.textContent = this._bytesToLabeledString(estimate.quota); +                } +            } + +            this._setElementsVisible(this._storageUseFiniteNodes, valid && finite); +            this._setElementsVisible(this._storageUseInfiniteNodes, valid && !finite); +            this._setElementsVisible(this._storageUseValidNodes, valid); +            this._setElementsVisible(this._storageUseInvalidNodes, !valid); + +            return valid; +        } finally { +            this._isUpdating = false; +        } +    } + +    // 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; +        } +        try { +            const value = await navigator.storage.estimate(); +            this._mostRecentStorageEstimate = value; +            return value; +        } catch (e) { +            this._storageEstimateFailed = true; +        } +        return null; +    } + +    _bytesToLabeledString(size) { +        const base = 1000; +        const labels = [' bytes', 'KB', 'MB', 'GB', 'TB']; +        const maxLabelIndex = labels.length - 1; +        let labelIndex = 0; +        while (size >= base && labelIndex < maxLabelIndex) { +            size /= base; +            ++labelIndex; +        } +        const label = labelIndex === 0 ? `${size}` : size.toFixed(1); +        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) { +            element.hidden = visible; +        } +    } +}  |