diff options
Diffstat (limited to 'ext/bg/js/settings.js')
-rw-r--r-- | ext/bg/js/settings.js | 197 |
1 files changed, 166 insertions, 31 deletions
diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index 4bf7181f..49bf264d 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -193,7 +193,7 @@ async function onReady() { await dictionaryGroupsPopulate(options); await formMainDictionaryOptionsPopulate(options); } catch (e) { - dictionaryErrorShow(e); + dictionaryErrorsShow([e]); } try { @@ -203,6 +203,8 @@ async function onReady() { } formUpdateVisibility(options); + + storageInfoInitialize(); } $(document).ready(utilAsync(onReady)); @@ -212,36 +214,63 @@ $(document).ready(utilAsync(onReady)); * Dictionary */ -function dictionaryErrorShow(error) { +function dictionaryErrorToString(error) { + if (error.toString) { + error = error.toString(); + } else { + error = `${error}`; + } + + for (const [match, subst] of dictionaryErrorToString.overrides) { + if (error.includes(match)) { + error = subst; + break; + } + } + + return error; +} +dictionaryErrorToString.overrides = [ + [ + 'A mutation operation was attempted on a database that did not allow mutations.', + 'Access to IndexedDB appears to be restricted. Firefox seems to require that the history preference is set to "Remember history" before IndexedDB use of any kind is allowed.' + ], + [ + 'The operation failed for reasons unrelated to the database itself and not covered by any other error code.', + 'Unable to access IndexedDB due to a possibly corrupt user profile. Try using the "Refresh Firefox" feature to reset your user profile.' + ], + [ + 'BulkError', + 'Unable to finish importing dictionary data into IndexedDB. This may indicate that you do not have sufficient disk space available to complete this operation.' + ] +]; + +function dictionaryErrorsShow(errors) { const dialog = $('#dict-error'); - if (error) { - const overrides = [ - [ - 'A mutation operation was attempted on a database that did not allow mutations.', - 'Access to IndexedDB appears to be restricted. Firefox seems to require that the history preference is set to "Remember history" before IndexedDB use of any kind is allowed.' - ], - [ - 'The operation failed for reasons unrelated to the database itself and not covered by any other error code.', - 'Unable to access IndexedDB due to a possibly corrupt user profile. Try using the "Refresh Firefox" feature to reset your user profile.' - ], - [ - 'BulkError', - 'Unable to finish importing dictionary data into IndexedDB. This may indicate that you do not have sufficient disk space available to complete this operation.' - ] - ]; - - if (error.toString) { - error = error.toString(); + dialog.show().text(''); + + if (errors !== null && errors.length > 0) { + const uniqueErrors = {}; + for (let e of errors) { + e = dictionaryErrorToString(e); + uniqueErrors[e] = uniqueErrors.hasOwnProperty(e) ? uniqueErrors[e] + 1 : 1; } - for (const [match, subst] of overrides) { - if (error.includes(match)) { - error = subst; - break; + for (const e in uniqueErrors) { + const count = uniqueErrors[e]; + const div = document.createElement('p'); + if (count > 1) { + div.textContent = `${e} `; + const em = document.createElement('em'); + em.textContent = `(${count})`; + div.appendChild(em); + } else { + div.textContent = `${e}`; } + dialog.append($(div)); } - dialog.show().text(error); + dialog.show(); } else { dialog.hide(); } @@ -317,7 +346,7 @@ async function onDictionaryPurge(e) { const dictProgress = $('#dict-purge').show(); try { - dictionaryErrorShow(); + dictionaryErrorsShow(null); dictionarySpinnerShow(true); await utilDatabasePurge(); @@ -329,12 +358,16 @@ async function onDictionaryPurge(e) { await dictionaryGroupsPopulate(options); await formMainDictionaryOptionsPopulate(options); } catch (e) { - dictionaryErrorShow(e); + dictionaryErrorsShow([e]); } finally { dictionarySpinnerShow(false); dictControls.show(); dictProgress.hide(); + + if (storageEstimate.mostRecent !== null) { + storageUpdateStats(); + } } } @@ -344,25 +377,37 @@ async function onDictionaryImport(e) { const dictProgress = $('#dict-import-progress').show(); try { - dictionaryErrorShow(); + dictionaryErrorsShow(null); dictionarySpinnerShow(true); const setProgress = percent => dictProgress.find('.progress-bar').css('width', `${percent}%`); - const updateProgress = (total, current) => setProgress(current / total * 100.0); + const updateProgress = (total, current) => { + setProgress(current / total * 100.0); + if (storageEstimate.mostRecent !== null && !storageUpdateStats.isUpdating) { + storageUpdateStats(); + } + }; setProgress(0.0); + const exceptions = []; const options = await optionsLoad(); - const summary = await utilDatabaseImport(e.target.files[0], updateProgress); + const summary = await utilDatabaseImport(e.target.files[0], updateProgress, exceptions); options.dictionaries[summary.title] = {enabled: true, priority: 0, allowSecondarySearches: false}; if (summary.sequenced && options.general.mainDictionary === '') { options.general.mainDictionary = summary.title; } + + if (exceptions.length > 0) { + exceptions.push(`Dictionary may not have been imported properly: ${exceptions.length} error${exceptions.length === 1 ? '' : 's'} reported.`); + dictionaryErrorsShow(exceptions); + } + await optionsSave(options); await dictionaryGroupsPopulate(options); await formMainDictionaryOptionsPopulate(options); } catch (e) { - dictionaryErrorShow(e); + dictionaryErrorsShow([e]); } finally { dictionarySpinnerShow(false); @@ -520,3 +565,93 @@ async function onAnkiFieldTemplatesReset(e) { ankiErrorShow(e); } } + + +/* + * Storage + */ + +async function getBrowser() { + if (typeof chrome !== "undefined") { + if (typeof browser !== "undefined") { + try { + const info = await browser.runtime.getBrowserInfo(); + if (info.name === "Fennec") { + return "firefox-mobile"; + } + } catch (e) { } + return "firefox"; + } else { + return "chrome"; + } + } else { + return "edge"; + } +} + +function storageBytesToLabeledString(size) { + const base = 1000; + const labels = ["bytes", "KB", "MB", "GB"]; + let labelIndex = 0; + while (size >= base) { + size /= base; + ++labelIndex; + } + const label = size.toFixed(1); + return `${label}${labels[labelIndex]}`; +} + +async function storageEstimate() { + try { + return (storageEstimate.mostRecent = await navigator.storage.estimate()); + } catch (e) { } + return null; +} +storageEstimate.mostRecent = null; + +async function storageInfoInitialize() { + const browser = await getBrowser(); + const container = document.querySelector("#storage-info"); + container.setAttribute("data-browser", browser); + + await storageShowInfo(); + + container.classList.remove("storage-hidden"); + + document.querySelector("#storage-refresh").addEventListener('click', () => storageShowInfo(), false); +} + +async function storageUpdateStats() { + storageUpdateStats.isUpdating = true; + + const estimate = await storageEstimate(); + const valid = (estimate !== null); + + if (valid) { + document.querySelector("#storage-usage").textContent = storageBytesToLabeledString(estimate.usage); + document.querySelector("#storage-quota").textContent = storageBytesToLabeledString(estimate.quota); + } + + storageUpdateStats.isUpdating = false; + return valid; +} +storageUpdateStats.isUpdating = false; + +async function storageShowInfo() { + storageSpinnerShow(true); + + const valid = await storageUpdateStats(); + document.querySelector("#storage-use").classList.toggle("storage-hidden", !valid); + document.querySelector("#storage-error").classList.toggle("storage-hidden", valid); + + storageSpinnerShow(false); +} + +function storageSpinnerShow(show) { + const spinner = $('#storage-spinner'); + if (show) { + spinner.show(); + } else { + spinner.hide(); + } +} |