mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-08-02 17:12:16 +03:00
Fix browser time format handling (#22694)
* implement hook to return resolved "24hour" | "12hour" string delegate to existing use24HourTime(), which correctly detects the browser's locale preference via Intl.DateTimeFormat * update frontend to use use24HourTime(config) or useTimeFormat(config) instead of directly comparing config.ui.time_format
This commit is contained in:
@@ -19,7 +19,7 @@ import { useResizeObserver } from "@/hooks/resize-observer";
|
||||
import { Skeleton } from "@/components/ui/skeleton";
|
||||
import ActivityIndicator from "@/components/indicators/activity-indicator";
|
||||
import TimeAgo from "@/components/dynamic/TimeAgo";
|
||||
import { useFormattedTimestamp } from "@/hooks/use-date-utils";
|
||||
import { useFormattedTimestamp, use24HourTime } from "@/hooks/use-date-utils";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
|
||||
const MOTION_HEATMAP_GRID_SIZE = 16;
|
||||
@@ -165,9 +165,10 @@ function MotionPreviewClip({
|
||||
const [fallbackFrameIndex, setFallbackFrameIndex] = useState(0);
|
||||
const [fallbackFramesReady, setFallbackFramesReady] = useState(false);
|
||||
|
||||
const is24Hour = use24HourTime(config);
|
||||
const formattedDate = useFormattedTimestamp(
|
||||
range.start_time,
|
||||
config?.ui.time_format == "24hour"
|
||||
is24Hour
|
||||
? t("time.formattedTimestampMonthDayHourMinute.24hour", {
|
||||
ns: "common",
|
||||
})
|
||||
|
||||
@@ -43,8 +43,9 @@ import { TimezoneAwareCalendar } from "@/components/overlay/ReviewActivityCalend
|
||||
|
||||
import { useApiHost } from "@/api";
|
||||
import { useResizeObserver } from "@/hooks/resize-observer";
|
||||
import { useFormattedTimestamp } from "@/hooks/use-date-utils";
|
||||
import { useFormattedTimestamp, use24HourTime } from "@/hooks/use-date-utils";
|
||||
import { getUTCOffset } from "@/utils/dateUtil";
|
||||
import useSWR from "swr";
|
||||
import { cn } from "@/lib/utils";
|
||||
import MotionSearchROICanvas from "./MotionSearchROICanvas";
|
||||
import { TransformComponent, TransformWrapper } from "react-zoom-pan-pinch";
|
||||
@@ -452,7 +453,6 @@ export default function MotionSearchDialog({
|
||||
range={searchRange}
|
||||
setRange={setSearchRange}
|
||||
defaultRange={defaultRange}
|
||||
timeFormat={config.ui?.time_format}
|
||||
timezone={timezone}
|
||||
/>
|
||||
|
||||
@@ -476,7 +476,6 @@ type SearchRangeSelectorProps = {
|
||||
range?: TimeRange;
|
||||
setRange: React.Dispatch<React.SetStateAction<TimeRange | undefined>>;
|
||||
defaultRange: TimeRange;
|
||||
timeFormat?: "browser" | "12hour" | "24hour";
|
||||
timezone?: string;
|
||||
};
|
||||
|
||||
@@ -484,7 +483,6 @@ function SearchRangeSelector({
|
||||
range,
|
||||
setRange,
|
||||
defaultRange,
|
||||
timeFormat,
|
||||
timezone,
|
||||
}: SearchRangeSelectorProps) {
|
||||
const { t } = useTranslation(["views/motionSearch", "common"]);
|
||||
@@ -527,15 +525,18 @@ function SearchRangeSelector({
|
||||
return time;
|
||||
}, [range, defaultRange, timezoneOffset, localTimeOffset]);
|
||||
|
||||
const { data: config } = useSWR<FrigateConfig>("config");
|
||||
const is24Hour = use24HourTime(config);
|
||||
|
||||
const formattedStart = useFormattedTimestamp(
|
||||
startTime,
|
||||
timeFormat === "24hour"
|
||||
is24Hour
|
||||
? t("time.formattedTimestamp.24hour", { ns: "common" })
|
||||
: t("time.formattedTimestamp.12hour", { ns: "common" }),
|
||||
);
|
||||
const formattedEnd = useFormattedTimestamp(
|
||||
endTime,
|
||||
timeFormat === "24hour"
|
||||
is24Hour
|
||||
? t("time.formattedTimestamp.24hour", { ns: "common" })
|
||||
: t("time.formattedTimestamp.12hour", { ns: "common" }),
|
||||
);
|
||||
|
||||
@@ -51,7 +51,7 @@ import {
|
||||
RecordingSegment,
|
||||
} from "@/types/record";
|
||||
import { VideoResolutionType } from "@/types/live";
|
||||
import { useFormattedTimestamp } from "@/hooks/use-date-utils";
|
||||
import { useFormattedTimestamp, use24HourTime } from "@/hooks/use-date-utils";
|
||||
import MotionSearchROICanvas from "./MotionSearchROICanvas";
|
||||
import MotionSearchDialog from "./MotionSearchDialog";
|
||||
import { IoMdArrowRoundBack } from "react-icons/io";
|
||||
@@ -94,12 +94,13 @@ export default function MotionSearchView({
|
||||
]);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const is24Hour = use24HourTime(config);
|
||||
const resultTimestampFormat = useMemo(
|
||||
() =>
|
||||
config.ui?.time_format === "24hour"
|
||||
is24Hour
|
||||
? t("time.formattedTimestamp.24hour", { ns: "common" })
|
||||
: t("time.formattedTimestamp.12hour", { ns: "common" }),
|
||||
[config.ui?.time_format, t],
|
||||
[is24Hour, t],
|
||||
);
|
||||
|
||||
// Refs
|
||||
|
||||
@@ -31,6 +31,7 @@ import Chip from "@/components/indicators/Chip";
|
||||
import { TooltipPortal } from "@radix-ui/react-tooltip";
|
||||
import SearchActionGroup from "@/components/filter/SearchActionGroup";
|
||||
import { Trans, useTranslation } from "react-i18next";
|
||||
import { use24HourTime } from "@/hooks/use-date-utils";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { useAllowedCameras } from "@/hooks/use-allowed-cameras";
|
||||
|
||||
@@ -77,6 +78,7 @@ export default function SearchView({
|
||||
const { data: config } = useSWR<FrigateConfig>("config", {
|
||||
revalidateOnFocus: false,
|
||||
});
|
||||
const is24Hour = use24HourTime(config);
|
||||
const navigate = useNavigate();
|
||||
|
||||
const { data: exploreEvents } = useSWR<SearchResult[]>(
|
||||
@@ -191,10 +193,7 @@ export default function SearchView({
|
||||
sub_labels: allSubLabels,
|
||||
...(hasCustomClassificationModels && { attributes: allAttributes }),
|
||||
search_type: ["thumbnail", "description"] as SearchSource[],
|
||||
time_range:
|
||||
config?.ui.time_format == "24hour"
|
||||
? ["00:00-23:59"]
|
||||
: ["12:00AM-11:59PM"],
|
||||
time_range: is24Hour ? ["00:00-23:59"] : ["12:00AM-11:59PM"],
|
||||
before: [formatDateToLocaleString()],
|
||||
after: [formatDateToLocaleString(-5)],
|
||||
min_score: ["50"],
|
||||
@@ -209,6 +208,7 @@ export default function SearchView({
|
||||
}),
|
||||
[
|
||||
config,
|
||||
is24Hour,
|
||||
allLabels,
|
||||
allZones,
|
||||
allSubLabels,
|
||||
|
||||
@@ -39,6 +39,7 @@ import { Trigger, TriggerAction, TriggerType } from "@/types/trigger";
|
||||
import { useSearchEffect } from "@/hooks/use-overlay-state";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { formatUnixTimestampToDateTime } from "@/utils/dateUtil";
|
||||
import { use24HourTime } from "@/hooks/use-date-utils";
|
||||
import { Link } from "react-router-dom";
|
||||
import { useTriggers } from "@/api/ws";
|
||||
import { useCameraFriendlyName } from "@/hooks/use-camera-friendly-name";
|
||||
@@ -89,6 +90,7 @@ export default function TriggerView({
|
||||
const { t } = useTranslation("views/settings");
|
||||
const { data: config, mutate: updateConfig } =
|
||||
useSWR<FrigateConfig>("config");
|
||||
const is24Hour = use24HourTime(config);
|
||||
const { data: trigger_status, mutate } = useSWR(
|
||||
config?.cameras[selectedCamera]?.semantic_search?.triggers &&
|
||||
Object.keys(config.cameras[selectedCamera].semantic_search.triggers)
|
||||
@@ -581,20 +583,19 @@ export default function TriggerView({
|
||||
?.last_triggered,
|
||||
{
|
||||
timezone: config.ui.timezone,
|
||||
date_format:
|
||||
config.ui.time_format == "24hour"
|
||||
? t(
|
||||
"time.formattedTimestamp2.24hour",
|
||||
{
|
||||
ns: "common",
|
||||
},
|
||||
)
|
||||
: t(
|
||||
"time.formattedTimestamp2.12hour",
|
||||
{
|
||||
ns: "common",
|
||||
},
|
||||
),
|
||||
date_format: is24Hour
|
||||
? t(
|
||||
"time.formattedTimestamp2.24hour",
|
||||
{
|
||||
ns: "common",
|
||||
},
|
||||
)
|
||||
: t(
|
||||
"time.formattedTimestamp2.12hour",
|
||||
{
|
||||
ns: "common",
|
||||
},
|
||||
),
|
||||
time_style: "medium",
|
||||
date_style: "medium",
|
||||
},
|
||||
@@ -742,20 +743,19 @@ export default function TriggerView({
|
||||
?.last_triggered,
|
||||
{
|
||||
timezone: config.ui.timezone,
|
||||
date_format:
|
||||
config.ui.time_format == "24hour"
|
||||
? t(
|
||||
"time.formattedTimestamp2.24hour",
|
||||
{
|
||||
ns: "common",
|
||||
},
|
||||
)
|
||||
: t(
|
||||
"time.formattedTimestamp2.12hour",
|
||||
{
|
||||
ns: "common",
|
||||
},
|
||||
),
|
||||
date_format: is24Hour
|
||||
? t(
|
||||
"time.formattedTimestamp2.24hour",
|
||||
{
|
||||
ns: "common",
|
||||
},
|
||||
)
|
||||
: t(
|
||||
"time.formattedTimestamp2.12hour",
|
||||
{
|
||||
ns: "common",
|
||||
},
|
||||
),
|
||||
time_style: "medium",
|
||||
date_style: "medium",
|
||||
},
|
||||
|
||||
@@ -10,7 +10,11 @@ import {
|
||||
import useSWR from "swr";
|
||||
import { CiCircleAlert } from "react-icons/ci";
|
||||
import { FrigateConfig } from "@/types/frigateConfig";
|
||||
import { useFormattedTimestamp, useTimezone } from "@/hooks/use-date-utils";
|
||||
import {
|
||||
useFormattedTimestamp,
|
||||
useTimeFormat,
|
||||
useTimezone,
|
||||
} from "@/hooks/use-date-utils";
|
||||
import { RecordingsSummary } from "@/types/review";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TZDate } from "react-day-picker";
|
||||
@@ -81,7 +85,7 @@ export default function StorageMetrics({
|
||||
: null;
|
||||
}, [recordingsSummary, timezone]);
|
||||
|
||||
const timeFormat = config?.ui.time_format === "24hour" ? "24hour" : "12hour";
|
||||
const timeFormat = useTimeFormat(config);
|
||||
const format = useMemo(() => {
|
||||
return t(`time.formattedTimestampMonthDayYear.${timeFormat}`, {
|
||||
ns: "common",
|
||||
|
||||
Reference in New Issue
Block a user