import React from 'react'; import { OSMViewRef, Coordinate, LocationFix, LocationTrackingAccuracy } from '../types'; /** * Status of location tracking operations */ export type LocationTrackingStatus = 'idle' | 'starting' | 'active' | 'stopping' | 'error' | 'permission_required' | 'gps_disabled'; /** * Detailed error types for better handling */ export type LocationErrorType = 'permission_denied' | 'permission_restricted' | 'gps_disabled' | 'no_signal' | 'timeout' | 'view_not_ready' | 'unknown'; /** * Enhanced error information */ export interface LocationError { type: LocationErrorType; message: string; userMessage: string; canRetry: boolean; suggestedAction: string; } /** * Location tracking hook result */ export interface UseLocationTrackingResult { isTracking: boolean; status: LocationTrackingStatus; currentLocation: Coordinate | null; error: LocationError | null; startTracking: () => Promise; stopTracking: () => Promise; getCurrentLocation: () => Promise; waitForLocation: (timeoutSeconds?: number) => Promise; retryLastOperation: () => Promise; clearError: () => void; getHealthStatus: () => Promise; /** Buffered GPS fixes recorded since the last `clearTrack()` call. */ trackPoints: ReadonlyArray; /** Empties the recorded track buffer. */ clearTrack: () => void; /** * Feed a GPS fix into the track buffer. Wire this to `OSMView`'s * `onUserLocationChange` so every fix the map reports is considered for * recording: * * ```tsx * const tracking = useLocationTracking(mapRef, { recordTrack: true }); * * ``` * * No-ops when `recordTrack` is false or tracking is not active. */ ingestLocationFix: (fix: LocationFix) => void; /** * Serializes the recorded track as a GPX 1.1 XML string (lat, lon, * altitude, timestamp, accuracy, bearing, speed). Returns `null` when * fewer than 2 points have been recorded. */ exportTrackAsGpx: (options?: { trackName?: string; }) => string | null; } /** * System health status */ export interface LocationHealthStatus { isSupported: boolean; hasPermission: boolean; isGpsEnabled: boolean; isViewReady: boolean; lastLocationAge: number | null; networkAvailable: boolean; } /** * Hook options */ export interface UseLocationTrackingOptions { autoStart?: boolean; onLocationChange?: (location: LocationFix) => void; onError?: (error: LocationError) => void; maxWaitTime?: number; maxRetryAttempts?: number; fallbackLocation?: Coordinate; /** Accumulate GPS fixes (via `ingestLocationFix`) while tracking is active. Default false. */ recordTrack?: boolean; /** Max buffered track points before the oldest are dropped. Default 10000. */ maxTrackPoints?: number; /** Minimum distance (metres) a fix must be from the last recorded point to be kept — reduces GPS noise. Default 0 (record every fix). */ minTrackDistanceMeters?: number; /** * Keep tracking while the app is backgrounded or the screen is off. * Requires the config plugin's `enableBackgroundLocation: true`. While JS * is asleep, fixes are buffered natively; when the app returns to the * foreground (and when tracking stops) the hook automatically drains the * buffer into `trackPoints` if `recordTrack` is enabled, applying the same * `minTrackDistanceMeters`/`maxTrackPoints` filtering. Default false. */ background?: boolean; /** Accuracy/power preset forwarded to `startLocationTracking`. Default 'high' when set. */ accuracy?: LocationTrackingAccuracy; /** Android: persistent notification shown while background tracking runs. */ notification?: { title?: string; text?: string; }; } /** * Enhanced location tracking hook with bulletproof error handling * * This hook provides comprehensive error handling for all GPS and permission scenarios: * - Permission denied/revoked scenarios * - GPS disabled/unavailable * - No signal (indoor/underground) * - Timeout situations * - View lifecycle issues * - Network problems * - Hardware failures * * @param osmViewRef - Reference to the OSM view component * @param options - Hook configuration options * @returns Location tracking state and methods with comprehensive error handling * * @example * ```tsx * function MyMapComponent() { * const mapRef = useRef(null); * const { * isTracking, * currentLocation, * error, * startTracking, * stopTracking, * getCurrentLocation, * retryLastOperation, * getHealthStatus * } = useLocationTracking(mapRef, { * maxRetryAttempts: 3, * fallbackLocation: { latitude: 0, longitude: 0 }, * onError: (error) => { * console.error('Location error:', error.userMessage); * // Show user-friendly error message * if (error.canRetry) { * // Show retry button * } * } * }); * * return ( * * * {error && ( * * {error.userMessage} * {error.suggestedAction} * {error.canRetry && ( *