mirror of
https://github.com/wanderer-industries/wanderer
synced 2025-11-08 18:34:27 +00:00
Compare commits
10 Commits
map-events
...
v1.13.12
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
149ac98297 | ||
|
|
b90a2910c9 | ||
|
|
c4da8a3a8d | ||
|
|
3ca75583d2 | ||
|
|
5f4607ae6f | ||
|
|
d880c6873f | ||
|
|
937649b2ed | ||
|
|
78e912c886 | ||
|
|
696c7d2cd1 | ||
|
|
49c0cb026b |
37
CHANGELOG.md
37
CHANGELOG.md
@@ -1,6 +1,43 @@
|
||||
# Change Log
|
||||
|
||||
<!-- changelog -->
|
||||
|
||||
## [v1.13.12](https://github.com/wanderer-industries/wanderer/compare/v1.13.11...v1.13.12) (2024-11-04)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fix system revert issues
|
||||
|
||||
## [v1.13.11](https://github.com/wanderer-industries/wanderer/compare/v1.13.10...v1.13.11) (2024-11-02)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fix system revert issues
|
||||
|
||||
## [v1.13.10](https://github.com/wanderer-industries/wanderer/compare/v1.13.9...v1.13.10) (2024-11-01)
|
||||
|
||||
|
||||
|
||||
|
||||
### Bug Fixes:
|
||||
|
||||
* Map: Fix system revert issues
|
||||
|
||||
## [v1.13.9](https://github.com/wanderer-industries/wanderer/compare/v1.13.8...v1.13.9) (2024-11-01)
|
||||
|
||||
|
||||
|
||||
|
||||
## [v1.13.8](https://github.com/wanderer-industries/wanderer/compare/v1.13.7...v1.13.8) (2024-10-28)
|
||||
|
||||
|
||||
|
||||
## [v1.13.0](https://github.com/wanderer-industries/wanderer/compare/v1.12.11...v1.13.0) (2024-10-28)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -138,6 +138,7 @@ config :ueberauth, WandererApp.Ueberauth.Strategy.Eve.OAuth,
|
||||
System.get_env("EVE_CLIENT_WITH_CORP_WALLET_SECRET", "<EVE_CLIENT_WITH_CORP_WALLET_SECRET>")
|
||||
|
||||
config :logger,
|
||||
truncate: :infinity,
|
||||
level:
|
||||
String.to_existing_atom(
|
||||
System.get_env(
|
||||
|
||||
3
fly.toml
3
fly.toml
@@ -6,6 +6,7 @@
|
||||
app = 'wanderer'
|
||||
primary_region = 'ams'
|
||||
kill_signal = 'SIGTERM'
|
||||
swap_size_mb = 512
|
||||
|
||||
[build]
|
||||
|
||||
@@ -35,6 +36,6 @@ path = "/metrics"
|
||||
soft_limit = 1000
|
||||
|
||||
[[vm]]
|
||||
memory = '1gb'
|
||||
memory = '256mb'
|
||||
cpu_kind = 'shared'
|
||||
cpus = 1
|
||||
|
||||
@@ -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
|
||||
"""
|
||||
|
||||
@@ -3,6 +3,8 @@ defmodule WandererApp.Application do
|
||||
|
||||
use Application
|
||||
|
||||
require Logger
|
||||
|
||||
@impl true
|
||||
def start(_type, _args) do
|
||||
children =
|
||||
@@ -45,7 +47,16 @@ defmodule WandererApp.Application do
|
||||
# See https://hexdocs.pm/elixir/Supervisor.html
|
||||
# for other strategies and supported options
|
||||
opts = [strategy: :one_for_one, name: WandererApp.Supervisor]
|
||||
|
||||
Supervisor.start_link(children, opts)
|
||||
|> case do
|
||||
{:ok, _pid} = ok ->
|
||||
ok
|
||||
|
||||
{:error, info} = e ->
|
||||
Logger.error("Failed to start application: #{inspect(info)}")
|
||||
e
|
||||
end
|
||||
end
|
||||
|
||||
# Tell Phoenix to update the endpoint configuration
|
||||
|
||||
@@ -37,32 +37,32 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
|
||||
@logger Application.compile_env(:wanderer_app, :logger)
|
||||
|
||||
def get_server_status, do: _get("/status")
|
||||
def get_server_status, do: get("/status")
|
||||
|
||||
def set_autopilot_waypoint(add_to_beginning, clear_other_waypoints, destination_id, opts \\ []) do
|
||||
_post_esi(
|
||||
"/ui/autopilot/waypoint",
|
||||
opts
|
||||
|> Keyword.merge(
|
||||
params: %{
|
||||
add_to_beginning: add_to_beginning,
|
||||
clear_other_waypoints: clear_other_waypoints,
|
||||
destination_id: destination_id
|
||||
}
|
||||
def set_autopilot_waypoint(add_to_beginning, clear_other_waypoints, destination_id, opts \\ []),
|
||||
do:
|
||||
post_esi(
|
||||
"/ui/autopilot/waypoint",
|
||||
opts
|
||||
|> Keyword.merge(
|
||||
params: %{
|
||||
add_to_beginning: add_to_beginning,
|
||||
clear_other_waypoints: clear_other_waypoints,
|
||||
destination_id: destination_id
|
||||
}
|
||||
)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
def post_characters_affiliation(character_eve_ids, _opts)
|
||||
when is_list(character_eve_ids) do
|
||||
_post(
|
||||
"#{@base_url}/characters/affiliation/",
|
||||
json: character_eve_ids,
|
||||
params: %{
|
||||
datasource: "tranquility"
|
||||
}
|
||||
)
|
||||
end
|
||||
when is_list(character_eve_ids),
|
||||
do:
|
||||
post(
|
||||
"#{@base_url}/characters/affiliation/",
|
||||
json: character_eve_ids,
|
||||
params: %{
|
||||
datasource: "tranquility"
|
||||
}
|
||||
)
|
||||
|
||||
def find_routes(map_id, origin, hubs, routes_settings) do
|
||||
origin = origin |> String.to_integer()
|
||||
@@ -184,7 +184,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
routes =
|
||||
all_routes
|
||||
|> Enum.map(fn route_info ->
|
||||
_map_route_info(route_info)
|
||||
map_route_info(route_info)
|
||||
end)
|
||||
|> Enum.filter(fn route_info -> not is_nil(route_info) end)
|
||||
|
||||
@@ -200,7 +200,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
{:ok, result}
|
||||
|
||||
_ ->
|
||||
case _get_all_routes_custom(hubs, origin, params) do
|
||||
case get_all_routes_custom(hubs, origin, params) do
|
||||
{:ok, result} ->
|
||||
WandererApp.Cache.insert(
|
||||
cache_key,
|
||||
@@ -210,22 +210,21 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
|
||||
{:ok, result}
|
||||
|
||||
{:error, error} ->
|
||||
@logger.error("Error getting custom routes for #{inspect(origin)}: #{inspect(error)}")
|
||||
{:error, _error} ->
|
||||
@logger.error("Error getting custom routes for #{inspect(origin)}: #{inspect(hubs)}")
|
||||
|
||||
@logger.error(
|
||||
"Error getting custom routes for #{inspect(origin)}: #{inspect(params)}"
|
||||
)
|
||||
|
||||
_get_all_routes_eve(hubs, origin, params, opts)
|
||||
get_all_routes_eve(hubs, origin, params, opts)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
defp _get_all_routes_custom(hubs, origin, params),
|
||||
defp get_all_routes_custom(hubs, origin, params),
|
||||
do:
|
||||
_post(
|
||||
post(
|
||||
"#{get_custom_route_base_url()}/route/multiple",
|
||||
[
|
||||
json: %{
|
||||
@@ -239,7 +238,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
|> Keyword.merge(@timeout_opts)
|
||||
)
|
||||
|
||||
def _get_all_routes_eve(hubs, origin, params, opts),
|
||||
def get_all_routes_eve(hubs, origin, params, opts),
|
||||
do:
|
||||
{:ok,
|
||||
hubs
|
||||
@@ -308,7 +307,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
opts: [ttl: @ttl]
|
||||
)
|
||||
def get_character_info(eve_id, opts \\ []) do
|
||||
case _get(
|
||||
case get(
|
||||
"/characters/#{eve_id}/",
|
||||
opts |> _with_cache_opts()
|
||||
) do
|
||||
@@ -385,7 +384,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
|
||||
defp _get_routes_eve(origin, destination, params, opts),
|
||||
do:
|
||||
_get(
|
||||
get(
|
||||
"/route/#{origin}/#{destination}/?#{params |> Plug.Conn.Query.encode()}",
|
||||
opts |> _with_cache_opts()
|
||||
)
|
||||
@@ -394,14 +393,14 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
|
||||
defp _get_alliance_info(alliance_eve_id, info_path, opts),
|
||||
do:
|
||||
_get(
|
||||
get(
|
||||
"/alliances/#{alliance_eve_id}/#{info_path}",
|
||||
opts |> _with_cache_opts()
|
||||
)
|
||||
|
||||
defp _get_corporation_info(corporation_eve_id, info_path, opts),
|
||||
do:
|
||||
_get(
|
||||
get(
|
||||
"/corporations/#{corporation_eve_id}/#{info_path}",
|
||||
opts |> _with_cache_opts()
|
||||
)
|
||||
@@ -416,7 +415,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
character_id = opts |> Keyword.get(:character_id, nil)
|
||||
|
||||
if not _is_access_token_expired?(character_id) do
|
||||
_get(
|
||||
get(
|
||||
path,
|
||||
auth_opts,
|
||||
opts
|
||||
@@ -437,7 +436,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
|
||||
defp _get_corporation_auth_data(corporation_eve_id, info_path, opts),
|
||||
do:
|
||||
_get(
|
||||
get(
|
||||
"/corporations/#{corporation_eve_id}/#{info_path}",
|
||||
[params: opts[:params] || []] ++
|
||||
(opts |> _get_auth_opts() |> _with_cache_opts()),
|
||||
@@ -448,14 +447,14 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
opts |> Keyword.merge(@cache_opts) |> Keyword.merge(cache_dir: System.tmp_dir!())
|
||||
end
|
||||
|
||||
defp _post_esi(path, opts),
|
||||
defp post_esi(path, opts),
|
||||
do:
|
||||
_post(
|
||||
post(
|
||||
"#{@base_url}#{path}",
|
||||
[params: opts[:params] || []] ++ (opts |> _get_auth_opts())
|
||||
)
|
||||
|
||||
defp _get(path, api_opts \\ [], opts \\ []) do
|
||||
defp get(path, api_opts \\ [], opts \\ []) do
|
||||
try do
|
||||
case Req.get("#{@base_url}#{path}", api_opts |> Keyword.merge(@retry_opts)) do
|
||||
{:ok, %{status: 200, body: body}} ->
|
||||
@@ -487,7 +486,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
end
|
||||
end
|
||||
|
||||
defp _post(url, opts) do
|
||||
defp post(url, opts) do
|
||||
try do
|
||||
case Req.post("#{url}", opts) do
|
||||
{:ok, %{status: status, body: body}} when status in [200, 201] ->
|
||||
@@ -525,7 +524,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
{:ok, token} ->
|
||||
auth_opts = [access_token: token.access_token] |> _get_auth_opts()
|
||||
|
||||
_get(
|
||||
get(
|
||||
path,
|
||||
api_opts |> Keyword.merge(auth_opts),
|
||||
opts |> Keyword.merge(retry_count: retry_count + 1)
|
||||
@@ -600,7 +599,7 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
end
|
||||
end
|
||||
|
||||
defp _map_route_info(
|
||||
defp map_route_info(
|
||||
%{
|
||||
"origin" => origin,
|
||||
"destination" => destination,
|
||||
@@ -609,14 +608,14 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
} = _route_info
|
||||
),
|
||||
do:
|
||||
_map_route_info(%{
|
||||
map_route_info(%{
|
||||
origin: origin,
|
||||
destination: destination,
|
||||
systems: result_systems,
|
||||
success: success
|
||||
})
|
||||
|
||||
defp _map_route_info(
|
||||
defp map_route_info(
|
||||
%{origin: origin, destination: destination, systems: result_systems, success: success} =
|
||||
_route_info
|
||||
) do
|
||||
@@ -638,5 +637,5 @@ defmodule WandererApp.Esi.ApiClient do
|
||||
}
|
||||
end
|
||||
|
||||
defp _map_route_info(_), do: nil
|
||||
defp map_route_info(_), do: nil
|
||||
end
|
||||
|
||||
@@ -214,7 +214,7 @@ defmodule WandererApp.Map do
|
||||
%{visible: true} = system ->
|
||||
system
|
||||
|
||||
_ ->
|
||||
_system ->
|
||||
nil
|
||||
end
|
||||
end
|
||||
@@ -262,7 +262,7 @@ defmodule WandererApp.Map do
|
||||
case not Map.has_key?(systems, solar_system_id) do
|
||||
true ->
|
||||
map_id
|
||||
|> update_map(%{systems: Map.put_new(systems, solar_system_id, system)})
|
||||
|> update_map(%{systems: Map.put(systems, solar_system_id, system)})
|
||||
|
||||
:ok
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -134,7 +134,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
|
||||
def start_map(%__MODULE__{map: map, map_id: map_id} = state) do
|
||||
with :ok <- _track_acls(map.acls |> Enum.map(& &1.id)) do
|
||||
with :ok <- track_acls(map.acls |> Enum.map(& &1.id)) do
|
||||
@pubsub_client.subscribe(
|
||||
WandererApp.PubSub,
|
||||
"maps:#{map_id}"
|
||||
@@ -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)
|
||||
@@ -603,7 +605,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
def handle_event({:map_acl_updated, added_acls, removed_acls}, %{map: old_map} = state) do
|
||||
{:ok, map} = WandererApp.MapRepo.get(old_map.map_id, [:acls])
|
||||
|
||||
_track_acls(added_acls)
|
||||
track_acls(added_acls)
|
||||
|
||||
result =
|
||||
[added_acls | removed_acls]
|
||||
@@ -677,7 +679,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
} ->
|
||||
DateTime.diff(DateTime.utc_now(), inserted_at, :hour) >=
|
||||
@connection_auto_eol_hours and
|
||||
_is_connection_valid(
|
||||
is_connection_valid(
|
||||
:wormholes,
|
||||
solar_system_source_id,
|
||||
solar_system_target_id
|
||||
@@ -705,7 +707,7 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
solar_system_source: solar_system_source_id,
|
||||
solar_system_target: solar_system_target_id
|
||||
} ->
|
||||
connection_mark_eol_time = _get_connection_mark_eol_time(map_id, connection_id)
|
||||
connection_mark_eol_time = get_connection_mark_eol_time(map_id, connection_id)
|
||||
|
||||
reverse_connection =
|
||||
WandererApp.Map.get_connection(
|
||||
@@ -715,24 +717,23 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
)
|
||||
|
||||
is_connection_exist =
|
||||
_is_connection_exist(
|
||||
is_connection_exist(
|
||||
map_id,
|
||||
solar_system_source_id,
|
||||
solar_system_target_id
|
||||
)
|
||||
) || not is_nil(reverse_connection)
|
||||
|
||||
is_connection_valid =
|
||||
_is_connection_valid(
|
||||
is_connection_valid(
|
||||
:wormholes,
|
||||
solar_system_source_id,
|
||||
solar_system_target_id
|
||||
)
|
||||
|
||||
not is_connection_exist or
|
||||
not is_nil(reverse_connection) or
|
||||
(is_connection_valid and
|
||||
not is_connection_exist ||
|
||||
(is_connection_valid &&
|
||||
(DateTime.diff(DateTime.utc_now(), inserted_at, :hour) >=
|
||||
@connection_auto_expire_hours or
|
||||
@connection_auto_expire_hours ||
|
||||
DateTime.diff(DateTime.utc_now(), connection_mark_eol_time, :hour) >=
|
||||
@connection_auto_expire_hours - @connection_auto_eol_hours))
|
||||
end)
|
||||
@@ -806,12 +807,13 @@ 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: [
|
||||
layout: options |> Map.get("layout"),
|
||||
store_custom_labels: options |> Map.get("store_custom_labels")
|
||||
layout: options |> Map.get("layout", "left_to_right"),
|
||||
store_custom_labels:
|
||||
options |> Map.get("store_custom_labels", "false") |> String.to_existing_atom()
|
||||
]
|
||||
}
|
||||
|
||||
@@ -835,8 +837,9 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
:ok
|
||||
end
|
||||
|
||||
defp _get_connection_mark_eol_time(map_id, connection_id) do
|
||||
case WandererApp.Cache.get("map_#{map_id}:conn_#{connection_id}:mark_eol_time") do
|
||||
defp get_connection_mark_eol_time(map_id, connection_id) do
|
||||
WandererApp.Cache.get("map_#{map_id}:conn_#{connection_id}:mark_eol_time")
|
||||
|> case do
|
||||
nil ->
|
||||
DateTime.utc_now()
|
||||
|
||||
@@ -857,12 +860,12 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
%{map: map, map_id: map_id, rtree_name: rtree_name, map_opts: map_opts} = _state
|
||||
) do
|
||||
case is_nil(old_location.solar_system_id) and
|
||||
_can_add_location(map.scope, location.solar_system_id) do
|
||||
can_add_location(map.scope, location.solar_system_id) do
|
||||
true ->
|
||||
:ok = maybe_add_system(map_id, location, nil, rtree_name, map_opts)
|
||||
|
||||
_ ->
|
||||
case _is_connection_valid(
|
||||
case is_connection_valid(
|
||||
map.scope,
|
||||
old_location.solar_system_id,
|
||||
location.solar_system_id
|
||||
@@ -1153,7 +1156,8 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
rtree_name
|
||||
)
|
||||
|
||||
{:ok, existing_system}
|
||||
existing_system
|
||||
|> WandererApp.MapSystemRepo.update_visible(%{visible: true})
|
||||
else
|
||||
@ddrt.insert(
|
||||
{solar_system_id,
|
||||
@@ -1164,11 +1168,11 @@ 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!()
|
||||
|> WandererApp.MapSystemRepo.update_visible(%{visible: true})
|
||||
end
|
||||
|
||||
_ ->
|
||||
@@ -1211,8 +1215,6 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
solar_system_id: solar_system_id
|
||||
})
|
||||
|
||||
:telemetry.execute([:wanderer_app, :map, :system, :add], %{count: 1})
|
||||
|
||||
state
|
||||
end
|
||||
|
||||
@@ -1312,8 +1314,9 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
{:ok, map_options} = WandererApp.MapRepo.options_to_form_data(initial_map)
|
||||
|
||||
map_opts = [
|
||||
layout: map_options |> Map.get("layout"),
|
||||
store_custom_labels: map_options |> Map.get("store_custom_labels")
|
||||
layout: map_options |> Map.get("layout", "left_to_right"),
|
||||
store_custom_labels:
|
||||
map_options |> Map.get("store_custom_labels", "false") |> String.to_existing_atom()
|
||||
]
|
||||
|
||||
%{state | map: map, map_opts: map_opts}
|
||||
@@ -1442,13 +1445,13 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
broadcast!(map_id, :update_system, updated_system)
|
||||
end
|
||||
|
||||
defp _can_add_location(_scope, nil), do: false
|
||||
defp can_add_location(_scope, nil), do: false
|
||||
|
||||
defp _can_add_location(:all, _solar_system_id), do: true
|
||||
defp can_add_location(:all, _solar_system_id), do: true
|
||||
|
||||
defp _can_add_location(:none, _solar_system_id), do: false
|
||||
defp can_add_location(:none, _solar_system_id), do: false
|
||||
|
||||
defp _can_add_location(scope, solar_system_id) do
|
||||
defp can_add_location(scope, solar_system_id) do
|
||||
system_static_info =
|
||||
case WandererApp.CachedInfo.get_system_static_info(solar_system_id) do
|
||||
{:ok, system_static_info} when not is_nil(system_static_info) ->
|
||||
@@ -1473,14 +1476,14 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
end
|
||||
|
||||
defp _is_connection_exist(map_id, from_solar_system_id, to_solar_system_id),
|
||||
defp is_connection_exist(map_id, from_solar_system_id, to_solar_system_id),
|
||||
do:
|
||||
not is_nil(
|
||||
WandererApp.Map.find_system_by_location(
|
||||
map_id,
|
||||
%{solar_system_id: from_solar_system_id}
|
||||
)
|
||||
) and
|
||||
) &&
|
||||
not is_nil(
|
||||
WandererApp.Map.find_system_by_location(
|
||||
map_id,
|
||||
@@ -1488,13 +1491,13 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
)
|
||||
)
|
||||
|
||||
defp _is_connection_valid(_scope, nil, _to_solar_system_id), do: false
|
||||
defp is_connection_valid(_scope, nil, _to_solar_system_id), do: false
|
||||
|
||||
defp _is_connection_valid(:all, _from_solar_system_id, _to_solar_system_id), do: true
|
||||
defp is_connection_valid(:all, _from_solar_system_id, _to_solar_system_id), do: true
|
||||
|
||||
defp _is_connection_valid(:none, _from_solar_system_id, _to_solar_system_id), do: false
|
||||
defp is_connection_valid(:none, _from_solar_system_id, _to_solar_system_id), do: false
|
||||
|
||||
defp _is_connection_valid(scope, from_solar_system_id, to_solar_system_id) do
|
||||
defp is_connection_valid(scope, from_solar_system_id, to_solar_system_id) do
|
||||
{:ok, known_jumps} =
|
||||
WandererApp.Api.MapSolarSystemJumps.find(%{
|
||||
before_system_id: from_solar_system_id,
|
||||
@@ -1560,11 +1563,11 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
end
|
||||
end
|
||||
|
||||
defp _track_acls([]), do: :ok
|
||||
defp track_acls([]), do: :ok
|
||||
|
||||
defp _track_acls([acl_id | rest]) do
|
||||
defp track_acls([acl_id | rest]) do
|
||||
_track_acl(acl_id)
|
||||
_track_acls(rest)
|
||||
track_acls(rest)
|
||||
end
|
||||
|
||||
defp _track_acl(acl_id),
|
||||
@@ -1683,11 +1686,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 +1699,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 +1726,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,
|
||||
@@ -1747,17 +1752,19 @@ defmodule WandererApp.Map.Server.Impl do
|
||||
broadcast!(map_id, :add_system, new_system)
|
||||
WandererApp.Map.add_system(map_id, new_system)
|
||||
|
||||
_ ->
|
||||
error ->
|
||||
@logger.debug("Failed to create system: #{inspect(error, pretty: true)}")
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
{:error, _} ->
|
||||
error ->
|
||||
@logger.debug("Skip adding system: #{inspect(error, pretty: true)}")
|
||||
:ok
|
||||
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,19 +33,26 @@ 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()
|
||||
Keyword.get(opts, :store_custom_labels)
|
||||
|
||||
labels = get_filtered_labels(labels, store_custom_labels?)
|
||||
|
||||
system
|
||||
|> WandererApp.Api.MapSystem.update_labels!(%{
|
||||
|> update_labels!(%{
|
||||
labels: labels
|
||||
})
|
||||
end
|
||||
|
||||
def cleanup_tags(system) do
|
||||
system
|
||||
|> WandererApp.Api.MapSystem.update_tag(%{
|
||||
tag: nil
|
||||
})
|
||||
end
|
||||
|
||||
def cleanup_tags!(system) do
|
||||
system
|
||||
|> WandererApp.Api.MapSystem.update_tag!(%{
|
||||
tag: nil
|
||||
@@ -56,7 +63,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!()
|
||||
|
||||
@@ -97,6 +104,11 @@ defmodule WandererApp.MapSystemRepo do
|
||||
system
|
||||
|> WandererApp.Api.MapSystem.update_labels(update)
|
||||
|
||||
def update_labels!(system, update),
|
||||
do:
|
||||
system
|
||||
|> WandererApp.Api.MapSystem.update_labels!(update)
|
||||
|
||||
def update_position(system, update),
|
||||
do:
|
||||
system
|
||||
@@ -106,4 +118,14 @@ defmodule WandererApp.MapSystemRepo do
|
||||
do:
|
||||
system
|
||||
|> WandererApp.Api.MapSystem.update_position!(update)
|
||||
|
||||
def update_visible(system, update),
|
||||
do:
|
||||
system
|
||||
|> WandererApp.Api.MapSystem.update_visible(update)
|
||||
|
||||
def update_visible!(system, update),
|
||||
do:
|
||||
system
|
||||
|> WandererApp.Api.MapSystem.update_visible!(update)
|
||||
end
|
||||
|
||||
@@ -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