From 68b733b6d008350e587f9aecb1729c4ee387e693 Mon Sep 17 00:00:00 2001 From: Graham McIntire Date: Tue, 7 Apr 2026 14:44:24 -0500 Subject: [PATCH] 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. --- assets/js/locate_me_hook.js | 37 +++++++++++++++++++------ lib/microwaveprop_web/live/path_live.ex | 9 ++++-- 2 files changed, 35 insertions(+), 11 deletions(-) diff --git a/assets/js/locate_me_hook.js b/assets/js/locate_me_hook.js index 8fe27a45..09d57374 100644 --- a/assets/js/locate_me_hook.js +++ b/assets/js/locate_me_hook.js @@ -12,30 +12,49 @@ export const CopyLink = { export const LocateMe = { 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) - 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) { alert("Geolocation is not supported by this browser") return } + // Already watching — don't start another + if (this.watchId !== null) return + this.el.classList.add("loading", "loading-spinner") - navigator.geolocation.getCurrentPosition( + this.watchId = navigator.geolocation.watchPosition( (pos) => { - this.el.classList.remove("loading", "loading-spinner") - this.pushEvent("gps_location", { - lat: pos.coords.latitude, - lon: pos.coords.longitude - }) + const now = Date.now() + // Send immediately on first fix, then at most once per minute + if (this.lastSentAt === 0 || now - this.lastSentAt >= 60000) { + this.lastSentAt = now + 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") + navigator.geolocation.clearWatch(this.watchId) + this.watchId = null 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 8c3e964e..8160c44e 100644 --- a/lib/microwaveprop_web/live/path_live.ex +++ b/lib/microwaveprop_web/live/path_live.ex @@ -74,9 +74,14 @@ defmodule MicrowavepropWeb.PathLive do 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 - {: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 auto_calculate(socket, p) end