Compare commits

...

3 commits

Author SHA1 Message Date
a964662940 restyle radar observations
Some checks are pending
build-docker / Build Image (push) Waiting to run
2026-04-11 12:35:42 -04:00
edb955323d Regional forecast screen re-vamp 2026-04-11 12:13:39 -04:00
fef73485dd Improve screen layout for themes + Radar layout adjustments 2026-04-11 12:02:24 -04:00
10 changed files with 95 additions and 31 deletions

View file

@ -45,11 +45,15 @@ class CurrentWeather extends WeatherDisplay {
const wind = this.data.WindSpeed > 0 const wind = this.data.WindSpeed > 0
? this.data.WindDirection.padEnd(3, '') + this.data.WindSpeed.toString().padStart(3, ' ') ? this.data.WindDirection.padEnd(3, '') + this.data.WindSpeed.toString().padStart(3, ' ')
: 'Calm'; : 'Calm';
const isDefaultTheme = (document.documentElement.dataset.theme ?? 'default') === 'default';
const windText = !isDefaultTheme && this.data.WindGust > 0
? `${wind} - Gusts to ${this.data.WindGust}`
: wind;
const fill = { const fill = {
temp: this.data.Temperature + String.fromCharCode(176), temp: this.data.Temperature + String.fromCharCode(176),
condition, condition,
wind, wind: windText,
location: this.data.city.substr(0, 20), location: this.data.city.substr(0, 20),
humidity: `${this.data.Humidity}%`, humidity: `${this.data.Humidity}%`,
dewpoint: this.data.DewPoint + String.fromCharCode(176), dewpoint: this.data.DewPoint + String.fromCharCode(176),
@ -59,7 +63,7 @@ class CurrentWeather extends WeatherDisplay {
icon: { type: 'img', src: this.data.Icon }, icon: { type: 'img', src: this.data.Icon },
}; };
if (this.data.WindGust > 0) fill['wind-gusts'] = `Gusts to ${this.data.WindGust}`; if (isDefaultTheme && this.data.WindGust > 0) fill['wind-gusts'] = `Gusts to ${this.data.WindGust}`;
const area = this.elem.querySelector('.main'); const area = this.elem.querySelector('.main');
area.innerHTML = ''; area.innerHTML = '';

View file

@ -28,6 +28,38 @@ const getStoredLocationMetadata = () => {
const isUsLocation = (location) => ['US', 'USA'].includes((location?.countryCode ?? '').toUpperCase()); const isUsLocation = (location) => ['US', 'USA'].includes((location?.countryCode ?? '').toUpperCase());
const isWithinBounds = (latLon, bounds) => latLon.lat >= bounds.minLat
&& latLon.lat <= bounds.maxLat
&& latLon.lon >= bounds.minLon
&& latLon.lon <= bounds.maxLon;
const isWithinUsFallbackBounds = (latLon) => [
{
minLat: 24.0,
maxLat: 49.5,
minLon: -125.0,
maxLon: -66.5,
},
{
minLat: 51.0,
maxLat: 71.5,
minLon: -179.5,
maxLon: -129.5,
},
{
minLat: 18.5,
maxLat: 22.5,
minLon: -160.5,
maxLon: -154.5,
},
].some((bounds) => isWithinBounds(latLon, bounds));
const supportsNoaaLocation = (location, latLon) => {
if (isUsLocation(location)) return true;
if (!location?.countryCode) return isWithinUsFallbackBounds(latLon);
return false;
};
const getFallbackLocation = (latLon) => { const getFallbackLocation = (latLon) => {
const query = localStorage.getItem('latLonQuery') ?? `${latLon.lat.toFixed(4)}, ${latLon.lon.toFixed(4)}`; const query = localStorage.getItem('latLonQuery') ?? `${latLon.lat.toFixed(4)}, ${latLon.lon.toFixed(4)}`;
const [city = query, state = ''] = query.split(',').map((part) => part.trim()); const [city = query, state = ''] = query.split(',').map((part) => part.trim());
@ -94,22 +126,21 @@ const getWeather = async (latLon, haveDataCallback) => {
if (typeof haveDataCallback === 'function') haveDataCallback(location); if (typeof haveDataCallback === 'function') haveDataCallback(location);
try { try {
const supportsNoaaDisplays = isUsLocation(location); const noaaEligibleLocation = supportsNoaaLocation(location, latLon);
const shouldTryNoaaPoint = supportsNoaaDisplays || !location.countryCode;
let point = null; let point = null;
let stations = null; let stations = null;
let stationId = ''; let stationId = '';
if (shouldTryNoaaPoint) { if (noaaEligibleLocation) {
point = await getPoint(latLon.lat, latLon.lon); point = await getPoint(latLon.lat, latLon.lon);
} }
if (supportsNoaaDisplays && point?.properties?.observationStations) { if (noaaEligibleLocation && point?.properties?.observationStations) {
stations = await safeJson(point.properties.observationStations); stations = await safeJson(point.properties.observationStations);
stationId = stations?.features?.[0]?.properties?.stationIdentifier ?? ''; stationId = stations?.features?.[0]?.properties?.stationIdentifier ?? '';
} }
const supportsNoaaAlerts = !!(isUsLocation(location) || point); const supportsNoaaAlerts = noaaEligibleLocation;
const state = location.state || point?.properties?.relativeLocation?.properties?.state || ''; const state = location.state || point?.properties?.relativeLocation?.properties?.state || '';
let city = location.city || point?.properties?.relativeLocation?.properties?.city || localStorage.getItem('latLonQuery') || ''; let city = location.city || point?.properties?.relativeLocation?.properties?.city || localStorage.getItem('latLonQuery') || '';
@ -129,7 +160,7 @@ const getWeather = async (latLon, haveDataCallback) => {
weatherParameters.timeZone = openMeteoForecast.timezone; weatherParameters.timeZone = openMeteoForecast.timezone;
weatherParameters.forecast = aggregatedForecast; weatherParameters.forecast = aggregatedForecast;
weatherParameters.supportsNoaaAlerts = supportsNoaaAlerts; weatherParameters.supportsNoaaAlerts = supportsNoaaAlerts;
weatherParameters.supportsNoaaDisplays = !!(supportsNoaaDisplays && point && stations?.features?.length); weatherParameters.supportsNoaaDisplays = !!(noaaEligibleLocation && point && stations?.features?.length);
weatherParameters.zoneId = point?.properties?.forecastZone?.substr(-6) ?? ''; weatherParameters.zoneId = point?.properties?.forecastZone?.substr(-6) ?? '';
weatherParameters.radarId = point?.properties?.radarStation?.substr(-3) ?? ''; weatherParameters.radarId = point?.properties?.radarStation?.substr(-3) ?? '';
weatherParameters.stationId = stationId; weatherParameters.stationId = stationId;

View file

@ -57,6 +57,7 @@ const getThemeAssetUrl = (themeName, assetKey) => {
const applyTheme = (themeName) => { const applyTheme = (themeName) => {
const selectedTheme = getAvailableThemes().includes(themeName) ? themeName : DEFAULT_THEME; const selectedTheme = getAvailableThemes().includes(themeName) ? themeName : DEFAULT_THEME;
localStorage.setItem(THEME_STORAGE_KEY, selectedTheme); localStorage.setItem(THEME_STORAGE_KEY, selectedTheme);
document.documentElement.dataset.theme = selectedTheme;
document.documentElement.style.setProperty('--theme-background-1', `url('${getThemeAssetUrl(selectedTheme, 'background1')}')`); document.documentElement.style.setProperty('--theme-background-1', `url('${getThemeAssetUrl(selectedTheme, 'background1')}')`);
document.documentElement.style.setProperty('--theme-background-1-chart', `url('${getThemeAssetUrl(selectedTheme, 'background1Chart')}')`); document.documentElement.style.setProperty('--theme-background-1-chart', `url('${getThemeAssetUrl(selectedTheme, 'background1Chart')}')`);

View file

@ -23,7 +23,7 @@
&.right { &.right {
right: 0px; right: 0px;
font-family: "Star4000 Large"; font-family: "Star4000 Large";
font-size: 20px; font-size: 18px;
font-weight: bold; font-weight: bold;
line-height: 24px; line-height: 24px;
@ -93,3 +93,34 @@
} }
} }
} }
:root[data-theme]:not([data-theme='default']) {
.weather-display .main.current-weather {
&.main {
.col {
&.left {
margin-top: 35px;
}
&.right {
margin-top: 36px;
padding: 21px;
}
}
.wind-container {
display: block;
&>div {
width: 50%;
}
.wind {
text-align: right;
font-size: 22px;
display: contents;
}
}
}
}
}

View file

@ -24,3 +24,7 @@
line-height: 40px; line-height: 40px;
} }
} }
:root[data-theme]:not([data-theme='default']) .weather-display .local-forecast .forecasts {
margin-top: 16px;
}

View file

@ -49,9 +49,10 @@
.box { .box {
display: block; display: block;
border: 2px solid black; border: 2.7px solid #000;
width: 100%; width: 90%;
height: 22px; height: 12px;
margin-top: 4px;
padding: 0; padding: 0;
} }
@ -97,7 +98,7 @@
top: -20px; top: -20px;
font-family: 'Star4000 Small'; font-family: 'Star4000 Small';
font-size: 18pt; font-size: 18pt;
left: 130px; left: 132px;
} }
} }
} }
@ -163,14 +164,12 @@
border: 0; border: 0;
.nearby-weather-marker-inner { .nearby-weather-marker-inner {
display: flex; display: inline-flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
min-width: 72px; min-width: 72px;
padding: 2px 4px; padding: 2px 4px;
background: rgba(18, 34, 61, 0.88); background: rgb(18 34 61 / 0%);
border: 1px solid #000;
box-shadow: 1px 1px 0 #000;
color: #fff; color: #fff;
text-align: center; text-align: center;
} }
@ -182,6 +181,7 @@
white-space: nowrap; white-space: nowrap;
margin-bottom: 1px; margin-bottom: 1px;
text-shadow: 1px 1px 0 #000; text-shadow: 1px 1px 0 #000;
display: none;
} }
.details { .details {

View file

@ -53,25 +53,18 @@
border: 0; border: 0;
.nearby-weather-marker-inner { .nearby-weather-marker-inner {
display: flex; display: inline-flex;
flex-direction: column; flex-direction: column;
align-items: center; align-items: center;
min-width: 72px; min-width: 72px;
padding: 2px 4px; padding: 2px 4px;
background: rgba(18, 34, 61, 0.88); background: rgb(255 255 255 / 0%);
border: 1px solid #000;
box-shadow: 1px 1px 0 #000;
color: #fff; color: #fff;
text-align: center; text-align: center;
} }
.city { .city {
font-family: 'Star4000 Small'; display: none;
font-size: 11pt;
line-height: 1;
white-space: nowrap;
margin-bottom: 1px;
@include u.text-shadow();
} }
.details { .details {

File diff suppressed because one or more lines are too long