mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-05 22:57:40 +03:00
Miscellaneous fixes (#22762)
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
Some checks are pending
CI / AMD64 Build (push) Waiting to run
CI / ARM Build (push) Waiting to run
CI / Jetson Jetpack 6 (push) Waiting to run
CI / AMD64 Extra Build (push) Blocked by required conditions
CI / ARM Extra Build (push) Blocked by required conditions
CI / Synaptics Build (push) Blocked by required conditions
CI / Assemble and push default build (push) Blocked by required conditions
This commit is contained in:
parent
9ba81d6dc8
commit
d8c35d5a0f
@ -2,7 +2,7 @@ import type { FieldPathList, FieldProps } from "@rjsf/utils";
|
||||
import yaml from "js-yaml";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { useCallback, useEffect, useMemo, useState } from "react";
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
||||
|
||||
function formatYaml(value: unknown): string {
|
||||
if (
|
||||
@ -54,10 +54,14 @@ export function DictAsYamlField(props: FieldProps) {
|
||||
|
||||
const [text, setText] = useState(() => formatYaml(formData));
|
||||
const [error, setError] = useState<string>();
|
||||
const focusedRef = useRef(false);
|
||||
|
||||
useEffect(() => {
|
||||
setText(formatYaml(formData));
|
||||
setError(undefined);
|
||||
// Only sync from external formData changes, not our own onChange
|
||||
if (!focusedRef.current) {
|
||||
setText(formatYaml(formData));
|
||||
setError(undefined);
|
||||
}
|
||||
}, [formData]);
|
||||
|
||||
const handleChange = useCallback(
|
||||
@ -73,8 +77,13 @@ export function DictAsYamlField(props: FieldProps) {
|
||||
[onChange, fieldPath],
|
||||
);
|
||||
|
||||
const handleFocus = useCallback(() => {
|
||||
focusedRef.current = true;
|
||||
}, []);
|
||||
|
||||
const handleBlur = useCallback(
|
||||
(_e: React.FocusEvent<HTMLTextAreaElement>) => {
|
||||
focusedRef.current = false;
|
||||
// Reformat on blur if valid
|
||||
const { value } = parseYaml(text);
|
||||
if (value !== undefined) {
|
||||
@ -101,6 +110,7 @@ export function DictAsYamlField(props: FieldProps) {
|
||||
placeholder={"key: value"}
|
||||
rows={Math.max(3, text.split("\n").length + 1)}
|
||||
onChange={handleChange}
|
||||
onFocus={handleFocus}
|
||||
onBlur={handleBlur}
|
||||
/>
|
||||
{error && <p className="text-xs text-destructive">{error}</p>}
|
||||
|
||||
@ -195,6 +195,7 @@ export default function LivePlayer({
|
||||
}, [preferredLiveMode]);
|
||||
|
||||
const [key, setKey] = useState(0);
|
||||
const prevStreamNameRef = useRef(streamName);
|
||||
|
||||
const resetPlayer = () => {
|
||||
setLiveReady(false);
|
||||
@ -202,8 +203,11 @@ export default function LivePlayer({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (streamName) {
|
||||
resetPlayer();
|
||||
if (prevStreamNameRef.current !== streamName) {
|
||||
prevStreamNameRef.current = streamName;
|
||||
if (streamName) {
|
||||
resetPlayer();
|
||||
}
|
||||
}
|
||||
}, [streamName]);
|
||||
|
||||
|
||||
@ -81,6 +81,7 @@ function MSEPlayer({
|
||||
const wsRef = useRef<WebSocket | null>(null);
|
||||
const reconnectTIDRef = useRef<number | null>(null);
|
||||
const intentionalDisconnectRef = useRef<boolean>(false);
|
||||
const onCloseRef = useRef<(() => void) | null>(null);
|
||||
const ondataRef = useRef<((data: ArrayBufferLike) => void) | null>(null);
|
||||
const onmessageRef = useRef<{
|
||||
[key: string]: (msg: { value: string; type: string }) => void;
|
||||
@ -167,6 +168,8 @@ function MSEPlayer({
|
||||
wsRef.current = new WebSocket(wsURL);
|
||||
wsRef.current.binaryType = "arraybuffer";
|
||||
wsRef.current.addEventListener("open", onOpen);
|
||||
// Capture current onClose identity so removeEventListener can find it later
|
||||
onCloseRef.current = onClose;
|
||||
wsRef.current.addEventListener("close", onClose);
|
||||
// we know that these deps are correct
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
@ -200,20 +203,23 @@ function MSEPlayer({
|
||||
intentionalDisconnectRef.current = true;
|
||||
setWsState(WebSocket.CLOSED);
|
||||
|
||||
// Remove event listeners to prevent them firing during close
|
||||
// Remove event listeners to prevent them firing during close.
|
||||
// Use onCloseRef to remove the exact function that was attached in onConnect,
|
||||
// since onClose may have been recreated by React since then.
|
||||
try {
|
||||
ws.removeEventListener("open", onOpen);
|
||||
ws.removeEventListener("close", onClose);
|
||||
if (onCloseRef.current) {
|
||||
ws.removeEventListener("close", onCloseRef.current);
|
||||
onCloseRef.current = null;
|
||||
}
|
||||
} catch {
|
||||
// Ignore errors removing listeners
|
||||
}
|
||||
|
||||
// Only call close() if the socket is OPEN or CLOSING
|
||||
// For CONNECTING or CLOSED sockets, just let it die
|
||||
if (
|
||||
currentReadyState === WebSocket.OPEN ||
|
||||
currentReadyState === WebSocket.CLOSING
|
||||
) {
|
||||
// Close the socket in any non-CLOSED state, including CONNECTING.
|
||||
// A CONNECTING socket that is not closed will complete its handshake
|
||||
// and remain open, leaking a browser connection.
|
||||
if (currentReadyState !== WebSocket.CLOSED) {
|
||||
try {
|
||||
ws.close();
|
||||
} catch {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user