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:
2025-09-09 15:57:35 +01:00
parent 0c405d2038
commit 70d0d3234d
14 changed files with 163 additions and 113 deletions

View File

@@ -40,7 +40,7 @@ export function useGetOverviewSnapshot(cameraSide: string) {
queryKey: ["overviewSnapshot", cameraSide],
queryFn: () => fetchSnapshot(cameraSide),
refetchOnWindowFocus: false,
// refetchInterval: 1000,
refetchInterval: 250,
});
useEffect(() => {

View File

@@ -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,
};
}