diff --git a/assets/js/locate_me_hook.js b/assets/js/locate_me_hook.js index e57d7ae4..93e40df4 100644 --- a/assets/js/locate_me_hook.js +++ b/assets/js/locate_me_hook.js @@ -1,27 +1,32 @@ export const LocateMe = { mounted() { - this.el.addEventListener("click", () => { - if (!navigator.geolocation) { - alert("Geolocation is not supported by this browser") - return - } + this.el.addEventListener("click", () => this.locate()) - this.el.classList.add("loading", "loading-spinner") + // Also respond to server-pushed request (for source=gps URLs) + this.handleEvent("request_gps", () => this.locate()) + }, - navigator.geolocation.getCurrentPosition( - (pos) => { - this.el.classList.remove("loading", "loading-spinner") - this.pushEvent("gps_location", { - lat: pos.coords.latitude, - lon: pos.coords.longitude - }) - }, - (err) => { - this.el.classList.remove("loading", "loading-spinner") - alert("Could not get location: " + err.message) - }, - { enableHighAccuracy: true, timeout: 10000 } - ) - }) + locate() { + if (!navigator.geolocation) { + alert("Geolocation is not supported by this browser") + return + } + + this.el.classList.add("loading", "loading-spinner") + + navigator.geolocation.getCurrentPosition( + (pos) => { + this.el.classList.remove("loading", "loading-spinner") + this.pushEvent("gps_location", { + lat: pos.coords.latitude, + lon: pos.coords.longitude + }) + }, + (err) => { + this.el.classList.remove("loading", "loading-spinner") + alert("Could not get location: " + err.message) + }, + { enableHighAccuracy: true, timeout: 10000 } + ) } } diff --git a/lib/microwaveprop_web/live/path_live.ex b/lib/microwaveprop_web/live/path_live.ex index 42e7e7f8..c9f3a26f 100644 --- a/lib/microwaveprop_web/live/path_live.ex +++ b/lib/microwaveprop_web/live/path_live.ex @@ -70,8 +70,17 @@ defmodule MicrowavepropWeb.PathLive do dst_gain_dbi: p["dst_gain_dbi"] ) - # Auto-calculate if source and destination are in the URL - if p["source"] != "" and p["destination"] != "" and not socket.assigns.computing and is_nil(socket.assigns.result) do + # If source=gps, request device location via JS + if p["source"] == "gps" and connected?(socket) do + {:noreply, push_event(socket, "request_gps", %{})} + else + auto_calculate(socket, p) + end + end + + defp auto_calculate(socket, p) do + if p["source"] != "" and p["source"] != "gps" and p["destination"] != "" and + not socket.assigns.computing and is_nil(socket.assigns.result) do src_ht = parse_float(p["src_height_ft"], 30.0) dst_ht = parse_float(p["dst_height_ft"], 30.0) tx_dbm = parse_float(p["tx_power_dbm"], 20.0) @@ -152,9 +161,26 @@ defmodule MicrowavepropWeb.PathLive do end def handle_event("gps_location", %{"lat" => lat, "lon" => lon}, socket) do - # Use coordinate string as source — resolve_location handles lat,lon format source = "#{Float.round(lat / 1, 6)},#{Float.round(lon / 1, 6)}" - {:noreply, assign(socket, source: source)} + + # Replace gps with actual coords in URL and trigger calculation + socket = assign(socket, source: source, result: nil) + + url_params = + %{ + "source" => source, + "destination" => socket.assigns.destination, + "band" => socket.assigns.band, + "src_height_ft" => socket.assigns.src_height_ft, + "dst_height_ft" => socket.assigns.dst_height_ft, + "tx_power_dbm" => socket.assigns.tx_power_dbm, + "src_gain_dbi" => socket.assigns.src_gain_dbi, + "dst_gain_dbi" => socket.assigns.dst_gain_dbi + } + |> Enum.reject(fn {_k, v} -> v == "" end) + |> Map.new() + + {:noreply, push_patch(socket, to: ~p"/path?#{url_params}", replace: true)} end @impl true