diff --git a/.dialyzer_ignore.exs b/.dialyzer_ignore.exs index fe51488..e730133 100644 --- a/.dialyzer_ignore.exs +++ b/.dialyzer_ignore.exs @@ -1 +1,5 @@ -[] +[ + # Ignore all guard_test warnings from these files (false positives) + {"lib/aprsme_web/live/info_live/show.html.heex", :guard_test}, + {"lib/aprsme/packet_consumer.ex", :guard_test} +] diff --git a/lib/aprsme/packet.ex b/lib/aprsme/packet.ex index 4f16bf6..63e566d 100644 --- a/lib/aprsme/packet.ex +++ b/lib/aprsme/packet.ex @@ -304,8 +304,6 @@ defmodule Aprsme.Packet do |> put_message_fields(combined_data) end - defp extract_from_map(_), do: %{} - defp put_symbol_fields(map, data_extended) do map |> maybe_put(:symbol_code, data_extended[:symbol_code] || data_extended["symbol_code"]) diff --git a/lib/aprsme/packet_consumer.ex b/lib/aprsme/packet_consumer.ex index 82f60b1..a78e803 100644 --- a/lib/aprsme/packet_consumer.ex +++ b/lib/aprsme/packet_consumer.ex @@ -308,9 +308,6 @@ defmodule Aprsme.PacketConsumer do :error -> nil end - nil -> - nil - _ -> nil end diff --git a/lib/aprsme/packets.ex b/lib/aprsme/packets.ex index d1209ba..0d8c191 100644 --- a/lib/aprsme/packets.ex +++ b/lib/aprsme/packets.ex @@ -298,8 +298,6 @@ defmodule Aprsme.Packets do end end - defp extract_position_from_mic_e_struct(_), do: {nil, nil} - defp extract_position_from_mic_e(data_extended) do if is_number(data_extended[:lat_degrees]) and is_number(data_extended[:lat_minutes]) and is_number(data_extended[:lon_degrees]) and is_number(data_extended[:lon_minutes]) do diff --git a/lib/aprsme_web/live/info_live/show.html.heex b/lib/aprsme_web/live/info_live/show.html.heex index daf9f87..9ac5584 100644 --- a/lib/aprsme_web/live/info_live/show.html.heex +++ b/lib/aprsme_web/live/info_live/show.html.heex @@ -49,12 +49,12 @@ <%= if @packet do %>
- {@packet.comment} + {@packet.comment || ""}
- Location: {@packet.lat}, {@packet.lon} + Location: {@packet.lat || ""}, {@packet.lon || ""}
Last position: {AprsmeWeb.MapLive.PacketUtils.get_timestamp( @@ -67,15 +67,16 @@
- Device: {@packet.manufacturer} {@packet.equipment_type} + Device: {@packet.manufacturer || ""} {@packet.equipment_type || + ""}
-
Path: {@packet.path}
+
Path: {@packet.path || ""}
Raw: <%= if is_binary(@packet.raw_packet) do %> {Aprsme.EncodingUtils.sanitize_string(@packet.raw_packet)} <% else %> - {@packet.raw_packet} + {@packet.raw_packet || ""} <% end %>
@@ -124,8 +125,8 @@ /> <% end %> - {neighbor.distance} - {neighbor.last_heard} + {neighbor.distance || ""} + {neighbor.last_heard || ""} <% end %> diff --git a/lib/aprsme_web/live/map_live/index.ex b/lib/aprsme_web/live/map_live/index.ex index 07e9434..cb47fc7 100644 --- a/lib/aprsme_web/live/map_live/index.ex +++ b/lib/aprsme_web/live/map_live/index.ex @@ -1219,4 +1219,80 @@ defmodule AprsmeWeb.MapLive.Index do round4.(Map.get(b1, key)) == round4.(Map.get(b2, key)) end) end + + # --- Private bounds update helpers --- + @spec handle_bounds_update(map(), Socket.t()) :: {:noreply, Socket.t()} + defp handle_bounds_update(bounds, socket) do + # Update the map bounds from the client, converting to atom keys + map_bounds = %{ + north: bounds["north"], + south: bounds["south"], + east: bounds["east"], + west: bounds["west"] + } + + # Validate bounds to prevent invalid coordinates + if valid_bounds?(map_bounds) do + handle_valid_bounds_update(map_bounds, socket) + else + # Invalid bounds, skip update + {:noreply, socket} + end + end + + defp valid_bounds?(map_bounds) do + map_bounds.north <= 90 and map_bounds.south >= -90 and map_bounds.north > map_bounds.south + end + + defp handle_valid_bounds_update(map_bounds, socket) do + # Only schedule a bounds update if the bounds have actually changed (with rounding) + if compare_bounds(map_bounds, socket.assigns.map_bounds) do + {:noreply, socket} + else + schedule_bounds_update(map_bounds, socket) + end + end + + defp schedule_bounds_update(map_bounds, socket) do + if socket.assigns[:bounds_update_timer] do + Process.cancel_timer(socket.assigns.bounds_update_timer) + end + + timer_ref = Process.send_after(self(), {:process_bounds_update, map_bounds}, 250) + socket = assign(socket, bounds_update_timer: timer_ref, pending_bounds: map_bounds) + {:noreply, socket} + end + + @spec process_bounds_update(map(), Socket.t()) :: Socket.t() + defp process_bounds_update(map_bounds, socket) do + # Remove out-of-bounds packets and markers immediately + new_visible_packets = + socket.assigns.visible_packets + |> Enum.filter(fn {_k, packet} -> within_bounds?(packet, map_bounds) end) + |> Map.new() + + packets_to_remove = + socket.assigns.visible_packets + |> Enum.reject(fn {_k, packet} -> within_bounds?(packet, map_bounds) end) + |> Enum.map(fn {k, _} -> k end) + + # Remove markers for out-of-bounds packets + socket = + if packets_to_remove == [] do + socket + else + Enum.reduce(packets_to_remove, socket, fn k, acc -> + push_event(acc, "remove_marker", %{id: k}) + end) + end + + # Remove only out-of-bounds historical packets instead of clearing all + socket = push_event(socket, "filter_markers_by_bounds", %{bounds: map_bounds}) + + # Load additional historical packets for the new bounds if needed + socket = load_historical_packets_for_bounds(socket, map_bounds) + + # Update map bounds and visible packets + assign(socket, map_bounds: map_bounds, visible_packets: new_visible_packets) + end end diff --git a/mix.exs b/mix.exs index 15c9573..317acd5 100644 --- a/mix.exs +++ b/mix.exs @@ -12,7 +12,13 @@ defmodule Aprsme.MixProject do deps: deps(), releases: releases(), test_coverage: [tool: ExCoveralls], - listeners: [Phoenix.CodeReloader] + listeners: [Phoenix.CodeReloader], + dialyzer: [ + ignore_warnings: ".dialyzer_ignore.exs", + plt_file: + {:no_warn, + "_build/dev/dialyxir_erlang-#{:erlang.system_info(:otp_release)}_elixir-#{System.version()}_deps-dev.plt"} + ] ] end