diff --git a/assets/template.html b/assets/template.html
index de59c7f3a..f3fdae5bb 100644
--- a/assets/template.html
+++ b/assets/template.html
@@ -39,6 +39,7 @@
+ Revert
Download MEI
@@ -97,7 +98,7 @@
-->
-
+
@@ -105,7 +106,6 @@
Remove Empty Syllables
Remove Empty Neumes
Remove Out-of-bounds Glyphs
-
Revert
@@ -134,6 +134,16 @@
+
+
+
+
+
+ Enable Advanced Settings
+
+
+
diff --git a/cypress/e2e/errorlog.cy.ts b/cypress/e2e/errorlog.cy.ts
index c62790fb7..a5acb1e97 100644
--- a/cypress/e2e/errorlog.cy.ts
+++ b/cypress/e2e/errorlog.cy.ts
@@ -7,6 +7,8 @@ describe('test: error log', () => {
beforeEach(() => {
cy.visit('http://localhost:8080/editor.html?manifest=test');
cy.clearLocalStorage();
+
+ cy.get('#display-advanced').check({ force: true });
});
it('startup: error log should not be visible', () => {
diff --git a/src/DisplayPanel/DisplayPanel.ts b/src/DisplayPanel/DisplayPanel.ts
index 98b12b174..433456c8f 100644
--- a/src/DisplayPanel/DisplayPanel.ts
+++ b/src/DisplayPanel/DisplayPanel.ts
@@ -140,7 +140,7 @@ function displayControlsPanel (handleZoom: ZoomHandler): string {
* A class that sets the content of the display panel to the right and
* manages controls for viewing.
*/
-class DisplayPanel implements DisplayInterface {
+export class DisplayPanel implements DisplayInterface {
view: ViewInterface;
meiClass: string;
background: string;
@@ -216,4 +216,21 @@ class DisplayPanel implements DisplayInterface {
}
}
-export { DisplayPanel as default };
+export function updateDisplayAll (): void {
+ const displayAllBtn = document.querySelector('#display-all-btn');
+
+ const btns = document.querySelector('#display-single-container');
+ const checkboxes = Array.from(btns.querySelectorAll('input[type=checkbox]'));
+ const allChecked = checkboxes.every(box => box.checked);
+
+ if (allChecked) {
+ displayAllBtn.classList.add('selected');
+ displayAllBtn.innerHTML = 'Hide All';
+ } else {
+ displayAllBtn.classList.remove('selected');
+ displayAllBtn.innerHTML = 'Display All';
+ }
+
+}
+
+export default DisplayPanel;
diff --git a/src/InfoModule.ts b/src/InfoModule.ts
index c9ef5b246..b3d051c95 100644
--- a/src/InfoModule.ts
+++ b/src/InfoModule.ts
@@ -4,6 +4,7 @@ import NeonView from './NeonView';
import { InfoInterface } from './Interfaces';
import { Attributes } from './Types';
import { getSettings, setSettings } from './utils/LocalSettings';
+import { updateDisplayAll } from './DisplayPanel/DisplayPanel';
/**
* Map of contours to neume names.
@@ -29,12 +30,7 @@ function startInfoVisibility (): void {
*/
function updateInfoVisibility (): void {
const neumeInfo = document.getElementById('neume_info');
-
- const displayAllBtn = document.getElementById('display-all-btn');
const displayInfo = document.getElementById('displayInfo') as HTMLInputElement;
- const displayBBoxes = document.getElementById('displayBBox') as HTMLInputElement;
- const displayText = document.getElementById('displayText') as HTMLInputElement;
- const displayErrLog = document.getElementById('display-errors') as HTMLInputElement;
// save setting to localStorage
setSettings({ displayInfo: displayInfo.checked });
@@ -43,22 +39,11 @@ function updateInfoVisibility (): void {
neumeInfo.setAttribute('style', '');
// scroll neume info into view
//neumeInfo.scrollIntoView({ behavior: 'smooth' });
-
- // if this is the 3rd option to be checked (all three are selected),
- // set "Display/Hide All" button to "Hide All".
- if (displayInfo?.checked && displayBBoxes?.checked &&
- displayText?.checked && displayErrLog?.checked) {
- displayAllBtn.classList.add('selected');
- displayAllBtn.innerHTML = 'Hide All';
- }
} else {
neumeInfo.setAttribute('style', 'display: none');
- // if "Display/Hide All" button is in "Hide All" mode, set it to "Display All" mode
- if (displayAllBtn.classList.contains('selected')) {
- displayAllBtn.classList.remove('selected');
- displayAllBtn.innerHTML = 'Display All';
- }
}
+
+ updateDisplayAll();
}
/**
diff --git a/src/NeonView.ts b/src/NeonView.ts
index f97da87d9..290f5cad4 100644
--- a/src/NeonView.ts
+++ b/src/NeonView.ts
@@ -1,5 +1,4 @@
import NeonCore from './NeonCore';
-import * as Validation from './Validation';
import { parseManifest } from './utils/NeonManifest';
import setBody from './utils/template/Template';
import { ModalWindow } from './utils/ModalWindow';
@@ -13,9 +12,10 @@ import {
TextViewInterface,
ViewInterface
} from './Interfaces';
-import { initErrorLog } from '../src/utils/ErrorLog';
-import { setSavedStatus, listenUnsavedChanges } from './utils/Unsaved';
-import LocalSettings, { getSettings } from './utils/LocalSettings';
+import ErrorLog from '../src/utils/ErrorLog';
+import Unsaved from './utils/Unsaved';
+import LocalSettings from './utils/LocalSettings';
+import AdvancedSettings from './utils/AdvancedSettings';
/**
@@ -95,9 +95,9 @@ class NeonView {
this.core = new NeonCore(this.manifest);
this.info = new this.params.Info(this);
this.modal = new ModalWindow(this);
- Validation.init(this); // initialize validation
- initErrorLog(); // initialize notifications logs
- listenUnsavedChanges();
+
+ AdvancedSettings.init(this);
+ Unsaved.init();
this.setupEdit(this.params);
return this.core.initDb();
@@ -123,7 +123,7 @@ class NeonView {
* Redo an action performed on the current page (if there is one).
*/
redo (): Promise {
- setSavedStatus(false);
+ Unsaved.setSavedStatus(false);
return this.core.redo(this.view.getCurrentPageURI());
}
@@ -131,7 +131,7 @@ class NeonView {
* Undo the last action performed on the current page (if there is one).
*/
undo (): Promise {
- setSavedStatus(false);
+ Unsaved.setSavedStatus(false);
return this.core.undo(this.view.getCurrentPageURI());
}
@@ -190,7 +190,7 @@ class NeonView {
* Save the current state to the browser database.
*/
save (): Promise {
- setSavedStatus(true);
+ Unsaved.setSavedStatus(true);
return this.core.updateDatabase();
}
@@ -219,10 +219,10 @@ class NeonView {
/**
* Get the page's MEI file as a string.
- * @param pageNo - The identifying URI of the page.
+ * @param pageURI - The identifying URI of the page.
*/
- getPageMEI (pageNo: string): Promise {
- return this.core.getMEI(pageNo);
+ getPageMEI (pageURI: string): Promise {
+ return this.core.getMEI(pageURI);
}
/**
diff --git a/src/SingleView/SingleView.ts b/src/SingleView/SingleView.ts
index f04dc348c..b6f85dcb3 100644
--- a/src/SingleView/SingleView.ts
+++ b/src/SingleView/SingleView.ts
@@ -1,6 +1,6 @@
import { updateHighlight, setOpacityFromSlider, setBgOpacityFromSlider } from '../DisplayPanel/DisplayControls';
import NeonView from '../NeonView';
-import DisplayPanel from '../DisplayPanel/DisplayPanel';
+import { DisplayPanel } from '../DisplayPanel/DisplayPanel';
import ZoomHandler from './Zoom';
import { ViewInterface, DisplayConstructable } from '../Interfaces';
diff --git a/src/TextView.ts b/src/TextView.ts
index ca1a3334d..442814129 100644
--- a/src/TextView.ts
+++ b/src/TextView.ts
@@ -4,6 +4,7 @@ import { unselect } from './utils/SelectTools';
import { updateHighlight } from './DisplayPanel/DisplayControls';
import { TextViewInterface } from './Interfaces';
import { getSettings, setSettings } from './utils/LocalSettings';
+import { updateDisplayAll } from './DisplayPanel/DisplayPanel';
/*
* Class that manages getting the text for syllables in Neon from the mei file
@@ -74,12 +75,7 @@ class TextView implements TextViewInterface {
* Update visibility of text bounding boxes
*/
updateBBoxViewVisibility (): void {
-
- const displayAllBtn = document.getElementById('display-all-btn');
- const displayInfo = document.getElementById('displayInfo') as HTMLInputElement;
const displayBBoxes = document.getElementById('displayBBox') as HTMLInputElement;
- const displayText = document.getElementById('displayText') as HTMLInputElement;
- const displayErrLog = document.getElementById('display-errors') as HTMLInputElement;
// save to localStorage
setSettings({ displayBBox: displayBBoxes.checked });
@@ -95,14 +91,6 @@ class TextView implements TextViewInterface {
if (this.neonView.getUserMode() !== 'viewer' && this.neonView.TextEdit !== undefined) {
this.neonView.TextEdit.initSelectByBBoxButton();
}
-
- // if this is the 3rd option to be checked (all three are selected),
- // set "Display/Hide All" button to "Hide All".
- if (displayInfo?.checked && displayBBoxes?.checked &&
- displayText?.checked && displayErrLog?.checked) {
- displayAllBtn.classList.add('selected');
- displayAllBtn.innerHTML = 'Hide All';
- }
}
else {
if (document.getElementById('selByBBox')?.classList.contains('is-active')) {
@@ -124,13 +112,9 @@ class TextView implements TextViewInterface {
document.getElementById('selByBBox').style.display = 'none';
}
catch (e) {}
-
- // if "Display/Hide All" button is in "Hide All" mode, set it to "Display All" mode
- if (displayAllBtn.classList.contains('selected')) {
- displayAllBtn.classList.remove('selected');
- displayAllBtn.innerHTML = 'Display All';
- }
}
+
+ updateDisplayAll();
updateHighlight();
}
@@ -139,12 +123,7 @@ class TextView implements TextViewInterface {
* and add the event listeners to make sure the syl highlights when moused over
*/
updateTextViewVisibility (): void {
-
- const displayAllBtn = document.getElementById('display-all-btn');
- const displayInfo = document.getElementById('displayInfo') as HTMLInputElement;
- const displayBBoxes = document.getElementById('displayBBox') as HTMLInputElement;
const displayText = document.getElementById('displayText') as HTMLInputElement;
- const displayErrLog = document.getElementById('display-errors') as HTMLInputElement;
// save to localStorage
setSettings({ displayText: displayText.checked });
@@ -208,23 +187,13 @@ class TextView implements TextViewInterface {
// scroll the syllable text bubble into view
//sylText.scrollIntoView({ behavior: 'smooth' });
-
- // if this is the 3rd option to be checked (all three are selected),
- // set "Display/Hide All" button to "Hide All".
- if (displayInfo?.checked && displayBBoxes?.checked &&
- displayText?.checked && displayErrLog?.checked) {
- displayAllBtn.classList.add('selected');
- displayAllBtn.innerHTML = 'Hide All';
- }
}
else {
document.getElementById('syl_text').style.display = 'none';
// if "Display/Hide All" button is in "Hide All" mode, set it to "Display All" mode
- if (displayAllBtn.classList.contains('selected')) {
- displayAllBtn.classList.remove('selected');
- displayAllBtn.innerHTML = 'Display All';
- }
}
+
+ updateDisplayAll();
}
/**
diff --git a/src/Validation.ts b/src/Validation.ts
index 6a8b7f95e..a389136d5 100644
--- a/src/Validation.ts
+++ b/src/Validation.ts
@@ -1,5 +1,5 @@
-import NeonView from "./NeonView";
-import { ModalWindow, ModalWindowView } from "./utils/ModalWindow";
+import NeonView from './NeonView';
+import { ModalWindowView } from './utils/ModalWindow';
const schemaResponse = fetch(__ASSET_PREFIX__ + 'assets/mei-all.rng');
let worker: Worker, schema: string, statusField: HTMLSpanElement;
@@ -47,7 +47,7 @@ export async function init (neonView: NeonView): Promise {
if (fileStatusDiv !== null) {
const statusTitle = document.createElement('div');
statusTitle.textContent = 'MEI Status:';
- statusTitle.id = "validation_status_title";
+ statusTitle.id = 'validation_status_title';
const status = document.createElement('span');
status.id = 'validation_status';
status.textContent = 'unknown';
@@ -59,11 +59,23 @@ export async function init (neonView: NeonView): Promise {
}
}
+async function stop (): Promise {
+ if (worker) {
+ worker.terminate();
+ worker = null;
+ }
+
+ const fileStatusDiv = document.getElementById('file-status');
+ fileStatusDiv.innerHTML = '';
+}
+
/**
* Send the contents of an MEI file to the WebWorker for validation.
* @param {string} meiData
*/
export async function sendForValidation (meiData: string): Promise {
+ if (!worker) return;
+
if (statusField === undefined) {
return;
}
@@ -89,3 +101,5 @@ export function blankPage (): void {
statusField.textContent = 'No MEI';
statusField.style.color = 'color:gray';
}
+
+export default { init, stop, sendForValidation };
diff --git a/src/utils/AdvancedSettings.ts b/src/utils/AdvancedSettings.ts
new file mode 100644
index 000000000..68b64050b
--- /dev/null
+++ b/src/utils/AdvancedSettings.ts
@@ -0,0 +1,96 @@
+/*
+ `AdvancedSettings.ts`
+ Module that handles everything to do with advanced settings.
+
+ Any file that imports `AdvancedSettings` can only access the `init` and `isEnabled` functions.
+
+ I'm using the module design pattern, since that's what
+ JavaScript does internally with classes anyway.
+
+ We keep track of NeonView since it's a hassle to pass it around all the time.
+*/
+
+import Validation from '../Validation';
+import { getSettings, setSettings } from './LocalSettings';
+import NeonView from '../NeonView';
+import ErrorLog from './ErrorLog';
+import { updateDisplayAll } from '../DisplayPanel/DisplayPanel';
+
+
+let view: NeonView;
+
+function init(neonView: NeonView): void {
+ view = neonView;
+
+ const checkbox = document.querySelector('#display-advanced');
+
+ // Listen to click:
+ checkbox.addEventListener('click', handleClick);
+
+ // Load from localStorage:
+ const { displayAdvanced } = getSettings();
+ checkbox.checked = displayAdvanced;
+
+ toggle(checkbox.checked);
+ updateDisplayAll();
+}
+
+function handleClick() {
+ const checkbox = document.querySelector('#display-advanced');
+
+ // Before turning on advanced settings, make the user have to confirm the decision
+ if (checkbox.checked) {
+ const confirmed = window.confirm(
+ 'This option is for developers and testers, and is not recommended for general users. ' +
+ 'Are you sure you wish to proceed?'
+ );
+
+ if (!confirmed) {
+ checkbox.checked = false;
+ return;
+ }
+ }
+
+ toggle(checkbox.checked);
+ updateDisplayAll();
+}
+
+function isEnabled(): boolean {
+ return document.querySelector('#display-advanced').checked;
+}
+
+function toggle(isChecked: boolean) {
+ setSettings({ displayAdvanced: isChecked });
+
+ if (isChecked)
+ enable();
+ else
+ disable();
+}
+
+function $(query: string) {
+ return document.querySelector(query);
+}
+
+async function enable() {
+ ErrorLog.init();
+ await Validation.init(view);
+
+ // Retrieve the page MEI as a trivial action to do
+ // to activate validation of the current page
+ const uri = view.view.getCurrentPageURI();
+ const mei = await view.getPageMEI(uri);
+ await Validation.sendForValidation(mei);
+
+ // Show MEI actions dropdown
+ $('#mei-actions-dropdown').style.display = '';
+}
+
+function disable() {
+ ErrorLog.stop();
+ Validation.stop();
+
+ $('#mei-actions-dropdown').style.display = 'none';
+}
+
+export default { init, isEnabled };
diff --git a/src/utils/EditContents.ts b/src/utils/EditContents.ts
index ca3fad585..b932ab57c 100644
--- a/src/utils/EditContents.ts
+++ b/src/utils/EditContents.ts
@@ -34,14 +34,14 @@ export const navbarDropdownMEIActionsMenu: HTMLDivElement = document.createEleme
navbarDropdownMEIActionsMenu.classList.add('navbar-item', 'has-dropdown', 'is-hoverable');
const meiActionsDropdownBtn = document.createElement('div');
meiActionsDropdownBtn.classList.add('navbar-btn');
-meiActionsDropdownBtn.innerHTML = `MEI Actions
`;
+meiActionsDropdownBtn.innerHTML = 'MEI Actions
';
const meiActionsNavbarContents = document.createElement('div');
meiActionsNavbarContents.classList.add('navbar-dropdown');
meiActionsNavbarContents.id = 'navbar-dropdown-options';
const meiActionsDropdownContents = [
['remove-empty-syls', 'Remove Empty Syllables'],
['remove-empty-neumes', 'Remove Empty Neumes'],
- ['revert', 'Revert']
+ // ['revert', 'Revert']
];
meiActionsDropdownContents.forEach(content => {
diff --git a/src/utils/EditControls.ts b/src/utils/EditControls.ts
index fafb8062a..77bf7feaf 100644
--- a/src/utils/EditControls.ts
+++ b/src/utils/EditControls.ts
@@ -2,13 +2,11 @@ import * as Notification from './Notification';
import NeonView from '../NeonView';
import { convertStaffToSb } from './ConvertMei';
import { EditorAction } from '../Types';
-import ZoomHandler from '../SingleView/Zoom';
/**
* Set top navbar event listeners.
*/
export function initNavbar (neonView: NeonView): void {
-
// setup navbar listeners
const navbarDropdowns = document.querySelectorAll('.navbar-item.has-dropdown.is-hoverable');
Array.from(navbarDropdowns).forEach((dropDown) => {
@@ -235,7 +233,7 @@ export function initNavbar (neonView: NeonView): void {
});
});
- // Event listener for "Revert" button inside "MEI Actions" dropdown
+ // Event listener for "Revert" button inside "File" dropdown
document.getElementById('revert').addEventListener('click', function () {
if (window.confirm('Reverting will cause all changes to be lost. Press OK to continue.')) {
neonView.deleteDb().then(() => {
diff --git a/src/utils/ErrorLog.ts b/src/utils/ErrorLog.ts
index 97f46f70f..c6db533b2 100644
--- a/src/utils/ErrorLog.ts
+++ b/src/utils/ErrorLog.ts
@@ -1,10 +1,11 @@
import { Notification } from './Notification';
import { errorLogsPanelContents } from '../SquareEdit/Contents';
import { setSettings, getSettings } from './LocalSettings';
+import { updateDisplayAll } from '../DisplayPanel/DisplayPanel';
// TODO: styling
-function createLogMessage (notif: Notification): Element {
+function createLogMessage(notif: Notification): Element {
const notifDiv = document.createElement('div');
notifDiv.classList.add('notification-container');
notifDiv.innerHTML = `
@@ -39,7 +40,7 @@ function createLogMessage (notif: Notification): Element {
* Add notification to the persistent error log on the sidebar
* @param notif {Notification} Notification to add to the error log
*/
-export function recordNotification (notif: Notification): void {
+export function recordNotification(notif: Notification): void {
const log = document.querySelector('#errorLogContents');
log.prepend(createLogMessage(notif));
}
@@ -49,7 +50,7 @@ export function recordNotification (notif: Notification): void {
* Initialize error log.
* Adds necessary HTML to DOM.
*/
-export function initErrorLog(): void {
+export function init(): void {
// Error log panel
const log = document.querySelector('#error_log');
log.innerHTML = errorLogsPanelContents;
@@ -57,11 +58,18 @@ export function initErrorLog(): void {
initErrorLogControls();
}
+export function stop(): void {
+ // Hide the error log
+ document.querySelector('#error_log').classList.remove('visible');
+
+ // Hide the button
+ document.querySelector('#display-errors')?.parentElement?.remove();
+}
/**
* Set up event listeners for error Log panel
*/
-export function initErrorLogControls(): void {
+function initErrorLogControls(): void {
const errorPanel = document.querySelector('#error_log');
const heading = document.querySelector('#errorLogHeading');
const dropdownIcon = heading.querySelector('svg > use');
@@ -81,7 +89,7 @@ export function initErrorLogControls(): void {
contents.style.overflow = 'visible';
}, 200);
dropdownIcon.setAttribute('xlink:href', `${__ASSET_PREFIX__}assets/img/icons.svg#dropdown-down`);
- }
+ }
// if error panel is open, close it
else {
// set classes and styles for a closed panel
@@ -97,58 +105,43 @@ export function initErrorLogControls(): void {
initDisplayListener();
}
+function handleClick(): void {
+ const notifPanel = document.querySelector('#error_log');
+ const displayErrLog = document.getElementById('display-errors') as HTMLInputElement;
+
+ if (displayErrLog.checked) {
+ notifPanel.classList.add('visible');
+ setSettings({ displayErrLog: true });
+ }
+ else {
+ notifPanel.classList.remove('visible');
+ setSettings({ displayErrLog: false });
+ }
+
+ updateDisplayAll();
+}
/**
* Initializes click listener on "Show error logs" button in "View" dropdown.
*/
-export function initDisplayListener(): void {
- const notifPanel = document.querySelector('#error_log');
+function initDisplayListener(): void {
const checkboxesContainer = document.querySelector('#display-single-container');
- const errorsLabel = document.createElement('label');
- const erorrsBtn = document.createElement('input');
-
- erorrsBtn.classList.add('checkbox');
- errorsLabel.classList.add('checkbox-container', 'side-panel-btn');
- errorsLabel.textContent = 'Errors';
- erorrsBtn.id = 'display-errors';
- erorrsBtn.type = 'checkbox';
- erorrsBtn.checked = false;
- errorsLabel.appendChild(erorrsBtn);
- checkboxesContainer.append(errorsLabel);
-
+ const errorLabel = document.createElement('label');
+ const errorBtn = document.createElement('input');
+
+ errorBtn.classList.add('checkbox');
+ errorLabel.classList.add('checkbox-container', 'side-panel-btn');
+ errorLabel.textContent = 'Errors';
+ errorBtn.id = 'display-errors';
+ errorBtn.type = 'checkbox';
+ errorBtn.checked = false;
+ errorLabel.appendChild(errorBtn);
+ checkboxesContainer.append(errorLabel);
const { displayErrLog } = getSettings();
- if (displayErrLog) erorrsBtn.checked = true;
-
- erorrsBtn.addEventListener('click', () => {
+ if (displayErrLog) errorBtn.checked = true;
- // setSettings({ displayBBox: displayBBoxes.checked });
-
- const displayAllBtn = document.getElementById('display-all-btn');
- const displayInfo = document.getElementById('displayInfo') as HTMLInputElement;
- const displayBBoxes = document.getElementById('displayBBox') as HTMLInputElement;
- const displayText = document.getElementById('displayText') as HTMLInputElement;
- const displayErrLog = document.getElementById('display-errors') as HTMLInputElement;
-
-
- if (erorrsBtn.checked) {
- notifPanel.classList.add('visible');
- setSettings({ displayErrLog: true });
-
- if (displayInfo?.checked && displayBBoxes?.checked &&
- displayText?.checked && displayErrLog?.checked) {
- displayAllBtn.classList.add('selected');
- displayAllBtn.innerHTML = 'Hide All';
- }
- }
- else {
- notifPanel.classList.remove('visible');
- setSettings({ displayErrLog: false });
- if (displayAllBtn.classList.contains('selected')) {
- displayAllBtn.classList.remove('selected');
- displayAllBtn.innerHTML = 'Display All';
- }
- }
-
- });
+ errorBtn.addEventListener('click', handleClick);
}
+
+export default { init, stop };
diff --git a/src/utils/LocalSettings.ts b/src/utils/LocalSettings.ts
index d097f6435..9fb0c70f5 100644
--- a/src/utils/LocalSettings.ts
+++ b/src/utils/LocalSettings.ts
@@ -26,6 +26,7 @@ export interface Settings {
displayText: boolean;
displayInfo: boolean;
displayErrLog: boolean;
+ displayAdvanced: boolean;
viewBox: string;
}
@@ -46,6 +47,7 @@ const DEFAULT_SETTINGS: Settings = {
displayText: false,
displayInfo: false,
displayErrLog: false,
+ displayAdvanced: false,
viewBox: null
};
diff --git a/src/utils/Notification.ts b/src/utils/Notification.ts
index 21dc62f38..02b6c4552 100644
--- a/src/utils/Notification.ts
+++ b/src/utils/Notification.ts
@@ -1,3 +1,4 @@
+import AdvancedSettings from './AdvancedSettings';
import { recordNotification } from './ErrorLog';
import { uuidv4 } from './random';
@@ -132,7 +133,8 @@ export function queueNotification (notification: string, type: NotificationType
const notif = new Notification(notification, type);
notifications.push(notif);
- if (notif.type == 'error' || notif.type == 'warning') {
+ // It would be better if we actually had a persistent store of Neon's notifications.
+ if ((notif.type == 'error' || notif.type == 'warning') && AdvancedSettings.isEnabled()) {
recordNotification(notif);
}
diff --git a/src/utils/Unsaved.ts b/src/utils/Unsaved.ts
index ba92420b8..16b93d862 100644
--- a/src/utils/Unsaved.ts
+++ b/src/utils/Unsaved.ts
@@ -1,14 +1,15 @@
-
+// `Unsaved.ts`
+// Module that handles all logic about unsaved changes
+//
// Initial saved status
let saved = true;
-
/**
* Update status of saved status indicator
*/
-function updateIndicator (): void {
+function updateIndicator(): void {
const indicator = document.querySelector('#file-saved');
- const path = saved? `${__ASSET_PREFIX__}assets/img/saved-icon.svg` : `${__ASSET_PREFIX__}assets/img/unsaved-icon.svg`;
+ const path = saved ? `${__ASSET_PREFIX__}assets/img/saved-icon.svg` : `${__ASSET_PREFIX__}assets/img/unsaved-icon.svg`;
indicator.setAttribute('src', path);
}
@@ -18,7 +19,7 @@ function updateIndicator (): void {
*
* @param status boolean value. true if status is "saved", false if "not saved"
*/
-export function setSavedStatus (status: boolean = false): void {
+export function setSavedStatus(status = false): void {
saved = status;
updateIndicator();
}
@@ -27,11 +28,13 @@ export function setSavedStatus (status: boolean = false): void {
/**
* Function that defines event listener that checks for unsaved changes on page reload
*/
-export function listenUnsavedChanges (): void {
+function init(): void {
window.onbeforeunload = (e: BeforeUnloadEvent) => {
if (!saved) {
e.preventDefault();
return 'You have unsaved changes!';
}
};
-}
\ No newline at end of file
+}
+
+export default { init, setSavedStatus };