katja's git: oeffisearch

fast and simple tripplanner

commit e72c4f2fc34ab7e56603340c395ad14d79b7bf03
parent 8bde1ff49f98fd2f6c886902b5f4d63f30aaa26a
Author: Katja (ctucx) <git@ctu.cx>
Date: Mon, 21 Apr 2025 15:10:14 +0200

improve error handling, dont access `window` in `willUpdate` phase
5 files changed, 68 insertions(+), 31 deletions(-)
M
src/baseView.js
|
47
++++++++++++++++++++++++++++++-----------------
M
src/departuresView.js
|
9
+++++++--
M
src/journeyView.js
|
9
+++++++--
M
src/journeysView.js
|
25
+++++++++++++++++--------
M
src/tripView.js
|
9
+++++++--
diff --git a/src/baseView.js b/src/baseView.js
@@ -1,4 +1,5 @@
 import { LitElement, html, nothing } from 'lit';
+import { when } from 'lit/directives/when.js';
 import { choose } from 'lit/directives/choose.js';
 
 import { t } from './translate.js';

@@ -27,16 +28,17 @@ export class BaseView extends LitElement {
 		this.isUpdating = false;
 
 		this.overlayState = {
-			type:    'plain',
-			visible: false,
-			content: null,
-			title:   null,
+			type:     'plain',
+			visible:  false,
+			content:  null,
 		};
 	}
 
 	connectedCallback () {
 		super.connectedCallback();
 
+		this.hideOverlay();
+
 		window.addEventListener('online',  this.connectionHandler);
 		window.addEventListener('offline', this.connectionHandler);
 	}

