Add URL parameter handling for trail duration and historical data

Implemented URL persistence for map settings to preserve user preferences:

- Added `trail` parameter for trail duration (1, 6, 12, 24, 48, 168 hours)
- Added `hist` parameter for historical data hours (1, 3, 6, 12, 24 hours)
- Parameters only appear in URL when different from default value (1 hour)

Changes:
- Updated handle_url_update to include trail and hist parameters
- Modified mount to parse these parameters on page load
- Updated handle_params to parse parameters on URL changes
- Added update_url_with_current_state helper function
- Modified update_trail_duration and update_historical_hours event handlers
  to update URL when settings change
- Fixed finalize_mount_assigns to preserve parsed values

This allows users to share or bookmark URLs with specific trail duration
and historical data settings, improving the user experience.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Graham McIntire 2025-07-21 09:14:46 -05:00
parent 36621cbd64
commit aa168f8dcd
No known key found for this signature in database

View file

@ -39,9 +39,23 @@ defmodule AprsmeWeb.MapLive.Index do
# Parse and determine map location
{map_center, map_zoom, should_skip_initial_url_update} = Navigation.determine_map_location(params, session)
# Setup defaults
socket = assign_defaults(socket, one_hour_ago)
socket = assign(socket, initial_historical_completed: false)
# Parse trail duration and historical hours from URL
trail_duration = params |> Map.get("trail", "1") |> parse_trail_duration() |> to_string()
historical_hours = params |> Map.get("hist", "1") |> parse_historical_hours() |> to_string()
# Calculate packet age threshold based on trail duration
hours = String.to_integer(trail_duration)
packet_age_threshold = DateTime.add(DateTime.utc_now(), -hours * 3600, :second)
# Setup defaults with parsed values
socket = assign_defaults(socket, packet_age_threshold)
socket =
assign(socket,
initial_historical_completed: false,
trail_duration: trail_duration,
historical_hours: historical_hours
)
# Setup additional subscriptions if connected
socket = setup_additional_subscriptions(socket)
@ -122,6 +136,11 @@ defmodule AprsmeWeb.MapLive.Index do
deployed_at: deployed_at,
one_hour_ago: one_hour_ago
}) do
# Don't override trail_duration and historical_hours if they're already set
trail_duration = Map.get(socket.assigns, :trail_duration, "1")
historical_hours = Map.get(socket.assigns, :historical_hours, "1")
packet_age_threshold = Map.get(socket.assigns, :packet_age_threshold, one_hour_ago)
assign(socket,
map_ready: false,
map_bounds: initial_bounds,
@ -131,9 +150,9 @@ defmodule AprsmeWeb.MapLive.Index do
packet_state: PacketManager.init_packet_state(),
overlay_callsign: "",
tracked_callsign: tracked_callsign,
trail_duration: "1",
historical_hours: "1",
packet_age_threshold: one_hour_ago,
trail_duration: trail_duration,
historical_hours: historical_hours,
packet_age_threshold: packet_age_threshold,
slideover_open: true,
deployed_at: deployed_at,
map_page: true,
@ -179,8 +198,6 @@ defmodule AprsmeWeb.MapLive.Index do
pending_batch_tasks: [],
# Overlay controls
overlay_callsign: "",
trail_duration: "1",
historical_hours: "1",
# Slideover state - will be set based on screen size
slideover_open: true
)
@ -363,6 +380,9 @@ defmodule AprsmeWeb.MapLive.Index do
# Update client-side TrailManager with new duration
socket = push_event(socket, "update_trail_duration", %{duration_hours: hours})
# Update URL with new trail duration
socket = update_url_with_current_state(socket)
# Trigger cleanup to remove packets that are now outside the new duration
send(self(), :cleanup_old_packets)
@ -375,6 +395,9 @@ defmodule AprsmeWeb.MapLive.Index do
validated_hours = parse_historical_hours(hours)
socket = assign(socket, historical_hours: to_string(validated_hours))
# Update URL with new historical hours
socket = update_url_with_current_state(socket)
# Trigger a reload of historical packets with the new time range
if socket.assigns.map_ready do
send(self(), :reload_historical_packets)
@ -498,6 +521,13 @@ defmodule AprsmeWeb.MapLive.Index do
DisplayManager.handle_zoom_threshold_crossing(socket, zoom)
end
defp update_url_with_current_state(socket) do
lat = socket.assigns.map_center.lat
lng = socket.assigns.map_center.lng
zoom = socket.assigns.map_zoom
handle_url_update(socket, lat, lng, zoom)
end
defp handle_url_update(socket, lat, lng, zoom) do
if socket.assigns[:should_skip_initial_url_update] && !socket.assigns[:initial_bounds_loaded] do
require Logger
@ -507,7 +537,18 @@ defmodule AprsmeWeb.MapLive.Index do
else
require Logger
new_path = "/?lat=#{lat}&lng=#{lng}&z=#{zoom}"
# Include trail duration and historical hours in URL
trail_param =
if socket.assigns[:trail_duration] && socket.assigns[:trail_duration] != "1",
do: "&trail=#{socket.assigns[:trail_duration]}",
else: ""
hist_param =
if socket.assigns[:historical_hours] && socket.assigns[:historical_hours] != "1",
do: "&hist=#{socket.assigns[:historical_hours]}",
else: ""
new_path = "/?lat=#{lat}&lng=#{lng}&z=#{zoom}#{trail_param}#{hist_param}"
Logger.debug("Updating URL to: #{new_path}")
push_patch(socket, to: new_path, replace: true)
end
@ -558,21 +599,41 @@ defmodule AprsmeWeb.MapLive.Index do
# Parse new map state from URL parameters
{map_center, map_zoom} = UrlParams.parse_map_params(params)
# Update socket state
socket = assign(socket, map_center: map_center, map_zoom: map_zoom)
# Parse trail duration and historical hours from URL
trail_duration = params |> Map.get("trail", "1") |> parse_trail_duration() |> to_string()
historical_hours = params |> Map.get("hist", "1") |> parse_historical_hours() |> to_string()
# If map is ready, update the client-side map
# Update socket state
socket =
socket
|> assign(map_center: map_center, map_zoom: map_zoom)
|> assign(trail_duration: trail_duration, historical_hours: historical_hours)
# Update packet age threshold based on trail duration
hours = String.to_integer(trail_duration)
new_threshold = DateTime.add(DateTime.utc_now(), -hours * 3600, :second)
socket = assign(socket, packet_age_threshold: new_threshold)
# If map is ready, update the client-side map and trail duration
socket =
if socket.assigns.map_ready do
push_event(socket, "zoom_to_location", %{
socket
|> push_event("zoom_to_location", %{
lat: map_center.lat,
lng: map_center.lng,
zoom: map_zoom
})
|> push_event("update_trail_duration", %{duration_hours: hours})
else
socket
end
# Trigger cleanup and reload if settings changed
if socket.assigns[:map_ready] do
send(self(), :cleanup_old_packets)
send(self(), :reload_historical_packets)
end
{:noreply, socket}
end
end