Page exit prevention refactor (#637)

* Add page exit prevention functionality to SettingsController

* Update dictionary controller to use new page exit prevention system

* Remove page-exit-prevention.js
This commit is contained in:
toasted-nutbread 2020-07-03 11:56:26 -04:00 committed by GitHub
parent 1d02013642
commit c13160d784
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 42 additions and 68 deletions

View File

@ -1,59 +0,0 @@
/*
* Copyright (C) 2019-2020 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 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();

View File

@ -16,7 +16,6 @@
*/ */
/* global /* global
* PageExitPrevention
* api * api
* utilBackgroundIsolate * utilBackgroundIsolate
*/ */
@ -156,6 +155,11 @@ class SettingsDictionaryListUI extends EventDispatcher {
// Overwrite // Overwrite
} }
preventPageExit() {
// Overwrite
return {end: () => {}};
}
onDictionaryConfirmDelete(e) { onDictionaryConfirmDelete(e) {
e.preventDefault(); e.preventDefault();
const n = document.querySelector('#dict-delete-modal'); const n = document.querySelector('#dict-delete-modal');
@ -286,10 +290,8 @@ class SettingsDictionaryEntryUI {
const progressBar = this.content.querySelector('.progress-bar'); const progressBar = this.content.querySelector('.progress-bar');
this.isDeleting = true; this.isDeleting = true;
const prevention = new PageExitPrevention(); const prevention = this.parent.preventPageExit();
try { try {
prevention.start();
const onProgress = ({processed, count, storeCount, storesProcesed}) => { const onProgress = ({processed, count, storeCount, storesProcesed}) => {
let percent = 0.0; let percent = 0.0;
if (count > 0 && storesProcesed > 0) { if (count > 0 && storesProcesed > 0) {
@ -409,6 +411,7 @@ class DictionaryController {
document.querySelector('#dict-extra-template') document.querySelector('#dict-extra-template')
); );
this._dictionaryUI.save = () => this._settingsController.save(); this._dictionaryUI.save = () => this._settingsController.save();
this._dictionaryUI.preventPageExit = this._preventPageExit.bind(this);
this._dictionaryUI.on('databaseUpdated', this._onDatabaseUpdated.bind(this)); this._dictionaryUI.on('databaseUpdated', this._onDatabaseUpdated.bind(this));
document.querySelector('#dict-purge-button').addEventListener('click', this._onPurgeButtonClick.bind(this), false); document.querySelector('#dict-purge-button').addEventListener('click', this._onPurgeButtonClick.bind(this), false);
@ -610,10 +613,9 @@ class DictionaryController {
const dictProgress = document.querySelector('#dict-purge'); const dictProgress = document.querySelector('#dict-purge');
dictProgress.hidden = false; dictProgress.hidden = false;
const prevention = new PageExitPrevention(); const prevention = this._preventPageExit();
try { try {
prevention.start();
this._dictionaryErrorsShow(null); this._dictionaryErrorsShow(null);
this._dictionarySpinnerShow(true); this._dictionarySpinnerShow(true);
@ -649,10 +651,9 @@ class DictionaryController {
const dictProgress = $('#dict-import-progress').show(); const dictProgress = $('#dict-import-progress').show();
const dictImportInfo = document.querySelector('#dict-import-info'); const dictImportInfo = document.querySelector('#dict-import-info');
const prevention = new PageExitPrevention(); const prevention = this._preventPageExit();
try { try {
prevention.start();
this._dictionaryErrorsShow(null); this._dictionaryErrorsShow(null);
this._dictionarySpinnerShow(true); this._dictionarySpinnerShow(true);
@ -718,4 +719,8 @@ class DictionaryController {
optionsFull.global.database.prefixWildcardsSupported = !!e.target.checked; optionsFull.global.database.prefixWildcardsSupported = !!e.target.checked;
await this._settingsController.save(); await this._settingsController.save();
} }
_preventPageExit() {
return this.settingsController.preventPageExit();
}
} }

View File

@ -26,6 +26,8 @@ class SettingsController extends EventDispatcher {
super(); super();
this._profileIndex = profileIndex; this._profileIndex = profileIndex;
this._source = yomichan.generateId(16); this._source = yomichan.generateId(16);
this._pageExitPreventions = new Set();
this._pageExitPreventionEventListeners = new EventListenerCollection();
} }
get source() { get source() {
@ -109,6 +111,16 @@ class SettingsController extends EventDispatcher {
return {index: this._profileIndex}; return {index: this._profileIndex};
} }
preventPageExit() {
const obj = {end: null};
obj.end = this._endPreventPageExit.bind(this, obj);
if (this._pageExitPreventionEventListeners.size === 0) {
this._pageExitPreventionEventListeners.addEventListener(window, 'beforeunload', this._onBeforeUnload.bind(this), false);
}
this._pageExitPreventions.add(obj);
return obj;
}
// Private // Private
_setProfileIndex(value) { _setProfileIndex(value) {
@ -147,4 +159,21 @@ class SettingsController extends EventDispatcher {
targets = this._setupTargets(targets, extraFields); targets = this._setupTargets(targets, extraFields);
return await api.modifySettings(targets, this._source); return await api.modifySettings(targets, this._source);
} }
_onBeforeUnload(e) {
if (this._pageExitPreventions.size === 0) {
return;
}
e.preventDefault();
e.returnValue = '';
return '';
}
_endPreventPageExit(obj) {
this._pageExitPreventions.delete(obj);
if (this._pageExitPreventions.size === 0) {
this._pageExitPreventionEventListeners.removeAllEventListeners();
}
}
} }

View File

@ -1146,7 +1146,6 @@
<script src="/bg/js/dictionary.js"></script> <script src="/bg/js/dictionary.js"></script>
<script src="/bg/js/handlebars.js"></script> <script src="/bg/js/handlebars.js"></script>
<script src="/bg/js/options.js"></script> <script src="/bg/js/options.js"></script>
<script src="/bg/js/page-exit-prevention.js"></script>
<script src="/bg/js/profile-conditions.js"></script> <script src="/bg/js/profile-conditions.js"></script>
<script src="/bg/js/util.js"></script> <script src="/bg/js/util.js"></script>
<script src="/mixed/js/audio-system.js"></script> <script src="/mixed/js/audio-system.js"></script>