feat(weather-widget): add imperial windspeed option (#4253)
This commit is contained in:
@@ -47,3 +47,8 @@ export const humanFileSize = (size: number, concat = ""): string => {
|
|||||||
}
|
}
|
||||||
return "∞";
|
return "∞";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const IMPERIAL_MULTIPLIER = 1.609344;
|
||||||
|
|
||||||
|
export const metricToImperial = (metricValue: number) => metricValue / IMPERIAL_MULTIPLIER;
|
||||||
|
export const imperialToMetric = (imperialValue: number) => imperialValue * IMPERIAL_MULTIPLIER;
|
||||||
|
|||||||
@@ -88,6 +88,7 @@ const optionMapping: OptionMapping = {
|
|||||||
location: (oldOptions) => oldOptions.location,
|
location: (oldOptions) => oldOptions.location,
|
||||||
showCity: (oldOptions) => oldOptions.displayCityName,
|
showCity: (oldOptions) => oldOptions.displayCityName,
|
||||||
dateFormat: (oldOptions) => (oldOptions.dateFormat === "hide" ? undefined : oldOptions.dateFormat),
|
dateFormat: (oldOptions) => (oldOptions.dateFormat === "hide" ? undefined : oldOptions.dateFormat),
|
||||||
|
useImperialSpeed: () => undefined,
|
||||||
},
|
},
|
||||||
iframe: {
|
iframe: {
|
||||||
embedUrl: (oldOptions) => oldOptions.embedUrl,
|
embedUrl: (oldOptions) => oldOptions.embedUrl,
|
||||||
|
|||||||
@@ -1145,6 +1145,12 @@
|
|||||||
"groupNameTaken": "Group name already taken"
|
"groupNameTaken": "Group name already taken"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"unit": {
|
||||||
|
"speed": {
|
||||||
|
"kilometersPerHour": "km/h",
|
||||||
|
"milesPerHour": "mph"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"section": {
|
"section": {
|
||||||
@@ -1744,6 +1750,9 @@
|
|||||||
"label": "Show current wind speed",
|
"label": "Show current wind speed",
|
||||||
"description": "Only on current weather"
|
"description": "Only on current weather"
|
||||||
},
|
},
|
||||||
|
"useImperialSpeed": {
|
||||||
|
"label": "Use mph for windspeed"
|
||||||
|
},
|
||||||
"location": {
|
"location": {
|
||||||
"label": "Weather location"
|
"label": "Weather location"
|
||||||
},
|
},
|
||||||
@@ -1762,12 +1771,12 @@
|
|||||||
"description": "How the date should look like"
|
"description": "How the date should look like"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"currentWindSpeed": "{currentWindSpeed} km/h",
|
"currentWindSpeed": "{currentWindSpeed} {unit}",
|
||||||
"dailyForecast": {
|
"dailyForecast": {
|
||||||
"sunrise": "Sunrise",
|
"sunrise": "Sunrise",
|
||||||
"sunset": "Sunset",
|
"sunset": "Sunset",
|
||||||
"maxWindSpeed": "Max wind speed: {maxWindSpeed} km/h",
|
"maxWindSpeed": "Max wind speed: {maxWindSpeed} {unit}",
|
||||||
"maxWindGusts": "Max wind gusts: {maxWindGusts} km/h"
|
"maxWindGusts": "Max wind gusts: {maxWindGusts} {unit}"
|
||||||
},
|
},
|
||||||
"kind": {
|
"kind": {
|
||||||
"clear": "Clear",
|
"clear": "Clear",
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import dayjs from "dayjs";
|
|||||||
|
|
||||||
import type { RouterOutputs } from "@homarr/api";
|
import type { RouterOutputs } from "@homarr/api";
|
||||||
import { clientApi } from "@homarr/api/client";
|
import { clientApi } from "@homarr/api/client";
|
||||||
|
import { metricToImperial } from "@homarr/common";
|
||||||
import { useScopedI18n } from "@homarr/translation/client";
|
import { useScopedI18n } from "@homarr/translation/client";
|
||||||
|
|
||||||
import type { WidgetComponentProps } from "../definition";
|
import type { WidgetComponentProps } from "../definition";
|
||||||
@@ -52,6 +53,7 @@ interface WeatherProps extends Pick<WidgetComponentProps<"weather">, "options">
|
|||||||
|
|
||||||
const DailyWeather = ({ options, weather }: WeatherProps) => {
|
const DailyWeather = ({ options, weather }: WeatherProps) => {
|
||||||
const t = useScopedI18n("widget.weather");
|
const t = useScopedI18n("widget.weather");
|
||||||
|
const tCommon = useScopedI18n("common");
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -78,7 +80,17 @@ const DailyWeather = ({ options, weather }: WeatherProps) => {
|
|||||||
{options.showCurrentWindSpeed && (
|
{options.showCurrentWindSpeed && (
|
||||||
<Group className="weather-current-wind-speed-group" wrap="nowrap" gap="xs">
|
<Group className="weather-current-wind-speed-group" wrap="nowrap" gap="xs">
|
||||||
<IconWind size={16} />
|
<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>
|
||||||
)}
|
)}
|
||||||
<Group className="weather-max-min-temp-group" wrap="nowrap" gap="sm">
|
<Group className="weather-max-min-temp-group" wrap="nowrap" gap="sm">
|
||||||
@@ -180,6 +192,7 @@ function Forecast({ weather, options }: WeatherProps) {
|
|||||||
</HoverCard.Target>
|
</HoverCard.Target>
|
||||||
<HoverCard.Dropdown>
|
<HoverCard.Dropdown>
|
||||||
<WeatherDescription
|
<WeatherDescription
|
||||||
|
useImperialSpeed={options.useImperialSpeed}
|
||||||
dateFormat={dateFormat}
|
dateFormat={dateFormat}
|
||||||
time={dayWeather.time}
|
time={dayWeather.time}
|
||||||
weatherCode={dayWeather.weatherCode}
|
weatherCode={dayWeather.weatherCode}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from "@tabler/icons-react";
|
} from "@tabler/icons-react";
|
||||||
import dayjs from "dayjs";
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
|
import { metricToImperial } from "@homarr/common";
|
||||||
import type { TranslationObject } from "@homarr/translation";
|
import type { TranslationObject } from "@homarr/translation";
|
||||||
import { useScopedI18n } from "@homarr/translation/client";
|
import { useScopedI18n } from "@homarr/translation/client";
|
||||||
import type { TablerIcon } from "@homarr/ui";
|
import type { TablerIcon } from "@homarr/ui";
|
||||||
@@ -40,6 +41,7 @@ export const WeatherIcon = ({ code, size = 50 }: WeatherIconProps) => {
|
|||||||
|
|
||||||
interface WeatherDescriptionProps {
|
interface WeatherDescriptionProps {
|
||||||
weatherOnly?: boolean;
|
weatherOnly?: boolean;
|
||||||
|
useImperialSpeed?: boolean;
|
||||||
dateFormat?: WidgetProps<"weather">["options"]["dateFormat"];
|
dateFormat?: WidgetProps<"weather">["options"]["dateFormat"];
|
||||||
time?: string;
|
time?: string;
|
||||||
weatherCode: number;
|
weatherCode: number;
|
||||||
@@ -66,6 +68,7 @@ interface WeatherDescriptionProps {
|
|||||||
*/
|
*/
|
||||||
export const WeatherDescription = ({
|
export const WeatherDescription = ({
|
||||||
weatherOnly,
|
weatherOnly,
|
||||||
|
useImperialSpeed,
|
||||||
dateFormat,
|
dateFormat,
|
||||||
time,
|
time,
|
||||||
weatherCode,
|
weatherCode,
|
||||||
@@ -96,12 +99,18 @@ export const WeatherDescription = ({
|
|||||||
<List.Item icon={<IconMoon size={15} />}>{`${t("dailyForecast.sunset")}: ${sunset}`}</List.Item>
|
<List.Item icon={<IconMoon size={15} />}>{`${t("dailyForecast.sunset")}: ${sunset}`}</List.Item>
|
||||||
{maxWindSpeed !== undefined && (
|
{maxWindSpeed !== undefined && (
|
||||||
<List.Item icon={<IconWind size={15} />}>
|
<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>
|
</List.Item>
|
||||||
)}
|
)}
|
||||||
{maxWindGusts !== undefined && (
|
{maxWindGusts !== undefined && (
|
||||||
<List.Item icon={<IconWind size={15} />}>
|
<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.Item>
|
||||||
)}
|
)}
|
||||||
</List>
|
</List>
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export const { definition, componentLoader } = createWidgetDefinition("weather",
|
|||||||
isFormatFahrenheit: factory.switch(),
|
isFormatFahrenheit: factory.switch(),
|
||||||
disableTemperatureDecimals: factory.switch(),
|
disableTemperatureDecimals: factory.switch(),
|
||||||
showCurrentWindSpeed: factory.switch({ withDescription: true }),
|
showCurrentWindSpeed: factory.switch({ withDescription: true }),
|
||||||
|
useImperialSpeed: factory.switch(),
|
||||||
location: factory.location({
|
location: factory.location({
|
||||||
defaultValue: {
|
defaultValue: {
|
||||||
name: "Paris",
|
name: "Paris",
|
||||||
|
|||||||
Reference in New Issue
Block a user