feat(weather-widget): add imperial windspeed option (#4253)

This commit is contained in:
Meier Lukas
2025-10-10 19:59:05 +02:00
committed by GitHub
parent 6d0a1452a6
commit 50a23d76e3
6 changed files with 44 additions and 6 deletions

View File

@@ -47,3 +47,8 @@ export const humanFileSize = (size: number, concat = ""): string => {
}
return "∞";
};
const IMPERIAL_MULTIPLIER = 1.609344;
export const metricToImperial = (metricValue: number) => metricValue / IMPERIAL_MULTIPLIER;
export const imperialToMetric = (imperialValue: number) => imperialValue * IMPERIAL_MULTIPLIER;

View File

@@ -88,6 +88,7 @@ const optionMapping: OptionMapping = {
location: (oldOptions) => oldOptions.location,
showCity: (oldOptions) => oldOptions.displayCityName,
dateFormat: (oldOptions) => (oldOptions.dateFormat === "hide" ? undefined : oldOptions.dateFormat),
useImperialSpeed: () => undefined,
},
iframe: {
embedUrl: (oldOptions) => oldOptions.embedUrl,

View File

@@ -1145,6 +1145,12 @@
"groupNameTaken": "Group name already taken"
}
}
},
"unit": {
"speed": {
"kilometersPerHour": "km/h",
"milesPerHour": "mph"
}
}
},
"section": {
@@ -1744,6 +1750,9 @@
"label": "Show current wind speed",
"description": "Only on current weather"
},
"useImperialSpeed": {
"label": "Use mph for windspeed"
},
"location": {
"label": "Weather location"
},
@@ -1762,12 +1771,12 @@
"description": "How the date should look like"
}
},
"currentWindSpeed": "{currentWindSpeed} km/h",
"currentWindSpeed": "{currentWindSpeed} {unit}",
"dailyForecast": {
"sunrise": "Sunrise",
"sunset": "Sunset",
"maxWindSpeed": "Max wind speed: {maxWindSpeed} km/h",
"maxWindGusts": "Max wind gusts: {maxWindGusts} km/h"
"maxWindSpeed": "Max wind speed: {maxWindSpeed} {unit}",
"maxWindGusts": "Max wind gusts: {maxWindGusts} {unit}"
},
"kind": {
"clear": "Clear",

View File

@@ -7,6 +7,7 @@ import dayjs from "dayjs";
import type { RouterOutputs } from "@homarr/api";
import { clientApi } from "@homarr/api/client";
import { metricToImperial } from "@homarr/common";
import { useScopedI18n } from "@homarr/translation/client";
import type { WidgetComponentProps } from "../definition";
@@ -52,6 +53,7 @@ interface WeatherProps extends Pick<WidgetComponentProps<"weather">, "options">
const DailyWeather = ({ options, weather }: WeatherProps) => {
const t = useScopedI18n("widget.weather");
const tCommon = useScopedI18n("common");
return (
<>
@@ -78,7 +80,17 @@ const DailyWeather = ({ options, weather }: WeatherProps) => {
{options.showCurrentWindSpeed && (
<Group className="weather-current-wind-speed-group" wrap="nowrap" gap="xs">
<IconWind size={16} />
<Text fz={16}>{t("currentWindSpeed", { currentWindSpeed: String(weather.current.windspeed) })}</Text>
<Text fz={16}>
{t("currentWindSpeed", {
currentWindSpeed: (options.useImperialSpeed
? metricToImperial(weather.current.windspeed)
: weather.current.windspeed
).toFixed(1),
unit: options.useImperialSpeed
? tCommon("unit.speed.milesPerHour")
: tCommon("unit.speed.kilometersPerHour"),
})}
</Text>
</Group>
)}
<Group className="weather-max-min-temp-group" wrap="nowrap" gap="sm">
@@ -180,6 +192,7 @@ function Forecast({ weather, options }: WeatherProps) {
</HoverCard.Target>
<HoverCard.Dropdown>
<WeatherDescription
useImperialSpeed={options.useImperialSpeed}
dateFormat={dateFormat}
time={dayWeather.time}
weatherCode={dayWeather.weatherCode}

View File

@@ -15,6 +15,7 @@ import {
} from "@tabler/icons-react";
import dayjs from "dayjs";
import { metricToImperial } from "@homarr/common";
import type { TranslationObject } from "@homarr/translation";
import { useScopedI18n } from "@homarr/translation/client";
import type { TablerIcon } from "@homarr/ui";
@@ -40,6 +41,7 @@ export const WeatherIcon = ({ code, size = 50 }: WeatherIconProps) => {
interface WeatherDescriptionProps {
weatherOnly?: boolean;
useImperialSpeed?: boolean;
dateFormat?: WidgetProps<"weather">["options"]["dateFormat"];
time?: string;
weatherCode: number;
@@ -66,6 +68,7 @@ interface WeatherDescriptionProps {
*/
export const WeatherDescription = ({
weatherOnly,
useImperialSpeed,
dateFormat,
time,
weatherCode,
@@ -96,12 +99,18 @@ export const WeatherDescription = ({
<List.Item icon={<IconMoon size={15} />}>{`${t("dailyForecast.sunset")}: ${sunset}`}</List.Item>
{maxWindSpeed !== undefined && (
<List.Item icon={<IconWind size={15} />}>
{t("dailyForecast.maxWindSpeed", { maxWindSpeed: String(maxWindSpeed) })}
{t("dailyForecast.maxWindSpeed", {
maxWindSpeed: (useImperialSpeed ? metricToImperial(maxWindSpeed) : maxWindSpeed).toFixed(1),
unit: useImperialSpeed ? tCommon("unit.speed.milesPerHour") : tCommon("unit.speed.kilometersPerHour"),
})}
</List.Item>
)}
{maxWindGusts !== undefined && (
<List.Item icon={<IconWind size={15} />}>
{t("dailyForecast.maxWindGusts", { maxWindGusts: String(maxWindGusts) })}
{t("dailyForecast.maxWindGusts", {
maxWindGusts: (useImperialSpeed ? metricToImperial(maxWindGusts) : maxWindGusts).toFixed(1),
unit: useImperialSpeed ? tCommon("unit.speed.milesPerHour") : tCommon("unit.speed.kilometersPerHour"),
})}
</List.Item>
)}
</List>

View File

@@ -13,6 +13,7 @@ export const { definition, componentLoader } = createWidgetDefinition("weather",
isFormatFahrenheit: factory.switch(),
disableTemperatureDecimals: factory.switch(),
showCurrentWindSpeed: factory.switch({ withDescription: true }),
useImperialSpeed: factory.switch(),
location: factory.location({
defaultValue: {
name: "Paris",