mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-04 14:24:54 +03:00
revise url format
This commit is contained in:
parent
ec3fc782a8
commit
05d29ebc93
@ -24,6 +24,7 @@ import {
|
|||||||
import {
|
import {
|
||||||
parseRecordingReviewLink,
|
parseRecordingReviewLink,
|
||||||
RECORDING_REVIEW_START_PARAM,
|
RECORDING_REVIEW_START_PARAM,
|
||||||
|
RECORDING_REVIEW_TIMEZONE_PARAM,
|
||||||
} from "@/utils/recordingReviewUrl";
|
} from "@/utils/recordingReviewUrl";
|
||||||
import EventView from "@/views/events/EventView";
|
import EventView from "@/views/events/EventView";
|
||||||
import MotionSearchView from "@/views/motion-search/MotionSearchView";
|
import MotionSearchView from "@/views/motion-search/MotionSearchView";
|
||||||
@ -248,6 +249,7 @@ export default function Events() {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const timestamp = searchParams.get(RECORDING_REVIEW_START_PARAM);
|
const timestamp = searchParams.get(RECORDING_REVIEW_START_PARAM);
|
||||||
|
const timezone = searchParams.get(RECORDING_REVIEW_TIMEZONE_PARAM);
|
||||||
|
|
||||||
if (!timestamp) {
|
if (!timestamp) {
|
||||||
return;
|
return;
|
||||||
@ -257,7 +259,7 @@ export default function Events() {
|
|||||||
? decodeURIComponent(location.hash.substring(1))
|
? decodeURIComponent(location.hash.substring(1))
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
const reviewLink = parseRecordingReviewLink(camera, timestamp);
|
const reviewLink = parseRecordingReviewLink(camera, timestamp, timezone);
|
||||||
|
|
||||||
if (!reviewLink) {
|
if (!reviewLink) {
|
||||||
navigate(location.pathname + location.hash, {
|
navigate(location.pathname + location.hash, {
|
||||||
|
|||||||
@ -1,19 +1,39 @@
|
|||||||
|
import { formatInTimeZone, fromZonedTime } from "date-fns-tz";
|
||||||
|
|
||||||
export const RECORDING_REVIEW_START_PARAM = "start_time";
|
export const RECORDING_REVIEW_START_PARAM = "start_time";
|
||||||
|
export const RECORDING_REVIEW_TIMEZONE_PARAM = "timezone";
|
||||||
|
|
||||||
export type RecordingReviewLinkState = {
|
export type RecordingReviewLinkState = {
|
||||||
camera: string;
|
camera: string;
|
||||||
timestamp: number;
|
timestamp: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
function formatRecordingReviewTimestamp(
|
||||||
|
timestamp: number,
|
||||||
|
timezone: string | undefined,
|
||||||
|
): string {
|
||||||
|
const date = new Date(Math.floor(timestamp) * 1000);
|
||||||
|
|
||||||
|
if (timezone) {
|
||||||
|
return formatInTimeZone(date, timezone, "yyyy-MM-dd'T'HH:mm:ss");
|
||||||
|
}
|
||||||
|
|
||||||
|
return formatInTimeZone(date, "UTC", "yyyy-MM-dd'T'HH:mm:ss'Z'");
|
||||||
|
}
|
||||||
|
|
||||||
export function parseRecordingReviewLink(
|
export function parseRecordingReviewLink(
|
||||||
camera: string | null,
|
camera: string | null,
|
||||||
start: string | null,
|
start: string | null,
|
||||||
|
timezone: string | null,
|
||||||
): RecordingReviewLinkState | undefined {
|
): RecordingReviewLinkState | undefined {
|
||||||
if (!camera || !start) {
|
if (!camera || !start) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
const parsedTimestamp = Number(start);
|
const parsedDate = timezone
|
||||||
|
? fromZonedTime(start, timezone)
|
||||||
|
: new Date(start);
|
||||||
|
const parsedTimestamp = parsedDate.getTime() / 1000;
|
||||||
|
|
||||||
if (!Number.isFinite(parsedTimestamp)) {
|
if (!Number.isFinite(parsedTimestamp)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
@ -28,15 +48,19 @@ export function parseRecordingReviewLink(
|
|||||||
export function createRecordingReviewUrl(
|
export function createRecordingReviewUrl(
|
||||||
pathname: string,
|
pathname: string,
|
||||||
state: RecordingReviewLinkState,
|
state: RecordingReviewLinkState,
|
||||||
|
timezone?: string,
|
||||||
): string {
|
): string {
|
||||||
const url = new URL(window.location.href);
|
const url = new URL(globalThis.location.href);
|
||||||
url.pathname = pathname;
|
const formattedTimestamp = formatRecordingReviewTimestamp(
|
||||||
url.hash = state.camera;
|
state.timestamp,
|
||||||
url.search = "";
|
timezone,
|
||||||
url.searchParams.set(
|
|
||||||
RECORDING_REVIEW_START_PARAM,
|
|
||||||
`${Math.floor(state.timestamp)}`,
|
|
||||||
);
|
);
|
||||||
|
const normalizedPathname = pathname.startsWith("/")
|
||||||
|
? pathname
|
||||||
|
: `/${pathname}`;
|
||||||
|
const timezoneParam = timezone
|
||||||
|
? `&${RECORDING_REVIEW_TIMEZONE_PARAM}=${encodeURIComponent(timezone)}`
|
||||||
|
: "";
|
||||||
|
|
||||||
return url.toString();
|
return `${url.origin}${normalizedPathname}?${RECORDING_REVIEW_START_PARAM}=${formattedTimestamp}${timezoneParam}#${encodeURIComponent(state.camera)}`;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -334,16 +334,20 @@ export function RecordingView({
|
|||||||
}, [startTime, manuallySetCurrentTime]);
|
}, [startTime, manuallySetCurrentTime]);
|
||||||
|
|
||||||
const onCopyReviewLink = useCallback(() => {
|
const onCopyReviewLink = useCallback(() => {
|
||||||
const reviewUrl = createRecordingReviewUrl(location.pathname, {
|
const reviewUrl = createRecordingReviewUrl(
|
||||||
camera: mainCamera,
|
location.pathname,
|
||||||
timestamp: Math.floor(currentTime),
|
{
|
||||||
});
|
camera: mainCamera,
|
||||||
|
timestamp: Math.floor(currentTime),
|
||||||
|
},
|
||||||
|
config?.ui.timezone,
|
||||||
|
);
|
||||||
|
|
||||||
copy(reviewUrl);
|
copy(reviewUrl);
|
||||||
toast.success(t("toast.copyUrlToClipboard", { ns: "common" }), {
|
toast.success(t("toast.copyUrlToClipboard", { ns: "common" }), {
|
||||||
position: "top-center",
|
position: "top-center",
|
||||||
});
|
});
|
||||||
}, [location.pathname, mainCamera, currentTime, t]);
|
}, [location.pathname, mainCamera, currentTime, config?.ui.timezone, t]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!scrubbing) {
|
if (!scrubbing) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user