Reduser strømforbruk for avstandsindikatoren

Brukerrapport om høyt batteriforbruk. To justeringer i
hole-target-distance.tsx: maximumAge 1000ms -> 4000ms (umerkelig ved
gangfart, sjeldnere GPS-fix), og watchPosition pauses helt når
fanen/appen ikke er synlig (document.visibilitychange), gjenopptas
automatisk. enableHighAccuracy uendret -- lav nøyaktighet ville gjort
front/midt/bak-tallene meningsløse.

Verifisert i nettleser: clearWatch bekreftet kalt ved backgrounding,
watchPosition bekreftet kalt på nytt ved retur, ingen konsollfeil.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
Erol Haagenrud 2026-08-13 15:01:59 +02:00
parent ac11da7b87
commit 648293e1f8
2 changed files with 80 additions and 15 deletions

View file

@ -10834,3 +10834,32 @@ Neste steg:
backend/migrasjon rørt) -- `docker compose build teecup_frontend && backend/migrasjon rørt) -- `docker compose build teecup_frontend &&
up -d teecup_frontend`. Ingen konsollfeil på up -d teecup_frontend`. Ingen konsollfeil på
`https://teecup.golf/logg-inn` etter omstart. `https://teecup.golf/logg-inn` etter omstart.
**Tillegg samme dag (del 4) -- strømsparing.** Bruker rapporterte
høyt batteriforbruk nå som GPS-en er aktivert. To justeringer i
`hole-target-distance.tsx`, foreslått med tradeoffs FØR bygging (jf.
"Gi meg forslag før..."-arbeidsmåten): (1) `maximumAge` økt fra
1000ms til 4000ms -- en golfer beveger seg ~1,5 m/s, oppdatering
hvert 4. sekund er umerkelig men ber GPS-brikken om et ferskt fix
langt sjeldnere. (2) `watchPosition` pauses nå helt når fanen/appen
ikke er synlig (`document.visibilitychange`) -- ingen vits å holde
GPS aktiv for en skjerm ingen ser på (skjerm låst, annen app i
forgrunnen) -- og gjenopptas automatisk når brukeren kommer tilbake.
`enableHighAccuracy` bevisst UENDRET -- lav nøyaktighet ville gitt
titalls meters feilmargin, for upresist til at front/midt/bak-
tallene gir mening.
**Verifisert:** ny scratch-runde (samme fixture-cachede Tjøme-data),
ekte innlogging/import/runde, geolocation-emulering +
`initScript`-injisert `watchPosition`/`clearWatch`-spion (telte
faktiske kall). Bekreftet i nettleseren: `document.hidden = true` +
`visibilitychange``clearWatch` kalt umiddelbart, visningen gikk
til "Ikke live — sist målte posisjon" (siste kjente tall beholdt,
ikke nullstilt); `document.hidden = false` + `visibilitychange`
`watchPosition` kalt på nytt (kall-telleren gikk fra 1 til 2), "●
Live" gjenopprettet. `tsc --noEmit` rent, 45/45 vitest, ingen
konsollfeil. Scratch-ressurser ryddet opp, `teecup_db` uendret.
**Rullet ut 2026-08-13**, samme økt. Ren frontend-endring --
`docker compose build teecup_frontend && up -d teecup_frontend`.
Ingen konsollfeil på `https://teecup.golf/logg-inn` etter omstart.

View file

