diff --git a/src/components/SightingModal/SightingModal.tsx b/src/components/SightingModal/SightingModal.tsx
index 9e31bfc..668f202 100644
--- a/src/components/SightingModal/SightingModal.tsx
+++ b/src/components/SightingModal/SightingModal.tsx
@@ -23,8 +23,7 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:
const { dispatch } = useAlertHitContext();
const { query, mutation } = useCameraBlackboard();
- const hotlistName = getHotlistName(sighting?.metadata?.hotlistMatches);
-
+ const hotlistNames = getHotlistName(sighting?.metadata?.hotlistMatches);
const handleAcknowledgeButton = () => {
try {
if (!sighting) {
@@ -117,16 +116,6 @@ const SightingModal = ({ isSightingModalOpen, handleClose, sighting, onDelete }:

([]);
useNow(1000);
const { state } = useSoundContext();
@@ -78,6 +79,14 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
const hasAutoOpenedRef = useRef(false);
const npedRef = useRef(false);
+ const enqueue = useCallback((sighting: SightingType, kind: HitKind) => {
+ const id = sighting.vrm ?? sighting.ref;
+ if (processedRefs.current.has(id)) return;
+ processedRefs.current.add(id);
+
+ setModalQueue((q) => [...q, { id, sighting, kind }]);
+ }, []);
+
const reduceObject = (obj: SightingType): ReducedSightingType => {
return {
vrm: obj.vrm,
@@ -113,26 +122,15 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
const id = sighting.vrm;
if (processedRefs.current.has(id)) continue;
- const isHot = checkIsHotListHit(sighting);
- const cat = sighting?.metadata?.npedJSON?.["NPED CATEGORY"];
+ const isHotlistHit = checkIsHotListHit(sighting);
+ const npedcategory = sighting?.metadata?.npedJSON?.["NPED CATEGORY"];
+ const isNPED = npedcategory === "A" || npedcategory === "B" || npedcategory === "C";
- if (cat === "A" || cat === "B" || cat === "C") {
- npedSound();
- setSelectedSighting(sighting);
- setSightingModalOpen(true);
- processedRefs.current.add(id);
- break; // stop after one new open per render cycle
- }
-
- if (isHot) {
- hotlistsound();
- setSelectedSighting(sighting);
- setSightingModalOpen(true);
- processedRefs.current.add(id);
- break;
+ if (isNPED || isHotlistHit) {
+ enqueue(sighting, isNPED ? "NPED" : "HOTLIST"); // enqueue ONLY
}
}
- }, [rows, hotlistsound, npedSound, setSightingModalOpen, setSelectedSighting]);
+ }, [rows, enqueue]);
useEffect(() => {
rows?.forEach((obj) => {
@@ -165,22 +163,33 @@ export default function SightingHistoryWidget({ className, title }: SightingHist
});
if (firstNPED) {
- setSelectedSighting(firstNPED);
- npedSound();
- setSightingModalOpen(true);
+ enqueue(firstNPED, "NPED");
+
npedRef.current = true;
}
if (firstHot) {
- setSelectedSighting(firstHot);
- hotlistsound();
- setSightingModalOpen(true);
+ enqueue(firstHot, "HOTLIST");
+
hasAutoOpenedRef.current = true;
}
- }, [hotlistsound, npedSound, setSelectedSighting]);
+ }, [enqueue, hotlistsound, npedSound, rows, setSelectedSighting, setSightingModalOpen]);
+
+ useEffect(() => {
+ if (!isSightingModalOpen && modalQueue.length > 0) {
+ const next = modalQueue[0];
+
+ if (next.kind === "NPED") npedSound();
+ else hotlistsound();
+
+ setSelectedSighting(next.sighting);
+ setSightingModalOpen(true);
+ }
+ }, [isSightingModalOpen, npedSound, hotlistsound, setSelectedSighting, setSightingModalOpen, modalQueue]);
const handleClose = () => {
setSightingModalOpen(false);
+ setModalQueue((q) => q.slice(1));
};
return (
<>
diff --git a/src/types/types.ts b/src/types/types.ts
index 72a2369..504ae90 100644
--- a/src/types/types.ts
+++ b/src/types/types.ts
@@ -371,3 +371,11 @@ export type ModemSettingsType = {
password: string;
authenticationType: string;
};
+
+export type HitKind = "NPED" | "HOTLIST";
+
+export type QueuedHit = {
+ id: number | string;
+ sighting: SightingType;
+ kind: HitKind;
+};
diff --git a/src/utils/utils.ts b/src/utils/utils.ts
index dc164e9..537853e 100644
--- a/src/utils/utils.ts
+++ b/src/utils/utils.ts
@@ -147,10 +147,12 @@ export const checkIsHotListHit = (sigthing: SightingType | null) => {
};
export function getHotlistName(obj: HotlistMatches | undefined) {
- if (!obj || Object.values(obj).includes(false)) return;
+ if (!obj) return;
- const keys = Object.keys(obj);
- return keys;
+ const hotlistNames = Object.entries(obj)
+ .filter(([, value]) => value === true)
+ .map(([key]) => key);
+ return hotlistNames;
}
export const getNPEDCategory = (r?: SightingType | null) =>