mirror of
https://github.com/netbymatt/ws4kp.git
synced 2026-04-17 00:59:29 -07:00
complete kiosk mode and permalink close #33
This commit is contained in:
@@ -77,6 +77,14 @@ I've made several changes to this Weather Star 4000 simulation compared to the o
|
||||
* The nearby cities displayed on screens such as "Latest Observations" and "Regional Forecast" are likely not the same as they were in the 90's. The weather monitoring equipment at these stations move over time for one reason or another, and coming up with a simple formulaic way of finding nearby stations is sufficient to give the same look-and-feel as the original.
|
||||
* "Flavors" are not present in this simulation. Flavors refer to the order of the weather information that was shown on the original units. Instead, the order of the displays has been fixed and a checkboxes can be used to turn on and off individual displays. The travel forecast has been defaulted to off so only local information shows for new users.
|
||||
|
||||
## Sharing a permalink (bookmarking)
|
||||
Selected displays, the forecast city and widescreen setting are sticky from one session to the next. However if you would like to share your exact configuration or bookmark it click the "Copy Permalink" near the bottom of the page. A URL will be copied to your clipboard with all of you selected displays and location. You can then share this link or add it to your bookmarks.
|
||||
|
||||
## Kiosk mode
|
||||
Kiosk mode can be activated by a checkbox on the page. Note that there is no way out of kiosk mode (except refresh or closing the browser), and the play/pause and other controls will not be available. This is deliberate as a browser's kiosk mode it intended not to be exited or significantly modified.
|
||||
|
||||
It's also possible to enter kiosk mode using a permalink. First generate a [Permalink](#sharing-a-permalink-bookmarking), then to the end of it add `&kiosk=true`. Opening this link will load all of the selected displays included in the Permalink, enter kiosk mode immediately upon loading and start playing the forecast.
|
||||
|
||||
## Wish list
|
||||
|
||||
As time allows I will be working on the following enhancements.
|
||||
|
||||
@@ -5,6 +5,7 @@ import {
|
||||
} from './modules/navigation.mjs';
|
||||
import { round2 } from './modules/utils/units.mjs';
|
||||
import { parseQueryString } from './modules/share.mjs';
|
||||
import settings from './modules/settings.mjs';
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
init();
|
||||
@@ -100,7 +101,9 @@ const init = () => {
|
||||
btnGetGpsClick();
|
||||
}
|
||||
|
||||
const play = localStorage.getItem('play');
|
||||
// if kiosk mode was set via the query string, also play immediately
|
||||
settings.kiosk.value = parsedParameters['settings-kiosk-checkbox'] === 'true';
|
||||
const play = parsedParameters['settings-kiosk-checkbox'] ?? localStorage.getItem('play');
|
||||
if (play === null || play === 'true') postMessage('navButton', 'play');
|
||||
|
||||
document.querySelector('#btnClearQuery').addEventListener('click', () => {
|
||||
|
||||
@@ -275,7 +275,7 @@ const resize = () => {
|
||||
const heightZoomPercent = (window.innerHeight) / 480;
|
||||
|
||||
const scale = Math.min(widthZoomPercent, heightZoomPercent);
|
||||
if (scale < 1.0 || document.fullscreenElement) {
|
||||
if (scale < 1.0 || document.fullscreenElement || settings.kiosk) {
|
||||
document.querySelector('#container').style.transform = `scale(${scale})`;
|
||||
} else {
|
||||
document.querySelector('#container').style.transform = 'unset';
|
||||
|
||||
@@ -8,7 +8,8 @@ const settings = {};
|
||||
|
||||
const init = () => {
|
||||
// create settings
|
||||
settings.wide = new Setting('wide', 'Widescreen', 'boolean', false, wideScreenChange);
|
||||
settings.wide = new Setting('wide', 'Widescreen', 'boolean', false, wideScreenChange, true);
|
||||
settings.kiosk = new Setting('kiosk', 'Kiosk', 'boolean', false, kioskChange, false);
|
||||
|
||||
// generate checkboxes
|
||||
const checkboxes = Object.values(settings).map((d) => d.generateCheckbox());
|
||||
@@ -28,4 +29,14 @@ const wideScreenChange = (value) => {
|
||||
}
|
||||
};
|
||||
|
||||
const kioskChange = (value) => {
|
||||
const body = document.querySelector('body');
|
||||
if (value) {
|
||||
body.classList.add('kiosk');
|
||||
window.dispatchEvent(new Event('resize'));
|
||||
} else {
|
||||
body.classList.remove('kiosk');
|
||||
}
|
||||
};
|
||||
|
||||
export default settings;
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
document.addEventListener('DOMContentLoaded', () => init());
|
||||
|
||||
// shorthand mappings for frequently used values
|
||||
const specialMappings = {
|
||||
kiosk: 'settings-kiosk-checkbox',
|
||||
};
|
||||
|
||||
const init = () => {
|
||||
// add action to existing link
|
||||
document.querySelector('#share-link').addEventListener('click', createLink);
|
||||
@@ -28,9 +33,6 @@ const createLink = async (e) => {
|
||||
|
||||
const url = new URL(`?${queryString}`, document.location.href);
|
||||
|
||||
console.log(queryStringElements);
|
||||
console.log(queryString);
|
||||
console.log(url.toString());
|
||||
try {
|
||||
await navigator.clipboard.writeText(url.toString());
|
||||
const confirmSpan = document.querySelector('#share-link-copied');
|
||||
@@ -47,8 +49,21 @@ const parseQueryString = () => {
|
||||
// return memoized result
|
||||
if (parseQueryString.params) return parseQueryString.params;
|
||||
const urlSearchParams = new URLSearchParams(window.location.search);
|
||||
|
||||
// turn into an array of key-value pairs
|
||||
const paramsArray = [...urlSearchParams];
|
||||
|
||||
// add additional expanded keys
|
||||
paramsArray.forEach((paramPair) => {
|
||||
const expandedKey = specialMappings[paramPair[0]];
|
||||
if (expandedKey) {
|
||||
paramsArray.push([expandedKey, paramPair[1]]);
|
||||
}
|
||||
});
|
||||
|
||||
// memoize result
|
||||
parseQueryString.params = Object.fromEntries(urlSearchParams.entries());
|
||||
parseQueryString.params = Object.fromEntries(paramsArray);
|
||||
|
||||
return parseQueryString.params;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
const SETTINGS_KEY = 'Settings';
|
||||
|
||||
class Setting {
|
||||
constructor(shortName, name, type, defaultValue, changeAction) {
|
||||
constructor(shortName, name, type, defaultValue, changeAction, sticky) {
|
||||
// store values
|
||||
this.shortName = shortName;
|
||||
this.name = name;
|
||||
this.defaultValue = defaultValue;
|
||||
this.myValue = defaultValue;
|
||||
this.type = type;
|
||||
// a defualt blank change function is provded
|
||||
// a default blank change function is provided
|
||||
this.changeAction = changeAction ?? (() => {});
|
||||
|
||||
// get existing value if present
|
||||
const storedValue = this.getFromLocalStorage();
|
||||
if (storedValue !== null) {
|
||||
if (sticky && storedValue !== null) {
|
||||
this.myValue = storedValue;
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ class Setting {
|
||||
}
|
||||
|
||||
storeToLocalStorage(value) {
|
||||
if (!this.sticky) return;
|
||||
const allSettingsString = localStorage?.getItem(SETTINGS_KEY) ?? '{}';
|
||||
const allSettings = JSON.parse(allSettingsString);
|
||||
allSettings[this.shortName] = value;
|
||||
@@ -86,7 +87,13 @@ class Setting {
|
||||
}
|
||||
|
||||
set value(newValue) {
|
||||
// update the state
|
||||
this.myValue = newValue;
|
||||
this.checkbox.checked = newValue;
|
||||
this.storeToLocalStorage(this.myValue);
|
||||
|
||||
// call change action
|
||||
this.changeAction(this.myValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -19,6 +19,10 @@ body {
|
||||
color: lightblue;
|
||||
}
|
||||
}
|
||||
|
||||
&.kiosk {
|
||||
margin: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
#divQuery {
|
||||
@@ -302,13 +306,18 @@ body {
|
||||
background: url(../images/BackGround1_1_wide.png)
|
||||
}
|
||||
|
||||
#divTwc:fullscreen #container {
|
||||
#divTwc:fullscreen #container,
|
||||
.kiosk #divTwc #container {
|
||||
// background-image: none;
|
||||
width: unset;
|
||||
height: unset;
|
||||
transform-origin: unset;
|
||||
}
|
||||
|
||||
.kiosk #divTwc #container {
|
||||
transform-origin: 0 0;
|
||||
}
|
||||
|
||||
#loading {
|
||||
width: 640px;
|
||||
height: 480px;
|
||||
@@ -344,7 +353,7 @@ body {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#enabledDisplays {
|
||||
#enabledDisplays, #settings {
|
||||
margin-bottom: 15px;
|
||||
@include u.status-colors();
|
||||
|
||||
@@ -396,18 +405,24 @@ body {
|
||||
transform: scale(0.75);
|
||||
}
|
||||
|
||||
#divTwc:fullscreen {
|
||||
#divTwc:fullscreen,
|
||||
.kiosk #divTwc {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
align-content: center;
|
||||
}
|
||||
.kiosk #divTwc {
|
||||
justify-content: unset;
|
||||
}
|
||||
|
||||
#divTwc:fullscreen #display {
|
||||
#divTwc:fullscreen #display,
|
||||
.kiosk #divTwc #display {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#divTwc:fullscreen #divTwcBottom {
|
||||
#divTwc:fullscreen #divTwcBottom,
|
||||
.kiosk #divTwc #divTwcBottom {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
background-color: rgb(0 0 0 / 0.5);
|
||||
@@ -417,6 +432,14 @@ body {
|
||||
bottom: 0px;
|
||||
}
|
||||
|
||||
.kiosk {
|
||||
#divTwc #divTwcBottom {
|
||||
>div {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navButton {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -703,4 +726,16 @@ body {
|
||||
#share-link-copied {
|
||||
color: c.$title-color;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.kiosk {
|
||||
#divQuery,
|
||||
>.info,
|
||||
>.heading,
|
||||
#enabledDisplays,
|
||||
#settings,
|
||||
#divInfo,
|
||||
#divRefresh {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
@@ -152,7 +152,7 @@
|
||||
</div>
|
||||
|
||||
<div class='info'>
|
||||
<a href='' id='share-link'>Copy Configuration Link</a> <span id="share-link-copied">Link copied to clipboard!</span>
|
||||
<a href='' id='share-link'>Copy Permalink</a> <span id="share-link-copied">Link copied to clipboard!</span>
|
||||
</div>
|
||||
|
||||
<div id="divInfo">
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
"files.exclude": {},
|
||||
"files.eol": "\n",
|
||||
"editor.codeActionsOnSave": {
|
||||
"source.fixAll.eslint": true
|
||||
"source.fixAll.eslint": "explicit"
|
||||
}
|
||||
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user