diff --git a/assets/js/hooks/Mapper/components/map/MapProvider.tsx b/assets/js/hooks/Mapper/components/map/MapProvider.tsx index e31d9587..e9ce7383 100644 --- a/assets/js/hooks/Mapper/components/map/MapProvider.tsx +++ b/assets/js/hooks/Mapper/components/map/MapProvider.tsx @@ -37,6 +37,7 @@ const INITIAL_DATA: MapData = { userPermissions: {}, systemSignatures: {} as Record, options: {} as Record, + is_subscription_active: false, }; export interface MapContextProps { diff --git a/assets/js/hooks/Mapper/components/mapInterface/constants.tsx b/assets/js/hooks/Mapper/components/mapInterface/constants.tsx index 75c587e1..02f84e43 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/constants.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/constants.tsx @@ -103,13 +103,3 @@ export const WIDGETS_CHECKBOXES_PROPS: WidgetsCheckboxesType = [ label: 'Kills', }, ]; - -export function getWidgetsCheckboxesProps(detailedKillsDisabled: boolean): WidgetsCheckboxesType { - return filterOutKills(WIDGETS_CHECKBOXES_PROPS, detailedKillsDisabled); -} - - -function filterOutKills(items: T[], shouldFilter: boolean) { - if (!shouldFilter) return items; - return items.filter((w) => w.id !== WidgetsIds.kills); -} diff --git a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKills.tsx b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKills.tsx index 808e006e..af00f0bb 100644 --- a/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKills.tsx +++ b/assets/js/hooks/Mapper/components/mapInterface/widgets/SystemKills/SystemKills.tsx @@ -9,7 +9,7 @@ import { KillsSettingsDialog } from './components/SystemKillsSettingsDialog'; export const SystemKills: React.FC = () => { const { - data: { selectedSystems, systems }, + data: { selectedSystems, systems, is_subscription_active: isSubscriptionActive }, outCommand, } = useMapRootState(); @@ -41,40 +41,49 @@ export const SystemKills: React.FC = () => {
setSettingsDialogVisible(true)} />}> - {isNothingSelected && ( + {!isSubscriptionActive && (
- No system selected (or toggle “Show all systems”) + Kills available with 'Active' map subscription only (contact map administrators)
)} + {isSubscriptionActive && ( + <> + {isNothingSelected && ( +
+ No system selected (or toggle “Show all systems”) +
+ )} - {!isNothingSelected && showLoading && ( -
- Loading Kills... -
- )} + {!isNothingSelected && showLoading && ( +
+ Loading Kills... +
+ )} - {!isNothingSelected && !showLoading && error && ( -
- {error} -
- )} + {!isNothingSelected && !showLoading && error && ( +
+ {error} +
+ )} - {!isNothingSelected && !showLoading && !error && (!kills || kills.length === 0) && ( -
- No kills found -
- )} + {!isNothingSelected && !showLoading && !error && (!kills || kills.length === 0) && ( +
+ No kills found +
+ )} - {!isNothingSelected && !showLoading && !error && ( -
- -
+ {!isNothingSelected && !showLoading && !error && ( +
+ +
+ )} + )}
diff --git a/assets/js/hooks/Mapper/components/mapRootContent/components/MapSettings/components/WidgetsSettings/WidgetsSettings.tsx b/assets/js/hooks/Mapper/components/mapRootContent/components/MapSettings/components/WidgetsSettings/WidgetsSettings.tsx index f2cc275c..df393ee0 100644 --- a/assets/js/hooks/Mapper/components/mapRootContent/components/MapSettings/components/WidgetsSettings/WidgetsSettings.tsx +++ b/assets/js/hooks/Mapper/components/mapRootContent/components/MapSettings/components/WidgetsSettings/WidgetsSettings.tsx @@ -1,5 +1,5 @@ import { PrettySwitchbox } from '@/hooks/Mapper/components/mapRootContent/components/MapSettings/components'; -import { getWidgetsCheckboxesProps, WidgetsIds } from '@/hooks/Mapper/components/mapInterface/constants.tsx'; +import { WIDGETS_CHECKBOXES_PROPS, WidgetsIds } from '@/hooks/Mapper/components/mapInterface/constants.tsx'; import { useMapRootState } from '@/hooks/Mapper/mapRootProvider'; import { useCallback } from 'react'; @@ -9,20 +9,17 @@ export interface WidgetsSettingsProps {} // eslint-disable-next-line no-empty-pattern export const WidgetsSettings = ({}: WidgetsSettingsProps) => { - const { windowsSettings, toggleWidgetVisibility, resetWidgets, data } = useMapRootState(); + const { windowsSettings, toggleWidgetVisibility, resetWidgets } = useMapRootState(); const handleWidgetSettingsChange = useCallback( (widget: WidgetsIds) => toggleWidgetVisibility(widget), [toggleWidgetVisibility], ); - const detailedKillsDisabled = data.options?.detailedKillsDisabled === true; - const widgetProps = getWidgetsCheckboxesProps(detailedKillsDisabled); - return (
- {widgetProps.map(widget => ( + {WIDGETS_CHECKBOXES_PROPS.map(widget => ( ; options: Record; + is_subscription_active: boolean; }; diff --git a/lib/wanderer_app/map.ex b/lib/wanderer_app/map.ex index 18a02579..80bea482 100644 --- a/lib/wanderer_app/map.ex +++ b/lib/wanderer_app/map.ex @@ -70,9 +70,14 @@ defmodule WandererApp.Map do def get_characters_limit(map_id), do: {:ok, map_id |> get_map!() |> Map.get(:characters_limit, 50)} - def is_subscription_active?(map_id) do + def is_subscription_active?(map_id), + do: is_subscription_active?(map_id, WandererApp.Env.map_subscriptions_enabled?()) + + def is_subscription_active?(_map_id, false), do: {:ok, true} + + def is_subscription_active?(map_id, _map_subscriptions_enabled) do {:ok, %{plan: plan}} = WandererApp.Map.SubscriptionManager.get_active_map_subscription(map_id) - not WandererApp.Env.map_subscriptions_enabled?() || plan != :alpha + {:ok, plan != :alpha} end def get_options(map_id), diff --git a/lib/wanderer_app/map/map_zkb_data_fetcher.ex b/lib/wanderer_app/map/map_zkb_data_fetcher.ex index 07459b14..f214639a 100644 --- a/lib/wanderer_app/map/map_zkb_data_fetcher.ex +++ b/lib/wanderer_app/map/map_zkb_data_fetcher.ex @@ -28,6 +28,8 @@ defmodule WandererApp.Map.ZkbDataFetcher do @impl true def handle_info(:fetch_data, %{iteration: iteration} = state) do + zkill_preload_disabled = WandererApp.Env.zkill_preload_disabled?() + WandererApp.Map.RegistryHelper.list_all_maps() |> Task.async_stream( fn %{id: map_id, pid: _server_pid} -> @@ -35,7 +37,11 @@ defmodule WandererApp.Map.ZkbDataFetcher do if WandererApp.Map.Server.map_pid(map_id) do update_map_kills(map_id) - unless WandererApp.Env.zkill_preload_disabled?() do + {:ok, is_subscription_active} = map_id |> WandererApp.Map.is_subscription_active?() + + can_preload_zkill = not zkill_preload_disabled && is_subscription_active + + if can_preload_zkill do update_detailed_map_kills(map_id) end end @@ -52,7 +58,7 @@ defmodule WandererApp.Map.ZkbDataFetcher do new_iteration = iteration + 1 cond do - WandererApp.Env.zkill_preload_disabled?() -> + zkill_preload_disabled -> # If preload is disabled, just update iteration {:noreply, %{state | iteration: new_iteration}} @@ -138,11 +144,11 @@ defmodule WandererApp.Map.ZkbDataFetcher do end) WandererApp.Cache.put("map_#{map_id}:zkb_ids", updated_ids_map, - ttl: :timer.hours(KillsCache.killmail_ttl) + ttl: :timer.hours(KillsCache.killmail_ttl()) ) WandererApp.Cache.put("map_#{map_id}:zkb_detailed_kills", updated_details_map, - ttl: :timer.hours(KillsCache.killmail_ttl) + ttl: :timer.hours(KillsCache.killmail_ttl()) ) changed_data = Map.take(updated_details_map, changed_systems) diff --git a/lib/wanderer_app/zkb/zkb_kills_preloader.ex b/lib/wanderer_app/zkb/zkb_kills_preloader.ex index 89e74992..69e50ad4 100644 --- a/lib/wanderer_app/zkb/zkb_kills_preloader.ex +++ b/lib/wanderer_app/zkb/zkb_kills_preloader.ex @@ -65,15 +65,18 @@ defmodule WandererApp.Zkb.KillsPreloader do last_active_maps_result = WandererApp.Api.MapState.get_last_active(cutoff_time) last_active_maps = resolve_last_active_maps(last_active_maps_result) + active_maps_with_subscription = get_active_maps_with_subscription(last_active_maps) # Gather systems from those maps - system_tuples = gather_visible_systems(last_active_maps) + system_tuples = gather_visible_systems(active_maps_with_subscription) unique_systems = Enum.uniq(system_tuples) - Logger.debug(""" - [KillsPreloader] Found #{length(unique_systems)} unique systems \ - across #{length(last_active_maps)} map(s) - """) + Logger.debug(fn -> + """ + [KillsPreloader] Found #{length(unique_systems)} unique systems \ + across #{length(active_maps_with_subscription)} map(s) + """ + end) # ---- QUICK PASS ---- state_quick = %{state | phase: :quick_pass} @@ -83,7 +86,9 @@ defmodule WandererApp.Zkb.KillsPreloader do do_pass(unique_systems, :quick, @quick_hours, @quick_limit, state_quick) end) - Logger.info("[KillsPreloader] Phase 1 (quick) done => calls_count=#{state_after_quick.calls_count}, elapsed=#{time_quick_ms}ms") + Logger.info( + "[KillsPreloader] Phase 1 (quick) done => calls_count=#{state_after_quick.calls_count}, elapsed=#{time_quick_ms}ms" + ) # ---- EXPANDED PASS ---- state_expanded = %{state_after_quick | phase: :expanded_pass} @@ -93,7 +98,9 @@ defmodule WandererApp.Zkb.KillsPreloader do do_pass(unique_systems, :expanded, @quick_hours, @expanded_limit, state_expanded) end) - Logger.info("[KillsPreloader] Phase 2 (expanded) done => calls_count=#{final_state.calls_count}, elapsed=#{time_expanded_ms}ms") + Logger.info( + "[KillsPreloader] Phase 2 (expanded) done => calls_count=#{final_state.calls_count}, elapsed=#{time_expanded_ms}ms" + ) # Reset phase to :idle {:noreply, %{final_state | phase: :idle}} @@ -125,6 +132,13 @@ defmodule WandererApp.Zkb.KillsPreloader do [] end + defp get_active_maps_with_subscription(maps) do + maps + |> Enum.filter(fn map -> + {:ok, is_subscription_active} = map.id |> WandererApp.Map.is_subscription_active?() + is_subscription_active + end) + end defp gather_visible_systems(maps) do maps @@ -136,15 +150,19 @@ defmodule WandererApp.Zkb.KillsPreloader do Enum.map(systems, fn sys -> {the_map_id, sys.solar_system_id} end) {:error, reason} -> - Logger.warning("[KillsPreloader] get_visible_by_map failed => map_id=#{inspect(the_map_id)}, reason=#{inspect(reason)}") + Logger.warning( + "[KillsPreloader] get_visible_by_map failed => map_id=#{inspect(the_map_id)}, reason=#{inspect(reason)}" + ) + [] end end) end - defp do_pass(unique_systems, pass_type, hours, limit, state) do - Logger.info("[KillsPreloader] Starting #{pass_type} pass => #{length(unique_systems)} systems") + Logger.info( + "[KillsPreloader] Starting #{pass_type} pass => #{length(unique_systems)} systems" + ) {final_state, kills_map} = unique_systems @@ -167,29 +185,45 @@ defmodule WandererApp.Zkb.KillsPreloader do end defp fetch_kills_for_system(system_id, :quick, hours, limit, state) do - Logger.debug("[KillsPreloader] Quick fetch => system=#{system_id}, hours=#{hours}, limit=#{limit}") + Logger.debug(fn -> + "[KillsPreloader] Quick fetch => system=#{system_id}, hours=#{hours}, limit=#{limit}" + end) - case KillsProvider.Fetcher.fetch_kills_for_system(system_id, hours, state, limit: limit, force: false) do + case KillsProvider.Fetcher.fetch_kills_for_system(system_id, hours, state, + limit: limit, + force: false + ) do {:ok, kills, updated_state} -> {:ok, system_id, kills, updated_state} {:error, reason, updated_state} -> - Logger.warning("[KillsPreloader] Quick fetch failed => system=#{system_id}, reason=#{inspect(reason)}") + Logger.warning( + "[KillsPreloader] Quick fetch failed => system=#{system_id}, reason=#{inspect(reason)}" + ) + {:error, reason, updated_state} end end defp fetch_kills_for_system(system_id, :expanded, hours, limit, state) do - Logger.debug("[KillsPreloader] Expanded fetch => system=#{system_id}, hours=#{hours}, limit=#{limit} (forcing refresh)") + Logger.debug(fn -> + "[KillsPreloader] Expanded fetch => system=#{system_id}, hours=#{hours}, limit=#{limit} (forcing refresh)" + end) with {:ok, kills_1h, updated_state} <- - KillsProvider.Fetcher.fetch_kills_for_system(system_id, hours, state, limit: limit, force: true), + KillsProvider.Fetcher.fetch_kills_for_system(system_id, hours, state, + limit: limit, + force: true + ), {:ok, final_kills, final_state} <- maybe_fetch_more_if_needed(system_id, kills_1h, limit, updated_state) do {:ok, system_id, final_kills, final_state} else {:error, reason, updated_state} -> - Logger.warning("[KillsPreloader] Expanded fetch (#{hours}h) failed => system=#{system_id}, reason=#{inspect(reason)}") + Logger.warning( + "[KillsPreloader] Expanded fetch (#{hours}h) failed => system=#{system_id}, reason=#{inspect(reason)}" + ) + {:error, reason, updated_state} end end @@ -198,9 +232,15 @@ defmodule WandererApp.Zkb.KillsPreloader do defp maybe_fetch_more_if_needed(system_id, kills_1h, limit, state) do if length(kills_1h) < limit do needed = limit - length(kills_1h) - Logger.debug("[KillsPreloader] Expanding to #{@expanded_hours}h => system=#{system_id}, need=#{needed} more kills") - case KillsProvider.Fetcher.fetch_kills_for_system(system_id, @expanded_hours, state, limit: needed, force: true) do + Logger.debug(fn -> + "[KillsPreloader] Expanding to #{@expanded_hours}h => system=#{system_id}, need=#{needed} more kills" + end) + + case KillsProvider.Fetcher.fetch_kills_for_system(system_id, @expanded_hours, state, + limit: needed, + force: true + ) do {:ok, _kills_24h, updated_state2} -> final_kills = KillsCache.fetch_cached_kills(system_id) @@ -209,7 +249,10 @@ defmodule WandererApp.Zkb.KillsPreloader do {:ok, final_kills, updated_state2} {:error, reason2, updated_state2} -> - Logger.warning("[KillsPreloader] #{@expanded_hours}h fetch failed => system=#{system_id}, reason=#{inspect(reason2)}") + Logger.warning( + "[KillsPreloader] #{@expanded_hours}h fetch failed => system=#{system_id}, reason=#{inspect(reason2)}" + ) + {:error, reason2, updated_state2} end else @@ -243,7 +286,9 @@ defmodule WandererApp.Zkb.KillsPreloader do do: Logger.error("[KillsPreloader] Expanded fetch task failed => #{inspect(reason)}") defp broadcast_all_kills(kills_map, pass_type) do - Logger.info("[KillsPreloader] Broadcasting kills => #{map_size(kills_map)} systems (#{pass_type})") + Logger.info( + "[KillsPreloader] Broadcasting kills => #{map_size(kills_map)} systems (#{pass_type})" + ) Phoenix.PubSub.broadcast!( WandererApp.PubSub, diff --git a/lib/wanderer_app/zkb/zkills_provider/zkb_api.ex b/lib/wanderer_app/zkb/zkills_provider/zkb_api.ex index 7814b6b8..97a4a5e2 100644 --- a/lib/wanderer_app/zkb/zkills_provider/zkb_api.ex +++ b/lib/wanderer_app/zkb/zkills_provider/zkb_api.ex @@ -40,7 +40,7 @@ defmodule WandererApp.Zkb.KillsProvider.ZkbApi do defp do_req_get(system_id, page) do url = "#{@zkillboard_api}/kills/systemID/#{system_id}/page/#{page}/" - Logger.debug("[ZkbApi] GET => system=#{system_id}, page=#{page}, url=#{url}") + Logger.debug(fn -> "[ZkbApi] GET => system=#{system_id}, page=#{page}, url=#{url}" end) try do resp = Req.get!(url, decode_body: :json) @@ -56,6 +56,7 @@ defmodule WandererApp.Zkb.KillsProvider.ZkbApi do [ZkbApi] do_req_get => exception: #{Exception.message(e)} #{Exception.format_stacktrace(__STACKTRACE__)} """) + {:error, :exception} end end @@ -72,7 +73,7 @@ defmodule WandererApp.Zkb.KillsProvider.ZkbApi do :ok {:error, limit} -> - Logger.debug("[ZkbApi] RATE_LIMIT => limit=#{inspect(limit)}") + Logger.debug(fn -> "[ZkbApi] RATE_LIMIT => limit=#{inspect(limit)}" end) {:error, :rate_limited} end end diff --git a/lib/wanderer_app_web/live/maps/event_handlers/map_core_event_handler.ex b/lib/wanderer_app_web/live/maps/event_handlers/map_core_event_handler.ex index c886d577..8a1f9abd 100644 --- a/lib/wanderer_app_web/live/maps/event_handlers/map_core_event_handler.ex +++ b/lib/wanderer_app_web/live/maps/event_handlers/map_core_event_handler.ex @@ -468,6 +468,7 @@ defmodule WandererAppWeb.MapCoreEventHandler do socket |> assign( map_loaded?: true, + is_subscription_active?: Map.get(initial_data, :is_subscription_active, false), user_characters: user_character_eve_ids, has_tracked_characters?: has_tracked_characters? ) @@ -530,6 +531,7 @@ defmodule WandererAppWeb.MapCoreEventHandler do {:ok, connections} = map_id |> WandererApp.Map.list_connections() {:ok, systems} = map_id |> WandererApp.Map.list_systems() {:ok, options} = map_id |> WandererApp.Map.get_options() + {:ok, is_subscription_active} = map_id |> WandererApp.Map.is_subscription_active?() %{ systems: @@ -537,7 +539,8 @@ defmodule WandererAppWeb.MapCoreEventHandler do |> Enum.map(fn system -> MapEventHandler.map_ui_system(system, include_static_data?) end), hubs: hubs, connections: connections |> Enum.map(&MapEventHandler.map_ui_connection/1), - options: options + options: options, + is_subscription_active: is_subscription_active } end diff --git a/lib/wanderer_app_web/live/maps/map_audit_live.ex b/lib/wanderer_app_web/live/maps/map_audit_live.ex index dfadf517..de8dce29 100755 --- a/lib/wanderer_app_web/live/maps/map_audit_live.ex +++ b/lib/wanderer_app_web/live/maps/map_audit_live.ex @@ -34,13 +34,15 @@ defmodule WandererAppWeb.MapAuditLive do case user_permissions.delete_map do true -> + {:ok, is_subscription_active} = map_id |> WandererApp.Map.is_subscription_active?() + {:ok, socket |> assign( map_id: map_id, map_name: map_name, map_slug: map_slug, - map_subscription_active: WandererApp.Map.is_subscription_active?(map_id), + map_subscription_active: is_subscription_active, activity: activity, can_undo_types: [:systems_removed], period: period || "1H", diff --git a/lib/wanderer_app_web/live/maps/map_event_handler.ex b/lib/wanderer_app_web/live/maps/map_event_handler.ex index e3f5895c..1a945c3e 100644 --- a/lib/wanderer_app_web/live/maps/map_event_handler.ex +++ b/lib/wanderer_app_web/live/maps/map_event_handler.ex @@ -155,7 +155,14 @@ defmodule WandererAppWeb.MapEventHandler do when event_name in @map_signatures_events, do: MapSignaturesEventHandler.handle_server_event(event, socket) - def handle_event(socket, %{event: event_name} = event) + def handle_event( + %{ + assigns: %{ + is_subscription_active?: true + } + } = socket, + %{event: event_name} = event + ) when event_name in @map_kills_events, do: MapKillsEventHandler.handle_server_event(event, socket) @@ -212,7 +219,15 @@ defmodule WandererAppWeb.MapEventHandler do when event in @map_activity_ui_events, do: MapActivityEventHandler.handle_ui_event(event, body, socket) - def handle_ui_event(event, body, socket) + def handle_ui_event( + event, + body, + %{ + assigns: %{ + is_subscription_active?: true + } + } = socket + ) when event in @map_kills_ui_events, do: MapKillsEventHandler.handle_ui_event(event, body, socket)