More messing about, and learning how it all works. Added time to header. Changed some padding. Changed video to preview not target detection. Added TODO list.
This commit is contained in:
@@ -40,7 +40,7 @@ export function useGetOverviewSnapshot(cameraSide: string) {
|
||||
queryKey: ["overviewSnapshot", cameraSide],
|
||||
queryFn: () => fetchSnapshot(cameraSide),
|
||||
refetchOnWindowFocus: false,
|
||||
// refetchInterval: 1000,
|
||||
refetchInterval: 250,
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
|
||||
@@ -1,89 +1,70 @@
|
||||
import { useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import type { SightingWidgetType } from "../types/types";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
|
||||
// const url = `http://100.82.205.44/SightingListFront/sightingSummary?mostRecentRef=-1`;
|
||||
|
||||
async function fetchSighting(url: string, ref: number, signal?: AbortSignal) {
|
||||
const dynamicUrl = `${url}${ref}`;
|
||||
|
||||
const res = await fetch(dynamicUrl, { signal });
|
||||
async function fetchSighting(url: string, ref: number): Promise<SightingWidgetType> {
|
||||
const res = await fetch(`${url}${ref}`);
|
||||
if (!res.ok) throw new Error(String(res.status));
|
||||
return (await res.json()) as SightingWidgetType;
|
||||
return await res.json();
|
||||
}
|
||||
|
||||
export function useSightingFeed(url: string) {
|
||||
const [sightings, setSightings] = useState<SightingWidgetType[]>(
|
||||
() => Array(7).fill(null) as unknown as SightingWidgetType[]
|
||||
);
|
||||
const [noSighting, setNoSighting] = useState(false);
|
||||
const [sightings, setSightings] = useState<SightingWidgetType[]>([]);
|
||||
const [selectedRef, setSelectedRef] = useState<number | null>(null);
|
||||
const [mostRecent, setMostRecent] = useState<SightingWidgetType | null>(null);
|
||||
|
||||
const mostRecentRef = useRef<number>(-1);
|
||||
|
||||
const lastSeenRef = useRef<number | null>(null);
|
||||
|
||||
const { data, isPending } = useQuery({
|
||||
queryKey: ["sighting"],
|
||||
queryFn: ({ signal }) => fetchSighting(url, mostRecentRef.current, signal),
|
||||
refetchInterval: 2000,
|
||||
refetchIntervalInBackground: true,
|
||||
refetchOnWindowFocus: false,
|
||||
staleTime: 0,
|
||||
notifyOnChangeProps: ["data"],
|
||||
});
|
||||
const currentRef = useRef<number>(-1);
|
||||
const pollingTimeout = useRef<ReturnType<typeof setTimeout> | null>(null);
|
||||
const lastValidTimestamp = useRef<number>(Date.now());
|
||||
|
||||
useEffect(() => {
|
||||
if (!data) return;
|
||||
const poll = async () => {
|
||||
try {
|
||||
const data = await fetchSighting(url, currentRef.current);
|
||||
|
||||
if (data.ref === -1) {
|
||||
setNoSighting(true);
|
||||
} else {
|
||||
setNoSighting(false);
|
||||
}
|
||||
if (data.ref === lastSeenRef.current) return; // duplicate payload → do nothing
|
||||
lastSeenRef.current = data.ref;
|
||||
const now = Date.now();
|
||||
|
||||
setMostRecent(data);
|
||||
if (data.ref === -1) {
|
||||
if (now - lastValidTimestamp.current > 60000) {
|
||||
console.warn("No valid sighting in over a minute. Restarting...");
|
||||
currentRef.current = -1;
|
||||
lastValidTimestamp.current = now;
|
||||
}
|
||||
|
||||
setSightings((prev) => {
|
||||
const existing = prev.find((p) => p?.ref === data.ref);
|
||||
const next = existing
|
||||
? prev
|
||||
: [data, ...prev.filter(Boolean)].slice(0, 7);
|
||||
pollingTimeout.current = setTimeout(poll, 400);
|
||||
} else {
|
||||
currentRef.current = data.ref;
|
||||
lastValidTimestamp.current = now;
|
||||
|
||||
const stillHasSelection =
|
||||
selectedRef != null && next.some((s) => s?.ref === selectedRef);
|
||||
if (!stillHasSelection) {
|
||||
setSelectedRef(data.ref);
|
||||
setSightings(prev => {
|
||||
const updated = [data, ...prev].slice(0, 7);
|
||||
return updated;
|
||||
});
|
||||
|
||||
setMostRecent(data);
|
||||
setSelectedRef(data.ref);
|
||||
|
||||
pollingTimeout.current = setTimeout(poll, 100);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error("Polling error:", err);
|
||||
pollingTimeout.current = setTimeout(poll, 100);
|
||||
}
|
||||
};
|
||||
|
||||
return next;
|
||||
});
|
||||
// setMostRecent(sightings[0]);
|
||||
// setMostRecent(data);
|
||||
mostRecentRef.current = data.ref ?? -1;
|
||||
}, [data, selectedRef, sightings]);
|
||||
poll();
|
||||
|
||||
const selected = useMemo(
|
||||
() =>
|
||||
selectedRef == null
|
||||
? null
|
||||
: sightings.find((s) => s?.ref === selectedRef) ?? null,
|
||||
[sightings, selectedRef]
|
||||
);
|
||||
return () => {
|
||||
if (pollingTimeout.current) clearTimeout(pollingTimeout.current);
|
||||
};
|
||||
}, [url]);
|
||||
|
||||
const effectiveSelected = selected ?? mostRecent ?? null;
|
||||
const selected = sightings.find(s => s?.ref === selectedRef) ?? mostRecent;
|
||||
|
||||
return {
|
||||
sightings,
|
||||
selectedRef,
|
||||
setSelectedRef,
|
||||
mostRecent,
|
||||
effectiveSelected,
|
||||
mostRecentRef,
|
||||
isPending,
|
||||
noSighting,
|
||||
effectiveSelected: selected,
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user