@@ -30,13 +30,26 @@ const bandFromAnyFrequency = (freq) => {
3030 return normalizeBandKey ( getBandFromFreq ( n ) ) ;
3131} ;
3232
33- export function useLayer ( { enabled = false , opacity = 0.7 , map = null , mapBandFilter } ) {
33+ const findLatestLocatedQso = ( qsos ) => {
34+ for ( let i = qsos . length - 1 ; i >= 0 ; i -= 1 ) {
35+ const qso = qsos [ i ] ;
36+ const lat = parseFloat ( qso ?. lat ) ;
37+ const lon = parseFloat ( qso ?. lon ) ;
38+ if ( Number . isFinite ( lat ) && Number . isFinite ( lon ) ) {
39+ return { qso, lat, lon } ;
40+ }
41+ }
42+ return null ;
43+ } ;
44+
45+ export function useLayer ( { enabled = false , opacity = 0.7 , map = null , onDXChange, mapBandFilter } ) {
3446 const [ qsos , setQsos ] = useState ( [ ] ) ;
3547 const [ deLocation , setDeLocation ] = useState ( null ) ;
3648 const markersRef = useRef ( [ ] ) ;
3749 const linesRef = useRef ( [ ] ) ;
3850 const pollRef = useRef ( null ) ;
3951 const configLoadedRef = useRef ( false ) ;
52+ const lastHandledTargetKeyRef = useRef ( null ) ;
4053
4154 useEffect ( ( ) => {
4255 if ( ! enabled || configLoadedRef . current ) return ;
@@ -80,6 +93,31 @@ export function useLayer({ enabled = false, opacity = 0.7, map = null, mapBandFi
8093 } ;
8194 } , [ enabled ] ) ;
8295
96+ useEffect ( ( ) => {
97+ if ( ! enabled ) {
98+ lastHandledTargetKeyRef . current = null ;
99+ }
100+ } , [ enabled ] ) ;
101+
102+ useEffect ( ( ) => {
103+ if ( ! enabled || typeof onDXChange !== 'function' ) return ;
104+
105+ const latestLocated = findLatestLocatedQso ( qsos ) ;
106+ if ( ! latestLocated ) return ;
107+
108+ const { qso : latestLocatedQso , lat, lon } = latestLocated ;
109+ const targetKey =
110+ latestLocatedQso . id ||
111+ `${ latestLocatedQso . timestamp || '' } :${ latestLocatedQso . dxCall || '' } :${ lat . toFixed ( 4 ) } :${ lon . toFixed ( 4 ) } ` ;
112+
113+ if ( lastHandledTargetKeyRef . current === targetKey ) return ;
114+
115+ // Remember handled QSOs even while DX is locked so unlocking later
116+ // does not retroactively replay an older contest contact.
117+ lastHandledTargetKeyRef . current = targetKey ;
118+ onDXChange ( { lat, lon } ) ;
119+ } , [ enabled , qsos , onDXChange ] ) ;
120+
83121 useEffect ( ( ) => {
84122 if ( ! map || typeof L === 'undefined' ) return ;
85123
0 commit comments