Throttle GPS updates on path page to once per minute

Switch from getCurrentPosition (which looped via push_patch) to
watchPosition with a 60-second throttle. Break the server-side
request_gps loop by skipping re-request when coords already exist.
This commit is contained in:
Graham McIntire 2026-04-07 14:44:24 -05:00
parent 7ffa20bee7
commit 68b733b6d0
2 changed files with 35 additions and 11 deletions

View file

@ -12,30 +12,49 @@ export const CopyLink = {
export const LocateMe = { export const LocateMe = {
mounted() { mounted() {
this.el.addEventListener("click", () => this.locate()) this.watchId = null
this.lastSentAt = 0
this.el.addEventListener("click", () => this.startWatching())
// Also respond to server-pushed request (for source=gps URLs) // Also respond to server-pushed request (for source=gps URLs)
this.handleEvent("request_gps", () => this.locate()) this.handleEvent("request_gps", () => this.startWatching())
}, },
locate() { destroyed() {
if (this.watchId !== null) {
navigator.geolocation.clearWatch(this.watchId)
}
},
startWatching() {
if (!navigator.geolocation) { if (!navigator.geolocation) {
alert("Geolocation is not supported by this browser") alert("Geolocation is not supported by this browser")
return return
} }
// Already watching — don't start another
if (this.watchId !== null) return
this.el.classList.add("loading", "loading-spinner") this.el.classList.add("loading", "loading-spinner")
navigator.geolocation.getCurrentPosition( this.watchId = navigator.geolocation.watchPosition(
(pos) => { (pos) => {
this.el.classList.remove("loading", "loading-spinner") const now = Date.now()
this.pushEvent("gps_location", { // Send immediately on first fix, then at most once per minute
lat: pos.coords.latitude, if (this.lastSentAt === 0 || now - this.lastSentAt >= 60000) {
lon: pos.coords.longitude this.lastSentAt = now
}) this.el.classList.remove("loading", "loading-spinner")
this.pushEvent("gps_location", {
lat: pos.coords.latitude,
lon: pos.coords.longitude
})
}
}, },
(err) => { (err) => {
this.el.classList.remove("loading", "loading-spinner") this.el.classList.remove("loading", "loading-spinner")
navigator.geolocation.clearWatch(this.watchId)
this.watchId = null
alert("Could not get location: " + err.message) alert("Could not get location: " + err.message)
}, },
{ enableHighAccuracy: true, timeout: 10000 } { enableHighAccuracy: true, timeout: 10000 }

View file

@ -74,9 +74,14 @@ defmodule MicrowavepropWeb.PathLive do
source_is_gps: is_gps source_is_gps: is_gps
) )
# If source=gps, request device location via JS # If source=gps and we already have coords from a previous fix, just recalculate.
# Only request GPS from the device on the initial page load (no coords yet).
if p["source"] == "gps" and connected?(socket) do if p["source"] == "gps" and connected?(socket) do
{:noreply, push_event(socket, "request_gps", %{})} if socket.assigns.source != "" and socket.assigns.source != nil do
auto_calculate(socket, Map.put(p, "source", socket.assigns.source))
else
{:noreply, push_event(socket, "request_gps", %{})}
end
else else
auto_calculate(socket, p) auto_calculate(socket, p)
end end