Skip to content

Commit eff8dac

Browse files
authored
Merge pull request #572 from accius/Staging
Staging
2 parents 375aeee + 4da8846 commit eff8dac

12 files changed

Lines changed: 55 additions & 92 deletions

File tree

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "openhamclock",
3-
"version": "15.6.1",
3+
"version": "15.6.2",
44
"description": "Amateur Radio Dashboard - A modern web-based HamClock alternative",
55
"main": "electron/main.js",
66
"scripts": {

src/App.jsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,6 @@ const App = () => {
6262
const [showPSKFilters, setShowPSKFilters] = useState(false);
6363
const [layoutResetKey, setLayoutResetKey] = useState(0);
6464
const [, setBandColorChangeVersion] = useState(0);
65-
const [tempUnit, setTempUnit] = useState(() => {
66-
try {
67-
return localStorage.getItem('openhamclock_tempUnit') || 'F';
68-
} catch {
69-
return 'F';
70-
}
71-
});
7265
const [updateInProgress, setUpdateInProgress] = useState(false);
7366

7467
useEffect(() => {
@@ -175,8 +168,8 @@ const App = () => {
175168
const propagation = usePropagation(config.location, dxLocation, config.propagation);
176169
const mySpots = useMySpots(config.callsign);
177170
const satellites = useSatellites(config.location);
178-
const localWeather = useWeather(config.location, tempUnit);
179-
const dxWeather = useWeather(dxLocation, tempUnit);
171+
const localWeather = useWeather(config.location, config.units);
172+
const dxWeather = useWeather(dxLocation, config.units);
180173
const pskReporter = usePSKReporter(config.callsign, {
181174
minutes: config.lowMemoryMode ? 5 : 30,
182175
enabled: config.callsign !== 'N0CALL',
@@ -296,8 +289,6 @@ const App = () => {
296289
handleToggleDxLock,
297290
deSunTimes,
298291
dxSunTimes,
299-
tempUnit,
300-
setTempUnit,
301292
localWeather,
302293
dxWeather,
303294
spaceWeather,

src/DockableApp.jsx

Lines changed: 3 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ export const DockableApp = ({
7777
// Weather
7878
localWeather,
7979
dxWeather,
80-
tempUnit,
81-
setTempUnit,
8280
showDxWeather,
8381

8482
// Space weather & solar
@@ -406,13 +404,7 @@ export const DockableApp = ({
406404

407405
<WeatherPanel
408406
weatherData={localWeather}
409-
tempUnit={tempUnit}
410-
onTempUnitChange={(unit) => {
411-
setTempUnit(unit);
412-
try {
413-
localStorage.setItem('openhamclock_tempUnit', unit);
414-
} catch {}
415-
}}
407+
units={config.units}
416408
nodeId={nodeId}
417409
/>
418410
</div>
@@ -517,13 +509,7 @@ export const DockableApp = ({
517509
{showDxWeather && (
518510
<WeatherPanel
519511
weatherData={dxWeather}
520-
tempUnit={tempUnit}
521-
onTempUnitChange={(unit) => {
522-
setTempUnit(unit);
523-
try {
524-
localStorage.setItem('openhamclock_tempUnit', unit);
525-
} catch {}
526-
}}
512+
units={config.units}
527513
nodeId={nodeId}
528514
/>
529515
)}
@@ -862,13 +848,7 @@ export const DockableApp = ({
862848
case 'ambient':
863849
content = (
864850
<AmbientPanel
865-
tempUnit={tempUnit}
866-
onTempUnitChange={(unit) => {
867-
setTempUnit(unit);
868-
try {
869-
localStorage.setItem('openhamclock_tempUnit', unit);
870-
} catch {}
871-
}}
851+
units={config.units}
872852
/>
873853
);
874854
break;
@@ -909,7 +889,6 @@ export const DockableApp = ({
909889
deSunTimes,
910890
dxSunTimes,
911891
showDxWeather,
912-
tempUnit,
913892
localWeather,
914893
dxWeather,
915894
solarIndices,

src/components/AmbientPanel.jsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,9 @@ function fmtBoolOk(v) {
9292
return v ? 'OK' : 'LOW';
9393
}
9494

95-
export default function AmbientPanel({ tempUnit = 'F' }) {
95+
export default function AmbientPanel({ units = 'imperial' }) {
9696
// ✅ Hooks must always run in the same order
97-
const ambient = useAmbientWeather(tempUnit);
97+
const ambient = useAmbientWeather(units);
9898
const w = ambient.data;
9999

100100
const [prefs, setPrefs] = useState(loadPanelPrefs);
@@ -104,7 +104,7 @@ export default function AmbientPanel({ tempUnit = 'F' }) {
104104
}, [prefs]);
105105

106106
// ✅ Derive units safely even when w is null
107-
const deg = ${w?.tempUnit || tempUnit}`;
107+
const deg = ${w?.tempUnit || (units === 'metric' ? 'C' : 'F')}`;
108108
const windUnit = w?.windUnit || 'mph';
109109
const rainUnit = w?.rainUnit || 'in';
110110
const pressureUnit = w?.pressureUnit || 'inHg';

src/components/WeatherPanel.jsx

Lines changed: 4 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,7 @@ import { usePanelResize } from '../contexts';
1717

1818
export const WeatherPanel = ({
1919
location,
20-
tempUnit,
21-
onTempUnitChange,
20+
units = 'imperial',
2221
nodeId,
2322
weatherData, // Optional: pre-fetched { data, loading, error } from useWeather
2423
}) => {
@@ -63,7 +62,7 @@ export const WeatherPanel = ({
6362
}, [weatherExpanded, nodeId, requestResize, resetSize]);
6463

6564
// Use pre-fetched data if provided, otherwise fetch our own
66-
const ownWeather = useWeather(weatherData ? null : location, tempUnit);
65+
const ownWeather = useWeather(weatherData ? null : location, units);
6766
const weather = weatherData || ownWeather;
6867

6968
const { data: w, loading, error } = weather;
@@ -128,7 +127,7 @@ export const WeatherPanel = ({
128127
// No data, no error, no loading — location probably not set
129128
if (!w) return null;
130129

131-
const deg = ${w.tempUnit || tempUnit}`;
130+
const deg = ${w.tempUnit || (units === 'metric' ? 'C' : 'F')}`;
132131
const wind = t(`weather.unit.${w.windUnit === 'km/h' ? 'kmh' : 'mph'}`);
133132
const vis = t(`weather.unit.${w.visUnit === 'km' ? 'km' : 'mi'}`);
134133

@@ -192,30 +191,6 @@ export const WeatherPanel = ({
192191
193192
</span>
194193
</div>
195-
{/* F/C toggle */}
196-
{onTempUnitChange && (
197-
<button
198-
onClick={(e) => {
199-
e.stopPropagation();
200-
onTempUnitChange(tempUnit === 'F' ? 'C' : 'F');
201-
}}
202-
style={{
203-
background: 'var(--bg-tertiary)',
204-
border: '1px solid var(--border-color)',
205-
color: 'var(--text-secondary)',
206-
fontSize: '10px',
207-
padding: '1px 5px',
208-
borderRadius: '3px',
209-
cursor: 'pointer',
210-
fontFamily: 'JetBrains Mono, monospace',
211-
fontWeight: '600',
212-
flexShrink: 0,
213-
}}
214-
title={t('weather.switchUnit', { unit: tempUnit === 'F' ? 'C' : 'F' })}
215-
>
216-
°{tempUnit === 'F' ? 'C' : 'F'}
217-
</button>
218-
)}
219194
</div>
220195

221196
{/* Error badge — show when data is stale but we have cached data */}
@@ -299,7 +274,7 @@ export const WeatherPanel = ({
299274
<div style={{ display: 'flex', justifyContent: 'space-between' }}>
300275
<span style={{ color: 'var(--text-muted)' }}>{t('weather.pressure')}</span>
301276
<span style={{ color: 'var(--text-secondary)' }}>
302-
{w.pressure} {t('weather.hpa')}
277+
{w.pressure} {w.pressureUnit || t('weather.hpa')}
303278
</span>
304279
</div>
305280
)}

src/components/WhatsNew.jsx

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,28 @@ import { useState, useEffect } from 'react';
99
// Add new versions at the TOP of this array.
1010
// Each entry: { version, date, heading, features: [...] }
1111
const CHANGELOG = [
12+
{
13+
version: '15.6.2',
14+
date: '2026-02-22',
15+
heading: 'Surprise! Sunday Updates',
16+
features: [
17+
{
18+
icon: '🌡️',
19+
title: 'Unified Weather Units',
20+
desc: 'Weather displays now follow the global Settings unit choice (metric/imperial) everywhere — no more separate °F/°C toggle button inside each weather panel. Pressure reads correctly per system: hPa for metric, inHg for imperial. One setting, consistent behavior across all layouts.',
21+
},
22+
{
23+
icon: '🔀',
24+
title: 'Staging Branch Merge Cleanup',
25+
desc: 'Resolved merge conflicts across DockableApp and WorldMap bringing all Staging features cleanly into the codebase: WWBOTA spots & labels, DX weather overlays, night darkness slider, and the map legend toggle. Zero conflict markers, zero duplicate functions.',
26+
},
27+
{
28+
icon: '🗺️',
29+
title: 'WWFF Legend Badge Fix',
30+
desc: 'The WWFF entry in the map legend was rendering taller than POTA/SOTA/WWBOTA because the ▼ symbol and text could wrap to two lines. Fixed with a non-breaking space to match all other legend badges.',
31+
},
32+
],
33+
},
1234
{
1335
version: '15.6.1',
1436
date: '2026-02-25',

src/components/WorldMap.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2256,7 +2256,7 @@ export const WorldMap = ({
22562256
fontWeight: '600',
22572257
}}
22582258
>
2259-
WWFF
2259+
&nbsp;WWFF
22602260
</span>
22612261
</div>
22622262
)}

src/hooks/useAmbientWeather.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ function getEnv(name) {
5151
return undefined;
5252
}
5353

54-
export const useAmbientWeather = (tempUnit = 'F') => {
54+
export const useAmbientWeather = (units = 'imperial') => {
5555
const [rawDevice, setRawDevice] = useState(null); // { macAddress, info, lastData }
5656
const [loading, setLoading] = useState(true);
5757
const [error, setError] = useState(null);
@@ -113,7 +113,7 @@ export const useAmbientWeather = (tempUnit = 'F') => {
113113
const data = useMemo(() => {
114114
if (!rawDevice?.lastData) return null;
115115

116-
const isMetric = tempUnit === 'C';
116+
const isMetric = units === 'metric';
117117
const ld = rawDevice.lastData;
118118

119119
const updatedAtMs = safeNum(ld.dateutc) ?? (ld.date ? Date.parse(ld.date) : null);
@@ -201,7 +201,7 @@ export const useAmbientWeather = (tempUnit = 'F') => {
201201
rainUnit: isMetric ? 'mm' : 'in',
202202
pressureUnit: isMetric ? 'hPa' : 'inHg',
203203
};
204-
}, [rawDevice, tempUnit]);
204+
}, [rawDevice, units]);
205205

206206
return { data, loading, error };
207207
};

src/hooks/useWeather.js

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
* — distributes rate limits across all users instead of concentrating on server.
66
* — optional API key support via localStorage ('ohc_openmeteo_apikey')
77
*
8-
* Always fetches in metric (Celsius, km/h, mm) and converts client-side.
8+
* Always fetches in metric (Celsius, km/h, mm) and converts client-side
9+
* based on the global `units` setting ('imperial' or 'metric').
910
*/
1011
import { useState, useEffect, useRef } from 'react';
1112

@@ -67,15 +68,16 @@ const cToF = (c) => (c * 9) / 5 + 32;
6768
const kmhToMph = (k) => k * 0.621371;
6869
const mmToInch = (mm) => mm * 0.0393701;
6970
const kmToMi = (km) => km * 0.621371;
71+
const hPaToInHg = (hPa) => hPa * 0.02953;
7072

7173
/**
7274
* Convert raw Open-Meteo API response to display-ready weather data.
7375
* Exported so WeatherPanel can use pre-fetched data without its own hook.
7476
*/
75-
export function convertWeatherData(rawData, tempUnit = 'F') {
77+
export function convertWeatherData(rawData, units = 'imperial') {
7678
if (!rawData) return null;
7779

78-
const isMetric = tempUnit === 'C';
80+
const isMetric = units === 'metric';
7981
const current = rawData.current || {};
8082
const daily = rawData.daily || {};
8183
const hourly = rawData.hourly || {};
@@ -131,7 +133,12 @@ export function convertWeatherData(rawData, tempUnit = 'F') {
131133
icon: weather.icon,
132134
humidity: Math.round(current.relative_humidity_2m || 0),
133135
dewPoint: convTemp(current.dew_point_2m),
134-
pressure: current.pressure_msl ? current.pressure_msl.toFixed(1) : null,
136+
pressure: current.pressure_msl
137+
? isMetric
138+
? current.pressure_msl.toFixed(1)
139+
: hPaToInHg(current.pressure_msl).toFixed(2)
140+
: null,
141+
pressureUnit: isMetric ? 'hPa' : 'inHg',
135142
cloudCover: current.cloud_cover || 0,
136143
windSpeed: convWind(current.wind_speed_10m),
137144
windDir: windDirection(current.wind_direction_10m),
@@ -197,7 +204,7 @@ async function fetchOpenMeteoDirect(lat, lon) {
197204
return data;
198205
}
199206

200-
export const useWeather = (location, tempUnit = 'F') => {
207+
export const useWeather = (location, units = 'imperial') => {
201208
const [rawData, setRawData] = useState(null);
202209
const [loading, setLoading] = useState(true);
203210
const [error, setError] = useState(null); // { message, retryIn }
@@ -255,8 +262,8 @@ export const useWeather = (location, tempUnit = 'F') => {
255262
};
256263
}, [location?.lat, location?.lon]);
257264

258-
// Convert raw API data to display data based on current tempUnit
259-
const data = convertWeatherData(rawData, tempUnit);
265+
// Convert raw API data to display data based on current units
266+
const data = convertWeatherData(rawData, units);
260267

261268
return { data, loading, error };
262269
};

src/layouts/ModernLayout.jsx

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@ export default function ModernLayout(props) {
5757
handleToggleDxLock,
5858
deSunTimes,
5959
dxSunTimes,
60-
tempUnit,
61-
setTempUnit,
6260
showDxWeather,
6361
currentTime,
6462
classicAnalogClock,
@@ -112,13 +110,6 @@ export default function ModernLayout(props) {
112110
}
113111
};
114112

115-
const tempUnitToggle = (unit) => {
116-
setTempUnit(unit);
117-
try {
118-
localStorage.setItem('openhamclock_tempUnit', unit);
119-
} catch {}
120-
};
121-
122113
// ─── Shared map component ───
123114
const mapComponent = (style) => (
124115
<div style={{ position: 'relative', borderRadius: '6px', overflow: 'hidden', ...style }}>
@@ -196,7 +187,7 @@ export default function ModernLayout(props) {
196187
<span style={{ color: 'var(--accent-purple)', fontWeight: '600' }}>{deSunTimes.sunset}</span>
197188
</div>
198189
</div>
199-
<WeatherPanel weatherData={localWeather} tempUnit={tempUnit} onTempUnitChange={tempUnitToggle} />
190+
<WeatherPanel weatherData={localWeather} units={config.units} />
200191
</div>
201192
);
202193

@@ -262,7 +253,7 @@ export default function ModernLayout(props) {
262253
<span style={{ color: 'var(--accent-purple)', fontWeight: '600' }}>{dxSunTimes.sunset}</span>
263254
</div>
264255
</div>
265-
{showDxWeather && <WeatherPanel weatherData={dxWeather} tempUnit={tempUnit} onTempUnitChange={tempUnitToggle} />}
256+
{showDxWeather && <WeatherPanel weatherData={dxWeather} units={config.units} />}
266257
</div>
267258
);
268259

0 commit comments

Comments
 (0)