From 56dacdcbbd194b71fb046873090684d44fda2fa0 Mon Sep 17 00:00:00 2001 From: Dmitry Popov Date: Tue, 6 Jan 2026 16:37:29 +0100 Subject: [PATCH] fix(core): fixed rally point cancel logic --- .../PingsInterface/PingsInterface.tsx | 81 ++++++++++--------- .../mapRootProvider/hooks/useComments.ts | 1 - lib/wanderer_app/map/map_manager.ex | 2 +- .../map/server/map_server_pings_impl.ex | 30 ++++--- .../event_handlers/map_pings_event_handler.ex | 40 ++++----- 5 files changed, 82 insertions(+), 72 deletions(-) diff --git a/assets/js/hooks/Mapper/components/mapInterface/components/PingsInterface/PingsInterface.tsx b/assets/js/hooks/Mapper/components/mapInterface/components/PingsInterface/PingsInterface.tsx index 1b14ba55..9c7233b1 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/components/PingsInterface/PingsInterface.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/components/PingsInterface/PingsInterface.tsx @@ -121,6 +121,7 @@ export const PingsInterface = ({ hasLeftOffset }: PingsInterfaceProps) => { useEffect(() => { if (!ping) { + setIsShow(false); return; } @@ -161,27 +162,26 @@ export const PingsInterface = ({ hasLeftOffset }: PingsInterfaceProps) => { }; }, [interfaceSettings]); - if (!ping) { - return null; - } - - const isShowSelectedSystem = selectedSystem != null && selectedSystem !== ping.solar_system_id; + const isShowSelectedSystem = ping && selectedSystem != null && selectedSystem !== ping.solar_system_id; + // Only render Toast when there's a ping return ( <> - ( -
-
- + {ping && ( + ( +
+
+
@@ -253,28 +253,33 @@ export const PingsInterface = ({ hasLeftOffset }: PingsInterfaceProps) => { {/*/>*/}
- )} - >
+ )} + > + )} - + {ping && ( + <> + - + + + )} ); }; diff --git a/assets/js/hooks/Mapper/mapRootProvider/hooks/useComments.ts b/assets/js/hooks/Mapper/mapRootProvider/hooks/useComments.ts index f281329a..d311d7ab 100644 --- a/assets/js/hooks/Mapper/mapRootProvider/hooks/useComments.ts +++ b/assets/js/hooks/Mapper/mapRootProvider/hooks/useComments.ts @@ -63,7 +63,6 @@ export const useComments = ({ outCommand }: UseCommentsProps): UseCommentsData = const removeComment = useCallback((systemId: number, commentId: string) => { const cSystem = commentBySystemsRef.current.get(systemId); - console.log('cSystem', cSystem); if (!cSystem) { return; } diff --git a/lib/wanderer_app/map/map_manager.ex b/lib/wanderer_app/map/map_manager.ex index a4b06ded..ceb69ac1 100644 --- a/lib/wanderer_app/map/map_manager.ex +++ b/lib/wanderer_app/map/map_manager.ex @@ -16,7 +16,7 @@ defmodule WandererApp.Map.Manager do @maps_queue :maps_queue @check_maps_queue_interval :timer.seconds(1) - @pings_cleanup_interval :timer.minutes(1) + @pings_cleanup_interval :timer.minutes(5) @pings_expire_minutes 60 # Test-aware async task runner diff --git a/lib/wanderer_app/map/server/map_server_pings_impl.ex b/lib/wanderer_app/map/server/map_server_pings_impl.ex index 1f7a097a..68935fb3 100644 --- a/lib/wanderer_app/map/server/map_server_pings_impl.ex +++ b/lib/wanderer_app/map/server/map_server_pings_impl.ex @@ -72,14 +72,15 @@ defmodule WandererApp.Map.Server.PingsImpl do type: type } = _ping_info ) do - Logger.debug("cancel_ping called: map_id=#{map_id}, ping_id=#{ping_id}, type=#{type}") - case WandererApp.MapPingsRepo.get_by_id(ping_id) do + result = WandererApp.MapPingsRepo.get_by_id(ping_id) + + case result do {:ok, %{system: %{id: system_id, name: system_name, solar_system_id: solar_system_id}} = ping} -> with {:ok, character} <- WandererApp.Character.get_character(character_id), :ok <- WandererApp.MapPingsRepo.destroy(ping) do - Logger.debug("Ping #{ping_id} destroyed successfully") + Logger.debug("Ping #{ping_id} destroyed successfully, broadcasting :ping_cancelled") Impl.broadcast!(map_id, :ping_cancelled, %{ id: ping_id, @@ -87,6 +88,8 @@ defmodule WandererApp.Map.Server.PingsImpl do type: type }) + Logger.debug("Broadcast :ping_cancelled sent for ping #{ping_id}") + # Broadcast rally point removal events to external clients (webhooks/SSE) if type == 1 do WandererApp.ExternalEvents.broadcast(map_id, :rally_point_removed, %{ @@ -113,8 +116,6 @@ defmodule WandererApp.Map.Server.PingsImpl do # Handle case where ping exists but system was deleted (nil) {:ok, %{system: nil} = ping} -> - Logger.warning("Ping #{ping_id} has no associated system, destroying orphaned ping") - case WandererApp.MapPingsRepo.destroy(ping) do :ok -> Impl.broadcast!(map_id, :ping_cancelled, %{ @@ -129,19 +130,22 @@ defmodule WandererApp.Map.Server.PingsImpl do {:error, %Ash.Error.Query.NotFound{}} -> # Ping already deleted (possibly by cascade deletion from map/system/character removal, - # auto-expiry, or concurrent cancellation). This is not an error - the desired state - # (ping is gone) is already achieved. Just broadcast the cancellation event. - Logger.debug( - "Ping #{ping_id} not found during cancellation - already deleted, skipping broadcast" - ) + # auto-expiry, or concurrent cancellation). Broadcast cancellation so frontend updates. + Impl.broadcast!(map_id, :ping_cancelled, %{ + id: ping_id, + solar_system_id: nil, + type: type + }) :ok {:error, %Ash.Error.Invalid{errors: [%Ash.Error.Query.NotFound{} | _]}} -> # Same as above, but Ash wraps NotFound inside Invalid in some cases - Logger.debug( - "Ping #{ping_id} not found during cancellation - already deleted, skipping broadcast" - ) + Impl.broadcast!(map_id, :ping_cancelled, %{ + id: ping_id, + solar_system_id: nil, + type: type + }) :ok diff --git a/lib/wanderer_app_web/live/map/event_handlers/map_pings_event_handler.ex b/lib/wanderer_app_web/live/map/event_handlers/map_pings_event_handler.ex index be2e8d58..b1e02fe4 100644 --- a/lib/wanderer_app_web/live/map/event_handlers/map_pings_event_handler.ex +++ b/lib/wanderer_app_web/live/map/event_handlers/map_pings_event_handler.ex @@ -51,14 +51,18 @@ defmodule WandererAppWeb.MapPingsEventHandler do map_ui_ping(ping_info) ]) - def handle_server_event(%{event: :ping_cancelled, payload: ping_info}, socket), - do: - socket - |> MapEventHandler.push_map_event("ping_cancelled", %{ - id: ping_info.id, - solar_system_id: ping_info.solar_system_id, - type: ping_info.type - }) + def handle_server_event(%{event: :ping_cancelled, payload: ping_info}, socket) do + Logger.debug( + "handle_server_event :ping_cancelled - id: #{ping_info.id}, is_version_valid?: #{inspect(socket.assigns[:is_version_valid?])}" + ) + + socket + |> MapEventHandler.push_map_event("ping_cancelled", %{ + id: ping_info.id, + solar_system_id: ping_info.solar_system_id, + type: ping_info.type + }) + end def handle_server_event(event, socket), do: MapCoreEventHandler.handle_server_event(event, socket) @@ -153,8 +157,6 @@ defmodule WandererAppWeb.MapPingsEventHandler do socket ) when not is_nil(main_character_id) do - Logger.debug("handle_ui_event cancel_ping: id=#{id}, type=#{type}, map_id=#{map_id}") - map_id |> WandererApp.Map.Server.cancel_ping(%{ id: id, @@ -172,8 +174,6 @@ defmodule WandererAppWeb.MapPingsEventHandler do _event, %{assigns: %{main_character_id: nil}} = socket ) do - Logger.warning("add_ping blocked: main_character_id is nil") - {:noreply, socket |> MapEventHandler.push_map_event("ping_blocked", %{ @@ -188,8 +188,6 @@ defmodule WandererAppWeb.MapPingsEventHandler do _event, %{assigns: %{has_tracked_characters?: false}} = socket ) do - Logger.warning("add_ping blocked: no tracked characters") - {:noreply, socket |> MapEventHandler.push_map_event("ping_blocked", %{ @@ -204,8 +202,6 @@ defmodule WandererAppWeb.MapPingsEventHandler do _event, %{assigns: %{is_subscription_active?: false}} = socket ) do - Logger.warning("add_ping blocked: subscription not active") - {:noreply, socket |> MapEventHandler.push_map_event("ping_blocked", %{ @@ -220,8 +216,6 @@ defmodule WandererAppWeb.MapPingsEventHandler do _event, %{assigns: %{user_permissions: %{update_system: false}}} = socket ) do - Logger.warning("add_ping blocked: no update_system permission") - {:noreply, socket |> MapEventHandler.push_map_event("ping_blocked", %{ @@ -236,7 +230,15 @@ defmodule WandererAppWeb.MapPingsEventHandler do _event, %{assigns: %{main_character_id: nil}} = socket ) do - Logger.warning("cancel_ping blocked: main_character_id is nil") + {:noreply, socket} + end + + # Catch-all for cancel_ping to debug why it doesn't match + def handle_ui_event( + "cancel_ping", + event, + %{assigns: assigns} = socket + ) do {:noreply, socket} end