fix: prevent incoming packets from closing user-opened map popup
Add a client-side userOpenedPopupMarkerId lock that's set instantly when a user manually opens a popup (via click, OMS spiderfy click, or long-press) and cleared when the popup closes. All programmatic openPopup paths (highlight_packet, addMarker openPopup flag) now respect the lock. Closes the network round-trip race where new packets arriving between the user's click and the server's marker_clicked ack could steal the popup.
This commit is contained in:
parent
5e277ddb9d
commit
f005a1a119
2 changed files with 22 additions and 6 deletions
|
|
@ -682,6 +682,10 @@ let MapAPRSMap = {
|
|||
|
||||
// Add click handler for spiderfied markers
|
||||
self.oms.addListener("click", function (marker: Marker) {
|
||||
const aprsMarker = marker as APRSMarker;
|
||||
if (aprsMarker._markerId) {
|
||||
self.userOpenedPopupMarkerId = aprsMarker._markerId;
|
||||
}
|
||||
if (marker.openPopup) marker.openPopup();
|
||||
});
|
||||
|
||||
|
|
@ -760,6 +764,10 @@ let MapAPRSMap = {
|
|||
});
|
||||
|
||||
if (nearestMarker) {
|
||||
const aprsMarker = nearestMarker as APRSMarker;
|
||||
if (aprsMarker._markerId) {
|
||||
self.userOpenedPopupMarkerId = aprsMarker._markerId;
|
||||
}
|
||||
nearestMarker.openPopup();
|
||||
}
|
||||
};
|
||||
|
|
@ -1263,8 +1271,10 @@ let MapAPRSMap = {
|
|||
|
||||
// Handle highlighting the latest packet (open its popup)
|
||||
self.currentPopupMarkerId = null;
|
||||
self.userOpenedPopupMarkerId = null;
|
||||
self.handleEvent("highlight_packet", (data: { id: string }) => {
|
||||
if (!data.id || !self.markers || !self.markerStates) return;
|
||||
if (self.userOpenedPopupMarkerId) return;
|
||||
|
||||
// Close previous popup if open
|
||||
if (
|
||||
|
|
@ -1843,8 +1853,8 @@ let MapAPRSMap = {
|
|||
|
||||
if (!positionChanged && !dataChanged) {
|
||||
// No changes needed, skip update
|
||||
// But if openPopup is requested, open it
|
||||
if (data.openPopup && existingMarker.openPopup) {
|
||||
// But if openPopup is requested and no user popup is locked, open it
|
||||
if (data.openPopup && existingMarker.openPopup && !self.userOpenedPopupMarkerId) {
|
||||
existingMarker.openPopup();
|
||||
}
|
||||
return;
|
||||
|
|
@ -1898,6 +1908,7 @@ let MapAPRSMap = {
|
|||
const marker = L.marker([lat, lng], {
|
||||
icon: self.createMarkerIcon(data),
|
||||
});
|
||||
(marker as APRSMarker)._markerId = data.id;
|
||||
|
||||
// Add popup if content provided
|
||||
if (data.popup) {
|
||||
|
|
@ -1905,7 +1916,9 @@ let MapAPRSMap = {
|
|||
|
||||
// Handle popup close events - check if hook is still connected
|
||||
marker.on("popupclose", () => {
|
||||
// Only send event if not destroyed and pushEvent is still the original function
|
||||
if (self.userOpenedPopupMarkerId === data.id) {
|
||||
self.userOpenedPopupMarkerId = null;
|
||||
}
|
||||
if (
|
||||
!self.isDestroyed &&
|
||||
self.pushEvent &&
|
||||
|
|
@ -1914,7 +1927,6 @@ let MapAPRSMap = {
|
|||
try {
|
||||
self.pushEvent("popup_closed", {});
|
||||
} catch (e) {
|
||||
// Silently ignore errors if context is lost
|
||||
console.debug("Unable to send popup_closed event:", e);
|
||||
}
|
||||
}
|
||||
|
|
@ -1927,9 +1939,11 @@ let MapAPRSMap = {
|
|||
// The OMS will handle the click and open the popup after spiderfying
|
||||
if (self.oms && marker._oms && marker._omsData) {
|
||||
// Marker is currently spiderfied, allow normal popup
|
||||
self.userOpenedPopupMarkerId = data.id;
|
||||
if (marker.openPopup) marker.openPopup();
|
||||
} else if (!self.oms || !marker._oms) {
|
||||
// Normal marker not managed by OMS
|
||||
self.userOpenedPopupMarkerId = data.id;
|
||||
if (marker.openPopup) marker.openPopup();
|
||||
}
|
||||
// If marker._oms is true but no _omsData, let OMS handle it (will spiderfy)
|
||||
|
|
@ -2059,8 +2073,8 @@ let MapAPRSMap = {
|
|||
);
|
||||
}
|
||||
|
||||
// Open popup if requested
|
||||
if (data.openPopup && marker.openPopup) {
|
||||
// Open popup if requested and no user popup is locked
|
||||
if (data.openPopup && marker.openPopup && !self.userOpenedPopupMarkerId) {
|
||||
marker.openPopup();
|
||||
}
|
||||
|
||||
|
|
|
|||
2
assets/js/types/map.d.ts
vendored
2
assets/js/types/map.d.ts
vendored
|
|
@ -23,6 +23,8 @@ export interface LiveViewHookContext {
|
|||
maxInitializationAttempts?: number;
|
||||
lastZoom?: number;
|
||||
currentPopupMarkerId?: string | null;
|
||||
userOpenedPopupMarkerId?: string | null;
|
||||
markerZIndexCounter?: number;
|
||||
oms?: OverlappingMarkerSpiderfier;
|
||||
programmaticMoveId?: string;
|
||||
programmaticMoveTimeout?: ReturnType<typeof setTimeout>;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue