diff --git a/ext/bg/js/settings-dictionaries.js b/ext/bg/js/settings-dictionaries.js index c40648e0..786fcbd5 100644 --- a/ext/bg/js/settings-dictionaries.js +++ b/ext/bg/js/settings-dictionaries.js @@ -222,7 +222,10 @@ class SettingsDictionaryEntryUI { const progressBar = this.content.querySelector('.progress-bar'); this.isDeleting = true; + const prevention = new PageExitPrevention(); try { + prevention.start(); + const onProgress = ({processed, count, storeCount, storesProcesed}) => { let percent = 0.0; if (count > 0 && storesProcesed > 0) { @@ -235,6 +238,7 @@ class SettingsDictionaryEntryUI { } catch (e) { dictionaryErrorsShow([e]); } finally { + prevention.end(); this.isDeleting = false; progress.hidden = true; @@ -479,7 +483,10 @@ async function onDictionaryPurge(e) { const dictProgress = document.querySelector('#dict-purge'); dictProgress.hidden = false; + const prevention = new PageExitPrevention(); + try { + prevention.start(); dictionaryErrorsShow(null); dictionarySpinnerShow(true); @@ -496,6 +503,8 @@ async function onDictionaryPurge(e) { } catch (err) { dictionaryErrorsShow([err]); } finally { + prevention.end(); + dictionarySpinnerShow(false); dictControls.show(); @@ -513,7 +522,10 @@ async function onDictionaryImport(e) { const dictProgress = $('#dict-import-progress').show(); const dictImportInfo = document.querySelector('#dict-import-info'); + const prevention = new PageExitPrevention(); + try { + prevention.start(); dictionaryErrorsShow(null); dictionarySpinnerShow(true); @@ -559,6 +571,7 @@ async function onDictionaryImport(e) { } catch (err) { dictionaryErrorsShow([err]); } finally { + prevention.end(); dictionarySpinnerShow(false); dictImportInfo.hidden = false; diff --git a/ext/bg/js/settings.js b/ext/bg/js/settings.js index e4446851..d4b1549e 100644 --- a/ext/bg/js/settings.js +++ b/ext/bg/js/settings.js @@ -211,6 +211,52 @@ async function onReady() { $(document).ready(utilAsync(onReady)); +/* + * Page exit prevention + */ + +class PageExitPrevention { + constructor() { + } + + start() { + PageExitPrevention._addInstance(this); + } + + end() { + PageExitPrevention._removeInstance(this); + } + + static _addInstance(instance) { + const size = PageExitPrevention._instances.size; + PageExitPrevention._instances.set(instance, true); + if (size === 0) { + window.addEventListener('beforeunload', PageExitPrevention._onBeforeUnload); + } + } + + static _removeInstance(instance) { + if ( + PageExitPrevention._instances.delete(instance) && + PageExitPrevention._instances.size === 0 + ) { + window.removeEventListener('beforeunload', PageExitPrevention._onBeforeUnload); + } + } + + static _onBeforeUnload(e) { + if (PageExitPrevention._instances.size === 0) { + return; + } + + e.preventDefault(); + e.returnValue = ''; + return ''; + } +} +PageExitPrevention._instances = new Map(); + + /* * Appearance */