diff --git a/frontend/src/components/repeater/RepeaterLppTelemetryPane.tsx b/frontend/src/components/repeater/RepeaterLppTelemetryPane.tsx index 6680fd3..d78a460 100644 --- a/frontend/src/components/repeater/RepeaterLppTelemetryPane.tsx +++ b/frontend/src/components/repeater/RepeaterLppTelemetryPane.tsx @@ -1,4 +1,5 @@ import { RepeaterPane, NotFetched, LppSensorRow } from './repeaterPaneShared'; +import { useDistanceUnit } from '../../contexts/DistanceUnitContext'; import type { RepeaterLppTelemetryResponse, PaneState } from '../../types'; export function LppTelemetryPane({ @@ -12,6 +13,7 @@ export function LppTelemetryPane({ onRefresh: () => void; disabled?: boolean; }) { + const { distanceUnit } = useDistanceUnit(); return ( {!data ? ( @@ -21,7 +23,7 @@ export function LppTelemetryPane({ ) : (
{data.sensors.map((sensor, i) => ( - + ))}
)} diff --git a/frontend/src/components/repeater/RepeaterTelemetryHistoryPane.tsx b/frontend/src/components/repeater/RepeaterTelemetryHistoryPane.tsx index ce8363b..8286018 100644 --- a/frontend/src/components/repeater/RepeaterTelemetryHistoryPane.tsx +++ b/frontend/src/components/repeater/RepeaterTelemetryHistoryPane.tsx @@ -11,7 +11,8 @@ import { import { cn } from '@/lib/utils'; import { Button } from '../ui/button'; import { Separator } from '../ui/separator'; -import { LPP_UNIT_MAP } from './repeaterPaneShared'; +import { lppDisplayUnit } from './repeaterPaneShared'; +import { useDistanceUnit } from '../../contexts/DistanceUnitContext'; import type { TelemetryHistoryEntry, TelemetryLppSensor, Contact } from '../../types'; const MAX_TRACKED = 8; @@ -83,6 +84,7 @@ export function TelemetryHistoryPane({ trackedTelemetryRepeaters, onToggleTrackedTelemetry, }: TelemetryHistoryPaneProps) { + const { distanceUnit } = useDistanceUnit(); const [metric, setMetric] = useState('battery_volts'); const [toggling, setToggling] = useState(false); @@ -105,7 +107,7 @@ export function TelemetryHistoryPane({ info.type_name.charAt(0).toUpperCase() + info.type_name.slice(1).replace(/_/g, ' ') + ` Ch${info.channel}`; - const unit = LPP_UNIT_MAP[info.type_name] ?? ''; + const { unit } = lppDisplayUnit(info.type_name, 0, distanceUnit); result.push({ key: k, config: { label, unit, color: LPP_COLORS[colorIdx % LPP_COLORS.length] }, @@ -115,7 +117,7 @@ export function TelemetryHistoryPane({ colorIdx++; } return result; - }, [entries]); + }, [entries, distanceUnit]); const allMetricKeys = useMemo( () => [...BUILTIN_METRICS, ...lppMetrics.map((m) => m.key)], @@ -145,13 +147,15 @@ export function TelemetryHistoryPane({ packets_sent: d.packets_sent, uptime_seconds: d.uptime_seconds, }; - // Flatten LPP sensors into the point + // Flatten LPP sensors into the point, converting units as needed for (const s of d.lpp_sensors ?? []) { - point[lppKey(s)] = typeof s.value === 'number' ? s.value : undefined; + if (typeof s.value === 'number') { + point[lppKey(s)] = lppDisplayUnit(s.type_name, s.value, distanceUnit).value; + } } return point; }); - }, [entries]); + }, [entries, distanceUnit]); const dataKeys = activeMetric === 'packets' ? ['packets_received', 'packets_sent'] : [activeMetric]; diff --git a/frontend/src/components/repeater/repeaterPaneShared.tsx b/frontend/src/components/repeater/repeaterPaneShared.tsx index cac74d1..a3d3720 100644 --- a/frontend/src/components/repeater/repeaterPaneShared.tsx +++ b/frontend/src/components/repeater/repeaterPaneShared.tsx @@ -223,11 +223,26 @@ export const LPP_UNIT_MAP: Record = { colour: '', }; +/** + * Return the display unit and converted value for an LPP sensor, + * respecting the user's unit preference for temperature. + */ +export function lppDisplayUnit( + typeName: string, + value: number, + unitPref: 'metric' | 'imperial' | string +): { unit: string; value: number } { + if (typeName === 'temperature' && unitPref === 'imperial') { + return { unit: '°F', value: (value * 9) / 5 + 32 }; + } + return { unit: LPP_UNIT_MAP[typeName] ?? '', value }; +} + export function formatLppLabel(typeName: string): string { return typeName.charAt(0).toUpperCase() + typeName.slice(1).replace(/_/g, ' '); } -export function LppSensorRow({ sensor }: { sensor: LppSensor }) { +export function LppSensorRow({ sensor, unitPref }: { sensor: LppSensor; unitPref?: string }) { const label = formatLppLabel(sensor.type_name); if (typeof sensor.value === 'object' && sensor.value !== null) { @@ -248,10 +263,10 @@ export function LppSensorRow({ sensor }: { sensor: LppSensor }) { ); } - const unit = LPP_UNIT_MAP[sensor.type_name] ?? ''; + const display = lppDisplayUnit(sensor.type_name, sensor.value as number, unitPref ?? 'metric'); const formatted = typeof sensor.value === 'number' - ? `${sensor.value % 1 === 0 ? sensor.value : sensor.value.toFixed(2)}${unit ? ` ${unit}` : ''}` + ? `${display.value % 1 === 0 ? display.value : display.value.toFixed(2)}${display.unit ? ` ${display.unit}` : ''}` : String(sensor.value); return ; diff --git a/frontend/src/components/settings/SettingsDatabaseSection.tsx b/frontend/src/components/settings/SettingsDatabaseSection.tsx index ae40810..59e3a37 100644 --- a/frontend/src/components/settings/SettingsDatabaseSection.tsx +++ b/frontend/src/components/settings/SettingsDatabaseSection.tsx @@ -6,7 +6,8 @@ import { Separator } from '../ui/separator'; import { toast } from '../ui/sonner'; import { api } from '../../api'; import { formatTime } from '../../utils/messageParser'; -import { LPP_UNIT_MAP } from '../repeater/repeaterPaneShared'; +import { lppDisplayUnit } from '../repeater/repeaterPaneShared'; +import { useDistanceUnit } from '../../contexts/DistanceUnitContext'; import { BulkDeleteContactsModal } from './BulkDeleteContactsModal'; import type { AppSettings, @@ -45,6 +46,7 @@ export function SettingsDatabaseSection({ onToggleTrackedTelemetry?: (publicKey: string) => Promise; className?: string; }) { + const { distanceUnit } = useDistanceUnit(); const [retentionDays, setRetentionDays] = useState('14'); const [cleaning, setCleaning] = useState(false); const [purgingDecryptedRaw, setPurgingDecryptedRaw] = useState(false); @@ -310,18 +312,18 @@ export function SettingsDatabaseSection({ tx {d.packets_sent != null ? d.packets_sent.toLocaleString() : '?'} {d.lpp_sensors?.map((s) => { - const unit = LPP_UNIT_MAP[s.type_name] ?? ''; + const display = lppDisplayUnit(s.type_name, s.value, distanceUnit); const val = - typeof s.value === 'number' - ? s.value % 1 === 0 - ? s.value - : s.value.toFixed(1) - : s.value; + typeof display.value === 'number' + ? display.value % 1 === 0 + ? display.value + : display.value.toFixed(1) + : display.value; const label = s.type_name.charAt(0).toUpperCase() + s.type_name.slice(1); return ( {label} {val} - {unit ? ` ${unit}` : ''} + {display.unit ? ` ${display.unit}` : ''} ); })}