mirror of
				https://github.com/wanderer-industries/wanderer
				synced 2025-11-04 00:14:52 +00:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
			v1.48.0
			...
			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