mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-15 07:35:27 +03:00
Handle time range in am/pm based on browser
This commit is contained in:
parent
28d2f72a96
commit
ce2bb45c55
@ -17,6 +17,8 @@ import {
|
|||||||
SearchFilter,
|
SearchFilter,
|
||||||
SearchFilters,
|
SearchFilters,
|
||||||
SearchSource,
|
SearchSource,
|
||||||
|
DEFAULT_TIME_RANGE_AFTER,
|
||||||
|
DEFAULT_TIME_RANGE_BEFORE,
|
||||||
} from "@/types/search";
|
} from "@/types/search";
|
||||||
import { DateRange } from "react-day-picker";
|
import { DateRange } from "react-day-picker";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
@ -26,6 +28,7 @@ import { MdLabel } from "react-icons/md";
|
|||||||
import SearchSourceIcon from "../icons/SearchSourceIcon";
|
import SearchSourceIcon from "../icons/SearchSourceIcon";
|
||||||
import PlatformAwareDialog from "../overlay/dialog/PlatformAwareDialog";
|
import PlatformAwareDialog from "../overlay/dialog/PlatformAwareDialog";
|
||||||
import { FaArrowRight, FaClock } from "react-icons/fa";
|
import { FaArrowRight, FaClock } from "react-icons/fa";
|
||||||
|
import { useFormattedHour } from "@/hooks/use-date-utils";
|
||||||
|
|
||||||
type SearchFilterGroupProps = {
|
type SearchFilterGroupProps = {
|
||||||
className: string;
|
className: string;
|
||||||
@ -172,6 +175,7 @@ export default function SearchFilterGroup({
|
|||||||
)}
|
)}
|
||||||
{filters.includes("time") && (
|
{filters.includes("time") && (
|
||||||
<TimeRangeFilterButton
|
<TimeRangeFilterButton
|
||||||
|
config={config}
|
||||||
timeRange={filter?.time_range}
|
timeRange={filter?.time_range}
|
||||||
updateTimeRange={(time_range) =>
|
updateTimeRange={(time_range) =>
|
||||||
onUpdateFilter({ ...filter, time_range })
|
onUpdateFilter({ ...filter, time_range })
|
||||||
@ -395,10 +399,12 @@ export function GeneralFilterContent({
|
|||||||
}
|
}
|
||||||
|
|
||||||
type TimeRangeFilterButtonProps = {
|
type TimeRangeFilterButtonProps = {
|
||||||
|
config?: FrigateConfig;
|
||||||
timeRange?: string;
|
timeRange?: string;
|
||||||
updateTimeRange: (range: string | undefined) => void;
|
updateTimeRange: (range: string | undefined) => void;
|
||||||
};
|
};
|
||||||
function TimeRangeFilterButton({
|
function TimeRangeFilterButton({
|
||||||
|
config,
|
||||||
timeRange,
|
timeRange,
|
||||||
updateTimeRange,
|
updateTimeRange,
|
||||||
}: TimeRangeFilterButtonProps) {
|
}: TimeRangeFilterButtonProps) {
|
||||||
@ -408,7 +414,7 @@ function TimeRangeFilterButton({
|
|||||||
|
|
||||||
const [afterHour, beforeHour] = useMemo(() => {
|
const [afterHour, beforeHour] = useMemo(() => {
|
||||||
if (!timeRange || !timeRange.includes(",")) {
|
if (!timeRange || !timeRange.includes(",")) {
|
||||||
return ["00:00", "24:00"];
|
return [DEFAULT_TIME_RANGE_AFTER, DEFAULT_TIME_RANGE_BEFORE];
|
||||||
}
|
}
|
||||||
|
|
||||||
return timeRange.split(",");
|
return timeRange.split(",");
|
||||||
@ -417,6 +423,13 @@ function TimeRangeFilterButton({
|
|||||||
const [selectedAfterHour, setSelectedAfterHour] = useState(afterHour);
|
const [selectedAfterHour, setSelectedAfterHour] = useState(afterHour);
|
||||||
const [selectedBeforeHour, setSelectedBeforeHour] = useState(beforeHour);
|
const [selectedBeforeHour, setSelectedBeforeHour] = useState(beforeHour);
|
||||||
|
|
||||||
|
// format based on locale
|
||||||
|
|
||||||
|
const formattedAfter = useFormattedHour(config, afterHour);
|
||||||
|
const formattedBefore = useFormattedHour(config, beforeHour);
|
||||||
|
const formattedSelectedAfter = useFormattedHour(config, selectedAfterHour);
|
||||||
|
const formattedSelectedBefore = useFormattedHour(config, selectedBeforeHour);
|
||||||
|
|
||||||
const trigger = (
|
const trigger = (
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
@ -429,7 +442,7 @@ function TimeRangeFilterButton({
|
|||||||
<div
|
<div
|
||||||
className={`${timeRange ? "text-selected-foreground" : "text-primary"}`}
|
className={`${timeRange ? "text-selected-foreground" : "text-primary"}`}
|
||||||
>
|
>
|
||||||
{timeRange ? `${afterHour} - ${beforeHour}` : "All Times"}
|
{timeRange ? `${formattedAfter} - ${formattedBefore}` : "All Times"}
|
||||||
</div>
|
</div>
|
||||||
</Button>
|
</Button>
|
||||||
);
|
);
|
||||||
@ -456,7 +469,7 @@ function TimeRangeFilterButton({
|
|||||||
setEndOpen(false);
|
setEndOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedAfterHour}
|
{formattedSelectedAfter}
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="flex flex-col items-center">
|
<PopoverContent className="flex flex-col items-center">
|
||||||
@ -493,7 +506,7 @@ function TimeRangeFilterButton({
|
|||||||
setStartOpen(false);
|
setStartOpen(false);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{selectedBeforeHour}
|
{formattedSelectedBefore}
|
||||||
</Button>
|
</Button>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="flex flex-col items-center">
|
<PopoverContent className="flex flex-col items-center">
|
||||||
@ -519,7 +532,10 @@ function TimeRangeFilterButton({
|
|||||||
<Button
|
<Button
|
||||||
variant="select"
|
variant="select"
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
if (selectedAfterHour == "00:00" && selectedBeforeHour == "24:00") {
|
if (
|
||||||
|
selectedAfterHour == DEFAULT_TIME_RANGE_AFTER &&
|
||||||
|
selectedBeforeHour == DEFAULT_TIME_RANGE_BEFORE
|
||||||
|
) {
|
||||||
updateTimeRange(undefined);
|
updateTimeRange(undefined);
|
||||||
} else {
|
} else {
|
||||||
updateTimeRange(`${selectedAfterHour},${selectedBeforeHour}`);
|
updateTimeRange(`${selectedAfterHour},${selectedBeforeHour}`);
|
||||||
@ -532,8 +548,8 @@ function TimeRangeFilterButton({
|
|||||||
</Button>
|
</Button>
|
||||||
<Button
|
<Button
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSelectedAfterHour("00:00");
|
setSelectedAfterHour(DEFAULT_TIME_RANGE_AFTER);
|
||||||
setSelectedBeforeHour("24:00");
|
setSelectedBeforeHour(DEFAULT_TIME_RANGE_BEFORE);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
Reset
|
Reset
|
||||||
|
|||||||
@ -43,3 +43,49 @@ export function useTimezone(config: FrigateConfig | undefined) {
|
|||||||
);
|
);
|
||||||
}, [config]);
|
}, [config]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function use24HourTime(config: FrigateConfig | undefined) {
|
||||||
|
const localeUses24HourTime = useMemo(
|
||||||
|
() =>
|
||||||
|
new Intl.DateTimeFormat(undefined, {
|
||||||
|
hour: "numeric",
|
||||||
|
})
|
||||||
|
?.formatToParts(new Date(2020, 0, 1, 13))
|
||||||
|
?.find((part) => part.type === "hour")?.value?.length === 2,
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
if (!config) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config.ui.time_format != "browser") {
|
||||||
|
return config.ui.time_format == "24hour";
|
||||||
|
}
|
||||||
|
|
||||||
|
return localeUses24HourTime;
|
||||||
|
}, [config, localeUses24HourTime]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useFormattedHour(
|
||||||
|
config: FrigateConfig | undefined,
|
||||||
|
time: string, // hour is assumed to be in 24 hour format per the Date object
|
||||||
|
) {
|
||||||
|
const hour24 = use24HourTime(config);
|
||||||
|
|
||||||
|
return useMemo(() => {
|
||||||
|
if (hour24) {
|
||||||
|
return time;
|
||||||
|
}
|
||||||
|
|
||||||
|
const [hour, minute] = time.includes(":") ? time.split(":") : [time, "00"];
|
||||||
|
const hourNum = parseInt(hour);
|
||||||
|
|
||||||
|
if (hourNum < 12) {
|
||||||
|
return `${hourNum}:${minute} AM`;
|
||||||
|
} else {
|
||||||
|
return `${hourNum - 12}:${minute} PM`;
|
||||||
|
}
|
||||||
|
}, [hour24, time]);
|
||||||
|
}
|
||||||
|
|||||||
@ -61,6 +61,9 @@ export type SearchFilter = {
|
|||||||
event_id?: string;
|
event_id?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const DEFAULT_TIME_RANGE_AFTER = "00:00";
|
||||||
|
export const DEFAULT_TIME_RANGE_BEFORE = "23:59";
|
||||||
|
|
||||||
export type SearchQueryParams = {
|
export type SearchQueryParams = {
|
||||||
cameras?: string[];
|
cameras?: string[];
|
||||||
labels?: string[];
|
labels?: string[];
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user