mirror of
				https://github.com/wanderer-industries/wanderer
				synced 2025-10-31 14:37:04 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			v1.67.5
			...
			map-events
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | b1f1098df6 | ||
|   | ed5d824c0a | ||
|   | d8e4631981 | 
| @@ -79,7 +79,7 @@ export const SystemCustomLabelDialog = ({ systemId, visible, setVisible }: Syste | ||||
|  | ||||
|   // @ts-ignore | ||||
|   const handleInput = useCallback(e => { | ||||
|     e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9[\](){}]/g, ''); | ||||
|     e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9\-[\](){}]/g, ''); | ||||
|   }, []); | ||||
|  | ||||
|   return ( | ||||
|   | ||||
| @@ -90,7 +90,7 @@ export const SystemSettingsDialog = ({ systemId, visible, setVisible }: SystemSe | ||||
|   }, []); | ||||
|  | ||||
|   const handleInput = useCallback((e: any) => { | ||||
|     e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9[\](){}]/g, ''); | ||||
|     e.target.value = e.target.value.toUpperCase().replace(/[^A-Z0-9\-[\](){}]/g, ''); | ||||
|   }, []); | ||||
|  | ||||
|   return ( | ||||
|   | ||||
| @@ -55,11 +55,11 @@ map_subscriptions_enabled = | ||||
|  | ||||
| map_subscription_characters_limit = | ||||
|   config_dir | ||||
|   |> get_int_from_path_or_env("WANDERER_MAP_SUBSCRIPTION_CHARACTERS_LIMIT", 100) | ||||
|   |> get_int_from_path_or_env("WANDERER_MAP_SUBSCRIPTION_CHARACTERS_LIMIT", 10_000) | ||||
|  | ||||
| map_subscription_hubs_limit = | ||||
|   config_dir | ||||
|   |> get_int_from_path_or_env("WANDERER_MAP_SUBSCRIPTION_HUBS_LIMIT", 10) | ||||
|   |> get_int_from_path_or_env("WANDERER_MAP_SUBSCRIPTION_HUBS_LIMIT", 100) | ||||
|  | ||||
| wallet_tracking_enabled = | ||||
|   config_dir | ||||
|   | ||||
| @@ -7,6 +7,8 @@ defmodule WandererApp do | ||||
|   if it comes from the database, an external API or others. | ||||
|   """ | ||||
|  | ||||
|   require Logger | ||||
|  | ||||
|   @doc """ | ||||
|   When used, dispatch to the appropriate domain service | ||||
|   """ | ||||
|   | ||||
| @@ -75,7 +75,7 @@ defmodule WandererApp.Map.PositionCalculator do | ||||
|   def get_available_positions(level, x, y, opts), | ||||
|     do: adjusted_coordinates(1 + level * 2, x, y, opts) | ||||
|  | ||||
|   defp edge_coordinates(n, opts) when n > 1 do | ||||
|   defp edge_coordinates(n, _opts) when n > 1 do | ||||
|     min = -div(n, 2) | ||||
|     max = div(n, 2) | ||||
|     # Top edge | ||||
|   | ||||
| @@ -193,7 +193,9 @@ defmodule WandererApp.Map.Server.Impl do | ||||
|  | ||||
|         :ok | ||||
|       else | ||||
|         {:error, _error} -> | ||||
|         _error -> | ||||
|           {:ok, character} = WandererApp.Character.get_character(character_id) | ||||
|           broadcast!(map_id, :character_added, character) | ||||
|           :ok | ||||
|       end | ||||
|     end) | ||||
| @@ -806,7 +808,7 @@ defmodule WandererApp.Map.Server.Impl do | ||||
|     } | ||||
|   end | ||||
|  | ||||
|   def handle_event({:options_updated, options}, %{map: map, map_id: map_id} = state), | ||||
|   def handle_event({:options_updated, options}, state), | ||||
|     do: %{ | ||||
|       state | ||||
|       | map_opts: [ | ||||
| @@ -1164,11 +1166,10 @@ defmodule WandererApp.Map.Server.Impl do | ||||
|               rtree_name | ||||
|             ) | ||||
|  | ||||
|             {:ok, | ||||
|              existing_system | ||||
|              |> WandererApp.MapSystemRepo.update_position!(%{position_x: x, position_y: y}) | ||||
|              |> WandererApp.MapSystemRepo.cleanup_labels(map_opts) | ||||
|              |> WandererApp.MapSystemRepo.cleanup_tags()} | ||||
|             existing_system | ||||
|             |> WandererApp.MapSystemRepo.update_position!(%{position_x: x, position_y: y}) | ||||
|             |> WandererApp.MapSystemRepo.cleanup_labels!(map_opts) | ||||
|             |> WandererApp.MapSystemRepo.cleanup_tags() | ||||
|           end | ||||
|  | ||||
|         _ -> | ||||
| @@ -1211,8 +1212,6 @@ defmodule WandererApp.Map.Server.Impl do | ||||
|         solar_system_id: solar_system_id | ||||
|       }) | ||||
|  | ||||
|     :telemetry.execute([:wanderer_app, :map, :system, :add], %{count: 1}) | ||||
|  | ||||
|     state | ||||
|   end | ||||
|  | ||||
| @@ -1683,11 +1682,11 @@ defmodule WandererApp.Map.Server.Impl do | ||||
|  | ||||
|   defp maybe_add_connection(_map_id, _location, _old_location, _character_id), do: :ok | ||||
|  | ||||
|   defp maybe_add_system(map_id, location, old_location, rtree_name, opts) | ||||
|   defp maybe_add_system(map_id, location, old_location, rtree_name, map_opts) | ||||
|        when not is_nil(location) do | ||||
|     case WandererApp.Map.check_location(map_id, location) do | ||||
|       {:ok, location} -> | ||||
|         {:ok, position} = calc_new_system_position(map_id, old_location, rtree_name, opts) | ||||
|         {:ok, position} = calc_new_system_position(map_id, old_location, rtree_name, map_opts) | ||||
|  | ||||
|         case WandererApp.MapSystemRepo.get_by_map_and_solar_system_id( | ||||
|                map_id, | ||||
| @@ -1696,10 +1695,12 @@ defmodule WandererApp.Map.Server.Impl do | ||||
|           {:ok, existing_system} when not is_nil(existing_system) -> | ||||
|             {:ok, updated_system} = | ||||
|               existing_system | ||||
|               |> WandererApp.MapSystemRepo.update_position(%{ | ||||
|               |> WandererApp.MapSystemRepo.update_position!(%{ | ||||
|                 position_x: position.x, | ||||
|                 position_y: position.y | ||||
|               }) | ||||
|               |> WandererApp.MapSystemRepo.cleanup_labels!(map_opts) | ||||
|               |> WandererApp.MapSystemRepo.cleanup_tags() | ||||
|  | ||||
|             @ddrt.insert( | ||||
|               {existing_system.solar_system_id, | ||||
| @@ -1721,7 +1722,7 @@ defmodule WandererApp.Map.Server.Impl do | ||||
|  | ||||
|           _ -> | ||||
|             {:ok, solar_system_info} = | ||||
|               WandererApp.Api.MapSolarSystem.by_solar_system_id(location.solar_system_id) | ||||
|               WandererApp.CachedInfo.get_system_static_info(location.solar_system_id) | ||||
|  | ||||
|             WandererApp.MapSystemRepo.create(%{ | ||||
|               map_id: map_id, | ||||
| @@ -1757,7 +1758,7 @@ defmodule WandererApp.Map.Server.Impl do | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   defp maybe_add_system(_map_id, _location, _old_location, _rtree_name, _opts), do: :ok | ||||
|   defp maybe_add_system(_map_id, _location, _old_location, _rtree_name, _map_opts), do: :ok | ||||
|  | ||||
|   defp calc_new_system_position(map_id, old_location, rtree_name, opts), | ||||
|     do: | ||||
|   | ||||
| @@ -33,7 +33,7 @@ defmodule WandererApp.MapSystemRepo do | ||||
|       {:error, error} | ||||
|   end | ||||
|  | ||||
|   def cleanup_labels(%{labels: labels} = system, opts) do | ||||
|   def cleanup_labels!(%{labels: labels} = system, opts) do | ||||
|     store_custom_labels? = | ||||
|       Keyword.get(opts, :store_custom_labels, "false") |> String.to_existing_atom() | ||||
|  | ||||
| @@ -47,7 +47,7 @@ defmodule WandererApp.MapSystemRepo do | ||||
|  | ||||
|   def cleanup_tags(system) do | ||||
|     system | ||||
|     |> WandererApp.Api.MapSystem.update_tag!(%{ | ||||
|     |> WandererApp.Api.MapSystem.update_tag(%{ | ||||
|       tag: nil | ||||
|     }) | ||||
|   end | ||||
| @@ -56,7 +56,7 @@ defmodule WandererApp.MapSystemRepo do | ||||
|     labels | ||||
|     |> Jason.decode!() | ||||
|     |> case do | ||||
|       %{"customLabel" => customLabel} = labels when is_binary(customLabel) -> | ||||
|       %{"customLabel" => customLabel} when is_binary(customLabel) -> | ||||
|         %{"customLabel" => customLabel, "labels" => []} | ||||
|         |> Jason.encode!() | ||||
|  | ||||
|   | ||||
| @@ -12,6 +12,7 @@ defmodule WandererAppWeb.MapPicker do | ||||
|     {:ok, socket} | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def update( | ||||
|         %{ | ||||
|           current_user: current_user, | ||||
| @@ -29,6 +30,7 @@ defmodule WandererAppWeb.MapPicker do | ||||
|      end)} | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def render(assigns) do | ||||
|     ~H""" | ||||
|     <div id={@id}> | ||||
| @@ -56,6 +58,7 @@ defmodule WandererAppWeb.MapPicker do | ||||
|     """ | ||||
|   end | ||||
|  | ||||
|   @impl true | ||||
|   def handle_event("select", %{"map_slug" => map_slug} = _params, socket) do | ||||
|     notify_to(socket.assigns.notify_to, socket.assigns.event_name, map_slug) | ||||
|  | ||||
|   | ||||
| @@ -0,0 +1,49 @@ | ||||
| defmodule WandererAppWeb.MapActivityEventHandler do | ||||
|   use WandererAppWeb, :live_component | ||||
|   use Phoenix.Component | ||||
|   require Logger | ||||
|  | ||||
|   alias WandererAppWeb.{MapEventHandler, MapCoreEventHandler} | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{ | ||||
|           event: :character_activity, | ||||
|           payload: character_activity | ||||
|         }, | ||||
|         socket | ||||
|       ), | ||||
|       do: socket |> assign(:character_activity, character_activity) | ||||
|  | ||||
|   def handle_server_event(event, socket), | ||||
|     do: MapCoreEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_ui_event("show_activity", _, %{assigns: %{map_id: map_id}} = socket) do | ||||
|     Task.async(fn -> | ||||
|       {:ok, character_activity} = map_id |> get_character_activity() | ||||
|  | ||||
|       {:character_activity, character_activity} | ||||
|     end) | ||||
|  | ||||
|     {:noreply, | ||||
|      socket | ||||
|      |> assign(:show_activity?, true)} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event("hide_activity", _, socket), | ||||
|     do: {:noreply, socket |> assign(show_activity?: false)} | ||||
|  | ||||
|   def handle_ui_event(event, body, socket), | ||||
|     do: MapCoreEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   defp get_character_activity(map_id) do | ||||
|     {:ok, jumps} = WandererApp.Api.MapChainPassages.by_map_id(%{map_id: map_id}) | ||||
|  | ||||
|     jumps = | ||||
|       jumps | ||||
|       |> Enum.map(fn p -> | ||||
|         %{p | character: p.character |> MapEventHandler.map_ui_character_stat()} | ||||
|       end) | ||||
|  | ||||
|     {:ok, %{jumps: jumps}} | ||||
|   end | ||||
| end | ||||
| @@ -0,0 +1,388 @@ | ||||
| defmodule WandererAppWeb.MapCharactersEventHandler do | ||||
|   use WandererAppWeb, :live_component | ||||
|   use Phoenix.Component | ||||
|   require Logger | ||||
|  | ||||
|   alias WandererAppWeb.{MapEventHandler, MapCoreEventHandler} | ||||
|  | ||||
|   def handle_server_event(%{event: :character_added, payload: character}, socket) do | ||||
|     socket | ||||
|     |> MapEventHandler.push_map_event( | ||||
|       "character_added", | ||||
|       character |> map_ui_character() | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   def handle_server_event(%{event: :character_removed, payload: character}, socket) do | ||||
|     socket | ||||
|     |> MapEventHandler.push_map_event( | ||||
|       "character_removed", | ||||
|       character |> map_ui_character() | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   def handle_server_event(%{event: :character_updated, payload: character}, socket) do | ||||
|     socket | ||||
|     |> MapEventHandler.push_map_event( | ||||
|       "character_updated", | ||||
|       character |> map_ui_character() | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{event: :characters_updated}, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     characters = | ||||
|       map_id | ||||
|       |> WandererApp.Map.list_characters() | ||||
|       |> Enum.map(&map_ui_character/1) | ||||
|  | ||||
|     socket | ||||
|     |> MapEventHandler.push_map_event( | ||||
|       "characters_updated", | ||||
|       characters | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{event: :present_characters_updated, payload: present_character_eve_ids}, | ||||
|         socket | ||||
|       ), | ||||
|       do: | ||||
|         socket | ||||
|         |> MapEventHandler.push_map_event( | ||||
|           "present_characters", | ||||
|           present_character_eve_ids | ||||
|         ) | ||||
|  | ||||
|   def handle_server_event(event, socket), | ||||
|     do: MapCoreEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "add_character", | ||||
|         _, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             current_user: current_user, | ||||
|             map_id: map_id, | ||||
|             user_permissions: %{track_character: true} | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     {:ok, character_settings} = | ||||
|       case WandererApp.Api.MapCharacterSettings.read_by_map(%{map_id: map_id}) do | ||||
|         {:ok, settings} -> {:ok, settings} | ||||
|         _ -> {:ok, []} | ||||
|       end | ||||
|  | ||||
|     {:noreply, | ||||
|      socket | ||||
|      |> assign( | ||||
|        show_tracking?: true, | ||||
|        character_settings: character_settings | ||||
|      ) | ||||
|      |> assign_async(:characters, fn -> | ||||
|        {:ok, map} = | ||||
|          map_id | ||||
|          |> WandererApp.MapRepo.get([:acls]) | ||||
|  | ||||
|        map | ||||
|        |> WandererApp.Maps.load_characters( | ||||
|          character_settings, | ||||
|          current_user.id | ||||
|        ) | ||||
|      end)} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "add_character", | ||||
|         _, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             user_permissions: %{track_character: false} | ||||
|           } | ||||
|         } = socket | ||||
|       ), | ||||
|       do: | ||||
|         {:noreply, | ||||
|          socket | ||||
|          |> put_flash( | ||||
|            :error, | ||||
|            "You don't have permissions to track characters. Please contact administrator." | ||||
|          )} | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "toggle_track", | ||||
|         %{"character-id" => character_id}, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             character_settings: character_settings, | ||||
|             current_user: current_user, | ||||
|             only_tracked_characters: only_tracked_characters | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     socket = | ||||
|       case character_settings |> Enum.find(&(&1.character_id == character_id)) do | ||||
|         nil -> | ||||
|           {:ok, map_character_settings} = | ||||
|             WandererApp.Api.MapCharacterSettings.create(%{ | ||||
|               character_id: character_id, | ||||
|               map_id: map_id, | ||||
|               tracked: true | ||||
|             }) | ||||
|  | ||||
|           character = map_character_settings |> Ash.load!(:character) |> Map.get(:character) | ||||
|  | ||||
|           :ok = track_characters([character], map_id, true) | ||||
|           :ok = add_characters([character], map_id, true) | ||||
|  | ||||
|           socket | ||||
|  | ||||
|         character_setting -> | ||||
|           case character_setting.tracked do | ||||
|             true -> | ||||
|               {:ok, map_character_settings} = | ||||
|                 character_setting | ||||
|                 |> WandererApp.Api.MapCharacterSettings.untrack() | ||||
|  | ||||
|               character = map_character_settings |> Ash.load!(:character) |> Map.get(:character) | ||||
|  | ||||
|               :ok = untrack_characters([character], map_id) | ||||
|               :ok = remove_characters([character], map_id) | ||||
|  | ||||
|               if only_tracked_characters do | ||||
|                 Process.send_after(self(), :not_all_characters_tracked, 10) | ||||
|               end | ||||
|  | ||||
|               socket | ||||
|  | ||||
|             _ -> | ||||
|               {:ok, map_character_settings} = | ||||
|                 character_setting | ||||
|                 |> WandererApp.Api.MapCharacterSettings.track() | ||||
|  | ||||
|               character = map_character_settings |> Ash.load!(:character) |> Map.get(:character) | ||||
|  | ||||
|               :ok = track_characters([character], map_id, true) | ||||
|               :ok = add_characters([character], map_id, true) | ||||
|  | ||||
|               socket | ||||
|           end | ||||
|       end | ||||
|  | ||||
|     %{result: characters} = socket.assigns.characters | ||||
|  | ||||
|     {:ok, map_characters} = get_tracked_map_characters(map_id, current_user) | ||||
|  | ||||
|     user_character_eve_ids = map_characters |> Enum.map(& &1.eve_id) | ||||
|  | ||||
|     {:ok, character_settings} = | ||||
|       case WandererApp.Api.MapCharacterSettings.read_by_map(%{map_id: map_id}) do | ||||
|         {:ok, settings} -> {:ok, settings} | ||||
|         _ -> {:ok, []} | ||||
|       end | ||||
|  | ||||
|     characters = | ||||
|       characters | ||||
|       |> Enum.map(fn c -> | ||||
|         WandererApp.Maps.map_character( | ||||
|           c, | ||||
|           character_settings |> Enum.find(&(&1.character_id == c.id)) | ||||
|         ) | ||||
|       end) | ||||
|  | ||||
|     {:noreply, | ||||
|      socket | ||||
|      |> assign(user_characters: user_character_eve_ids) | ||||
|      |> assign(has_tracked_characters?: has_tracked_characters?(user_character_eve_ids)) | ||||
|      |> assign(character_settings: character_settings) | ||||
|      |> assign_async(:characters, fn -> | ||||
|        {:ok, %{characters: characters}} | ||||
|      end) | ||||
|      |> MapEventHandler.push_map_event( | ||||
|        "init", | ||||
|        %{ | ||||
|          user_characters: user_character_eve_ids, | ||||
|          reset: false | ||||
|        } | ||||
|      )} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event("hide_tracking", _, socket), | ||||
|     do: {:noreply, socket |> assign(show_tracking?: false)} | ||||
|  | ||||
|   def handle_ui_event(event, body, socket), | ||||
|     do: MapCoreEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   def has_tracked_characters?([]), do: false | ||||
|   def has_tracked_characters?(_user_characters), do: true | ||||
|  | ||||
|   def get_tracked_map_characters(map_id, current_user) do | ||||
|     case WandererApp.Api.MapCharacterSettings.tracked_by_map(%{ | ||||
|            map_id: map_id, | ||||
|            character_ids: current_user.characters |> Enum.map(& &1.id) | ||||
|          }) do | ||||
|       {:ok, settings} -> | ||||
|         {:ok, | ||||
|          settings | ||||
|          |> Enum.map(fn s -> s |> Ash.load!(:character) |> Map.get(:character) end)} | ||||
|  | ||||
|       _ -> | ||||
|         {:ok, []} | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def map_ui_character(character), | ||||
|     do: | ||||
|       character | ||||
|       |> Map.take([ | ||||
|         :eve_id, | ||||
|         :name, | ||||
|         :online, | ||||
|         :corporation_id, | ||||
|         :corporation_name, | ||||
|         :corporation_ticker, | ||||
|         :alliance_id, | ||||
|         :alliance_name, | ||||
|         :alliance_ticker | ||||
|       ]) | ||||
|       |> Map.put_new(:ship, WandererApp.Character.get_ship(character)) | ||||
|       |> Map.put_new(:location, get_location(character)) | ||||
|  | ||||
|   def add_characters([], _map_id, _track_character), do: :ok | ||||
|  | ||||
|   def add_characters([character | characters], map_id, track_character) do | ||||
|     map_id | ||||
|     |> WandererApp.Map.Server.add_character(character, track_character) | ||||
|  | ||||
|     add_characters(characters, map_id, track_character) | ||||
|   end | ||||
|  | ||||
|   def remove_characters([], _map_id), do: :ok | ||||
|  | ||||
|   def remove_characters([character | characters], map_id) do | ||||
|     map_id | ||||
|     |> WandererApp.Map.Server.remove_character(character.id) | ||||
|  | ||||
|     remove_characters(characters, map_id) | ||||
|   end | ||||
|  | ||||
|   def untrack_characters(characters, map_id) do | ||||
|     characters | ||||
|     |> Enum.each(fn character -> | ||||
|       WandererAppWeb.Presence.untrack(self(), map_id, character.id) | ||||
|  | ||||
|       WandererApp.Cache.put( | ||||
|         "#{inspect(self())}_map_#{map_id}:character_#{character.id}:tracked", | ||||
|         false | ||||
|       ) | ||||
|  | ||||
|       :ok = | ||||
|         Phoenix.PubSub.unsubscribe( | ||||
|           WandererApp.PubSub, | ||||
|           "character:#{character.eve_id}" | ||||
|         ) | ||||
|     end) | ||||
|   end | ||||
|  | ||||
|   def track_characters(_, _, false), do: :ok | ||||
|  | ||||
|   def track_characters([], _map_id, _is_track_character?), do: :ok | ||||
|  | ||||
|   def track_characters( | ||||
|         [character | characters], | ||||
|         map_id, | ||||
|         true | ||||
|       ) do | ||||
|     track_character(character, map_id) | ||||
|  | ||||
|     track_characters(characters, map_id, true) | ||||
|   end | ||||
|  | ||||
|   def track_character( | ||||
|         %{ | ||||
|           id: character_id, | ||||
|           eve_id: eve_id, | ||||
|           corporation_id: corporation_id, | ||||
|           alliance_id: alliance_id | ||||
|         }, | ||||
|         map_id | ||||
|       ) do | ||||
|     WandererAppWeb.Presence.track(self(), map_id, character_id, %{}) | ||||
|  | ||||
|     case WandererApp.Cache.lookup!( | ||||
|            "#{inspect(self())}_map_#{map_id}:character_#{character_id}:tracked", | ||||
|            false | ||||
|          ) do | ||||
|       true -> | ||||
|         :ok | ||||
|  | ||||
|       _ -> | ||||
|         :ok = | ||||
|           Phoenix.PubSub.subscribe( | ||||
|             WandererApp.PubSub, | ||||
|             "character:#{eve_id}" | ||||
|           ) | ||||
|  | ||||
|         :ok = | ||||
|           WandererApp.Cache.put( | ||||
|             "#{inspect(self())}_map_#{map_id}:character_#{character_id}:tracked", | ||||
|             true | ||||
|           ) | ||||
|     end | ||||
|  | ||||
|     case WandererApp.Cache.lookup( | ||||
|            "#{inspect(self())}_map_#{map_id}:corporation_#{corporation_id}:tracked", | ||||
|            false | ||||
|          ) do | ||||
|       {:ok, true} -> | ||||
|         :ok | ||||
|  | ||||
|       {:ok, false} -> | ||||
|         :ok = | ||||
|           Phoenix.PubSub.subscribe( | ||||
|             WandererApp.PubSub, | ||||
|             "corporation:#{corporation_id}" | ||||
|           ) | ||||
|  | ||||
|         :ok = | ||||
|           WandererApp.Cache.put( | ||||
|             "#{inspect(self())}_map_#{map_id}:corporation_#{corporation_id}:tracked", | ||||
|             true | ||||
|           ) | ||||
|     end | ||||
|  | ||||
|     case WandererApp.Cache.lookup( | ||||
|            "#{inspect(self())}_map_#{map_id}:alliance_#{alliance_id}:tracked", | ||||
|            false | ||||
|          ) do | ||||
|       {:ok, true} -> | ||||
|         :ok | ||||
|  | ||||
|       {:ok, false} -> | ||||
|         :ok = | ||||
|           Phoenix.PubSub.subscribe( | ||||
|             WandererApp.PubSub, | ||||
|             "alliance:#{alliance_id}" | ||||
|           ) | ||||
|  | ||||
|         :ok = | ||||
|           WandererApp.Cache.put( | ||||
|             "#{inspect(self())}_map_#{map_id}:alliance_#{alliance_id}:tracked", | ||||
|             true | ||||
|           ) | ||||
|     end | ||||
|  | ||||
|     :ok = WandererApp.Character.TrackerManager.start_tracking(character_id) | ||||
|   end | ||||
|  | ||||
|   defp get_location(character), | ||||
|     do: %{solar_system_id: character.solar_system_id, structure_id: character.structure_id} | ||||
| end | ||||
| @@ -0,0 +1,197 @@ | ||||
| defmodule WandererAppWeb.MapConnectionsEventHandler do | ||||
|   use WandererAppWeb, :live_component | ||||
|   use Phoenix.Component | ||||
|   require Logger | ||||
|  | ||||
|   alias WandererAppWeb.{MapEventHandler, MapCoreEventHandler} | ||||
|  | ||||
|   def handle_server_event(%{event: :update_connection, payload: connection}, socket), | ||||
|     do: | ||||
|       socket | ||||
|       |> MapEventHandler.push_map_event( | ||||
|         "update_connection", | ||||
|         MapEventHandler.map_ui_connection(connection) | ||||
|       ) | ||||
|  | ||||
|   def handle_server_event(%{event: :remove_connections, payload: connections}, socket) do | ||||
|     connection_ids = | ||||
|       connections |> Enum.map(&MapEventHandler.map_ui_connection/1) |> Enum.map(& &1.id) | ||||
|  | ||||
|     socket | ||||
|     |> MapEventHandler.push_map_event( | ||||
|       "remove_connections", | ||||
|       connection_ids | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   def handle_server_event(%{event: :add_connection, payload: connection}, socket) do | ||||
|     connections = [MapEventHandler.map_ui_connection(connection)] | ||||
|  | ||||
|     socket | ||||
|     |> MapEventHandler.push_map_event( | ||||
|       "add_connections", | ||||
|       connections | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   def handle_server_event(event, socket), | ||||
|     do: MapCoreEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "manual_add_connection", | ||||
|         %{"source" => solar_system_source_id, "target" => solar_system_target_id} = _event, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             current_user: current_user, | ||||
|             tracked_character_ids: tracked_character_ids, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{add_connection: true} | ||||
|           } | ||||
|         } = | ||||
|           socket | ||||
|       ) do | ||||
|     map_id | ||||
|     |> WandererApp.Map.Server.add_connection(%{ | ||||
|       solar_system_source_id: solar_system_source_id |> String.to_integer(), | ||||
|       solar_system_target_id: solar_system_target_id |> String.to_integer() | ||||
|     }) | ||||
|  | ||||
|     {:ok, _} = | ||||
|       WandererApp.User.ActivityTracker.track_map_event(:map_connection_added, %{ | ||||
|         character_id: tracked_character_ids |> List.first(), | ||||
|         user_id: current_user.id, | ||||
|         map_id: map_id, | ||||
|         solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(), | ||||
|         solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer() | ||||
|       }) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "manual_delete_connection", | ||||
|         %{"source" => solar_system_source_id, "target" => solar_system_target_id} = _event, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             current_user: current_user, | ||||
|             tracked_character_ids: tracked_character_ids, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{delete_connection: true} | ||||
|           } | ||||
|         } = | ||||
|           socket | ||||
|       ) do | ||||
|     map_id | ||||
|     |> WandererApp.Map.Server.delete_connection(%{ | ||||
|       solar_system_source_id: solar_system_source_id |> String.to_integer(), | ||||
|       solar_system_target_id: solar_system_target_id |> String.to_integer() | ||||
|     }) | ||||
|  | ||||
|     {:ok, _} = | ||||
|       WandererApp.User.ActivityTracker.track_map_event(:map_connection_removed, %{ | ||||
|         character_id: tracked_character_ids |> List.first(), | ||||
|         user_id: current_user.id, | ||||
|         map_id: map_id, | ||||
|         solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(), | ||||
|         solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer() | ||||
|       }) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "update_connection_" <> param, | ||||
|         %{ | ||||
|           "source" => solar_system_source_id, | ||||
|           "target" => solar_system_target_id, | ||||
|           "value" => value | ||||
|         } = _event, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             current_user: current_user, | ||||
|             tracked_character_ids: tracked_character_ids, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = | ||||
|           socket | ||||
|       ) do | ||||
|     method_atom = | ||||
|       case param do | ||||
|         "time_status" -> :update_connection_time_status | ||||
|         "mass_status" -> :update_connection_mass_status | ||||
|         "ship_size_type" -> :update_connection_ship_size_type | ||||
|         "locked" -> :update_connection_locked | ||||
|         "custom_info" -> :update_connection_custom_info | ||||
|         _ -> nil | ||||
|       end | ||||
|  | ||||
|     key_atom = | ||||
|       case param do | ||||
|         "time_status" -> :time_status | ||||
|         "mass_status" -> :mass_status | ||||
|         "ship_size_type" -> :ship_size_type | ||||
|         "locked" -> :locked | ||||
|         "custom_info" -> :custom_info | ||||
|         _ -> nil | ||||
|       end | ||||
|  | ||||
|     {:ok, _} = | ||||
|       WandererApp.User.ActivityTracker.track_map_event(:map_connection_updated, %{ | ||||
|         character_id: tracked_character_ids |> List.first(), | ||||
|         user_id: current_user.id, | ||||
|         map_id: map_id, | ||||
|         solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(), | ||||
|         solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer(), | ||||
|         key: key_atom, | ||||
|         value: value | ||||
|       }) | ||||
|  | ||||
|     apply(WandererApp.Map.Server, method_atom, [ | ||||
|       map_id, | ||||
|       %{ | ||||
|         solar_system_source_id: "#{solar_system_source_id}" |> String.to_integer(), | ||||
|         solar_system_target_id: "#{solar_system_target_id}" |> String.to_integer() | ||||
|       } | ||||
|       |> Map.put_new(key_atom, value) | ||||
|     ]) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "get_passages", | ||||
|         %{"from" => from, "to" => to} = _event, | ||||
|         %{assigns: %{map_id: map_id}} = socket | ||||
|       ) do | ||||
|     {:ok, passages} = map_id |> get_connection_passages(from, to) | ||||
|  | ||||
|     {:reply, passages, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event(event, body, socket), | ||||
|     do: MapCoreEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   defp get_connection_passages(map_id, from, to) do | ||||
|     {:ok, passages} = WandererApp.MapChainPassagesRepo.by_connection(map_id, from, to) | ||||
|  | ||||
|     passages = | ||||
|       passages | ||||
|       |> Enum.map(fn p -> | ||||
|         %{ | ||||
|           p | ||||
|           | character: p.character |> MapEventHandler.map_ui_character_stat() | ||||
|         } | ||||
|         |> Map.put_new( | ||||
|           :ship, | ||||
|           WandererApp.Character.get_ship(%{ship: p.ship_type_id, ship_name: p.ship_name}) | ||||
|         ) | ||||
|         |> Map.drop([:ship_type_id, :ship_name]) | ||||
|       end) | ||||
|  | ||||
|     {:ok, %{passages: passages}} | ||||
|   end | ||||
| end | ||||
| @@ -0,0 +1,544 @@ | ||||
| defmodule WandererAppWeb.MapCoreEventHandler do | ||||
|   use WandererAppWeb, :live_component | ||||
|   use Phoenix.Component | ||||
|   require Logger | ||||
|  | ||||
|   alias WandererAppWeb.{MapEventHandler, MapCharactersEventHandler} | ||||
|  | ||||
|   def handle_server_event(:update_permissions, socket) do | ||||
|     DebounceAndThrottle.Debounce.apply( | ||||
|       Process, | ||||
|       :send_after, | ||||
|       [self(), :refresh_permissions, 100], | ||||
|       "update_permissions_#{inspect(self())}", | ||||
|       1000 | ||||
|     ) | ||||
|  | ||||
|     socket | ||||
|   end | ||||
|  | ||||
|   def handle_server_event( | ||||
|         :refresh_permissions, | ||||
|         %{assigns: %{current_user: current_user, map_slug: map_slug}} = socket | ||||
|       ) do | ||||
|     {:ok, %{id: map_id, user_permissions: user_permissions, owner_id: owner_id}} = | ||||
|       map_slug | ||||
|       |> WandererApp.Api.Map.get_map_by_slug!() | ||||
|       |> Ash.load(:user_permissions, actor: current_user) | ||||
|  | ||||
|     user_permissions = | ||||
|       WandererApp.Permissions.get_map_permissions( | ||||
|         user_permissions, | ||||
|         owner_id, | ||||
|         current_user.characters |> Enum.map(& &1.id) | ||||
|       ) | ||||
|  | ||||
|     case user_permissions do | ||||
|       %{view_system: false} -> | ||||
|         socket | ||||
|         |> Phoenix.LiveView.put_flash(:error, "Your access to the map have been revoked.") | ||||
|         |> Phoenix.LiveView.push_navigate(to: ~p"/maps") | ||||
|  | ||||
|       %{track_character: track_character} -> | ||||
|         {:ok, map_characters} = | ||||
|           case WandererApp.Api.MapCharacterSettings.tracked_by_map(%{ | ||||
|                  map_id: map_id, | ||||
|                  character_ids: current_user.characters |> Enum.map(& &1.id) | ||||
|                }) do | ||||
|             {:ok, settings} -> | ||||
|               {:ok, | ||||
|                settings | ||||
|                |> Enum.map(fn s -> s |> Ash.load!(:character) |> Map.get(:character) end)} | ||||
|  | ||||
|             _ -> | ||||
|               {:ok, []} | ||||
|           end | ||||
|  | ||||
|         case track_character do | ||||
|           false -> | ||||
|             :ok = MapCharactersEventHandler.untrack_characters(map_characters, map_id) | ||||
|             :ok = MapCharactersEventHandler.remove_characters(map_characters, map_id) | ||||
|  | ||||
|           _ -> | ||||
|             :ok = MapCharactersEventHandler.track_characters(map_characters, map_id, true) | ||||
|  | ||||
|             :ok = | ||||
|               MapCharactersEventHandler.add_characters(map_characters, map_id, track_character) | ||||
|         end | ||||
|  | ||||
|         socket | ||||
|         |> assign(user_permissions: user_permissions) | ||||
|         |> MapEventHandler.push_map_event( | ||||
|           "user_permissions", | ||||
|           user_permissions | ||||
|         ) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{ | ||||
|           event: :load_map | ||||
|         }, | ||||
|         %{assigns: %{current_user: current_user, map_slug: map_slug}} = socket | ||||
|       ) do | ||||
|     ErrorTracker.set_context(%{user_id: current_user.id}) | ||||
|  | ||||
|     map_slug | ||||
|     |> WandererApp.MapRepo.get_by_slug_with_permissions(current_user) | ||||
|     |> case do | ||||
|       {:ok, map} -> | ||||
|         socket |> init_map(map) | ||||
|  | ||||
|       {:error, _} -> | ||||
|         socket | ||||
|         |> put_flash( | ||||
|           :error, | ||||
|           "Something went wrong. Please try one more time or submit an issue." | ||||
|         ) | ||||
|         |> push_navigate(to: ~p"/maps") | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{event: :map_server_started}, | ||||
|         socket | ||||
|       ), | ||||
|       do: socket |> handle_map_server_started() | ||||
|  | ||||
|   def handle_server_event(%{event: :update_map, payload: map_diff}, socket), | ||||
|     do: | ||||
|       socket | ||||
|       |> MapEventHandler.push_map_event( | ||||
|         "map_updated", | ||||
|         map_diff | ||||
|       ) | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{event: "presence_diff"}, | ||||
|         socket | ||||
|       ), | ||||
|       do: socket | ||||
|  | ||||
|   def handle_server_event(event, socket) do | ||||
|     Logger.warning(fn -> "unhandled map core event: #{inspect(event)}" end) | ||||
|     socket | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event("ui_loaded", _body, %{assigns: %{map_slug: map_slug} = assigns} = socket) do | ||||
|     assigns | ||||
|     |> Map.get(:map_id) | ||||
|     |> case do | ||||
|       map_id when not is_nil(map_id) -> | ||||
|         maybe_start_map(map_id) | ||||
|  | ||||
|       _ -> | ||||
|         WandererApp.Cache.insert("map_#{map_slug}:ui_loaded", true) | ||||
|     end | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "live_select_change", | ||||
|         %{"id" => id, "text" => text}, | ||||
|         socket | ||||
|       ) | ||||
|       when id == "_system_id_live_select_component" do | ||||
|     options = | ||||
|       WandererApp.Api.MapSolarSystem.find_by_name!(%{name: text}) | ||||
|       |> Enum.take(100) | ||||
|       |> Enum.map(&map_system/1) | ||||
|  | ||||
|     send_update(LiveSelect.Component, options: options, id: id) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event("toggle_track_" <> character_id, _, socket), | ||||
|     do: | ||||
|       MapCharactersEventHandler.handle_ui_event( | ||||
|         "toggle_track", | ||||
|         %{"character-id" => character_id}, | ||||
|         socket | ||||
|       ) | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "get_user_settings", | ||||
|         _, | ||||
|         %{assigns: %{map_id: map_id, current_user: current_user}} = socket | ||||
|       ) do | ||||
|     {:ok, user_settings} = | ||||
|       WandererApp.MapUserSettingsRepo.get!(map_id, current_user.id) | ||||
|       |> WandererApp.MapUserSettingsRepo.to_form_data() | ||||
|  | ||||
|     {:reply, %{user_settings: user_settings}, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "update_user_settings", | ||||
|         user_settings_form, | ||||
|         %{assigns: %{map_id: map_id, current_user: current_user}} = socket | ||||
|       ) do | ||||
|     settings = | ||||
|       user_settings_form | ||||
|       |> Map.take(["select_on_spash", "link_signature_on_splash", "delete_connection_with_sigs"]) | ||||
|       |> Jason.encode!() | ||||
|  | ||||
|     {:ok, user_settings} = | ||||
|       WandererApp.MapUserSettingsRepo.create_or_update(map_id, current_user.id, settings) | ||||
|  | ||||
|     {:noreply, | ||||
|      socket |> assign(user_settings_form: user_settings_form, map_user_settings: user_settings)} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "log_map_error", | ||||
|         %{"componentStack" => component_stack, "error" => error}, | ||||
|         socket | ||||
|       ) do | ||||
|     Logger.error(fn -> "map_ui_error: #{error}  \n#{component_stack} " end) | ||||
|  | ||||
|     {:noreply, | ||||
|      socket | ||||
|      |> put_flash(:error, "Something went wrong. Please try refresh page or submit an issue.") | ||||
|      |> push_event("js-exec", %{ | ||||
|        to: "#map-loader", | ||||
|        attr: "data-loading", | ||||
|        timeout: 100 | ||||
|      })} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event("noop", _, socket), do: {:noreply, socket} | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         _event, | ||||
|         _body, | ||||
|         %{assigns: %{has_tracked_characters?: false}} = | ||||
|           socket | ||||
|       ), | ||||
|       do: | ||||
|         {:noreply, | ||||
|          socket | ||||
|          |> put_flash( | ||||
|            :error, | ||||
|            "You should enable tracking for at least one character." | ||||
|          )} | ||||
|  | ||||
|   def handle_ui_event(event, body, socket) do | ||||
|     Logger.warning(fn -> "unhandled map ui event: #{event} #{inspect(body)}" end) | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   defp maybe_start_map(map_id) do | ||||
|     {:ok, map_server_started} = WandererApp.Cache.lookup("map_#{map_id}:started", false) | ||||
|  | ||||
|     if map_server_started do | ||||
|       Process.send_after(self(), %{event: :map_server_started}, 10) | ||||
|     else | ||||
|       WandererApp.Map.Manager.start_map(map_id) | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   defp init_map( | ||||
|          %{assigns: %{current_user: current_user, map_slug: map_slug}} = socket, | ||||
|          %{ | ||||
|            id: map_id, | ||||
|            deleted: false, | ||||
|            only_tracked_characters: only_tracked_characters, | ||||
|            user_permissions: user_permissions, | ||||
|            name: map_name, | ||||
|            owner_id: owner_id | ||||
|          } = map | ||||
|        ) do | ||||
|     user_permissions = | ||||
|       WandererApp.Permissions.get_map_permissions( | ||||
|         user_permissions, | ||||
|         owner_id, | ||||
|         current_user.characters |> Enum.map(& &1.id) | ||||
|       ) | ||||
|  | ||||
|     {:ok, character_settings} = | ||||
|       case WandererApp.Api.MapCharacterSettings.read_by_map(%{map_id: map_id}) do | ||||
|         {:ok, settings} -> {:ok, settings} | ||||
|         _ -> {:ok, []} | ||||
|       end | ||||
|  | ||||
|     {:ok, %{characters: availaible_map_characters}} = | ||||
|       WandererApp.Maps.load_characters(map, character_settings, current_user.id) | ||||
|  | ||||
|     can_view? = user_permissions.view_system | ||||
|     can_track? = user_permissions.track_character | ||||
|  | ||||
|     tracked_character_ids = | ||||
|       availaible_map_characters |> Enum.filter(& &1.tracked) |> Enum.map(& &1.id) | ||||
|  | ||||
|     all_character_tracked? = | ||||
|       not (availaible_map_characters |> Enum.empty?()) and | ||||
|         availaible_map_characters |> Enum.all?(& &1.tracked) | ||||
|  | ||||
|     cond do | ||||
|       (only_tracked_characters and can_track? and all_character_tracked?) or | ||||
|           (not only_tracked_characters and can_view?) -> | ||||
|         Phoenix.PubSub.subscribe(WandererApp.PubSub, map_id) | ||||
|         {:ok, ui_loaded} = WandererApp.Cache.get_and_remove("map_#{map_slug}:ui_loaded", false) | ||||
|  | ||||
|         if ui_loaded do | ||||
|           maybe_start_map(map_id) | ||||
|         end | ||||
|  | ||||
|         socket | ||||
|         |> assign( | ||||
|           map_id: map_id, | ||||
|           page_title: map_name, | ||||
|           user_permissions: user_permissions, | ||||
|           tracked_character_ids: tracked_character_ids, | ||||
|           only_tracked_characters: only_tracked_characters | ||||
|         ) | ||||
|  | ||||
|       only_tracked_characters and can_track? and not all_character_tracked? -> | ||||
|         Process.send_after(self(), :not_all_characters_tracked, 10) | ||||
|         socket | ||||
|  | ||||
|       true -> | ||||
|         Process.send_after(self(), :no_permissions, 10) | ||||
|         socket | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   defp init_map(socket, _map) do | ||||
|     Process.send_after(self(), :no_access, 10) | ||||
|     socket | ||||
|   end | ||||
|  | ||||
|   defp handle_map_server_started( | ||||
|          %{ | ||||
|            assigns: %{ | ||||
|              current_user: current_user, | ||||
|              map_id: map_id, | ||||
|              user_permissions: | ||||
|                %{view_system: true, track_character: track_character} = user_permissions | ||||
|            } | ||||
|          } = socket | ||||
|        ) do | ||||
|     with {:ok, _} <- current_user |> WandererApp.Api.User.update_last_map(%{last_map_id: map_id}), | ||||
|          {:ok, map_user_settings} <- WandererApp.MapUserSettingsRepo.get(map_id, current_user.id), | ||||
|          {:ok, tracked_map_characters} <- | ||||
|            MapCharactersEventHandler.get_tracked_map_characters(map_id, current_user), | ||||
|          {:ok, characters_limit} <- map_id |> WandererApp.Map.get_characters_limit(), | ||||
|          {:ok, present_character_ids} <- | ||||
|            WandererApp.Cache.lookup("map_#{map_id}:presence_character_ids", []), | ||||
|          {:ok, kills} <- WandererApp.Cache.lookup("map_#{map_id}:zkb_kills", Map.new()) do | ||||
|       user_character_eve_ids = tracked_map_characters |> Enum.map(& &1.eve_id) | ||||
|  | ||||
|       events = | ||||
|         case tracked_map_characters |> Enum.any?(&(&1.access_token == nil)) do | ||||
|           true -> | ||||
|             [:invalid_token_message] | ||||
|  | ||||
|           _ -> | ||||
|             [] | ||||
|         end | ||||
|  | ||||
|       events = | ||||
|         case tracked_map_characters |> Enum.empty?() do | ||||
|           true -> | ||||
|             events ++ [:empty_tracked_characters] | ||||
|  | ||||
|           _ -> | ||||
|             events | ||||
|         end | ||||
|  | ||||
|       events = | ||||
|         case present_character_ids |> Enum.count() < characters_limit do | ||||
|           true -> | ||||
|             events ++ [{:track_characters, tracked_map_characters, track_character}] | ||||
|  | ||||
|           _ -> | ||||
|             events ++ [:map_character_limit] | ||||
|         end | ||||
|  | ||||
|       initial_data = | ||||
|         map_id | ||||
|         |> get_map_data() | ||||
|         |> Map.merge(%{ | ||||
|           kills: | ||||
|             kills | ||||
|             |> Enum.filter(fn {_, kills} -> kills > 0 end) | ||||
|             |> Enum.map(&MapEventHandler.map_ui_kill/1), | ||||
|           present_characters: | ||||
|             present_character_ids | ||||
|             |> WandererApp.Character.get_character_eve_ids!(), | ||||
|           user_characters: user_character_eve_ids, | ||||
|           user_permissions: user_permissions, | ||||
|           system_static_infos: nil, | ||||
|           wormhole_types: nil, | ||||
|           effects: nil, | ||||
|           reset: false | ||||
|         }) | ||||
|  | ||||
|       system_static_infos = | ||||
|         map_id | ||||
|         |> WandererApp.Map.list_systems!() | ||||
|         |> Enum.map(&WandererApp.CachedInfo.get_system_static_info!(&1.solar_system_id)) | ||||
|         |> Enum.map(&MapEventHandler.map_ui_system_static_info/1) | ||||
|  | ||||
|       initial_data = | ||||
|         initial_data | ||||
|         |> Map.put( | ||||
|           :wormholes, | ||||
|           WandererApp.CachedInfo.get_wormhole_types!() | ||||
|         ) | ||||
|         |> Map.put( | ||||
|           :effects, | ||||
|           WandererApp.CachedInfo.get_effects!() | ||||
|         ) | ||||
|         |> Map.put( | ||||
|           :system_static_infos, | ||||
|           system_static_infos | ||||
|         ) | ||||
|         |> Map.put(:reset, true) | ||||
|  | ||||
|       socket | ||||
|       |> map_start(%{ | ||||
|         map_id: map_id, | ||||
|         map_user_settings: map_user_settings, | ||||
|         user_characters: user_character_eve_ids, | ||||
|         initial_data: initial_data, | ||||
|         events: events | ||||
|       }) | ||||
|     else | ||||
|       error -> | ||||
|         Logger.error(fn -> "map_start_error: #{error}" end) | ||||
|         Process.send_after(self(), :no_access, 10) | ||||
|  | ||||
|         socket | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   defp handle_map_server_started(socket) do | ||||
|     Process.send_after(self(), :no_access, 10) | ||||
|     socket | ||||
|   end | ||||
|  | ||||
|   defp map_start( | ||||
|          socket, | ||||
|          %{ | ||||
|            map_id: map_id, | ||||
|            map_user_settings: map_user_settings, | ||||
|            user_characters: user_character_eve_ids, | ||||
|            initial_data: initial_data, | ||||
|            events: events | ||||
|          } = _started_data | ||||
|        ) do | ||||
|     socket = | ||||
|       socket | ||||
|       |> handle_map_start_events(map_id, events) | ||||
|  | ||||
|     map_characters = map_id |> WandererApp.Map.list_characters() | ||||
|  | ||||
|     socket | ||||
|     |> assign( | ||||
|       map_loaded?: true, | ||||
|       map_user_settings: map_user_settings, | ||||
|       user_characters: user_character_eve_ids, | ||||
|       has_tracked_characters?: | ||||
|         MapCharactersEventHandler.has_tracked_characters?(user_character_eve_ids) | ||||
|     ) | ||||
|     |> MapEventHandler.push_map_event( | ||||
|       "init", | ||||
|       initial_data | ||||
|       |> Map.put( | ||||
|         :characters, | ||||
|         map_characters |> Enum.map(&MapCharactersEventHandler.map_ui_character/1) | ||||
|       ) | ||||
|     ) | ||||
|     |> push_event("js-exec", %{ | ||||
|       to: "#map-loader", | ||||
|       attr: "data-loaded" | ||||
|     }) | ||||
|   end | ||||
|  | ||||
|   defp handle_map_start_events(socket, map_id, events) do | ||||
|     events | ||||
|     |> Enum.reduce(socket, fn event, socket -> | ||||
|       case event do | ||||
|         {:track_characters, map_characters, track_character} -> | ||||
|           :ok = | ||||
|             MapCharactersEventHandler.track_characters(map_characters, map_id, track_character) | ||||
|  | ||||
|           :ok = MapCharactersEventHandler.add_characters(map_characters, map_id, track_character) | ||||
|           socket | ||||
|  | ||||
|         :invalid_token_message -> | ||||
|           socket | ||||
|           |> put_flash( | ||||
|             :error, | ||||
|             "One of your characters has expired token. Please refresh it on characters page." | ||||
|           ) | ||||
|  | ||||
|         :empty_tracked_characters -> | ||||
|           socket | ||||
|           |> put_flash( | ||||
|             :info, | ||||
|             "You should enable tracking for at least one character to work with map." | ||||
|           ) | ||||
|  | ||||
|         :map_character_limit -> | ||||
|           socket | ||||
|           |> put_flash( | ||||
|             :error, | ||||
|             "Map reached its character limit, your characters won't be tracked. Please contact administrator." | ||||
|           ) | ||||
|  | ||||
|         _ -> | ||||
|           socket | ||||
|       end | ||||
|     end) | ||||
|   end | ||||
|  | ||||
|   defp get_map_data(map_id, include_static_data? \\ true) do | ||||
|     {:ok, hubs} = map_id |> WandererApp.Map.list_hubs() | ||||
|     {:ok, connections} = map_id |> WandererApp.Map.list_connections() | ||||
|     {:ok, systems} = map_id |> WandererApp.Map.list_systems() | ||||
|  | ||||
|     %{ | ||||
|       systems: | ||||
|         systems | ||||
|         |> Enum.map(fn system -> MapEventHandler.map_ui_system(system, include_static_data?) end), | ||||
|       hubs: hubs, | ||||
|       connections: connections |> Enum.map(&MapEventHandler.map_ui_connection/1) | ||||
|     } | ||||
|   end | ||||
|  | ||||
|   defp get_tracked_map_characters(map_id, current_user) do | ||||
|     case WandererApp.Api.MapCharacterSettings.tracked_by_map(%{ | ||||
|            map_id: map_id, | ||||
|            character_ids: current_user.characters |> Enum.map(& &1.id) | ||||
|          }) do | ||||
|       {:ok, settings} -> | ||||
|         {:ok, | ||||
|          settings | ||||
|          |> Enum.map(fn s -> s |> Ash.load!(:character) |> Map.get(:character) end)} | ||||
|  | ||||
|       _ -> | ||||
|         {:ok, []} | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   defp map_system( | ||||
|          %{ | ||||
|            solar_system_name: solar_system_name, | ||||
|            constellation_name: constellation_name, | ||||
|            region_name: region_name, | ||||
|            solar_system_id: solar_system_id, | ||||
|            class_title: class_title | ||||
|          } = _system | ||||
|        ), | ||||
|        do: %{ | ||||
|          label: solar_system_name, | ||||
|          value: solar_system_id, | ||||
|          constellation_name: constellation_name, | ||||
|          region_name: region_name, | ||||
|          class_title: class_title | ||||
|        } | ||||
| end | ||||
| @@ -0,0 +1,131 @@ | ||||
| defmodule WandererAppWeb.MapRoutesEventHandler do | ||||
|   use WandererAppWeb, :live_component | ||||
|   use Phoenix.Component | ||||
|   require Logger | ||||
|  | ||||
|   alias WandererAppWeb.{MapEventHandler, MapCoreEventHandler} | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{ | ||||
|           event: :routes, | ||||
|           payload: {solar_system_id, %{routes: routes, systems_static_data: systems_static_data}} | ||||
|         }, | ||||
|         socket | ||||
|       ), | ||||
|       do: | ||||
|         socket | ||||
|         |> MapEventHandler.push_map_event( | ||||
|           "routes", | ||||
|           %{ | ||||
|             solar_system_id: solar_system_id, | ||||
|             loading: false, | ||||
|             routes: routes, | ||||
|             systems_static_data: systems_static_data | ||||
|           } | ||||
|         ) | ||||
|  | ||||
|   def handle_server_event(event, socket), | ||||
|     do: MapCoreEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "get_routes", | ||||
|         %{"system_id" => solar_system_id, "routes_settings" => routes_settings} = _event, | ||||
|         %{assigns: %{map_id: map_id, map_loaded?: true}} = socket | ||||
|       ) do | ||||
|     Task.async(fn -> | ||||
|       {:ok, hubs} = map_id |> WandererApp.Map.list_hubs() | ||||
|  | ||||
|       {:ok, routes} = | ||||
|         WandererApp.Maps.find_routes( | ||||
|           map_id, | ||||
|           hubs, | ||||
|           solar_system_id, | ||||
|           get_routes_settings(routes_settings) | ||||
|         ) | ||||
|  | ||||
|       {:routes, {solar_system_id, routes}} | ||||
|     end) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "set_autopilot_waypoint", | ||||
|         %{ | ||||
|           "character_eve_ids" => character_eve_ids, | ||||
|           "add_to_beginning" => add_to_beginning, | ||||
|           "clear_other_waypoints" => clear_other_waypoints, | ||||
|           "destination_id" => destination_id | ||||
|         } = _event, | ||||
|         %{assigns: %{current_user: current_user, has_tracked_characters?: true}} = socket | ||||
|       ) do | ||||
|     character_eve_ids | ||||
|     |> Task.async_stream(fn character_eve_id -> | ||||
|       set_autopilot_waypoint( | ||||
|         current_user, | ||||
|         character_eve_id, | ||||
|         add_to_beginning, | ||||
|         clear_other_waypoints, | ||||
|         destination_id | ||||
|       ) | ||||
|     end) | ||||
|     |> Enum.map(fn _result -> :skip end) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event(event, body, socket), | ||||
|     do: MapCoreEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   defp get_routes_settings(%{ | ||||
|          "path_type" => path_type, | ||||
|          "include_mass_crit" => include_mass_crit, | ||||
|          "include_eol" => include_eol, | ||||
|          "include_frig" => include_frig, | ||||
|          "include_cruise" => include_cruise, | ||||
|          "avoid_wormholes" => avoid_wormholes, | ||||
|          "avoid_pochven" => avoid_pochven, | ||||
|          "avoid_edencom" => avoid_edencom, | ||||
|          "avoid_triglavian" => avoid_triglavian, | ||||
|          "include_thera" => include_thera, | ||||
|          "avoid" => avoid | ||||
|        }), | ||||
|        do: %{ | ||||
|          path_type: path_type, | ||||
|          include_mass_crit: include_mass_crit, | ||||
|          include_eol: include_eol, | ||||
|          include_frig: include_frig, | ||||
|          include_cruise: include_cruise, | ||||
|          avoid_wormholes: avoid_wormholes, | ||||
|          avoid_pochven: avoid_pochven, | ||||
|          avoid_edencom: avoid_edencom, | ||||
|          avoid_triglavian: avoid_triglavian, | ||||
|          include_thera: include_thera, | ||||
|          avoid: avoid | ||||
|        } | ||||
|  | ||||
|   defp get_routes_settings(_), do: %{} | ||||
|  | ||||
|   defp set_autopilot_waypoint( | ||||
|          current_user, | ||||
|          character_eve_id, | ||||
|          add_to_beginning, | ||||
|          clear_other_waypoints, | ||||
|          destination_id | ||||
|        ) do | ||||
|     case current_user.characters | ||||
|          |> Enum.find(fn c -> c.eve_id == character_eve_id end) do | ||||
|       nil -> | ||||
|         :skip | ||||
|  | ||||
|       %{id: character_id} = _character -> | ||||
|         character_id | ||||
|         |> WandererApp.Character.set_autopilot_waypoint(destination_id, | ||||
|           add_to_beginning: add_to_beginning, | ||||
|           clear_other_waypoints: clear_other_waypoints | ||||
|         ) | ||||
|  | ||||
|         :skip | ||||
|     end | ||||
|   end | ||||
| end | ||||
| @@ -0,0 +1,350 @@ | ||||
| defmodule WandererAppWeb.MapSignaturesEventHandler do | ||||
|   use WandererAppWeb, :live_component | ||||
|   use Phoenix.Component | ||||
|   require Logger | ||||
|  | ||||
|   alias WandererAppWeb.{MapEventHandler, MapCoreEventHandler} | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{ | ||||
|           event: :maybe_link_signature, | ||||
|           payload: %{ | ||||
|             character_id: character_id, | ||||
|             solar_system_source: solar_system_source, | ||||
|             solar_system_target: solar_system_target | ||||
|           } | ||||
|         }, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             current_user: current_user, | ||||
|             map_id: map_id, | ||||
|             map_user_settings: map_user_settings | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     is_user_character = | ||||
|       current_user.characters |> Enum.map(& &1.id) |> Enum.member?(character_id) | ||||
|  | ||||
|     is_link_signature_on_splash = | ||||
|       map_user_settings | ||||
|       |> WandererApp.MapUserSettingsRepo.to_form_data!() | ||||
|       |> WandererApp.MapUserSettingsRepo.get_boolean_setting("link_signature_on_splash") | ||||
|  | ||||
|     {:ok, signatures} = | ||||
|       WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{ | ||||
|         map_id: map_id, | ||||
|         solar_system_id: solar_system_source | ||||
|       }) | ||||
|       |> case do | ||||
|         {:ok, system} -> | ||||
|           {:ok, get_system_signatures(system.id)} | ||||
|  | ||||
|         _ -> | ||||
|           {:ok, []} | ||||
|       end | ||||
|  | ||||
|     (is_user_character && is_link_signature_on_splash && not (signatures |> Enum.empty?())) | ||||
|     |> case do | ||||
|       true -> | ||||
|         socket | ||||
|         |> MapEventHandler.push_map_event("link_signature_to_system", %{ | ||||
|           solar_system_source: solar_system_source, | ||||
|           solar_system_target: solar_system_target | ||||
|         }) | ||||
|  | ||||
|       false -> | ||||
|         socket | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{event: :signatures_updated, payload: solar_system_id}, | ||||
|         socket | ||||
|       ), | ||||
|       do: | ||||
|         socket | ||||
|         |> MapEventHandler.push_map_event( | ||||
|           "signatures_updated", | ||||
|           solar_system_id | ||||
|         ) | ||||
|  | ||||
|   def handle_server_event(event, socket), | ||||
|     do: MapCoreEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "update_signatures", | ||||
|         %{ | ||||
|           "system_id" => solar_system_id, | ||||
|           "added" => added_signatures, | ||||
|           "updated" => updated_signatures, | ||||
|           "removed" => removed_signatures | ||||
|         }, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             map_user_settings: map_user_settings, | ||||
|             user_characters: user_characters, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{ | ||||
|       map_id: map_id, | ||||
|       solar_system_id: solar_system_id |> String.to_integer() | ||||
|     }) | ||||
|     |> case do | ||||
|       {:ok, system} -> | ||||
|         first_character_eve_id = | ||||
|           user_characters |> List.first() | ||||
|  | ||||
|         case not is_nil(first_character_eve_id) do | ||||
|           true -> | ||||
|             added_signatures = | ||||
|               added_signatures | ||||
|               |> parse_signatures(first_character_eve_id, system.id) | ||||
|  | ||||
|             updated_signatures = | ||||
|               updated_signatures | ||||
|               |> parse_signatures(first_character_eve_id, system.id) | ||||
|  | ||||
|             updated_signatures_eve_ids = | ||||
|               updated_signatures | ||||
|               |> Enum.map(fn s -> s.eve_id end) | ||||
|  | ||||
|             removed_signatures_eve_ids = | ||||
|               removed_signatures | ||||
|               |> parse_signatures(first_character_eve_id, system.id) | ||||
|               |> Enum.map(fn s -> s.eve_id end) | ||||
|  | ||||
|             delete_connection_with_sigs = | ||||
|               map_user_settings | ||||
|               |> WandererApp.MapUserSettingsRepo.to_form_data!() | ||||
|               |> WandererApp.MapUserSettingsRepo.get_boolean_setting( | ||||
|                 "delete_connection_with_sigs" | ||||
|               ) | ||||
|  | ||||
|             WandererApp.Api.MapSystemSignature.by_system_id!(system.id) | ||||
|             |> Enum.filter(fn s -> s.eve_id in removed_signatures_eve_ids end) | ||||
|             |> Enum.each(fn s -> | ||||
|               if delete_connection_with_sigs && not is_nil(s.linked_system_id) do | ||||
|                 map_id | ||||
|                 |> WandererApp.Map.Server.delete_connection(%{ | ||||
|                   solar_system_source_id: solar_system_id |> String.to_integer(), | ||||
|                   solar_system_target_id: s.linked_system_id | ||||
|                 }) | ||||
|               end | ||||
|  | ||||
|               s | ||||
|               |> Ash.destroy!() | ||||
|             end) | ||||
|  | ||||
|             WandererApp.Api.MapSystemSignature.by_system_id!(system.id) | ||||
|             |> Enum.filter(fn s -> s.eve_id in updated_signatures_eve_ids end) | ||||
|             |> Enum.each(fn s -> | ||||
|               updated = updated_signatures |> Enum.find(fn u -> u.eve_id == s.eve_id end) | ||||
|  | ||||
|               if not is_nil(updated) do | ||||
|                 s | ||||
|                 |> WandererApp.Api.MapSystemSignature.update(updated) | ||||
|               end | ||||
|             end) | ||||
|  | ||||
|             added_signatures | ||||
|             |> Enum.map(fn s -> | ||||
|               s |> WandererApp.Api.MapSystemSignature.create!() | ||||
|             end) | ||||
|  | ||||
|             Phoenix.PubSub.broadcast!(WandererApp.PubSub, map_id, %{ | ||||
|               event: :signatures_updated, | ||||
|               payload: system.solar_system_id | ||||
|             }) | ||||
|  | ||||
|             {:reply, %{signatures: get_system_signatures(system.id)}, socket} | ||||
|  | ||||
|           _ -> | ||||
|             {:reply, %{signatures: []}, | ||||
|              socket | ||||
|              |> put_flash( | ||||
|                :error, | ||||
|                "You should enable tracking for at least one character to work with signatures." | ||||
|              )} | ||||
|         end | ||||
|  | ||||
|       _ -> | ||||
|         {:noreply, socket} | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "get_signatures", | ||||
|         %{"system_id" => solar_system_id}, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     case WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{ | ||||
|            map_id: map_id, | ||||
|            solar_system_id: solar_system_id |> String.to_integer() | ||||
|          }) do | ||||
|       {:ok, system} -> | ||||
|         {:reply, %{signatures: get_system_signatures(system.id)}, socket} | ||||
|  | ||||
|       _ -> | ||||
|         {:reply, %{signatures: []}, socket} | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "link_signature_to_system", | ||||
|         %{ | ||||
|           "signature_eve_id" => signature_eve_id, | ||||
|           "solar_system_source" => solar_system_source, | ||||
|           "solar_system_target" => solar_system_target | ||||
|         }, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             user_characters: user_characters, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     case WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{ | ||||
|            map_id: map_id, | ||||
|            solar_system_id: solar_system_source | ||||
|          }) do | ||||
|       {:ok, system} -> | ||||
|         first_character_eve_id = | ||||
|           user_characters |> List.first() | ||||
|  | ||||
|         case not is_nil(first_character_eve_id) do | ||||
|           true -> | ||||
|             WandererApp.Api.MapSystemSignature.by_system_id!(system.id) | ||||
|             |> Enum.filter(fn s -> s.eve_id == signature_eve_id end) | ||||
|             |> Enum.each(fn s -> | ||||
|               s | ||||
|               |> WandererApp.Api.MapSystemSignature.update_linked_system(%{ | ||||
|                 linked_system_id: solar_system_target | ||||
|               }) | ||||
|             end) | ||||
|  | ||||
|             Phoenix.PubSub.broadcast!(WandererApp.PubSub, map_id, %{ | ||||
|               event: :signatures_updated, | ||||
|               payload: solar_system_source | ||||
|             }) | ||||
|  | ||||
|             {:noreply, socket} | ||||
|  | ||||
|           _ -> | ||||
|             {:noreply, | ||||
|              socket | ||||
|              |> put_flash( | ||||
|                :error, | ||||
|                "You should enable tracking for at least one character to work with signatures." | ||||
|              )} | ||||
|         end | ||||
|  | ||||
|       _ -> | ||||
|         {:noreply, socket} | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "unlink_signature", | ||||
|         %{ | ||||
|           "signature_eve_id" => signature_eve_id, | ||||
|           "solar_system_source" => solar_system_source | ||||
|         }, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             user_characters: user_characters, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     case WandererApp.Api.MapSystem.read_by_map_and_solar_system(%{ | ||||
|            map_id: map_id, | ||||
|            solar_system_id: solar_system_source | ||||
|          }) do | ||||
|       {:ok, system} -> | ||||
|         first_character_eve_id = | ||||
|           user_characters |> List.first() | ||||
|  | ||||
|         case not is_nil(first_character_eve_id) do | ||||
|           true -> | ||||
|             WandererApp.Api.MapSystemSignature.by_system_id!(system.id) | ||||
|             |> Enum.filter(fn s -> s.eve_id == signature_eve_id end) | ||||
|             |> Enum.each(fn s -> | ||||
|               s | ||||
|               |> WandererApp.Api.MapSystemSignature.update_linked_system(%{ | ||||
|                 linked_system_id: nil | ||||
|               }) | ||||
|             end) | ||||
|  | ||||
|             Phoenix.PubSub.broadcast!(WandererApp.PubSub, map_id, %{ | ||||
|               event: :signatures_updated, | ||||
|               payload: solar_system_source | ||||
|             }) | ||||
|  | ||||
|             {:noreply, socket} | ||||
|  | ||||
|           _ -> | ||||
|             {:noreply, | ||||
|              socket | ||||
|              |> put_flash( | ||||
|                :error, | ||||
|                "You should enable tracking for at least one character to work with signatures." | ||||
|              )} | ||||
|         end | ||||
|  | ||||
|       _ -> | ||||
|         {:noreply, socket} | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event(event, body, socket), | ||||
|     do: MapCoreEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   defp get_system_signatures(system_id), | ||||
|     do: | ||||
|       system_id | ||||
|       |> WandererApp.Api.MapSystemSignature.by_system_id!() | ||||
|       |> Enum.map(fn %{updated_at: updated_at, linked_system_id: linked_system_id} = s -> | ||||
|         s | ||||
|         |> Map.take([ | ||||
|           :eve_id, | ||||
|           :name, | ||||
|           :description, | ||||
|           :kind, | ||||
|           :group, | ||||
|           :type, | ||||
|           :updated_at | ||||
|         ]) | ||||
|         |> Map.put(:linked_system, MapEventHandler.get_system_static_info(linked_system_id)) | ||||
|         |> Map.put(:updated_at, updated_at |> Calendar.strftime("%Y/%m/%d %H:%M:%S")) | ||||
|       end) | ||||
|  | ||||
|   defp parse_signatures(signatures, character_eve_id, system_id), | ||||
|     do: | ||||
|       signatures | ||||
|       |> Enum.map(fn %{ | ||||
|                        "eve_id" => eve_id, | ||||
|                        "name" => name, | ||||
|                        "kind" => kind, | ||||
|                        "group" => group | ||||
|                      } = signature -> | ||||
|         %{ | ||||
|           system_id: system_id, | ||||
|           eve_id: eve_id, | ||||
|           name: name, | ||||
|           description: Map.get(signature, "description"), | ||||
|           kind: kind, | ||||
|           group: group, | ||||
|           type: Map.get(signature, "type"), | ||||
|           character_eve_id: character_eve_id | ||||
|         } | ||||
|       end) | ||||
| end | ||||
| @@ -0,0 +1,326 @@ | ||||
| defmodule WandererAppWeb.MapSystemsEventHandler do | ||||
|   use WandererAppWeb, :live_component | ||||
|   use Phoenix.Component | ||||
|   require Logger | ||||
|  | ||||
|   alias WandererAppWeb.{MapEventHandler, MapCoreEventHandler} | ||||
|  | ||||
|   def handle_server_event(%{event: :add_system, payload: system}, socket), | ||||
|     do: | ||||
|       socket | ||||
|       |> MapEventHandler.push_map_event("add_systems", [MapEventHandler.map_ui_system(system)]) | ||||
|  | ||||
|   def handle_server_event(%{event: :update_system, payload: system}, socket), | ||||
|     do: | ||||
|       socket | ||||
|       |> MapEventHandler.push_map_event("update_systems", [MapEventHandler.map_ui_system(system)]) | ||||
|  | ||||
|   def handle_server_event(%{event: :systems_removed, payload: solar_system_ids}, socket), | ||||
|     do: | ||||
|       socket | ||||
|       |> MapEventHandler.push_map_event("remove_systems", solar_system_ids) | ||||
|  | ||||
|   def handle_server_event( | ||||
|         %{ | ||||
|           event: :maybe_select_system, | ||||
|           payload: %{ | ||||
|             character_id: character_id, | ||||
|             solar_system_id: solar_system_id | ||||
|           } | ||||
|         }, | ||||
|         %{assigns: %{current_user: current_user, map_user_settings: map_user_settings}} = socket | ||||
|       ) do | ||||
|     is_user_character = | ||||
|       current_user.characters |> Enum.map(& &1.id) |> Enum.member?(character_id) | ||||
|  | ||||
|     is_select_on_spash = | ||||
|       map_user_settings | ||||
|       |> WandererApp.MapUserSettingsRepo.to_form_data!() | ||||
|       |> WandererApp.MapUserSettingsRepo.get_boolean_setting("select_on_spash") | ||||
|  | ||||
|     (is_user_character && is_select_on_spash) | ||||
|     |> case do | ||||
|       true -> | ||||
|         socket | ||||
|         |> MapEventHandler.push_map_event("select_system", solar_system_id) | ||||
|  | ||||
|       false -> | ||||
|         socket | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_server_event(%{event: :kills_updated, payload: kills}, socket) do | ||||
|     kills = | ||||
|       kills | ||||
|       |> Enum.map(&MapEventHandler.map_ui_kill/1) | ||||
|  | ||||
|     socket | ||||
|     |> MapEventHandler.push_map_event( | ||||
|       "kills_updated", | ||||
|       kills | ||||
|     ) | ||||
|   end | ||||
|  | ||||
|   def handle_server_event(event, socket), | ||||
|     do: MapCoreEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "add_system", | ||||
|         %{"system_id" => solar_system_id} = _event, | ||||
|         %{ | ||||
|           assigns: | ||||
|             %{ | ||||
|               map_id: map_id, | ||||
|               map_slug: map_slug, | ||||
|               current_user: current_user, | ||||
|               tracked_character_ids: tracked_character_ids, | ||||
|               user_permissions: %{add_system: true} | ||||
|             } = assigns | ||||
|         } = socket | ||||
|       ) | ||||
|       when is_binary(solar_system_id) and solar_system_id != "" do | ||||
|     coordinates = Map.get(assigns, :coordinates) | ||||
|  | ||||
|     WandererApp.Map.Server.add_system( | ||||
|       map_id, | ||||
|       %{ | ||||
|         solar_system_id: solar_system_id |> String.to_integer(), | ||||
|         coordinates: coordinates | ||||
|       }, | ||||
|       current_user.id, | ||||
|       tracked_character_ids |> List.first() | ||||
|     ) | ||||
|  | ||||
|     {:noreply, | ||||
|      socket | ||||
|      |> push_patch(to: ~p"/#{map_slug}")} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "manual_add_system", | ||||
|         %{"coordinates" => coordinates} = _event, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             has_tracked_characters?: true, | ||||
|             map_slug: map_slug, | ||||
|             user_permissions: %{add_system: true} | ||||
|           } | ||||
|         } = | ||||
|           socket | ||||
|       ), | ||||
|       do: | ||||
|         {:noreply, | ||||
|          socket | ||||
|          |> assign(coordinates: coordinates) | ||||
|          |> push_patch(to: ~p"/#{map_slug}/add-system")} | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "add_hub", | ||||
|         %{"system_id" => solar_system_id} = _event, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             current_user: current_user, | ||||
|             tracked_character_ids: tracked_character_ids, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = | ||||
|           socket | ||||
|       ) do | ||||
|     map_id | ||||
|     |> WandererApp.Map.Server.add_hub(%{ | ||||
|       solar_system_id: solar_system_id | ||||
|     }) | ||||
|  | ||||
|     {:ok, _} = | ||||
|       WandererApp.User.ActivityTracker.track_map_event(:hub_added, %{ | ||||
|         character_id: tracked_character_ids |> List.first(), | ||||
|         user_id: current_user.id, | ||||
|         map_id: map_id, | ||||
|         solar_system_id: solar_system_id | ||||
|       }) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "delete_hub", | ||||
|         %{"system_id" => solar_system_id} = _event, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             current_user: current_user, | ||||
|             tracked_character_ids: tracked_character_ids, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = | ||||
|           socket | ||||
|       ) do | ||||
|     map_id | ||||
|     |> WandererApp.Map.Server.remove_hub(%{ | ||||
|       solar_system_id: solar_system_id | ||||
|     }) | ||||
|  | ||||
|     {:ok, _} = | ||||
|       WandererApp.User.ActivityTracker.track_map_event(:hub_removed, %{ | ||||
|         character_id: tracked_character_ids |> List.first(), | ||||
|         user_id: current_user.id, | ||||
|         map_id: map_id, | ||||
|         solar_system_id: solar_system_id | ||||
|       }) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "update_system_position", | ||||
|         position, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     map_id | ||||
|     |> update_system_position(position) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "update_system_positions", | ||||
|         positions, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = socket | ||||
|       ) do | ||||
|     map_id | ||||
|     |> update_system_positions(positions) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "update_system_" <> param, | ||||
|         %{"system_id" => solar_system_id, "value" => value} = _event, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             current_user: current_user, | ||||
|             tracked_character_ids: tracked_character_ids, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{update_system: true} | ||||
|           } | ||||
|         } = | ||||
|           socket | ||||
|       ) do | ||||
|     method_atom = | ||||
|       case param do | ||||
|         "name" -> :update_system_name | ||||
|         "description" -> :update_system_description | ||||
|         "labels" -> :update_system_labels | ||||
|         "locked" -> :update_system_locked | ||||
|         "tag" -> :update_system_tag | ||||
|         "status" -> :update_system_status | ||||
|         _ -> nil | ||||
|       end | ||||
|  | ||||
|     key_atom = | ||||
|       case param do | ||||
|         "name" -> :name | ||||
|         "description" -> :description | ||||
|         "labels" -> :labels | ||||
|         "locked" -> :locked | ||||
|         "tag" -> :tag | ||||
|         "status" -> :status | ||||
|         _ -> :none | ||||
|       end | ||||
|  | ||||
|     apply(WandererApp.Map.Server, method_atom, [ | ||||
|       map_id, | ||||
|       %{ | ||||
|         solar_system_id: "#{solar_system_id}" |> String.to_integer() | ||||
|       } | ||||
|       |> Map.put_new(key_atom, value) | ||||
|     ]) | ||||
|  | ||||
|     {:ok, _} = | ||||
|       WandererApp.User.ActivityTracker.track_map_event(:system_updated, %{ | ||||
|         character_id: tracked_character_ids |> List.first(), | ||||
|         user_id: current_user.id, | ||||
|         map_id: map_id, | ||||
|         solar_system_id: "#{solar_system_id}" |> String.to_integer(), | ||||
|         key: key_atom, | ||||
|         value: value | ||||
|       }) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "get_system_static_infos", | ||||
|         %{"solar_system_ids" => solar_system_ids} = _event, | ||||
|         socket | ||||
|       ) do | ||||
|     system_static_infos = | ||||
|       solar_system_ids | ||||
|       |> Enum.map(&WandererApp.CachedInfo.get_system_static_info!/1) | ||||
|       |> Enum.map(&MapEventHandler.map_ui_system_static_info/1) | ||||
|  | ||||
|     {:reply, %{system_static_infos: system_static_infos}, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event( | ||||
|         "delete_systems", | ||||
|         solar_system_ids, | ||||
|         %{ | ||||
|           assigns: %{ | ||||
|             map_id: map_id, | ||||
|             current_user: current_user, | ||||
|             tracked_character_ids: tracked_character_ids, | ||||
|             has_tracked_characters?: true, | ||||
|             user_permissions: %{delete_system: true} | ||||
|           } | ||||
|         } = | ||||
|           socket | ||||
|       ) do | ||||
|     map_id | ||||
|     |> WandererApp.Map.Server.delete_systems( | ||||
|       solar_system_ids |> Enum.map(&String.to_integer/1), | ||||
|       current_user.id, | ||||
|       tracked_character_ids |> List.first() | ||||
|     ) | ||||
|  | ||||
|     {:noreply, socket} | ||||
|   end | ||||
|  | ||||
|   def handle_ui_event(event, body, socket), | ||||
|     do: MapCoreEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   defp update_system_positions(_map_id, []), do: :ok | ||||
|  | ||||
|   defp update_system_positions(map_id, [position | rest]) do | ||||
|     update_system_position(map_id, position) | ||||
|     update_system_positions(map_id, rest) | ||||
|   end | ||||
|  | ||||
|   defp update_system_position(map_id, %{ | ||||
|          "position" => %{"x" => x, "y" => y}, | ||||
|          "solar_system_id" => solar_system_id | ||||
|        }), | ||||
|        do: | ||||
|          map_id | ||||
|          |> WandererApp.Map.Server.update_system_position(%{ | ||||
|            solar_system_id: solar_system_id |> String.to_integer(), | ||||
|            position_x: x, | ||||
|            position_y: y | ||||
|          }) | ||||
| end | ||||
							
								
								
									
										292
									
								
								lib/wanderer_app_web/live/maps/map_event_handler.ex
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								lib/wanderer_app_web/live/maps/map_event_handler.ex
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,292 @@ | ||||
| defmodule WandererAppWeb.MapEventHandler do | ||||
|   use WandererAppWeb, :live_component | ||||
|   use Phoenix.Component | ||||
|   require Logger | ||||
|  | ||||
|   alias WandererAppWeb.{ | ||||
|     MapActivityEventHandler, | ||||
|     MapCharactersEventHandler, | ||||
|     MapConnectionsEventHandler, | ||||
|     MapCoreEventHandler, | ||||
|     MapRoutesEventHandler, | ||||
|     MapSignaturesEventHandler, | ||||
|     MapSystemsEventHandler | ||||
|   } | ||||
|  | ||||
|   @map_characters_events [ | ||||
|     :character_added, | ||||
|     :character_removed, | ||||
|     :character_updated, | ||||
|     :characters_updated, | ||||
|     :present_characters_updated | ||||
|   ] | ||||
|  | ||||
|   @map_characters_ui_events [ | ||||
|     "add_character", | ||||
|     "toggle_track", | ||||
|     "hide_tracking" | ||||
|   ] | ||||
|  | ||||
|   @map_system_events [ | ||||
|     :add_system, | ||||
|     :update_system, | ||||
|     :systems_removed, | ||||
|     :maybe_select_system, | ||||
|     :kills_updated | ||||
|   ] | ||||
|  | ||||
|   @map_system_ui_events [ | ||||
|     "add_hub", | ||||
|     "delete_hub", | ||||
|     "add_system", | ||||
|     "delete_systems", | ||||
|     "manual_add_system", | ||||
|     "get_system_static_infos", | ||||
|     "update_system_position", | ||||
|     "update_system_positions", | ||||
|     "update_system_name", | ||||
|     "update_system_description", | ||||
|     "update_system_labels", | ||||
|     "update_system_locked", | ||||
|     "update_system_tag", | ||||
|     "update_system_status" | ||||
|   ] | ||||
|  | ||||
|   @map_connection_events [ | ||||
|     :add_connection, | ||||
|     :remove_connections, | ||||
|     :update_connection | ||||
|   ] | ||||
|  | ||||
|   @map_connection_ui_events [ | ||||
|     "manual_add_connection", | ||||
|     "manual_delete_connection", | ||||
|     "get_passages", | ||||
|     "update_connection_time_status", | ||||
|     "update_connection_mass_status", | ||||
|     "update_connection_ship_size_type", | ||||
|     "update_connection_locked", | ||||
|     "update_connection_custom_info" | ||||
|   ] | ||||
|  | ||||
|   @map_activity_events [ | ||||
|     :character_activity | ||||
|   ] | ||||
|  | ||||
|   @map_activity_ui_events [ | ||||
|     "show_activity", | ||||
|     "hide_activity" | ||||
|   ] | ||||
|  | ||||
|   @map_routes_events [ | ||||
|     :routes | ||||
|   ] | ||||
|  | ||||
|   @map_routes_ui_events [ | ||||
|     "get_routes", | ||||
|     "set_autopilot_waypoint" | ||||
|   ] | ||||
|  | ||||
|   @map_signatures_events [ | ||||
|     :maybe_link_signature, | ||||
|     :signatures_updated | ||||
|   ] | ||||
|  | ||||
|   @map_signatures_ui_events [ | ||||
|     "update_signatures", | ||||
|     "get_signatures", | ||||
|     "link_signature_to_system", | ||||
|     "unlink_signature" | ||||
|   ] | ||||
|  | ||||
|   def handle_event(socket, %{event: event_name} = event) | ||||
|       when event_name in @map_characters_events, | ||||
|       do: MapCharactersEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_event(socket, %{event: event_name} = event) | ||||
|       when event_name in @map_system_events, | ||||
|       do: MapSystemsEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_event(socket, %{event: event_name} = event) | ||||
|       when event_name in @map_connection_events, | ||||
|       do: MapConnectionsEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_event(socket, %{event: event_name} = event) | ||||
|       when event_name in @map_activity_events, | ||||
|       do: MapActivityEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_event(socket, %{event: event_name} = event) | ||||
|       when event_name in @map_routes_events, | ||||
|       do: MapRoutesEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_event(socket, %{event: event_name} = event) | ||||
|       when event_name in @map_signatures_events, | ||||
|       do: MapSignaturesEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_event(socket, {ref, result}) when is_reference(ref) do | ||||
|     Process.demonitor(ref, [:flush]) | ||||
|  | ||||
|     case result do | ||||
|       {:map_error, map_error} -> | ||||
|         Process.send_after(self(), map_error, 100) | ||||
|         socket | ||||
|  | ||||
|       {event, payload} -> | ||||
|         Process.send_after( | ||||
|           self(), | ||||
|           %{ | ||||
|             event: event, | ||||
|             payload: payload | ||||
|           }, | ||||
|           10 | ||||
|         ) | ||||
|  | ||||
|         socket | ||||
|  | ||||
|       _ -> | ||||
|         socket | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def handle_event(socket, event), | ||||
|     do: MapCoreEventHandler.handle_server_event(event, socket) | ||||
|  | ||||
|   def handle_ui_event(event, body, socket) | ||||
|       when event in @map_characters_ui_events, | ||||
|       do: MapSystemsEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   def handle_ui_event(event, body, socket) | ||||
|       when event in @map_system_ui_events, | ||||
|       do: MapSystemsEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   def handle_ui_event(event, body, socket) | ||||
|       when event in @map_connection_ui_events, | ||||
|       do: MapConnectionsEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   def handle_ui_event(event, body, socket) | ||||
|       when event in @map_routes_ui_events, | ||||
|       do: MapRoutesEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   def handle_ui_event(event, body, socket) | ||||
|       when event in @map_signatures_ui_events, | ||||
|       do: MapSignaturesEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   def handle_ui_event(event, body, socket) | ||||
|       when event in @map_activity_ui_events, | ||||
|       do: MapActivityEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   def handle_ui_event(event, body, socket), | ||||
|     do: MapCoreEventHandler.handle_ui_event(event, body, socket) | ||||
|  | ||||
|   def get_system_static_info(nil), do: nil | ||||
|  | ||||
|   def get_system_static_info(solar_system_id) do | ||||
|     case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do | ||||
|       {:ok, system_static_info} -> | ||||
|         map_ui_system_static_info(system_static_info) | ||||
|  | ||||
|       _ -> | ||||
|         %{} | ||||
|     end | ||||
|   end | ||||
|  | ||||
|   def push_map_event(socket, type, body), | ||||
|     do: | ||||
|       socket | ||||
|       |> Phoenix.LiveView.Utils.push_event("map_event", %{ | ||||
|         type: type, | ||||
|         body: body | ||||
|       }) | ||||
|  | ||||
|   def map_ui_character_stat(character), | ||||
|     do: | ||||
|       character | ||||
|       |> Map.take([ | ||||
|         :eve_id, | ||||
|         :name, | ||||
|         :corporation_ticker, | ||||
|         :alliance_ticker | ||||
|       ]) | ||||
|  | ||||
|   def map_ui_connection( | ||||
|         %{ | ||||
|           solar_system_source: solar_system_source, | ||||
|           solar_system_target: solar_system_target, | ||||
|           mass_status: mass_status, | ||||
|           time_status: time_status, | ||||
|           ship_size_type: ship_size_type, | ||||
|           locked: locked | ||||
|         } = _connection | ||||
|       ), | ||||
|       do: %{ | ||||
|         id: "#{solar_system_source}_#{solar_system_target}", | ||||
|         mass_status: mass_status, | ||||
|         time_status: time_status, | ||||
|         ship_size_type: ship_size_type, | ||||
|         locked: locked, | ||||
|         source: "#{solar_system_source}", | ||||
|         target: "#{solar_system_target}" | ||||
|       } | ||||
|  | ||||
|   def map_ui_system( | ||||
|         %{ | ||||
|           solar_system_id: solar_system_id, | ||||
|           name: name, | ||||
|           description: description, | ||||
|           position_x: position_x, | ||||
|           position_y: position_y, | ||||
|           locked: locked, | ||||
|           tag: tag, | ||||
|           labels: labels, | ||||
|           status: status, | ||||
|           visible: visible | ||||
|         } = _system, | ||||
|         _include_static_data? \\ true | ||||
|       ) do | ||||
|     system_static_info = get_system_static_info(solar_system_id) | ||||
|  | ||||
|     %{ | ||||
|       id: "#{solar_system_id}", | ||||
|       position: %{x: position_x, y: position_y}, | ||||
|       description: description, | ||||
|       name: name, | ||||
|       system_static_info: system_static_info, | ||||
|       labels: labels, | ||||
|       locked: locked, | ||||
|       status: status, | ||||
|       tag: tag, | ||||
|       visible: visible | ||||
|     } | ||||
|   end | ||||
|  | ||||
|   def map_ui_system_static_info(nil), do: %{} | ||||
|  | ||||
|   def map_ui_system_static_info(system_static_info), | ||||
|     do: | ||||
|       system_static_info | ||||
|       |> Map.take([ | ||||
|         :region_id, | ||||
|         :constellation_id, | ||||
|         :solar_system_id, | ||||
|         :solar_system_name, | ||||
|         :solar_system_name_lc, | ||||
|         :constellation_name, | ||||
|         :region_name, | ||||
|         :system_class, | ||||
|         :security, | ||||
|         :type_description, | ||||
|         :class_title, | ||||
|         :is_shattered, | ||||
|         :effect_name, | ||||
|         :effect_power, | ||||
|         :statics, | ||||
|         :wandering, | ||||
|         :triglavian_invasion_status, | ||||
|         :sun_type_id | ||||
|       ]) | ||||
|  | ||||
|   def map_ui_kill({solar_system_id, kills}), | ||||
|     do: %{solar_system_id: solar_system_id, kills: kills} | ||||
|  | ||||
|   def map_ui_kill(_kill), do: %{} | ||||
| end | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -104,20 +104,18 @@ | ||||
|       id="characters-tracking-table" | ||||
|       class="h-[400px] !overflow-y-auto" | ||||
|       rows={characters} | ||||
|       row_click={fn character -> send(self(), "toggle_track_#{character.id}") end} | ||||
|  | ||||
|     > | ||||
|       <:col :let={character} label="Tracked"> | ||||
|         <div class="flex items-center gap-3"> | ||||
|           <label> | ||||
|             <input | ||||
|               type="checkbox" | ||||
|               class="checkbox" | ||||
|               phx-click="toggle_track" | ||||
|               phx-value-character-id={character.id} | ||||
|               id={"character-track-#{character.id}"} | ||||
|               checked={character.tracked} | ||||
|             /> | ||||
|           </label> | ||||
|         <label class="flex items-center gap-3"> | ||||
|           <input | ||||
|             type="checkbox" | ||||
|             class="checkbox" | ||||
|             phx-click="toggle_track" | ||||
|             phx-value-character-id={character.id} | ||||
|             id={"character-track-#{character.id}"} | ||||
|             checked={character.tracked} | ||||
|           /> | ||||
|           <div class="flex items-center gap-3"> | ||||
|             <.avatar url={member_icon_url(character.eve_id)} label={character.name} /> | ||||
|             <div> | ||||
| @@ -127,7 +125,7 @@ | ||||
|               <div class="text-sm opacity-50"></div> | ||||
|             </div> | ||||
|           </div> | ||||
|         </div> | ||||
|         </label> | ||||
|       </:col> | ||||
|     </.table> | ||||
|   </.async_result> | ||||
|   | ||||
| @@ -8,11 +8,14 @@ defmodule WandererAppWeb.MapsLive do | ||||
|   @pubsub_client Application.compile_env(:wanderer_app, :pubsub_client) | ||||
|  | ||||
|   @impl true | ||||
|   def mount(_params, %{"user_id" => user_id} = _session, socket) when not is_nil(user_id) do | ||||
|   def mount( | ||||
|         _params, | ||||
|         %{"user_id" => user_id} = _session, | ||||
|         %{assigns: %{current_user: current_user}} = socket | ||||
|       ) | ||||
|       when not is_nil(user_id) do | ||||
|     {:ok, active_characters} = WandererApp.Api.Character.active_by_user(%{user_id: user_id}) | ||||
|  | ||||
|     current_user = socket.assigns.current_user | ||||
|  | ||||
|     user_characters = | ||||
|       active_characters | ||||
|       |> Enum.map(&map_character/1) | ||||
| @@ -601,16 +604,6 @@ defmodule WandererAppWeb.MapsLive do | ||||
|  | ||||
|         {added_acls, removed_acls} = map.acls |> Enum.map(& &1.id) |> _get_acls_diff(form["acls"]) | ||||
|  | ||||
|         added_acls | ||||
|         |> Enum.each(fn acl_id -> | ||||
|           :telemetry.execute([:wanderer_app, :map, :acl, :add], %{count: 1}) | ||||
|         end) | ||||
|  | ||||
|         removed_acls | ||||
|         |> Enum.each(fn acl_id -> | ||||
|           :telemetry.execute([:wanderer_app, :map, :acl, :remove], %{count: 1}) | ||||
|         end) | ||||
|  | ||||
|         Phoenix.PubSub.broadcast( | ||||
|           WandererApp.PubSub, | ||||
|           "maps:#{map.id}", | ||||
|   | ||||
		Reference in New Issue
	
	Block a user