mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-05-09 15:05:26 +03:00
Compare commits
5 Commits
e10d816798
...
02de01261e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02de01261e | ||
|
|
8d462588fc | ||
|
|
0fb507ae3c | ||
|
|
3e83c1b0a5 | ||
|
|
390700edb8 |
@ -101,7 +101,7 @@
|
|||||||
"recording": {
|
"recording": {
|
||||||
"shareTimestamp": {
|
"shareTimestamp": {
|
||||||
"label": "Share Timestamp",
|
"label": "Share Timestamp",
|
||||||
"title": "Share Review Timestamp",
|
"title": "Share Timestamp",
|
||||||
"description": "Share a timestamped URL of current player position or choose a custom timestamp. Note that this is not a public share URL and is only accessible to users with access to Frigate and this camera.",
|
"description": "Share a timestamped URL of current player position or choose a custom timestamp. Note that this is not a public share URL and is only accessible to users with access to Frigate and this camera.",
|
||||||
"current": "Current Player Timestamp",
|
"current": "Current Player Timestamp",
|
||||||
"custom": "Custom Timestamp",
|
"custom": "Custom Timestamp",
|
||||||
|
|||||||
@ -518,12 +518,6 @@ export default function MobileReviewSettingsDrawer({
|
|||||||
content = (
|
content = (
|
||||||
<div className="w-full">
|
<div className="w-full">
|
||||||
<div className="relative h-8 w-full">
|
<div className="relative h-8 w-full">
|
||||||
<div
|
|
||||||
className="absolute left-0 text-selected"
|
|
||||||
onClick={() => setDrawerMode("select")}
|
|
||||||
>
|
|
||||||
{t("button.back", { ns: "common" })}
|
|
||||||
</div>
|
|
||||||
<div className="absolute left-1/2 -translate-x-1/2 text-muted-foreground">
|
<div className="absolute left-1/2 -translate-x-1/2 text-muted-foreground">
|
||||||
{t("recording.shareTimestamp.title", { ns: "components/dialog" })}
|
{t("recording.shareTimestamp.title", { ns: "components/dialog" })}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -16,7 +16,7 @@ import {
|
|||||||
} from "@/components/ui/popover";
|
} from "@/components/ui/popover";
|
||||||
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group";
|
||||||
import { Separator } from "@/components/ui/separator";
|
import { Separator } from "@/components/ui/separator";
|
||||||
import { useFormattedTimestamp } from "@/hooks/use-date-utils";
|
import { useFormattedTimestamp, useTimeFormat } from "@/hooks/use-date-utils";
|
||||||
import { cn } from "@/lib/utils";
|
import { cn } from "@/lib/utils";
|
||||||
import { FrigateConfig } from "@/types/frigateConfig";
|
import { FrigateConfig } from "@/types/frigateConfig";
|
||||||
import { getUTCOffset } from "@/utils/dateUtil";
|
import { getUTCOffset } from "@/utils/dateUtil";
|
||||||
@ -84,7 +84,7 @@ export default function ShareTimestampDialog({
|
|||||||
<Dialog open={open} onOpenChange={handleOpenChange}>
|
<Dialog open={open} onOpenChange={handleOpenChange}>
|
||||||
<DialogContent className="sm:rounded-lg md:rounded-2xl">
|
<DialogContent className="sm:rounded-lg md:rounded-2xl">
|
||||||
<DialogHeader>
|
<DialogHeader>
|
||||||
<DialogTitle>
|
<DialogTitle className="whitespace-nowrap">
|
||||||
{t("recording.shareTimestamp.title", { ns: "components/dialog" })}
|
{t("recording.shareTimestamp.title", { ns: "components/dialog" })}
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<DialogDescription className="sr-only">
|
<DialogDescription className="sr-only">
|
||||||
@ -120,9 +120,10 @@ export function ShareTimestampContent({
|
|||||||
}: Readonly<ShareTimestampContentProps>) {
|
}: Readonly<ShareTimestampContentProps>) {
|
||||||
const { t } = useTranslation(["common", "components/dialog"]);
|
const { t } = useTranslation(["common", "components/dialog"]);
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
|
const timeFormat = useTimeFormat(config);
|
||||||
const currentTimestampLabel = useFormattedTimestamp(
|
const currentTimestampLabel = useFormattedTimestamp(
|
||||||
currentTime,
|
currentTime,
|
||||||
config?.ui.time_format == "24hour"
|
timeFormat == "24hour"
|
||||||
? t("time.formattedTimestamp.24hour")
|
? t("time.formattedTimestamp.24hour")
|
||||||
: t("time.formattedTimestamp.12hour"),
|
: t("time.formattedTimestamp.12hour"),
|
||||||
config?.ui.timezone,
|
config?.ui.timezone,
|
||||||
@ -199,7 +200,7 @@ export function ShareTimestampContent({
|
|||||||
className={cn("mt-4", !isDesktop && "flex flex-col-reverse gap-4")}
|
className={cn("mt-4", !isDesktop && "flex flex-col-reverse gap-4")}
|
||||||
>
|
>
|
||||||
{onCancel && (
|
{onCancel && (
|
||||||
<Button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={cn(
|
className={cn(
|
||||||
"cursor-pointer p-2 text-center",
|
"cursor-pointer p-2 text-center",
|
||||||
@ -208,7 +209,7 @@ export function ShareTimestampContent({
|
|||||||
onClick={onCancel}
|
onClick={onCancel}
|
||||||
>
|
>
|
||||||
{t("button.cancel", { ns: "common" })}
|
{t("button.cancel", { ns: "common" })}
|
||||||
</Button>
|
</button>
|
||||||
)}
|
)}
|
||||||
<Button
|
<Button
|
||||||
className={cn(!isDesktop && "w-full")}
|
className={cn(!isDesktop && "w-full")}
|
||||||
@ -236,6 +237,7 @@ function CustomTimestampSelector({
|
|||||||
}: Readonly<CustomTimestampSelectorProps>) {
|
}: Readonly<CustomTimestampSelectorProps>) {
|
||||||
const { t } = useTranslation(["common"]);
|
const { t } = useTranslation(["common"]);
|
||||||
const { data: config } = useSWR<FrigateConfig>("config");
|
const { data: config } = useSWR<FrigateConfig>("config");
|
||||||
|
const timeFormat = useTimeFormat(config);
|
||||||
|
|
||||||
const timezoneOffset = useMemo(
|
const timezoneOffset = useMemo(
|
||||||
() =>
|
() =>
|
||||||
@ -271,7 +273,7 @@ function CustomTimestampSelector({
|
|||||||
|
|
||||||
const formattedTimestamp = useFormattedTimestamp(
|
const formattedTimestamp = useFormattedTimestamp(
|
||||||
displayTimestamp,
|
displayTimestamp,
|
||||||
config?.ui.time_format == "24hour"
|
timeFormat == "24hour"
|
||||||
? t("time.formattedTimestamp.24hour")
|
? t("time.formattedTimestamp.24hour")
|
||||||
: t("time.formattedTimestamp.12hour"),
|
: t("time.formattedTimestamp.12hour"),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -280,6 +280,7 @@ export default function Events() {
|
|||||||
// this pattern is also used LiveCameraView to enter recording view
|
// this pattern is also used LiveCameraView to enter recording view
|
||||||
severity: "alert",
|
severity: "alert",
|
||||||
timelineType: notificationTab,
|
timelineType: notificationTab,
|
||||||
|
navigationSource: "shared-link",
|
||||||
},
|
},
|
||||||
true,
|
true,
|
||||||
);
|
);
|
||||||
|
|||||||
@ -40,6 +40,7 @@ export type RecordingStartingPoint = {
|
|||||||
startTime: number;
|
startTime: number;
|
||||||
severity: ReviewSeverity;
|
severity: ReviewSeverity;
|
||||||
timelineType?: TimelineType;
|
timelineType?: TimelineType;
|
||||||
|
navigationSource?: "shared-link";
|
||||||
};
|
};
|
||||||
|
|
||||||
export type RecordingPlayerError = "stalled" | "startup";
|
export type RecordingPlayerError = "stalled" | "startup";
|
||||||
|
|||||||
@ -349,6 +349,16 @@ export function RecordingView({
|
|||||||
[location.pathname, mainCamera, t],
|
[location.pathname, mainCamera, t],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const handleBack = useCallback(() => {
|
||||||
|
// if we came from a direct share link, there is no history to go back to, so navigate to the homepage instead
|
||||||
|
if (recording?.navigationSource === "shared-link") {
|
||||||
|
navigate("/");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
navigate(-1);
|
||||||
|
}, [navigate, recording?.navigationSource]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!scrubbing) {
|
if (!scrubbing) {
|
||||||
if (Math.abs(currentTime - playerTime) > 10) {
|
if (Math.abs(currentTime - playerTime) > 10) {
|
||||||
@ -599,7 +609,7 @@ export function RecordingView({
|
|||||||
className="flex items-center gap-2.5 rounded-lg"
|
className="flex items-center gap-2.5 rounded-lg"
|
||||||
aria-label={t("label.back", { ns: "common" })}
|
aria-label={t("label.back", { ns: "common" })}
|
||||||
size="sm"
|
size="sm"
|
||||||
onClick={() => navigate(-1)}
|
onClick={handleBack}
|
||||||
>
|
>
|
||||||
<IoMdArrowRoundBack className="size-5 text-secondary-foreground" />
|
<IoMdArrowRoundBack className="size-5 text-secondary-foreground" />
|
||||||
{isDesktop && (
|
{isDesktop && (
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user