mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-07-26 13:48:59 +03:00
Miscellaneous Fixes (#20897)
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
* don't flatten the search result cache when updating this would cause an infinite swr fetch if something was mutated and then fetch was called again * Properly sort keys for recording summary in StorageMetrics * tracked object description box tweaks * Remove ability to right click on elements inside of face popup * Update reprocess message * don't show object track until video metadata is loaded * fix blue line height calc for in progress events * Use timeline tab by default for notifications but add a query arg for customization * Try and improve notification opening behavior * Reduce review item buffering behavior * ensure logging config is passed to camera capture and tracker processes * ensure on demand recording stops when browser closes * improve active line progress height with resize observer * remove icons and duplicate find similar link in explore context menu * fix for initial broken image when creating trigger from explore * display friendly names for triggers in toasts * lpr and triggers docs updates * remove icons from dropdowns in face and classification * fix comma dangle linter issue * re-add incorrectly removed face library button icons * fix sidebar nav links on < 768px desktop layout * allow text to wrap on mark as reviewed button * match exact pixels * clarify LPR docs --------- Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
This commit is contained in:
co-authored by
Nicolas Mowen
parent
097673b845
commit
fbf4388b37
@@ -16,7 +16,6 @@ import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { FaFolderPlus } from "react-icons/fa";
|
||||
import { MdModelTraining } from "react-icons/md";
|
||||
import { LuPencil, LuTrash2 } from "react-icons/lu";
|
||||
import { FiMoreVertical } from "react-icons/fi";
|
||||
import useSWR from "swr";
|
||||
import Heading from "@/components/ui/heading";
|
||||
@@ -352,11 +351,9 @@ function ModelCard({ config, onClick, onUpdate, onDelete }: ModelCardProps) {
|
||||
onClick={(e) => e.stopPropagation()}
|
||||
>
|
||||
<DropdownMenuItem onClick={handleEditClick}>
|
||||
<LuPencil className="mr-2 size-4" />
|
||||
<span>{t("button.edit", { ns: "common" })}</span>
|
||||
</DropdownMenuItem>
|
||||
<DropdownMenuItem onClick={handleDeleteClick}>
|
||||
<LuTrash2 className="mr-2 size-4" />
|
||||
<span>{t("button.delete", { ns: "common" })}</span>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
|
||||
@@ -799,7 +799,7 @@ function DetectionReview({
|
||||
(itemsToReview ?? 0) > 0 && (
|
||||
<div className="col-span-full flex items-center justify-center">
|
||||
<Button
|
||||
className="text-white"
|
||||
className="text-balance text-white"
|
||||
aria-label={t("markTheseItemsAsReviewed")}
|
||||
variant="select"
|
||||
onClick={() => {
|
||||
|
||||
@@ -850,6 +850,29 @@ function FrigateCameraFeatures({
|
||||
}
|
||||
}, [activeToastId, t]);
|
||||
|
||||
const endEventViaBeacon = useCallback(() => {
|
||||
if (!recordingEventIdRef.current) return;
|
||||
|
||||
const url = `${window.location.origin}/api/events/${recordingEventIdRef.current}/end`;
|
||||
const payload = JSON.stringify({
|
||||
end_time: Math.ceil(Date.now() / 1000),
|
||||
});
|
||||
|
||||
// this needs to be a synchronous XMLHttpRequest to guarantee the PUT
|
||||
// reaches the server before the browser kills the page
|
||||
const xhr = new XMLHttpRequest();
|
||||
try {
|
||||
xhr.open("PUT", url, false);
|
||||
xhr.setRequestHeader("Content-Type", "application/json");
|
||||
xhr.setRequestHeader("X-CSRF-TOKEN", "1");
|
||||
xhr.setRequestHeader("X-CACHE-BYPASS", "1");
|
||||
xhr.withCredentials = true;
|
||||
xhr.send(payload);
|
||||
} catch (e) {
|
||||
// Silently ignore errors during unload
|
||||
}
|
||||
}, []);
|
||||
|
||||
const handleEventButtonClick = useCallback(() => {
|
||||
if (isRecording) {
|
||||
endEvent();
|
||||
@@ -887,8 +910,19 @@ function FrigateCameraFeatures({
|
||||
}, [camera.name, isRestreamed, preferredLiveMode, t]);
|
||||
|
||||
useEffect(() => {
|
||||
// Handle page unload/close (browser close, tab close, refresh, navigation to external site)
|
||||
const handleBeforeUnload = () => {
|
||||
if (recordingEventIdRef.current) {
|
||||
endEventViaBeacon();
|
||||
}
|
||||
};
|
||||
|
||||
window.addEventListener("beforeunload", handleBeforeUnload);
|
||||
|
||||
// ensure manual event is stopped when component unmounts
|
||||
return () => {
|
||||
window.removeEventListener("beforeunload", handleBeforeUnload);
|
||||
|
||||
if (recordingEventIdRef.current) {
|
||||
endEvent();
|
||||
}
|
||||
|
||||
@@ -201,12 +201,17 @@ export default function TriggerView({
|
||||
.then((configResponse) => {
|
||||
if (configResponse.status === 200) {
|
||||
updateConfig();
|
||||
const displayName =
|
||||
friendly_name && friendly_name !== ""
|
||||
? `${friendly_name} (${name})`
|
||||
: name;
|
||||
|
||||
toast.success(
|
||||
t(
|
||||
isEdit
|
||||
? "triggers.toast.success.updateTrigger"
|
||||
: "triggers.toast.success.createTrigger",
|
||||
{ name },
|
||||
{ name: displayName },
|
||||
),
|
||||
{ position: "top-center" },
|
||||
);
|
||||
@@ -351,8 +356,19 @@ export default function TriggerView({
|
||||
.then((configResponse) => {
|
||||
if (configResponse.status === 200) {
|
||||
updateConfig();
|
||||
const friendly =
|
||||
config?.cameras?.[selectedCamera]?.semantic_search
|
||||
?.triggers?.[name]?.friendly_name;
|
||||
|
||||
const displayName =
|
||||
friendly && friendly !== ""
|
||||
? `${friendly} (${name})`
|
||||
: name;
|
||||
|
||||
toast.success(
|
||||
t("triggers.toast.success.deleteTrigger", { name }),
|
||||
t("triggers.toast.success.deleteTrigger", {
|
||||
name: displayName,
|
||||
}),
|
||||
{
|
||||
position: "top-center",
|
||||
},
|
||||
@@ -381,7 +397,7 @@ export default function TriggerView({
|
||||
setIsLoading(false);
|
||||
});
|
||||
},
|
||||
[t, updateConfig, selectedCamera, setUnsavedChanges],
|
||||
[t, updateConfig, selectedCamera, setUnsavedChanges, config],
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
@@ -843,7 +859,14 @@ export default function TriggerView({
|
||||
/>
|
||||
<DeleteTriggerDialog
|
||||
show={showDelete}
|
||||
triggerName={selectedTrigger?.name ?? ""}
|
||||
triggerName={
|
||||
selectedTrigger
|
||||
? selectedTrigger.friendly_name &&
|
||||
selectedTrigger.friendly_name !== ""
|
||||
? `${selectedTrigger.friendly_name} (${selectedTrigger.name})`
|
||||
: selectedTrigger.name
|
||||
: ""
|
||||
}
|
||||
isLoading={isLoading}
|
||||
onCancel={() => {
|
||||
setShowDelete(false);
|
||||
|
||||
@@ -72,8 +72,7 @@ export default function StorageMetrics({
|
||||
const earliestDate = useMemo(() => {
|
||||
const keys = Object.keys(recordingsSummary || {});
|
||||
return keys.length
|
||||
? new TZDate(keys[keys.length - 1] + "T00:00:00", timezone).getTime() /
|
||||
1000
|
||||
? new TZDate(keys[0] + "T00:00:00", timezone).getTime() / 1000
|
||||
: null;
|
||||
}, [recordingsSummary, timezone]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user