-address fixes and changes per feedback from Matt and Brad
This commit is contained in:
@@ -4,7 +4,7 @@ import { useEffect, useMemo, useState } from "react";
|
||||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { faEye, faEyeSlash } from "@fortawesome/free-regular-svg-icons";
|
||||
import CardHeader from "../UI/CardHeader";
|
||||
import { useCameraZoom } from "../../hooks/useCameraZoom";
|
||||
import { useCameraMode, useCameraZoom } from "../../hooks/useCameraZoom";
|
||||
import { parseRTSPUrl, reverseZoomMapping, zoomMapping } from "../../utils/utils";
|
||||
|
||||
type CameraSettingsProps = {
|
||||
@@ -20,16 +20,21 @@ const CameraSettingFields = ({
|
||||
updateCameraConfig,
|
||||
zoomLevel,
|
||||
onZoomLevelChange,
|
||||
updateCameraConfigError,
|
||||
}: CameraSettingsProps) => {
|
||||
const [showPwd, setShowPwd] = useState(false);
|
||||
|
||||
const cameraControllerSide = initialData?.id === "CameraA" ? "CameraControllerA" : "CameraControllerB";
|
||||
const { mutation, query } = useCameraZoom({ camera: cameraControllerSide });
|
||||
const { cameraModeQuery, cameraModeMutation } = useCameraMode({ camera: cameraControllerSide });
|
||||
const zoomOptions = [1, 2, 4];
|
||||
const magnification = query?.data?.propMagnification?.value;
|
||||
const apiZoom = reverseZoomMapping(magnification);
|
||||
const parsed = parseRTSPUrl(initialData?.propURI?.value);
|
||||
const cameraMode = cameraModeQuery?.data?.propDayNightMode?.value;
|
||||
|
||||
const handleModeClick = async (mode: string) => {
|
||||
await cameraModeMutation.mutate({ camera: cameraControllerSide, mode });
|
||||
};
|
||||
useEffect(() => {
|
||||
if (!query?.data) return;
|
||||
onZoomLevelChange?.(apiZoom);
|
||||
@@ -194,7 +199,30 @@ const CameraSettingFields = ({
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<div className="mt-3">
|
||||
<div>
|
||||
<CardHeader title="Mode" />
|
||||
<div className="mx-auto grid grid-cols-2 place-items-center">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleModeClick("day")}
|
||||
className={`px-8 py-2 rounded-md border border-gray-300 ${
|
||||
cameraMode === "day" ? "bg-gray-100 text-blue-600" : ""
|
||||
}`}
|
||||
>
|
||||
Day
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => handleModeClick("night")}
|
||||
className={`px-8 py-2 rounded-md border border-gray-300 ${
|
||||
cameraMode === "night" ? "bg-gray-100 text-blue-600" : ""
|
||||
}`}
|
||||
>
|
||||
Night
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{/* <div className="mt-3">
|
||||
{updateCameraConfigError ? (
|
||||
<button className="bg-red-500 text-white rounded-lg p-2 mx-auto h-[100%] w-full" disabled>
|
||||
Retry
|
||||
@@ -205,11 +233,10 @@ const CameraSettingFields = ({
|
||||
className="bg-blue-700 text-white rounded-lg p-2 mx-auto h-[100%] w-full"
|
||||
disabled
|
||||
>
|
||||
{/* {isSubmitting ? "Saving" : "Save settings"} bg-[#26B170] */}
|
||||
{"Disabled: Coming soon"}
|
||||
{isSubmitting ? "Saving" : "Save settings"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
</div> */}
|
||||
</div>
|
||||
</Form>
|
||||
)}
|
||||
|
||||
@@ -18,7 +18,7 @@ const CameraSettings = ({
|
||||
const { data, updateCameraConfig, updateCameraConfigError } = useFetchCameraConfig(side);
|
||||
|
||||
return (
|
||||
<Card className="overflow-hidden min-h-[40vh] md:min-h-[60vh] max-h-[80vh] lg:w-[40%] p-4">
|
||||
<Card className="overflow-x-auto min-h-[40vh] md:min-h-[60vh] max-h-[83vh] lg:w-[40%] p-4">
|
||||
<div className="relative flex flex-col space-y-3">
|
||||
<CardHeader title={title} icon={faWrench} />
|
||||
|
||||
|
||||
@@ -115,7 +115,35 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
|
||||
} rounded-lg w-full md:w-60`}
|
||||
/>
|
||||
</FormGroup>
|
||||
|
||||
{/* Overview quality and scale */}
|
||||
<FormGroup>
|
||||
<label htmlFor="overviewQuality">Overview quality and scale</label>
|
||||
<Field
|
||||
name={"overviewQuality"}
|
||||
as="select"
|
||||
id="overviewQuality"
|
||||
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445] w-full md:w-60"
|
||||
>
|
||||
<option value={"HIGH"}>High</option>
|
||||
<option value={"MEDIUM"}>Medium</option>
|
||||
<option value={"LOW"}>Low</option>
|
||||
</Field>
|
||||
</FormGroup>
|
||||
{/* propOverviewImageScaleFactor cropSizeFactor */}
|
||||
<FormGroup>
|
||||
<label htmlFor="cropSizeFactor">Crop Size Factor</label>
|
||||
<Field
|
||||
name={"cropSizeFactor"}
|
||||
as="select"
|
||||
id="cropSizeFactor"
|
||||
className="p-2 border border-gray-400 rounded-lg text-white bg-[#253445] w-full md:w-60"
|
||||
>
|
||||
<option value={"FULL"}>Full</option>
|
||||
<option value={"3/4"}>3/4</option>
|
||||
<option value={"1/2"}>1/2</option>
|
||||
<option value={"1/4"}>1/4</option>
|
||||
</Field>
|
||||
</FormGroup>
|
||||
{format?.toLowerCase() === "bof2" && (
|
||||
<>
|
||||
<div className="space-y-3">
|
||||
@@ -176,7 +204,7 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
|
||||
<h2 className="font-bold">{values.format} Lane ID Config</h2>
|
||||
</div>
|
||||
<FormGroup>
|
||||
<label htmlFor="LID1">Lane ID 1</label>
|
||||
<label htmlFor="LID1">Lane ID 1 (Camera A)</label>
|
||||
<Field
|
||||
name={"LID1"}
|
||||
type="text"
|
||||
@@ -188,7 +216,7 @@ const ChannelFields = ({ touched, isSubmitting, format }: ChannelFieldsProps) =>
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<label htmlFor="LID2">Lane ID 2</label>
|
||||
<label htmlFor="LID2">Lane ID 2 (Camera B)</label>
|
||||
<Field
|
||||
name={"LID2"}
|
||||
type="text"
|
||||
|
||||
@@ -12,6 +12,7 @@ import type {
|
||||
import { useQueryClient } from "@tanstack/react-query";
|
||||
import { useUpdateBackOfficeConfig } from "../../../hooks/useBackOfficeConfig";
|
||||
import { useFormVaidate } from "../../../hooks/useFormValidate";
|
||||
import { useSightingAmend } from "../../../hooks/useSightingAmend";
|
||||
|
||||
const SettingForms = () => {
|
||||
const qc = useQueryClient();
|
||||
@@ -20,10 +21,14 @@ const SettingForms = () => {
|
||||
const { backOfficeMutation } = useUpdateBackOfficeConfig();
|
||||
const { bof2ConstantsQuery } = useGetDispatcherConfig();
|
||||
const { validateMutation } = useFormVaidate();
|
||||
const { sightingAmendQuery, sightingAmendMutation } = useSightingAmend();
|
||||
|
||||
const format = dispatcherQuery?.data?.propFormat?.value;
|
||||
const enabled = dispatcherQuery?.data?.propEnabled?.value;
|
||||
|
||||
const sightingQuality = sightingAmendQuery?.data?.propOverviewQuality?.value;
|
||||
const cropSizeFactor = sightingAmendQuery?.data?.propOverviewImageScaleFactor?.value;
|
||||
|
||||
const LID1 = laneIdQuery?.data?.propLaneID1?.value;
|
||||
const LID2 = laneIdQuery?.data?.propLaneID2?.value;
|
||||
|
||||
@@ -43,6 +48,8 @@ const SettingForms = () => {
|
||||
password: "",
|
||||
connectTimeoutSeconds: Number(5),
|
||||
readTimeoutSeconds: Number(15),
|
||||
overviewQuality: sightingQuality ?? "HIGH",
|
||||
cropSizeFactor: cropSizeFactor ?? "3/4",
|
||||
|
||||
// Bof2 - optional constants
|
||||
FFID: FFID ?? "",
|
||||
@@ -91,6 +98,7 @@ const SettingForms = () => {
|
||||
|
||||
if (validResponse?.reason === "OK") {
|
||||
await backOfficeMutation.mutateAsync(values);
|
||||
await sightingAmendMutation.mutateAsync(values);
|
||||
|
||||
if (values.format.toLowerCase() === "bof2") {
|
||||
const bof2ConstantsData: OptionalBOF2Constants = {
|
||||
|
||||
@@ -8,9 +8,8 @@ import { useDNSSettings, useSystemConfig } from "../../../hooks/useSystemConfig"
|
||||
|
||||
const SystemConfigFields = () => {
|
||||
const { saveSystemSettings, systemSettingsData, saveSystemSettingsLoading } = useSystemConfig();
|
||||
const { softRebootMutation, hardRebootMutation } = useReboots();
|
||||
const { hardRebootMutation } = useReboots();
|
||||
const { dnsQuery, dnsMutation } = useDNSSettings();
|
||||
console.log(dnsQuery?.data);
|
||||
|
||||
const dnsPrimary = dnsQuery?.data?.propNameServerPrimary?.value;
|
||||
const dnsSecondary = dnsQuery?.data?.propNameServerSecondary?.value;
|
||||
@@ -39,9 +38,9 @@ const SystemConfigFields = () => {
|
||||
return errors;
|
||||
};
|
||||
|
||||
const handleSoftReboot = async () => {
|
||||
await softRebootMutation.mutate();
|
||||
};
|
||||
// const handleSoftReboot = async () => {
|
||||
// await softRebootMutation.mutate();
|
||||
// };
|
||||
|
||||
const handleHardReboot = async () => {
|
||||
await hardRebootMutation.mutate();
|
||||
@@ -111,34 +110,7 @@ const SystemConfigFields = () => {
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<label htmlFor="serverPrimary" className="font-medium whitespace-nowrap md:w-1/2 text-left">
|
||||
Server Primary
|
||||
</label>
|
||||
|
||||
<Field
|
||||
id="serverPrimary"
|
||||
name="serverPrimary"
|
||||
type="text"
|
||||
className="p-2 border border-gray-400 rounded-lg w-full max-w-xs"
|
||||
placeholder="Enter DNS primary address"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<label htmlFor="serverSecondary" className="font-medium whitespace-nowrap md:w-1/2 text-left">
|
||||
Server Secondary
|
||||
</label>
|
||||
|
||||
<Field
|
||||
id="serverSecondary"
|
||||
name="serverSecondary"
|
||||
type="text"
|
||||
className="p-2 border border-gray-400 rounded-lg w-full max-w-xs"
|
||||
placeholder="Enter DNS secondary address"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<label htmlFor="sntpInterval" className="font-medium whitespace-nowrap md:w-1/2 text-left">
|
||||
SNTP Interval minutes
|
||||
@@ -155,6 +127,34 @@ const SystemConfigFields = () => {
|
||||
className="p-2 border border-gray-400 rounded-lg w-full max-w-xs"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<label htmlFor="serverPrimary" className="font-medium whitespace-nowrap md:w-1/2 text-left">
|
||||
Primary DNS Server
|
||||
</label>
|
||||
|
||||
<Field
|
||||
id="serverPrimary"
|
||||
name="serverPrimary"
|
||||
type="text"
|
||||
className="p-2 border border-gray-400 rounded-lg w-full max-w-xs"
|
||||
placeholder="Enter DNS primary address"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormGroup>
|
||||
<FormGroup>
|
||||
<label htmlFor="serverSecondary" className="font-medium whitespace-nowrap md:w-1/2 text-left">
|
||||
Secondary DNS Server
|
||||
</label>
|
||||
|
||||
<Field
|
||||
id="serverSecondary"
|
||||
name="serverSecondary"
|
||||
type="text"
|
||||
className="p-2 border border-gray-400 rounded-lg w-full max-w-xs"
|
||||
placeholder="Enter DNS secondary address"
|
||||
autoComplete="off"
|
||||
/>
|
||||
</FormGroup>
|
||||
<button
|
||||
type="submit"
|
||||
className="w-1/4 text-white bg-green-700 hover:bg-green-800 font-small rounded-lg text-sm px-2 py-2.5"
|
||||
@@ -167,13 +167,13 @@ const SystemConfigFields = () => {
|
||||
<p>Reboot</p>
|
||||
</div>
|
||||
|
||||
<button
|
||||
{/* <button
|
||||
type="button"
|
||||
className="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition w-full md:w-[50%]"
|
||||
onClick={handleSoftReboot}
|
||||
>
|
||||
{softRebootMutation.isPending || isSubmitting ? "Rebooting..." : "Software Reboot"}
|
||||
</button>
|
||||
</button> */}
|
||||
<button
|
||||
type="button"
|
||||
className="bg-red-600 text-white px-4 py-2 rounded hover:bg-red-700 transition w-full md:w-[50%]"
|
||||
|
||||
@@ -59,11 +59,10 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
isLoading,
|
||||
} = useSightingFeedContext();
|
||||
|
||||
const { dispatch } = useAlertHitContext();
|
||||
const { dispatch, state: alertState } = useAlertHitContext();
|
||||
const { state: integrationState, dispatch: integrationDispatch } = useIntegrationsContext();
|
||||
const sessionStarted = integrationState.sessionStarted;
|
||||
const sessionPaused = integrationState.sessionPaused;
|
||||
|
||||
const processedRefs = useRef<Set<number | string>>(new Set());
|
||||
|
||||
const hasAutoOpenedRef = useRef(false);
|
||||
@@ -72,6 +71,11 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
const enqueue = useCallback((sighting: SightingType, kind: HitKind) => {
|
||||
const id = sighting.vrm ?? sighting.ref;
|
||||
if (processedRefs.current.has(id)) return;
|
||||
|
||||
const inList = alertState?.alertList?.find((sighting) => sighting.vrm === id);
|
||||
if (inList) {
|
||||
return;
|
||||
}
|
||||
processedRefs.current.add(id);
|
||||
|
||||
setModalQueue((q) => [...q, { id, sighting, kind }]);
|
||||
@@ -154,7 +158,6 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
|
||||
if (firstNPED) {
|
||||
enqueue(firstNPED, "NPED");
|
||||
|
||||
npedRef.current = true;
|
||||
}
|
||||
|
||||
@@ -173,6 +176,7 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
|
||||
else hotlistsound();
|
||||
|
||||
setSelectedSighting(next.sighting);
|
||||
|
||||
setSightingModalOpen(true);
|
||||
}
|
||||
}, [isSightingModalOpen, npedSound, hotlistsound, setSelectedSighting, setSightingModalOpen, modalQueue]);
|
||||
|
||||
@@ -8,7 +8,7 @@ const camBase = import.meta.env.MODE !== "development" ? CAM_BASE : "";
|
||||
|
||||
const getAllBlackboardData = async () => {
|
||||
const response = await fetch(`${camBase}/api/blackboard`, {
|
||||
signal: AbortSignal.timeout(500),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error("Failed to fetch blackboard data");
|
||||
|
||||
@@ -8,7 +8,7 @@ const fetchCameraSideConfig = async ({ queryKey }: { queryKey: string[] }) => {
|
||||
const [, cameraSide] = queryKey;
|
||||
const fetchUrl = `${base_url}/fetch-config?id=${cameraSide}`;
|
||||
const response = await fetch(fetchUrl, {
|
||||
signal: AbortSignal.timeout(500),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
});
|
||||
if (!response.ok) throw new Error("cannot react cameraSide ");
|
||||
return response.json();
|
||||
|
||||
@@ -7,7 +7,7 @@ const camBase = import.meta.env.MODE !== "development" ? CAM_BASE : "";
|
||||
|
||||
const getWiFiSettings = async () => {
|
||||
const response = await fetch(`${camBase}/api/fetch-config?id=ModemAndWifiManager-wifi`, {
|
||||
signal: AbortSignal.timeout(500),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error("Cannot fetch Wifi settings");
|
||||
@@ -29,7 +29,7 @@ const updateWifiSettings = async (wifiConfig: WifiConfig) => {
|
||||
|
||||
const getModemSettings = async () => {
|
||||
const response = await fetch(`${camBase}/api/fetch-config?id=ModemAndWifiManager-modem`, {
|
||||
signal: AbortSignal.timeout(500),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error("Cannot fetch modem settings");
|
||||
|
||||
@@ -4,12 +4,35 @@ import type { zoomConfig, ZoomInOptions } from "../types/types";
|
||||
import { toast } from "sonner";
|
||||
import { useEffect } from "react";
|
||||
|
||||
const getCameraMode = async (options: { camera: string }) => {
|
||||
const response = await fetch(`${CAM_BASE}/api/fetch-config?id=Ip${options.camera}`);
|
||||
if (!response.ok) throw new Error("Cannot get camera mode");
|
||||
return response.json();
|
||||
};
|
||||
|
||||
const updateCameraMode = async (options: { camera: string; mode: string }) => {
|
||||
const dayNightPayload = {
|
||||
id: options.camera,
|
||||
fields: [
|
||||
{
|
||||
property: "propDayNightMode",
|
||||
value: options.mode,
|
||||
},
|
||||
],
|
||||
};
|
||||
const response = await fetch(`${CAM_BASE}/Ip${options.camera}-command?dayNightMode=${options.mode}`, {
|
||||
method: "post",
|
||||
body: JSON.stringify(dayNightPayload),
|
||||
});
|
||||
if (!response.ok) throw new Error("cannot update camera mode");
|
||||
return response.json();
|
||||
};
|
||||
|
||||
async function zoomIn(options: ZoomInOptions) {
|
||||
console.log(options);
|
||||
const response = await fetch(
|
||||
`${CAM_BASE}/Ip${options.camera}-command?magnification=${options.multiplierText?.toLowerCase()}`,
|
||||
{
|
||||
signal: AbortSignal.timeout(500),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
}
|
||||
);
|
||||
if (!response.ok) {
|
||||
@@ -22,7 +45,7 @@ async function zoomIn(options: ZoomInOptions) {
|
||||
async function fetchZoomInConfig({ queryKey }: QueryFunctionContext<[string, zoomConfig]>) {
|
||||
const [, { camera }] = queryKey;
|
||||
const response = await fetch(`${CAM_BASE}/api/fetch-config?id=Ip${camera}`, {
|
||||
signal: AbortSignal.timeout(500),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error("Cannot get camera zoom settings");
|
||||
@@ -34,11 +57,6 @@ export const useCameraZoom = (options: zoomConfig) => {
|
||||
const mutation = useMutation({
|
||||
mutationKey: ["zoomIn"],
|
||||
mutationFn: (options: ZoomInOptions) => zoomIn(options),
|
||||
onError: (err) => {
|
||||
toast.error(`Failed to update zoom settings: ${err.message}`, {
|
||||
id: "zoom",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const query = useQuery({
|
||||
@@ -52,3 +70,20 @@ export const useCameraZoom = (options: zoomConfig) => {
|
||||
|
||||
return { mutation, query };
|
||||
};
|
||||
|
||||
export const useCameraMode = (option: { camera: string }) => {
|
||||
const cameraModeQuery = useQuery({
|
||||
queryKey: ["getCameraMode"],
|
||||
queryFn: () => getCameraMode(option),
|
||||
});
|
||||
|
||||
const cameraModeMutation = useMutation({
|
||||
mutationKey: ["updateCameraMode"],
|
||||
mutationFn: updateCameraMode,
|
||||
});
|
||||
|
||||
return {
|
||||
cameraModeQuery,
|
||||
cameraModeMutation,
|
||||
};
|
||||
};
|
||||
|
||||
@@ -6,7 +6,7 @@ const apiUrl = CAM_BASE;
|
||||
// const fetch_url = `http://100.82.205.44/Colour-preview`;
|
||||
async function fetchSnapshot(cameraSide: string) {
|
||||
const response = await fetch(`${apiUrl}/${cameraSide}-preview`, {
|
||||
signal: AbortSignal.timeout(500),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
});
|
||||
if (!response.ok) {
|
||||
throw new Error("Cannot reach endpoint");
|
||||
|
||||
@@ -8,7 +8,7 @@ import { toast } from "sonner";
|
||||
async function fetchNPEDDetails() {
|
||||
const fetchUrl = `${CAM_BASE}/api/fetch-config?id=NPED`;
|
||||
const response = await fetch(fetchUrl, {
|
||||
signal: AbortSignal.timeout(500),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
});
|
||||
if (!response.ok) throw new Error("Cannot reach fetch-config endpoint");
|
||||
|
||||
|
||||
48
src/hooks/useSightingAmend.ts
Normal file
48
src/hooks/useSightingAmend.ts
Normal file
@@ -0,0 +1,48 @@
|
||||
import { useMutation, useQuery } from "@tanstack/react-query";
|
||||
import { CAM_BASE } from "../utils/config";
|
||||
import type { InitialValuesForm } from "../types/types";
|
||||
|
||||
const getSightingAmend = async () => {
|
||||
const response = await fetch(`${CAM_BASE}/api/fetch-config?id=SightingAmmendA`);
|
||||
if (!response.ok) throw new Error("Cannot reach sighting amend endpoint");
|
||||
return response.json();
|
||||
};
|
||||
|
||||
const updateSightingAmend = async (data: InitialValuesForm) => {
|
||||
const updateSightingAmendPayload = {
|
||||
id: "SightingAmmendA",
|
||||
fields: [
|
||||
{
|
||||
property: "propOverviewQuality",
|
||||
value: data.overviewQuality,
|
||||
},
|
||||
{
|
||||
property: "propOverviewImageScaleFactor",
|
||||
value: data.cropSizeFactor,
|
||||
},
|
||||
],
|
||||
};
|
||||
const response = await fetch(`${CAM_BASE}/api/update-config?id=SightingAmmendA`, {
|
||||
method: "Post",
|
||||
body: JSON.stringify(updateSightingAmendPayload),
|
||||
});
|
||||
if (!response.ok) throw new Error("cannot update camera control");
|
||||
return response.json();
|
||||
};
|
||||
|
||||
export const useSightingAmend = () => {
|
||||
const sightingAmendQuery = useQuery({
|
||||
queryKey: ["getSightingAmend"],
|
||||
queryFn: getSightingAmend,
|
||||
});
|
||||
|
||||
const sightingAmendMutation = useMutation({
|
||||
mutationKey: ["updateSightingAmend"],
|
||||
mutationFn: updateSightingAmend,
|
||||
});
|
||||
|
||||
return {
|
||||
sightingAmendQuery,
|
||||
sightingAmendMutation,
|
||||
};
|
||||
};
|
||||
@@ -12,7 +12,7 @@ import { useCachedSoundSrc } from "./usecachedSoundSrc";
|
||||
|
||||
async function fetchSighting(url: string | undefined, ref: number): Promise<SightingType> {
|
||||
const res = await fetch(`${url}${ref}`, {
|
||||
signal: AbortSignal.timeout(5000),
|
||||
signal: AbortSignal.timeout(300000),
|
||||
});
|
||||
if (!res.ok) throw new Error(String(res.status));
|
||||
return res.json();
|
||||
@@ -48,7 +48,7 @@ export function useSightingFeed(url: string | undefined) {
|
||||
return 100;
|
||||
}
|
||||
|
||||
if (now - lastValidTimestamp.current > 60_000) {
|
||||
if (now - lastValidTimestamp.current > 600_000) {
|
||||
currentRef.current = -1;
|
||||
lastValidTimestamp.current = now;
|
||||
}
|
||||
|
||||
@@ -58,6 +58,8 @@ export type InitialValuesForm = {
|
||||
password: string;
|
||||
connectTimeoutSeconds: number;
|
||||
readTimeoutSeconds: number;
|
||||
overviewQuality?: string;
|
||||
cropSizeFactor?: string;
|
||||
};
|
||||
|
||||
export type InitialValuesFormErrors = {
|
||||
|
||||
Reference in New Issue
Block a user