1- import { useCallback , useEffect , useMemo , useRef , useState , type RefObject } from "react" ;
2- import { Animated , Alert , InteractionManager } from "react-native" ;
3- import type { Details , MapPressEvent , Region } from "react-native-maps" ;
4- import type MapView from "react-native-maps" ;
5- import * as Location from "expo-location" ;
6-
71import { computeCircumstances } from "@eclipse-timer/engine" ;
82import type { Circumstances , EclipseRecord , Observer } from "@eclipse-timer/shared" ;
9-
3+ import * as Location from "expo-location" ;
4+ import { type RefObject , useCallback , useEffect , useMemo , useRef , useState } from "react" ;
5+ import { Alert , Animated , InteractionManager } from "react-native" ;
6+ import type MapView from "react-native-maps" ;
7+ import type { Details , MapPressEvent , Region } from "react-native-maps" ;
8+ import {
9+ type NotificationEntry ,
10+ type NotificationSettings ,
11+ notificationEntryId ,
12+ } from "../state/appState" ;
1013import {
1114 buildContactItems ,
12- nextEventCountdown ,
1315 type ContactItem ,
1416 type ContactKey ,
17+ nextEventCountdown ,
1518} from "../utils/contacts" ;
1619import {
1720 normalizeLongitude ,
@@ -20,17 +23,12 @@ import {
2023 sanitizeLatitude ,
2124 sanitizeRegion ,
2225} from "../utils/map" ;
23- import {
24- notificationEntryId ,
25- type NotificationEntry ,
26- type NotificationSettings ,
27- } from "../state/appState" ;
2826
2927type MapType3 = "standard" | "satellite" | "hybrid" ;
3028
3129type AlarmState = Record < ContactKey , boolean > ;
3230
33- type Pin = { lat : number ; lon : number } ;
31+ type Pin = { lat : number ; lon : number ; elevM : number } ;
3432type MarkerDragEndEvent = {
3533 nativeEvent : {
3634 coordinate : {
@@ -40,7 +38,7 @@ type MarkerDragEndEvent = {
4038 } ;
4139} ;
4240
43- const GIBRALTAR = { lat : 36.1408 , lon : - 5.3536 } ;
41+ const GIBRALTAR : Pin = { lat : 36.1408 , lon : - 5.3536 , elevM : 0 } ;
4442const MIN_REGION_DIFF = 0.00001 ;
4543const MIN_PIN_DIFF = 0.000001 ;
4644const EMPTY_ALARM_STATE : AlarmState = {
@@ -66,7 +64,9 @@ function hasMeaningfulRegionChange(prev: Region, next: Region): boolean {
6664}
6765
6866function hasMeaningfulPinChange ( prev : Pin , next : Pin ) : boolean {
69- return Math . abs ( prev . lat - next . lat ) > MIN_PIN_DIFF || Math . abs ( prev . lon - next . lon ) > MIN_PIN_DIFF ;
67+ return (
68+ Math . abs ( prev . lat - next . lat ) > MIN_PIN_DIFF || Math . abs ( prev . lon - next . lon ) > MIN_PIN_DIFF
69+ ) ;
7070}
7171
7272export type TimerState = {
@@ -114,7 +114,7 @@ export function useTimerState(
114114 removeNotificationEntry : ( id : string ) => void ,
115115) : TimerState {
116116 const mapRef = useRef < MapView > ( null ) ;
117- const [ pin , setPin ] = useState < Pin > ( { lat : GIBRALTAR . lat , lon : GIBRALTAR . lon } ) ;
117+ const [ pin , setPin ] = useState < Pin > ( { lat : GIBRALTAR . lat , lon : GIBRALTAR . lon , elevM : 0 } ) ;
118118 const [ mapType , setMapType ] = useState < MapType3 > ( "standard" ) ;
119119 const [ showVisibleOverlay , setShowVisibleOverlay ] = useState ( true ) ;
120120 const [ showCentralOverlay , setShowCentralOverlay ] = useState ( true ) ;
@@ -219,11 +219,11 @@ export function useTimerState(
219219 setShowDirectionsOverlay ( ( prev ) => ! prev ) ;
220220 } ;
221221
222- const jumpTo = ( lat : number , lon : number , delta = 3 ) => {
222+ const jumpTo = ( lat : number , lon : number , delta = 3 , elevM = 0 ) => {
223223 const safeLat = sanitizeLatitude ( lat ) ;
224224 const safeLon = normalizeLongitude ( lon ) ;
225225 const safeDelta = sanitizeDelta ( delta , 3 ) ;
226- const nextPin : Pin = { lat : safeLat , lon : safeLon } ;
226+ const nextPin : Pin = { lat : safeLat , lon : safeLon , elevM } ;
227227 const nextRegion : Region = {
228228 latitude : safeLat ,
229229 longitude : safeLon ,
@@ -250,7 +250,7 @@ export function useTimerState(
250250 const movePinKeepZoom = ( lat : number , lon : number ) => {
251251 const safeLat = sanitizeLatitude ( lat ) ;
252252 const safeLon = normalizeLongitude ( lon ) ;
253- const nextPin : Pin = { lat : safeLat , lon : safeLon } ;
253+ const nextPin : Pin = { lat : safeLat , lon : safeLon , elevM : 0 } ;
254254 const pinMoved = hasMeaningfulPinChange ( pin , nextPin ) ;
255255
256256 if ( pinMoved ) {
@@ -310,7 +310,8 @@ export function useTimerState(
310310
311311 const last = await Location . getLastKnownPositionAsync ( ) ;
312312 if ( last ?. coords ) {
313- jumpTo ( last . coords . latitude , last . coords . longitude , 2 ) ;
313+ const alt = last . coords . altitude ?? 0 ;
314+ jumpTo ( last . coords . latitude , last . coords . longitude , 2 , alt ) ;
314315 setStatus ( "Pin set from last known location" ) ;
315316 }
316317
@@ -330,7 +331,8 @@ export function useTimerState(
330331 ] ) ;
331332
332333 if ( current ?. coords ) {
333- jumpTo ( current . coords . latitude , current . coords . longitude , 2 ) ;
334+ const alt = current . coords . altitude ?? 0 ;
335+ jumpTo ( current . coords . latitude , current . coords . longitude , 2 , alt ) ;
334336 setStatus ( "Pin set from GPS" ) ;
335337 } else if ( ! last ) {
336338 setStatus ( "GPS timed out (try again or move near a window)" ) ;
@@ -346,7 +348,7 @@ export function useTimerState(
346348 return ;
347349 }
348350
349- const observer : Observer = { latDeg : pin . lat , lonDeg : pin . lon , elevM : 0 } ;
351+ const observer : Observer = { latDeg : pin . lat , lonDeg : pin . lon , elevM : pin . elevM } ;
350352
351353 cancelPendingCompute ( ) ;
352354 const runToken = computeRunTokenRef . current ;
@@ -364,7 +366,7 @@ export function useTimerState(
364366 if ( computeRunTokenRef . current !== runToken ) return ;
365367
366368 setResult ( out ) ;
367- setResultPin ( { lat : observer . latDeg , lon : observer . lonDeg } ) ;
369+ setResultPin ( { lat : observer . latDeg , lon : observer . lonDeg , elevM : observer . elevM ?? 0 } ) ;
368370 setStatus ( "Computed" ) ;
369371
370372 resultFlash . setValue ( 0 ) ;
0 commit comments