ctucx.git: trainsearch

web based trip-planner, fork of https://cyberchaos.dev/yuka/trainsearch

commit 5733299ea999eb0964b24dedf8d7eeb88472371a
parent d199240e69d2638fa84f28db8f42b57c59598b4e
Author: Yureka <yuka@yuka.dev>
Date: Wed, 18 Aug 2021 17:04:59 +0200

client cleanup
8 files changed, 194 insertions(+), 176 deletions(-)
M
client/src/app_functions.js
|
73
+++++++++++++++++++++++++++++++++++++++++++++----------------------------
M
client/src/dataStorage.js
|
101
+++++++++++++++++++------------------------------------------------------------
M
client/src/journeyView.js
|
17
++++++++---------
M
client/src/journeysView.js
|
21
+++++++--------------
M
client/src/main.js
|
9
+++++----
M
client/src/searchView.js
|
64
+++++++++++++++++++++++++++++-----------------------------------
A
client/src/settings.js
|
55
+++++++++++++++++++++++++++++++++++++++++++++++++++++++
M
client/src/settingsView.js
|
30
+++++++++++++++++++++---------
diff --git a/client/src/app_functions.js b/client/src/app_functions.js
@@ -1,25 +1,26 @@
-import { dbReady, getSettings, addHistoryEntry, getJourneysHistory } from './dataStorage.js';
-import { get } from './api.js';
+import { db } from './dataStorage.js';
+import { settings, subscribeSettings } from './settings.js';
+import { get, post } from './api.js';
 import { showModal } from './overlays.js';
 import { languages } from './languages.js';
 import { html } from 'lit-html';
 import { formatDateTime, getFrom, getTo } from './helpers.js';
 
 let ds100 = {};
-// we don't want to pass these around all the time
-let settings;
 
-export const applySettings = async newSettings => {
-	settings = newSettings;
+subscribeSettings(async () => {
 	if (settings.showRIL100Names) await loadDS100();
-};
+});
+
+export const getJourneysHistory = () => db.getAll('journeysHistory');
+
+export const addHistoryEntry = newEntry => db.put('journeysHistory', newEntry);
 