@ -8,14 +8,25 @@ import { haversineMeters, type LatLng } from "@/lib/geo"
// front/midt/bak, hindringer) og kombinerer dem klient-side med spillerens // front/midt/bak, hindringer) og kombinerer dem klient-side med spillerens
// LIVE GPS-posisjon via samme watchPosition-mønster som map-point-picker.tsx // LIVE GPS-posisjon via samme watchPosition-mønster som map-point-picker.tsx
// allerede bruker for slagmåling (ADR-048 tillegg 2026-08-08 del 2) -- // allerede bruker for slagmåling (ADR-048 tillegg 2026-08-08 del 2) --
// `enableHighAccuracy`, `maximumAge: 1000`, grasiøs degradering ved avslått // `enableHighAccuracy`, grasiøs degradering ved avslått tillatelse,
// tillatelse, `clearWatch` ved avmontering. `TargetDistance` selv forblir // `clearWatch` ved avmontering. `TargetDistance` selv forblir "dum"
// "dum" (V0-eksportert, ren visning) -- all logikk bor her. Ingen egen // (V0-eksportert, ren visning) -- all logikk bor her. Ingen egen
// rad-wrapper (border/padding) her -- kalleren styrer plassering/bredde. // rad-wrapper (border/padding) her -- kalleren styrer plassering/bredde.
// Montert i PlayerHoleCards sin hull-navigator (round-detail.tsx), // Montert i PlayerHoleCards sin hull-navigator (round-detail.tsx),
// size="full" -- IKKE i ScoringWizard-headeren (der den satt først, // size="full" -- IKKE i ScoringWizard-headeren (der den satt først,
// 2026-08-12): brukeren pekte ut hovedvisningen som riktig sted og ba // 2026-08-12): brukeren pekte ut hovedvisningen som riktig sted og ba
// om mer bredde enn den opprinnelige kompaktvarianten, 2026-08-13. // om mer bredde enn den opprinnelige kompaktvarianten, 2026-08-13.
//
// Strømsparing (2026-08-13, brukerrapport om høyt batteriforbruk):
// (1) `maximumAge` satt til 4000ms (var 1000ms) -- en golfer beveger seg
// ~1,5 m/s, oppdatering hvert 4. sekund er umerkelig i praksis men ber
// GPS-brikken om et ferskt fix mye sjeldnere. (2) `watchPosition` pauses
// helt når fanen/appen ikke er synlig (`document.visibilitychange`) --
// ingen vits å holde GPS-en aktiv for en skjerm ingen ser på (skjerm låst,
// annen app i forgrunnen), og gjenopptas automatisk når brukeren kommer
// tilbake. `enableHighAccuracy` beholdt UENDRET -- lav nøyaktighet ville
// gitt titalls meters feilmargin, for upresist til at front/midt/bak-
// tallene gir mening.
type ApiTargetPoint = { type ApiTargetPoint = {
poi_type: string poi_type: string
@ -68,7 +79,9 @@ export function HoleTargetDistance({
// dette hullet -- unngår unødvendig batteribruk/tillatelses-prompt. // dette hullet -- unngår unødvendig batteribruk/tillatelses-prompt.
if (!points || points.length === 0) return if (!points || points.length === 0) return
if (typeof navigator === "undefined" || !navigator.geolocation) return if (typeof navigator === "undefined" || !navigator.geolocation) return
if (typeof document === "undefined") return
function startWatch() {
watchIdRef.current = navigator.geolocation.watchPosition( watchIdRef.current = navigator.geolocation.watchPosition(
(pos) => { (pos) => {
setLivePosition({ lat: pos.coords.latitude, lng: pos.coords.longitude }) setLivePosition({ lat: pos.coords.latitude, lng: pos.coords.longitude })
@ -78,14 +91,37 @@ export function HoleTargetDistance({
// Avslått/feilet -- degraderer grasiøst, komponenten viser bare "ingen data". // Avslått/feilet -- degraderer grasiøst, komponenten viser bare "ingen data".
setIsLive(false) setIsLive(false)
}, },
{ enableHighAccuracy: true, maximumAge: 1000 }, { enableHighAccuracy: true, maximumAge: 4000 },
) )
return () => { }
function stopWatch() {
if (watchIdRef.current !== null && typeof navigator !== "undefined" && navigator.geolocation) { if (watchIdRef.current !== null && typeof navigator !== "undefined" && navigator.geolocation) {
navigator.geolocation.clearWatch(watchIdRef.current) navigator.geolocation.clearWatch(watchIdRef.current)
} }
watchIdRef.current = null watchIdRef.current = null
} }
// Pauser GPS-sporingen helt når fanen/appen ikke er synlig (skjerm
// låst, annen app i forgrunnen) -- gjenopptas automatisk når brukeren
// kommer tilbake. `isLive` settes til false mens pauset, så visningen
// tydelig viser "ikke live" fremfor å late som tallet fortsatt oppdateres.
function handleVisibilityChange() {
if (document.hidden) {
stopWatch()
setIsLive(false)
} else {
startWatch()
}
}
if (!document.hidden) startWatch()
document.addEventListener("visibilitychange", handleVisibilityChange)
return () => {
document.removeEventListener("visibilitychange", handleVisibilityChange)
stopWatch()
}
}, [points]) }, [points])
// Fortsatt laster, ELLER banen har rett og slett ingen koordinatdata // Fortsatt laster, ELLER banen har rett og slett ingen koordinatdata