@@ -54,24 +56,27 @@ export class BaseView extends LitElement {
 
 	connectionHandler = event => { this.isOffline = event.type === 'offline'; };
 
-	showLoaderOverlay = ()            => this.showOverlay('loader');
-	showDialogOverlay = (title, body) => this.showOverlay('dialog', body, title);
-	showAlertOverlay  = text          => this.showOverlay('alert', text);
-	showSelectOverlay = items         => this.showOverlay('select', items);
+	showLoaderOverlay = ()                  => this.showOverlay('loader');
+	showDialogOverlay = (title, body)       => this.showOverlay('dialog', { title, body });
+	showAlertOverlay  = (message, callback) => this.showOverlay('alert', { message, callback });
+	showSelectOverlay = items               => this.showOverlay('select', items);
 
 	hideOverlay = () => {
-		this.overlayState.visible = false;
-		this.requestUpdate();
+		this.overlayState = {
+			type:     'plain',
+			visible:  false,
+			content:  null,
+		};
 	};
 
-	showOverlay = (type, content, title) => {
+	showOverlay = (type, content) => {
 		this.overlayState = {
-			type, content, title,
+			type, content,
 			visible: true,
 		}
 	};
 
-	overlayHandler  = event => event.target === event.currentTarget && this.overlayState.type !== 'loader' ? this.hideOverlay() : true;
+	overlayHandler  = event => event.target === event.currentTarget && ![ 'loader', 'alert' ].includes(this.overlayState.type) ? this.hideOverlay() : true;
 	keyClickHandler = event => {
 		if ([ 'Enter', 'Space' ].includes(event.code)) {
 			event.preventDefault();

@@ -89,10 +94,10 @@ export class BaseView extends LitElement {
 				[ 'dialog', () => html`
 					<div class="modal dialog">
 						<div class="header flex-row">
-							<h4>${t(this.overlayState.title)}</h4>
+							<h4>${t(this.overlayState.content.title)}</h4>
 							<div class="icon-close" title="${t('close')}" @click=${this.hideOverlay}></div>
 						</div>
-						<div class="body">${this.overlayState.content}</div>
+						<div class="body">${this.overlayState.content.body}</div>
 					</div>
 				` ],
 				[ 'select', () => html`

@@ -103,7 +108,12 @@ export class BaseView extends LitElement {
 				` ],
 				[ 'alert', () => html`
 					<div class="modal alert" style="overflow:auto">
-						${this.overlayState.content}<br><button class="color" style="float:right" @click=${this.hideOverlay}>OK</button>
+						${this.overlayState.content.message}<br><button class="color" style="float:right"
+						@click=${when(
+							!this.overlayState.content.callback,
+							() => this.hideOverlay,
+							() => this.overlayState.content.callback
+						)}>OK</button>
 					</div>
 				` ],
 			]);

@@ -111,7 +121,10 @@ export class BaseView extends LitElement {
 
 		return [
 			this.renderView(),
-			!this.overlayState.visible ? nothing : html`<div class="overlay flex-center" @click=${this.overlayHandler}>${overlayContent}</div>`
+			when(
+				this.overlayState.visible,
+				() => html`<div class="overlay flex-center" @click=${this.overlayHandler}>${overlayContent}</div>`
+			)
 		];
 	};
 
diff --git a/src/departuresView.js b/src/departuresView.js
@@ -41,7 +41,7 @@ class DeparturesView extends BaseView {
 	async willUpdate (previous) {
 		if (previous.has('stopId')) this.viewState = null;
 
-		if (!this.viewState) await this.updateViewState();
+		if (!this.viewState && !this.overlayState.visible) await this.updateViewState();
 	}
 
 	updated (previous) {

@@ -74,7 +74,12 @@ class DeparturesView extends BaseView {
 
 			if (isDevServer) console.info('DeparturesView(viewState):', this.viewState);
 		} catch(e) {
-			this.showAlertOverlay(e.toString());
+			this.showAlertOverlay(
+				e.toString(),
+				() => {
+					window.location = '#/';
+				}
+			);
 			console.error(e);
 		}
 		this.isUpdating = false;
diff --git a/src/journeyView.js b/src/journeyView.js
@@ -59,7 +59,7 @@ class JourneyView extends BaseView {
 	async willUpdate (previous) {
 		if (previous.has('refreshToken')) this.viewState = null;
 
-		if (!this.viewState) await this.updateViewState();
+		if (!this.viewState && !this.overlayState.visible) await this.updateViewState();
 	}
 
 	updated (previous) {

@@ -257,7 +257,12 @@ class JourneyView extends BaseView {
 
 			if (isDevServer) console.info('JourneyView(viewState):', this.viewState);
 		} catch(e) {
-			this.showAlertOverlay(e.toString());
+			this.showAlertOverlay(
+				e.toString(),
+				() => {
+					window.location = '#/';
+				}
+			);
 			console.error(e);
 		}
 		this.isUpdating = false;
diff --git a/src/journeysView.js b/src/journeysView.js
@@ -61,17 +61,17 @@ export class JourneysView extends JourneysCanvas {
 	}
 
 	async willUpdate (previous) {
-		if (previous.has('slug')) this.viewState = null;
+		if (previous.has('slug')) {
+			this.resetCanvasPosition();
+			this.viewState = null;
+		}
 
 		if (previous.has('mode')) {
 			if (previous.get('mode') === 'canvas' && this.mode !== 'canvas') this.disconnectCanvas();
 			if (this.settingsState.journeysViewMode !== this.mode)           this.settingsState.setJourneysViewMode(this.mode);
 		}
 
-		if (!this.viewState) {
-			this.resetCanvasPosition();
-			await this.updateViewState();
-		}
+		if (!this.viewState && !this.overlayState.visible) await this.updateViewState();
 
 		if (this.mode === 'canvas') {
 			this.connectCanvas();

@@ -189,8 +189,12 @@ export class JourneysView extends JourneysCanvas {
 			let viewState = await getJourneys(this.slug);
 
 			if (!viewState) {
-				this.showAlertOverlay(html`journeys overview id invalid. <br>journeys overview links can not be shared across devices.`);
-				window.location = '#/';
+				this.showAlertOverlay(
+					html`journeys overview id invalid. <br>journeys overview links can not be shared across devices.`,
+					() => {
+						window.location = '#/';
+					}
+				);
 				return;
 			}
 

@@ -227,7 +231,12 @@ export class JourneysView extends JourneysCanvas {
 			this.viewState = viewState;
 			if (isDevServer) console.info('JourneysView(viewState):', this.viewState);
 		} catch(e) {
-			this.showAlertOverlay(e.toString());
+			this.showAlertOverlay(
+				e.toString(),
+				() => {
+					window.location = '#/';
+				}
+			);
 			console.error(e);
 		}
 	};
diff --git a/src/tripView.js b/src/tripView.js
@@ -43,7 +43,7 @@ class TripView extends BaseView {
 	async willUpdate (previous) {
 		if (previous.has('stopId')) this.viewState = null;
 
-		if (!this.viewState) await this.updateViewState();
+		if (!this.viewState && !this.overlayState.visible) await this.updateViewState();
 	}
 
 	updated (previous) {

@@ -91,7 +91,12 @@ class TripView extends BaseView {
 
 			if (isDevServer) console.info('TripView(viewState): ',this.viewState);
 		} catch(e) {
-			this.showAlertOverlay(e.toString());
+			this.showAlertOverlay(
+				e.toString(),
+				() => {
+					window.location = '#/';
+				}
+			);
 			console.error(e);
 		}
 		this.isUpdating = false;