-export const addJourneys = async data => {
+const addJourneys = async data => {
 	if (!data) return false;
 
 	ConsoleLog(data);
 
-	const db = await dbReady;
 	await db.put('journeys', data);
 
 	//const lastHistoryEntry = (await getJourneysHistory()).slice(-1);

@@ -39,20 +40,16 @@ export const addJourneys = async data => {
 	//}
 };
 
-export const getJourneys = async slug => {
-	if (!slug) return;
-
-	const db = await dbReady;
-	let data = await db.get('journeys', slug);
-	if (!data) {
-		data = await get("savedJourneys/" + slug, {
-			stopovers: true,
-			polylines: settings.showMap || false,
-			tickets: settings.showPrices || false,
-		});
-		await addJourneys(data);
-	}
+const mkParams = () => {
+	return {
+		stopovers: true,
+		polylines: settings.showMap || false,
+		tickets: settings.showPrices || false,
+		language: settings.language,
+	};
+};
 
+const processData = data => {
 	for (let journey of data.journeys) {
 		for (let leg of journey.legs) {
 			if (leg.plannedDeparture) leg.plannedDeparture = new Date(leg.plannedDeparture);

@@ -68,16 +65,36 @@ export const getJourneys = async slug => {
 		}
 	}
 	return data;
+}
+
+export const getJourneys = async slug => {
+	if (!slug) return;
+
+	let data = await db.get('journeys', slug);
+	if (!data) {
+		data = await get(`savedJourneys/${slug}`, mkParams());
+		await addJourneys(data);
+	}
+
+	return processData(data);
+};
+
+export const getMoreJourneys  = async (slug, mode, hideLoader) => {
+	const data = await post(`savedJourneys/${slug}/${mode}`, mkParams(), hideLoader);
+	await addJourneys(data);
+	return processData(data);
 };
 
 export const refreshJourneys = async (reqId, hideLoader) => {
-	const data = await get("savedJourneys/"+reqId, {
-		stopovers: true,
-		polylines: settings.showMap || false,
-		tickets: settings.showPrices || false,
-	}, hideLoader);
+	const data = await get(`savedJourneys/${reqId}`, mkParams(), hideLoader);
 	await addJourneys(data);
-	return data;
+	return processData(data);
+};
+
+export const newJourneys  = async (params, hideLoader) => {
+	const data = await post(`savedJourneys`, { ...mkParams(), ...params }, hideLoader);
+	await addJourneys(data);
+	return processData(data);
 };
 
 export const t = (key, ...params) => {
diff --git a/client/src/dataStorage.js b/client/src/dataStorage.js
@@ -3,82 +3,29 @@ import { openDB, deleteDB } from 'idb';
 export const devMode = false;
 const dbName = devMode ? 'trainsearch_dev' : 'trainsearch';
 
-const getDefaultLanguage = () => {
-	const userLang = navigator.language || navigator.userLanguage;
-	if (['en', 'de'].includes(userLang)) return userLang;
-	return 'en';
+export let db;
+
+export const initDataStorage = async () => {
+	db = await openDB(dbName, 1, {
+		upgrade: (db, oldVersion, newVersion, transaction) => {
+			console.log(`upgrading database from ${oldVersion} to ${newVersion}`);
+			switch (oldVersion) {
+				case 0:
+					if (!db.objectStoreNames.contains('journeys'))
+						db.createObjectStore('journeys', {keyPath: 'slug'});
+					if (!db.objectStoreNames.contains('journeysHistory'))
+						db.createObjectStore('journeysHistory', {autoIncrement: true});
+					if (!db.objectStoreNames.contains('settings'))
+						db.createObjectStore('settings');
+				case 1:
+					//... add migrations for 1->2 here
+			}
+		},
+		blocking: async () => {
+			db.close();
+			location.reload();
+		},
+	});
 };
 
-const defaultSettings = {
-	provider: 'DB',
-	products: {
-		"nationalExpress": true,
-		"national": true,
-		"regionalExp": true,
-		"regional": true,
-		"suburban": true,
-		"bus": true,
-		"ferry": true,
-		"subway": true,
-		"tram": true,
-		"taxi": true
-	},
-	accessibility: 'none',
-	advancedSelection: false,
-	showRIL100Names: false,
-	writeDebugLog: false,
-	language: getDefaultLanguage(),
-	travelynx: false,
-	journeysViewMode: 'canvas',
-	showMap: false,
-	showPrices: false,
-};
-
-export const dbReady = openDB(dbName, 1, {
-	upgrade: (db, oldVersion, newVersion, transaction) => {
-		console.log(`upgrading database from ${oldVersion} to ${newVersion}`);
-		switch (oldVersion) {
-			case 0:
-				if (!db.objectStoreNames.contains('journeys'))
-					db.createObjectStore('journeys', {keyPath: 'slug'});
-				if (!db.objectStoreNames.contains('journeysHistory'))
-					db.createObjectStore('journeysHistory', {autoIncrement: true});
-				if (!db.objectStoreNames.contains('settings'))
-					db.createObjectStore('settings');
-			case 1:
-				//... add migrations for 1->2 here
-		}
-	},
-	blocking: async () => {
-		const db = await dbReady;
-		db.close();
-		location.reload();
-	},
-});
-
-export const getSettings = async () => {
-	const db = await dbReady;
-	return (await db.get('settings', 'settings')) || defaultSettings;
-};
-
-export const setSettings = async newSettings => {
-	const db = await dbReady;
-	await db.put('settings', newSettings, 'settings');
-};
-
-export const modifySettings = async callback => {
-	const db = await dbReady;
-	const tx = db.transaction('settings', 'readwrite');
-	const settings = (await tx.store.get('settings')) || defaultSettings;
-	const newSettings = callback(settings);
-	await tx.store.put(newSettings, 'settings');
-	await tx.done;
-};
-
-export const getJourneysHistory = () => dbReady.then(db => db.getAll('journeysHistory'));
-
-export const addHistoryEntry = newEntry => dbReady.then(db => db.put('journeysHistory', newEntry));
-
-export const clearDataStorage = () => {
-	deleteDB(dbName);
-};
+export const clearDataStorage = () => deleteDB(dbName);
diff --git a/client/src/journeyView.js b/client/src/journeyView.js
@@ -1,6 +1,6 @@
-import { getSettings } from './dataStorage.js';
+import { settings } from './settings.js';
 import { showDiv, hideDiv, ElementById, formatDateTime, formatDuration } from './helpers.js';
-import { ConsoleLog, parseName, ds100Names, t, timeTemplate, getJourneys, addJourneys, refreshJourneys } from './app_functions.js';
+import { ConsoleLog, parseName, ds100Names, t, timeTemplate, getJourneys, refreshJourneys } from './app_functions.js';
 import { showModal } from './overlays.js';
 import { get } from './api.js';
 import { go } from './router.js';

@@ -27,7 +27,7 @@ const getAdditionalName = (line) => {
 		return null;
 };
 
-const travelynxTemplate = (settings, element) => {
+const travelynxTemplate = (element) => {
 	if (settings.travelynx && element.line && element.line.mode === 'train') {
 		let trainName = getAdditionalName(element.line) || element.line.name;
 

@@ -44,7 +44,7 @@ const remarksTemplate = ([type, remarks]) => !!remarks.length ? html`
 	<a class="link icon-${type}" @click=${() => showRemarksModal(type, remarks)}></a>
 ` : '';
 
-const legTemplate = (settings) => (leg) => {
+const legTemplate = leg => {
 	const allRemarks = leg.remarks || [];
 	const remarks = {
 		"status": allRemarks.filter(r => r.type === 'status'),

@@ -77,7 +77,7 @@ const legTemplate = (settings) => (leg) => {
 							`}
 							${leg.cancelled ? html`<b class="cancelled-text">${t('cancelled-ride')}</b>` : ''}
 							${Object.entries(remarks).map(remarksTemplate)}
-							${travelynxTemplate(settings, leg)}</span>
+							${travelynxTemplate(leg)}</span>
 						</td>
 					</tr>
 					<tr>

@@ -122,7 +122,7 @@ const legTemplate = (settings) => (leg) => {
 	`;
 };
 
-const journeyTemplate = (settings, data, requestId, journeyId) => {
+const journeyTemplate = (data, requestId, journeyId) => {
 	const duration = data.legs[data.legs.length - 1].arrival - data.legs[0].departure;
 
 	const legs = [];

@@ -163,7 +163,7 @@ const journeyTemplate = (settings, data, requestId, journeyId) => {
 				<a class="reload icon-reload" title="{{LABEL_RELOAD}}" @click=${() => refreshJourneyView(requestId, journeyId)}>{{LABEL_RELOAD}}</a>
 			</header>
 
-			${legs.map(legTemplate(settings))}
+			${legs.map(legTemplate)}
 		</div>
 	`;
 };

@@ -193,7 +193,6 @@ const stopPlatformTemplate = (data) => {
 };
 
 export const journeyView = async (match) => {
-	const settings = await getSettings();
 	const reqId = match[0];
 	const journeyId = Number(match[1]);
 

@@ -202,7 +201,7 @@ export const journeyView = async (match) => {
 	const data = all.journeys[journeyId + all.indexOffset];
 
 	ConsoleLog(data);
-	render(journeyTemplate(settings, data, reqId, journeyId), ElementById('content'));
+	render(journeyTemplate(data, reqId, journeyId), ElementById('content'));
 
 	/*const history_id = dataStorage.journeysHistory.findIndex(obj => obj.reqId === reqId);
 
diff --git a/client/src/journeysView.js b/client/src/journeysView.js
@@ -1,13 +1,13 @@
 import { showDiv, hideDiv, ElementById, formatDuration, formatFromTo, getFrom, getTo, padZeros } from './helpers.js';
-import { parseName, ConsoleLog, t, timeTemplate, getJourneys, addJourneys } from './app_functions.js';
-import { getSettings, modifySettings } from './dataStorage.js';
+import { parseName, ConsoleLog, t, timeTemplate, getJourneys, getMoreJourneys } from './app_functions.js';
+import { settings, modifySettings } from './settings.js';
 import { setupCanvas } from './canvas.js';
 import { post } from './api.js';
 import { go } from './router.js';
 import { html, render } from 'lit-html';
 import { showAlertModal } from './overlays.js';
 
-const journeysTemplate = (settings, data) => html`
+const journeysTemplate = (data) => html`
 	<div class="journeys">
 		<header id="header">
 			<a class="back icon-back" href="#/" title="${t('back')}">${t('back')}</a>

@@ -62,7 +62,7 @@ const journeysTemplate = (settings, data) => html`
 					</tr>
 				</thead>
 				<tbody>
-					${Object.entries(data.journeys).map(([key, val]) => journeyOverviewTemplate(settings, val, data.slug, key - data.indexOffset))}
+					${Object.entries(data.journeys).map(([key, val]) => journeyOverviewTemplate(val, data.slug, key - data.indexOffset))}
 				</tbody>
 			</table>
 			</div>

@@ -72,7 +72,7 @@ const journeysTemplate = (settings, data) => html`
 	</div>
 `;
 
-const journeyOverviewTemplate = (settings, entry, slug, key) => {
+const journeyOverviewTemplate = (entry, slug, key) => {
 	let firstLeg = entry.legs[0];
 	let lastLeg = entry.legs[entry.legs.length - 1];
 	let changes = 0;

@@ -134,10 +134,9 @@ const formatPrice = price => {
 export const journeysView = async (match, isUpdate) => {
 	const slug = match[0];
 
-	const settings = await getSettings();
 	const data = await getJourneys(slug);
 
-	render(journeysTemplate(settings, data), ElementById('content'));
+	render(journeysTemplate(data), ElementById('content'));
 
 	if (settings.journeysViewMode === 'canvas') setupCanvas(data, isUpdate);
 	if (settings.journeysViewMode === 'map') {

@@ -158,12 +157,6 @@ const changeMode = (mode) => {
 };
 
 export const moreJourneys  = async (slug, mode) => {
-	const settings = await getSettings();
-	const data = await post(`savedJourneys/${slug}/${mode}`, {
-		stopovers: true,
-		polylines: settings.showMap || false,
-		tickets: settings.showPrices || false,
-	});
-	await addJourneys(data);
+	await getMoreJourneys(slug, mode);
 	journeysView([slug], true);
 };
diff --git a/client/src/main.js b/client/src/main.js
@@ -2,13 +2,14 @@ import { route, go, start } from './router.js';
 import { searchView } from './searchView.js';
 import { journeysView } from './journeysView.js';
 import { journeyView } from './journeyView.js';
-import { applySettings } from './app_functions.js';
-import { getSettings } from './dataStorage.js';
+import { initSettings } from './settings.js';
+import { initDataStorage } from './dataStorage.js';
 import { showDiv, hideDiv, ElementById } from './helpers.js';
 
 (async () => {
-	const settings = await getSettings();
-	await applySettings(settings);
+	// read settings from indexeddb
+	await initDataStorage();
+	await initSettings();
 
 	route(/^\/$/, searchView);
 	route(/^\/([a-zA-Z0-9]+)$/, journeysView);
diff --git a/client/src/searchView.js b/client/src/searchView.js
@@ -1,13 +1,13 @@
 import { showDiv, ElementById, padZeros, isValidDate, formatFromTo } from './helpers.js';
-import { parseName, ConsoleLog, t, loadDS100, getJourneys, addJourneys } from './app_functions.js';
-import { getSettings, modifySettings, getJourneysHistory } from './dataStorage.js';
+import { parseName, ConsoleLog, t, loadDS100, getJourneys, getJourneysHistory, newJourneys } from './app_functions.js';
+import { modifySettings, settings } from './settings.js';
 import { get, post } from './api.js';
 import { go } from './router.js';
 import { html, render } from 'lit-html';
 import { showAlertModal, showSelectModal, showLoader, hideOverlay} from './overlays.js';
 import { showSettings } from './settingsView.js';
 
-let suggestionsCache     = {
+const suggestions = {
 	from: {},
 	via: {},
 	to: {},

@@ -21,7 +21,7 @@ let isArrValue           = false;
 let dateValue            = currDate.getFullYear()+'-'+padZeros(currDate.getMonth()+1)+'-'+padZeros(currDate.getDate());;
 let timeValue            = padZeros(currDate.getHours())+':'+padZeros(currDate.getMinutes());
 
-const searchTemplate = (settings, journeysHistory) => html`
+const searchTemplate = (journeysHistory) => html`
 	<div id="searchView" class="center">
 		<form class="search" onsubmit="return false;">
 			<div class="title">

@@ -167,9 +167,8 @@ const journeysHistoryAction = (journeysHistory, element) => {
 };
 
 export const searchView = async () => {
-	const settings = await getSettings();
 	const journeysHistory = (await getJourneysHistory()).slice().reverse();	
-	render(searchTemplate(settings, journeysHistory), ElementById('content'));
+	render(searchTemplate(journeysHistory), ElementById('content'));
 
 	ElementById('from').focus();
 

@@ -186,7 +185,6 @@ export const search = async (requestId) => {
 		settings.accessibility = document.querySelector('input[name="accessibility"]:checked').value;
 		return settings;
 	});
-	const settings = await getSettings();
 
 	const provider      = settings.provider;
 	let   isDep         = !ElementById('isarr').checked;

@@ -223,45 +221,45 @@ export const search = async (requestId) => {
 		time = padZeros(currDate.getHours())+':'+padZeros(currDate.getMinutes());
 	}
 
-	if (Object.entries(suggestionsCache.from).length !== 0) {
-		from = suggestionsCache.from;
+	if (Object.entries(suggestions.from).length !== 0) {
+		from = suggestions.from;
 	} else {
-		let suggestions = await get("locations",  {"query": fromValue, "results": 1}, true);
+		let data = await get("locations",  {"query": fromValue, "results": 1}, true);
 
-		if (!suggestions[0]) {
+		if (!data[0]) {
     		showAlertModal("Invalid From");
 			return;
   		}
 
-		from = suggestions[0]
+		from = data[0]
 	}
 
 	if (ElementById('via').value == "") {
 		via = null;
-	} else if (Object.entries(suggestionsCache.via).length !== 0) {
-		via = suggestionsCache.via;
+	} else if (Object.entries(suggestions.via).length !== 0) {
+		via = suggestions.via;
 	} else {
-		let suggestions = await get("locations",  {"query": viaValue, "results": 1}, true);
+		let data = await get("locations",  {"query": viaValue, "results": 1}, true);
 
-		if (!suggestions[0]) {
+		if (!data[0]) {
 			showAlertModal("Invalid Via");
 			return;
 		}
 
-		via = suggestions[0]
+		via = data[0]
 	}
 
-	if (Object.entries(suggestionsCache.to).length !== 0) {
-		to = suggestionsCache.to;
+	if (Object.entries(suggestions.to).length !== 0) {
+		to = suggestions.to;
 	} else {
-		let suggestions = await get("locations",  {"query": toValue, "results": 1}, true);
+		let data = await get("locations",  {"query": toValue, "results": 1}, true);
 
-		if (!suggestions[0]) {
+		if (!data[0]) {
 			showAlertModal("Invalid To");
 			return;
   		}
 
-		to = suggestions[0]
+		to = data[0]
 	}
 
 	const split_date = date.split('-');

@@ -274,9 +272,6 @@ export const search = async (requestId) => {
 	let params = {
 		from: formatFromTo(from),
 		to: formatFromTo(to),
-		stopovers: true,
-		polylines: settings.showMap || false,
-		tickets: settings.showPrices || false,
 		results: 6,
 		//"accessibility": settings.accessibility,
 		...settings.products,

@@ -289,15 +284,14 @@ export const search = async (requestId) => {
 	else
 		params.arrival = timestamp;
 
-	const data = await post("savedJourneys", params);
-	addJourneys(data);
-	go('/' + data.slug);
+	const { slug } = await newJourneys(params);
+	go('/' + slug);
 	return false;
 };
 
-const suggestionsTemplate = (suggestions, inputId) => html`
+const suggestionsTemplate = (data, inputId) => html`
   <div class="suggestionsbox" @mouseover=${mouseOverSuggestions} @mouseout=${stopMouseOverSuggestions}>
-  	${suggestions.map(element => html`
+  	${data.map(element => html`
   		<p class="suggestion" @click=${() => setSuggestion(encodeURI(JSON.stringify(element)), inputId)}>${parseName(element)}</p>
   	`)}
   </div>

@@ -305,10 +299,10 @@ const suggestionsTemplate = (suggestions, inputId) => html`
 
 const loadSuggestions = async (e, input) => {
 	const val = e.target.value;
-	suggestionsCache[e.target.id] = {};
-	const suggestions = val ? await get("locations",  {"query": val, "results": 10}, true) : [];
+	suggestions[e.target.id] = {};
+	const data = val ? await get("locations",  {"query": val, "results": 10}, true) : [];
 	const suggestionsEl = ElementById(e.target.id+'Suggestions');
-	render(suggestionsTemplate(suggestions, e.target.id), suggestionsEl);
+	render(suggestionsTemplate(data, e.target.id), suggestionsEl);
 };
 
 export const setSuggestion  = (data, inputId) => {

@@ -316,7 +310,7 @@ export const setSuggestion  = (data, inputId) => {
 		data = JSON.parse(decodeURI(data));
 	}
 
-	suggestionsCache[inputId] = data;
+	suggestions[inputId] = data;
 	ElementById(inputId).value = parseName(data);
 
 	if (inputId === 'from') {

@@ -332,7 +326,7 @@ export const setSuggestion  = (data, inputId) => {
 };
 
 export const swapFromTo  = () => {
-	suggestionsCache.from = [suggestionsCache.to, suggestionsCache.to = suggestionsCache.from][0];
+	suggestions.from = [suggestions.to, suggestions.to = suggestions.from][0];
 
 	let from = ElementById('from');
 	let to   = ElementById('to');
diff --git a/client/src/settings.js b/client/src/settings.js
@@ -0,0 +1,55 @@
+import { db } from './dataStorage.js';
+
+const getDefaultLanguage = () => {
+	const userLang = navigator.language || navigator.userLanguage;
+	if (['en', 'de'].includes(userLang)) return userLang;
+	return 'en';
+};
+
+const defaultSettings = {
+	provider: 'DB',
+	products: {
+		"nationalExpress": true,
+		"national": true,
+		"regionalExp": true,
+		"regional": true,
+		"suburban": true,
+		"bus": true,
+		"ferry": true,
+		"subway": true,
+		"tram": true,
+		"taxi": true
+	},
+	accessibility: 'none',
+	advancedSelection: false,
+	showRIL100Names: false,
+	writeDebugLog: false,
+	language: getDefaultLanguage(),
+	travelynx: false,
+	journeysViewMode: 'canvas',
+	showMap: false,
+	showPrices: false,
+};
+
+const subscribers = [];
+
+export let settings;
+
+export const subscribeSettings = cb => {
+	subscribers.push(cb);
+};
+
+export const initSettings = async () => {
+	settings = (await db.get('settings', 'settings')) || defaultSettings;
+	for (let cb of subscribers) await cb();
+};
+
+export const modifySettings = async callback => {
+	const tx = db.transaction('settings', 'readwrite');
+	const newSettings = callback(JSON.parse(JSON.stringify(settings)));
+	await tx.store.put(newSettings, 'settings');
+	await tx.done;
+	Object.freeze(newSettings);
+	settings = newSettings;
+	for (let cb of subscribers) await cb();
+};
diff --git a/client/src/settingsView.js b/client/src/settingsView.js
@@ -1,16 +1,16 @@
-import { getSettings, modifySettings, clearDataStorage } from './dataStorage.js';
+import { db, clearDataStorage } from './dataStorage.js';
+import { modifySettings, settings } from './settings.js';
 import { showModal } from './overlays.js';
 import { hideDiv, ElementById } from './helpers.js';
-import { ConsoleLog, t, applySettings } from './app_functions.js';
+import { ConsoleLog, t } from './app_functions.js';
 import { html, render } from 'lit-html';
 import { searchView } from './searchView.js';
 
 export const showSettings = async () => {
-	const settings = await getSettings();
-	showModal(t('settings'), settingsTemplate(settings))
+	showModal(t('settings'), settingsTemplate())
 };
 
-const settingsTemplate = settings => html`
+const settingsTemplate = () => html`
   <div id="settingsView">
 		<b>${t('options')}:</b><br>
 		<label><input type="checkbox" ?checked=${settings.showRIL100Names} id="ril100"> ${t('showds100')}</label><br>

@@ -44,17 +44,29 @@ const newAll = () => {
 };
 
 const saveSettings  = async () => {
+	let clearJourneys = false;
+	let clearJourneysHistory = false;
 	await modifySettings(settings => {
-		settings.language = document.querySelector('input[name="language"]:checked').value;
 		settings.showRIL100Names = ElementById('ril100').checked;
 		settings.writeDebugLog = ElementById('debug-messages').checked;
 		settings.travelynx = ElementById('travelynx').checked;
 		settings.advancedSelection = ElementById('advancedSelection').checked;
-		settings.showMap = ElementById('feature-map').checked;
-		settings.showPrices = ElementById('feature-prices').checked;
+
+		const language = document.querySelector('input[name="language"]:checked').value;
+		if (settings.language != language) clearJourneys = true;
+		settings.language = language;
+
+		const showMap = ElementById('feature-map').checked;
+		if (settings.showMap != showMap) clearJourneys = clearJourneys || showMap;
+		settings.showMap = showMap;
+
+		const showPrices = ElementById('feature-prices').checked;
+		if (settings.showPrices != showPrices) clearJourneys = clearJourneys || showPrices;
+		settings.showPrices = showPrices;
+
 		return settings;
 	});
-	await applySettings(await getSettings());
+	if (clearJourneys) await db.clear('journeys');
 	searchView();
 	hideDiv('overlay');
 };