Merge pull request #36 from aprsme/fix-info-page-map-flash
Fix info page map flash on packet updates
This commit is contained in:
commit
ea9e12883f
5 changed files with 154 additions and 21 deletions
|
|
@ -11,7 +11,9 @@ export const InfoMap = {
|
|||
const symbolHtml = this.el.dataset.symbolHtml;
|
||||
|
||||
// Validate coordinates
|
||||
const callsign = this.el.dataset.callsign;
|
||||
if (isNaN(lat) || isNaN(lon)) {
|
||||
console.warn(`InfoMap: Invalid coordinates lat=${lat}, lon=${lon} for ${callsign} during update`);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -61,10 +63,16 @@ export const InfoMap = {
|
|||
|
||||
// Validate coordinates
|
||||
if (isNaN(lat) || isNaN(lon)) {
|
||||
console.error("Invalid coordinates for InfoMap");
|
||||
console.warn(`InfoMap: Invalid coordinates lat=${lat}, lon=${lon} for ${callsign}`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Hide loading spinner
|
||||
const loadingEl = this.el.querySelector(`#${this.el.id}-loading`);
|
||||
if (loadingEl) {
|
||||
loadingEl.style.display = 'none';
|
||||
}
|
||||
|
||||
// Initialize the map
|
||||
try {
|
||||
this.map = L.map(this.el, {
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ config :aprsme, :cleanup_scheduler,
|
|||
# 6 hours in milliseconds
|
||||
interval: 6 * 60 * 60 * 1000
|
||||
|
||||
# Configure position tracking sensitivity
|
||||
config :aprsme, :position_tracking,
|
||||
# Position change threshold in degrees (~100 meters at equator)
|
||||
change_threshold: 0.001
|
||||
|
||||
config :aprsme,
|
||||
ecto_repos: [Aprsme.Repo]
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ defmodule AprsmeWeb.Components.InfoMapComponent do
|
|||
data-callsign={@callsign}
|
||||
data-symbol-html={@symbol_html}
|
||||
>
|
||||
<div class="h-full w-full bg-base-200 flex items-center justify-center">
|
||||
<div id={"#{@id}-loading"} class="h-full w-full bg-base-200 flex items-center justify-center">
|
||||
<span class="loading loading-spinner loading-lg"></span>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -67,27 +67,71 @@ defmodule AprsmeWeb.InfoLive.Show do
|
|||
"InfoLive received packet update for #{socket.assigns.callsign}: #{inspect(Map.get(incoming_packet, "raw_packet"))}"
|
||||
)
|
||||
|
||||
# Refresh all data when new packet arrives
|
||||
packet = get_latest_packet(socket.assigns.callsign)
|
||||
packet = if packet, do: SharedPacketHandler.enrich_with_device_info(packet)
|
||||
# Get locale from socket assigns
|
||||
locale = Map.get(socket.assigns, :locale, "en")
|
||||
neighbors = get_neighbors(packet, socket.assigns.callsign, locale)
|
||||
has_weather_packets = PacketUtils.has_weather_packets?(socket.assigns.callsign)
|
||||
other_ssids = get_other_ssids(socket.assigns.callsign)
|
||||
heard_by_stations = get_heard_by_stations(socket.assigns.callsign, locale)
|
||||
stations_heard_by = get_stations_heard_by(socket.assigns.callsign, locale)
|
||||
# Get the new packet data
|
||||
new_packet = get_latest_packet(socket.assigns.callsign)
|
||||
new_packet = if new_packet, do: SharedPacketHandler.enrich_with_device_info(new_packet)
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(:packet, packet)
|
||||
|> assign(:neighbors, neighbors)
|
||||
|> assign(:has_weather_packets, has_weather_packets)
|
||||
|> assign(:other_ssids, other_ssids)
|
||||
|> assign(:heard_by_stations, heard_by_stations)
|
||||
|> assign(:stations_heard_by, stations_heard_by)
|
||||
current_packet = socket.assigns.packet
|
||||
|
||||
{:noreply, socket}
|
||||
# Check if this is a position update by comparing location and other key fields
|
||||
position_changed = position_changed?(current_packet, new_packet)
|
||||
|
||||
if position_changed do
|
||||
# Only update position-related data if position changed
|
||||
# Get locale from socket assigns
|
||||
locale = Map.get(socket.assigns, :locale, "en")
|
||||
neighbors = get_neighbors(new_packet, socket.assigns.callsign, locale)
|
||||
|
||||
socket =
|
||||
socket
|
||||
|> assign(:packet, new_packet)
|
||||
|> assign(:neighbors, neighbors)
|
||||
|
||||
{:noreply, socket}
|
||||
else
|
||||
# Just update the packet data (for timestamp, comment, etc.) without affecting neighbors
|
||||
socket = assign(socket, :packet, new_packet)
|
||||
|
||||
{:noreply, socket}
|
||||
end
|
||||
end
|
||||
|
||||
defp position_changed?(nil, _new_packet), do: true
|
||||
defp position_changed?(_current_packet, nil), do: false
|
||||
|
||||
defp position_changed?(current_packet, new_packet) do
|
||||
# Compare lat/lon to see if position actually changed
|
||||
current_lat = to_float_safe(current_packet.lat)
|
||||
current_lon = to_float_safe(current_packet.lon)
|
||||
new_lat = to_float_safe(new_packet.lat)
|
||||
new_lon = to_float_safe(new_packet.lon)
|
||||
|
||||
# If any coordinate is invalid, consider it a change
|
||||
case {current_lat, current_lon, new_lat, new_lon} do
|
||||
{nil, _, _, _} ->
|
||||
true
|
||||
|
||||
{_, nil, _, _} ->
|
||||
true
|
||||
|
||||
{_, _, nil, _} ->
|
||||
true
|
||||
|
||||
{_, _, _, nil} ->
|
||||
true
|
||||
|
||||
{curr_lat, curr_lon, new_lat, new_lon} ->
|
||||
# Consider position changed if coordinates differ by more than the configured threshold
|
||||
threshold = Application.get_env(:aprsme, :position_tracking, [])[:change_threshold] || 0.001
|
||||
lat_diff = abs(curr_lat - new_lat)
|
||||
lon_diff = abs(curr_lon - new_lon)
|
||||
lat_diff > threshold or lon_diff > threshold
|
||||
end
|
||||
end
|
||||
|
||||
# Expose for testing
|
||||
if Mix.env() == :test do
|
||||
def position_changed_for_test(current, new), do: position_changed?(current, new)
|
||||
end
|
||||
|
||||
defp get_latest_packet(callsign) do
|
||||
|
|
@ -158,6 +202,10 @@ defmodule AprsmeWeb.InfoLive.Show do
|
|||
r * c
|
||||
end
|
||||
|
||||
# Safe float conversion that preserves nil for invalid coordinates
|
||||
defp to_float_safe(value), do: EncodingUtils.to_float(value)
|
||||
|
||||
# Legacy float conversion that defaults to 0.0 for backward compatibility
|
||||
defp to_float(value), do: EncodingUtils.to_float(value) || 0.0
|
||||
|
||||
defp format_timestamp_for_display(packet) do
|
||||
|
|
|
|||
72
test/aprsme_web/live/info_live/position_change_test.exs
Normal file
72
test/aprsme_web/live/info_live/position_change_test.exs
Normal file
|
|
@ -0,0 +1,72 @@
|
|||
defmodule AprsmeWeb.InfoLive.PositionChangeTest do
|
||||
@moduledoc """
|
||||
Tests for position change detection in InfoLive
|
||||
"""
|
||||
use ExUnit.Case, async: true
|
||||
|
||||
alias AprsmeWeb.InfoLive.Show
|
||||
|
||||
describe "position_changed?/2" do
|
||||
test "returns true when current packet is nil" do
|
||||
new_packet = %{lat: 40.7128, lon: -74.0060}
|
||||
assert Show.position_changed_for_test(nil, new_packet)
|
||||
end
|
||||
|
||||
test "returns false when new packet is nil" do
|
||||
current_packet = %{lat: 40.7128, lon: -74.0060}
|
||||
refute Show.position_changed_for_test(current_packet, nil)
|
||||
end
|
||||
|
||||
test "returns true when position changed significantly" do
|
||||
current_packet = %{lat: 40.7128, lon: -74.0060}
|
||||
# ~0.8km difference
|
||||
new_packet = %{lat: 40.7200, lon: -74.0060}
|
||||
assert Show.position_changed_for_test(current_packet, new_packet)
|
||||
end
|
||||
|
||||
test "returns false when position changed minimally" do
|
||||
current_packet = %{lat: 40.7128, lon: -74.0060}
|
||||
# ~10m difference
|
||||
new_packet = %{lat: 40.7129, lon: -74.0061}
|
||||
refute Show.position_changed_for_test(current_packet, new_packet)
|
||||
end
|
||||
|
||||
test "returns true when longitude changed significantly" do
|
||||
current_packet = %{lat: 40.7128, lon: -74.0060}
|
||||
# longitude changed
|
||||
new_packet = %{lat: 40.7128, lon: -74.0200}
|
||||
assert Show.position_changed_for_test(current_packet, new_packet)
|
||||
end
|
||||
|
||||
test "handles Decimal values" do
|
||||
current_packet = %{lat: Decimal.new("40.7128"), lon: Decimal.new("-74.0060")}
|
||||
new_packet = %{lat: Decimal.new("40.7200"), lon: Decimal.new("-74.0060")}
|
||||
assert Show.position_changed_for_test(current_packet, new_packet)
|
||||
end
|
||||
|
||||
test "handles coordinates at equator/prime meridian (0.0 is valid)" do
|
||||
current_packet = %{lat: 0.0, lon: 0.0}
|
||||
# Small change from valid 0.0
|
||||
new_packet = %{lat: 0.0005, lon: 0.0}
|
||||
refute Show.position_changed_for_test(current_packet, new_packet)
|
||||
end
|
||||
|
||||
test "detects change when coordinates become invalid (nil)" do
|
||||
current_packet = %{lat: 40.7128, lon: -74.0060}
|
||||
new_packet = %{lat: nil, lon: -74.0060}
|
||||
assert Show.position_changed_for_test(current_packet, new_packet)
|
||||
end
|
||||
|
||||
test "detects change when coordinates become valid from invalid" do
|
||||
current_packet = %{lat: nil, lon: -74.0060}
|
||||
new_packet = %{lat: 40.7128, lon: -74.0060}
|
||||
assert Show.position_changed_for_test(current_packet, new_packet)
|
||||
end
|
||||
|
||||
test "handles both coordinates being invalid" do
|
||||
current_packet = %{lat: nil, lon: nil}
|
||||
new_packet = %{lat: nil, lon: nil}
|
||||
assert Show.position_changed_for_test(current_packet, new_packet)
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Add table
Reference in a new issue