@bricks-soft/capacitor-location-tracking 8.0.1 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +375 -124
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/java/com/brickssoft/locationtracking/bridge/OptionParsers.kt +4 -1
- package/android/src/main/java/com/brickssoft/locationtracking/bridge/PluginHandlers.kt +14 -5
- package/android/src/main/java/com/brickssoft/locationtracking/config/Config.kt +10 -0
- package/android/src/main/java/com/brickssoft/locationtracking/config/ConfigJson.kt +70 -15
- package/android/src/main/java/com/brickssoft/locationtracking/config/ConfigStore.kt +6 -0
- package/android/src/main/java/com/brickssoft/locationtracking/config/ConfigValidator.kt +8 -3
- package/android/src/main/java/com/brickssoft/locationtracking/config/RuntimeStateJson.kt +10 -0
- package/android/src/main/java/com/brickssoft/locationtracking/config/SecretStore.kt +188 -0
- package/android/src/main/java/com/brickssoft/locationtracking/config/SharedPrefsConfigStore.kt +188 -17
- package/android/src/main/java/com/brickssoft/locationtracking/config/State.kt +11 -0
- package/android/src/main/java/com/brickssoft/locationtracking/core/Components.kt +21 -5
- package/android/src/main/java/com/brickssoft/locationtracking/core/ForceStopProbe.kt +20 -9
- package/android/src/main/java/com/brickssoft/locationtracking/core/TrackingEvent.kt +24 -2
- package/android/src/main/java/com/brickssoft/locationtracking/data/TrackingDatabase.kt +43 -1
- package/android/src/main/java/com/brickssoft/locationtracking/device/DefaultDeviceInfoProvider.kt +17 -0
- package/android/src/main/java/com/brickssoft/locationtracking/device/DeviceDetails.kt +167 -0
- package/android/src/main/java/com/brickssoft/locationtracking/engine/DefaultTrackingEngine.kt +191 -34
- package/android/src/main/java/com/brickssoft/locationtracking/engine/TrackingEngine.kt +6 -0
- package/android/src/main/java/com/brickssoft/locationtracking/engine/TrackingTimers.kt +3 -0
- package/android/src/main/java/com/brickssoft/locationtracking/heartbeat/DefaultHeartbeatScheduler.kt +52 -8
- package/android/src/main/java/com/brickssoft/locationtracking/heartbeat/HeartbeatAlarmReceiver.kt +22 -0
- package/android/src/main/java/com/brickssoft/locationtracking/http/AuthorizationManager.kt +78 -27
- package/android/src/main/java/com/brickssoft/locationtracking/http/ConfigChecks.kt +140 -0
- package/android/src/main/java/com/brickssoft/locationtracking/http/HttpSupport.kt +50 -12
- package/android/src/main/java/com/brickssoft/locationtracking/http/HttpSyncer.kt +17 -0
- package/android/src/main/java/com/brickssoft/locationtracking/http/OkHttpSyncer.kt +507 -92
- package/android/src/main/java/com/brickssoft/locationtracking/http/SyncPolicy.kt +6 -6
- package/android/src/main/java/com/brickssoft/locationtracking/http/TemplateRenderer.kt +23 -1
- package/android/src/main/java/com/brickssoft/locationtracking/http/UploadJobs.kt +217 -0
- package/android/src/main/java/com/brickssoft/locationtracking/http/UploadWait.kt +184 -0
- package/android/src/main/java/com/brickssoft/locationtracking/logging/FileLogger.kt +66 -7
- package/android/src/main/java/com/brickssoft/locationtracking/logging/LogRedaction.kt +31 -0
- package/android/src/main/java/com/brickssoft/locationtracking/model/DeviceModels.kt +44 -1
- package/android/src/main/java/com/brickssoft/locationtracking/model/ModelJson.kt +79 -8
- package/android/src/main/java/com/brickssoft/locationtracking/model/Record.kt +9 -0
- package/android/src/main/java/com/brickssoft/locationtracking/model/TrackedLocation.kt +12 -2
- package/android/src/main/java/com/brickssoft/locationtracking/position/DefaultPositionService.kt +10 -2
- package/android/src/main/java/com/brickssoft/locationtracking/position/PositionWatch.kt +24 -1
- package/android/src/main/java/com/brickssoft/locationtracking/processing/DefaultRecordFactory.kt +31 -10
- package/android/src/main/java/com/brickssoft/locationtracking/provider/Backends.kt +48 -3
- package/android/src/main/java/com/brickssoft/locationtracking/provider/DefaultProviderFactory.kt +60 -0
- package/android/src/main/java/com/brickssoft/locationtracking/provider/LocationSubscriptions.kt +180 -0
- package/android/src/main/java/com/brickssoft/locationtracking/provider/android/AndroidLocationBackend.kt +200 -126
- package/android/src/main/java/com/brickssoft/locationtracking/provider/android/LocationProviders.kt +20 -0
- package/android/src/main/java/com/brickssoft/locationtracking/provider/gms/GmsLocationBackend.kt +39 -51
- package/android/src/main/java/com/brickssoft/locationtracking/provider/gms/GmsProviderBundle.kt +8 -0
- package/android/src/main/java/com/brickssoft/locationtracking/provider/hms/HmsLocationBackend.kt +47 -53
- package/android/src/main/java/com/brickssoft/locationtracking/provider/hms/HmsProviderBundle.kt +34 -2
- package/android/src/main/java/com/brickssoft/locationtracking/record/RecordSink.kt +19 -1
- package/android/src/main/java/com/brickssoft/locationtracking/service/BootCountStore.kt +7 -0
- package/android/src/main/res/xml/lt_file_paths.xml +1 -1
- package/dist/esm/definitions.d.ts +107 -4
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/events.d.ts +8 -2
- package/dist/esm/events.js +7 -1
- package/dist/esm/events.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web/config.js +10 -0
- package/dist/esm/web/config.js.map +1 -1
- package/dist/esm/web/device.d.ts +1 -1
- package/dist/esm/web/device.js +8 -1
- package/dist/esm/web/device.js.map +1 -1
- package/dist/esm/web.d.ts +0 -8
- package/dist/esm/web.js +12 -3
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +39 -5
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +39 -5
- package/dist/plugin.js.map +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PermissionState, PluginListenerHandle } from '@capacitor/core';\n\nexport type CallbackID = string;\nexport type DesiredAccuracy = 'high' | 'balanced' | 'low' | 'passive';\nexport type LocationProviderSetting = 'auto' | 'gms' | 'hms' | 'android';\nexport type LocationBackend = 'gms' | 'hms' | 'android' | 'web';\nexport type TrackingMode = 'location' | 'geofences';\nexport type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug' | 'verbose';\nexport type ActivityType = 'still' | 'on_foot' | 'walking' | 'running' | 'on_bicycle' | 'in_vehicle' | 'unknown';\nexport type RecordEvent =\n | 'location'\n | 'motionchange'\n | 'current_position'\n | 'watch_position'\n | 'heartbeat'\n | 'geofence'\n | 'tracking_start'\n | 'tracking_stop'\n | 'providerchange';\nexport type GeofenceAction = 'ENTER' | 'EXIT' | 'DWELL';\nexport type HttpMethod = 'POST' | 'PUT' | 'PATCH';\nexport type NotificationPriority = 'min' | 'low' | 'default' | 'high' | 'max';\nexport type PermissionType = 'location' | 'backgroundLocation' | 'activityRecognition' | 'notifications';\nexport type ConnectivityType = 'wifi' | 'cellular' | 'ethernet' | 'other' | 'none';\nexport type HeartbeatStrategy = 'exact' | 'listener_with_backup' | 'idle_paced' | 'disabled';\n/** Rejection `code` of every failed promise. */\nexport type ErrorCode =\n | 'NOT_READY'\n | 'PERMISSION_DENIED'\n | 'LOCATION_DISABLED'\n | 'TIMEOUT'\n | 'UNAVAILABLE'\n | 'INVALID_ARGUMENT'\n | 'NOT_FOUND'\n | 'NO_URL'\n | 'HTTP_ERROR'\n | 'NETWORK_ERROR'\n | 'TOO_MANY_GEOFENCES'\n | 'NO_ACTIVITY'\n | 'IO_ERROR'\n | 'UNIMPLEMENTED'\n | 'INTERNAL';\n\n/* ================= CONFIG (all optional; defaults shown) ================= */\n\nexport interface LocationFilterConfig {\n /** @default false */\n useKalman?: boolean;\n /**\n * Reject fixes with accuracy worse than this (m).\n * @default 100\n */\n trackingAccuracyThreshold?: number;\n /**\n * Reject fixes implying speed above this (m/s); 0 = off.\n * @default 80\n */\n maxImpliedSpeed?: number;\n /**\n * Odometer ignores fixes worse than this (m).\n * @default 20\n */\n odometerAccuracyThreshold?: number;\n /** @default false */\n allowIdenticalLocations?: boolean;\n /**\n * Drop mock fixes entirely (otherwise they are kept with mock:true).\n * @default false\n */\n rejectMockLocations?: boolean;\n}\n\nexport interface GeolocationConfig {\n /** @default 'high' */\n desiredAccuracy?: DesiredAccuracy;\n /**\n * meters\n * @default 10\n */\n distanceFilter?: number;\n /**\n * ms\n * @default 1000\n */\n locationUpdateInterval?: number;\n /**\n * ms\n * @default 500\n */\n fastestLocationUpdateInterval?: number;\n /** @default false */\n disableElasticity?: boolean;\n /** @default 1 */\n elasticityMultiplier?: number;\n /**\n * meters\n * @default 25\n */\n stationaryRadius?: number;\n /**\n * minutes\n * @default 5\n */\n stopTimeout?: number;\n /**\n * minutes, 0 = off\n * @default 0\n */\n stopAfterElapsedMinutes?: number;\n /** @default false */\n stopOnStationary?: boolean;\n /**\n * default getCurrentPosition timeout, ms\n * @default 30000\n */\n locationTimeout?: number;\n filter?: LocationFilterConfig;\n}\n\nexport interface ActivityConfig {\n /** @default false */\n disableMotionActivityUpdates?: boolean;\n /**\n * ms\n * @default 10000\n */\n activityRecognitionInterval?: number;\n /**\n * 0-100\n * @default 75\n */\n minimumActivityRecognitionConfidence?: number;\n /**\n * ms\n * @default 0\n */\n motionTriggerDelay?: number;\n /** @default false */\n disableStopDetection?: boolean;\n}\n\nexport interface HeartbeatConfig {\n /** @default true */\n enabled?: boolean;\n /**\n * seconds, min 60\n * @default 180\n */\n minInterval?: number;\n /**\n * seconds, >= minInterval\n * @default 300\n */\n maxInterval?: number;\n}\n\nexport interface AuthorizationConfig {\n /** @default 'JWT' */\n strategy?: 'JWT';\n accessToken?: string;\n refreshToken?: string;\n refreshUrl?: string;\n /**\n * String values may contain `{refreshToken}`.\n * @default {}\n */\n refreshPayload?: Record<string, string>;\n refreshHeaders?: Record<string, string>;\n /** @default 'json' */\n refreshPayloadEncoding?: 'json' | 'form';\n /**\n * access-token expiry, epoch ms; -1 = unknown\n * @default -1\n */\n expires?: number;\n}\n\nexport interface HttpConfig {\n /** No url => nothing is uploaded (records stay queued). */\n url?: string | null;\n /** @default 'POST' */\n method?: HttpMethod;\n /** @default {} */\n headers?: Record<string, string>;\n /**\n * merged into the ROOT of every request body\n * @default {}\n */\n params?: Record<string, unknown>;\n /** @default true */\n autoSync?: boolean;\n /**\n * upload when queue >= threshold; 0 = every record\n * @default 0\n */\n autoSyncThreshold?: number;\n /**\n * s; upload normal records once the oldest queued one is this old; 0 = off\n * @default 0\n */\n syncInterval?: number;\n /** @default false */\n batchSync?: boolean;\n /** @default 100 */\n maxBatchSize?: number;\n /** @default false */\n disableAutoSyncOnCellular?: boolean;\n /**\n * '.' = no wrapping\n * @default 'location'\n */\n rootProperty?: string;\n /** JSON text with `<%= name %>` placeholders */\n locationTemplate?: string | null;\n /** used for event 'geofence'; falls back to locationTemplate */\n geofenceTemplate?: string | null;\n /**\n * ms\n * @default 60000\n */\n timeout?: number;\n authorization?: AuthorizationConfig | null;\n}\n\nexport interface PersistenceConfig {\n /** @default 7 */\n maxDaysToPersist?: number;\n /**\n * -1 = unlimited\n * @default -1\n */\n maxRecordsToPersist?: number;\n /**\n * merged into `extras` of every record at creation time\n * @default {}\n */\n extras?: Record<string, unknown>;\n}\n\nexport interface AppConfig {\n /** @default true */\n stopOnTerminate?: boolean;\n /** @default false */\n startOnBoot?: boolean;\n}\n\nexport interface NotificationActionButton {\n id: string;\n label: string;\n}\n\nexport interface NotificationConfig {\n /** @default app label */\n title?: string;\n /** @default 'Location tracking is active' */\n text?: string;\n /**\n * 'drawable/name' | 'mipmap/name'\n * @default plugin icon 'drawable/lt_ic_notification'\n */\n smallIcon?: string;\n largeIcon?: string;\n /** '#RRGGBB' */\n color?: string;\n /** @default 'default' */\n priority?: NotificationPriority;\n /** @default 'location_tracking' */\n channelId?: string;\n /** @default 'Location tracking' */\n channelName?: string;\n /** max 3; tap => 'notificationaction' event */\n actions?: NotificationActionButton[];\n /** notification that resumes tracking when Android refuses to restore it from the background (Android 14+) */\n resume?: ResumeNotificationConfig;\n}\n\n/**\n * Posted when Android refuses to restore tracking from the background (after a reboot, an app update or a process\n * restart), typically on Android 14+ without \"Allow all the time\". A tap resumes the session\n * (`tracking_start` reason `resume_notification`). Uses the tracking notification's small icon and color.\n */\nexport interface ResumeNotificationConfig {\n /** @default false */\n enabled?: boolean;\n /** @default app label */\n title?: string;\n /** @default 'Location tracking is paused. Tap to resume.' */\n text?: string;\n /** @default 'Paused location tracking' */\n channelName?: string;\n}\n\nexport interface GeofenceConfig {\n /** @default true */\n initialTriggerEntry?: boolean;\n}\n\nexport interface LoggerConfig {\n /** @default 'info' */\n logLevel?: LogLevel;\n /** @default 3 */\n logMaxDays?: number;\n}\n\nexport interface BackgroundPermissionRationale {\n /** defaults from plugin string resources */\n title?: string;\n message?: string;\n positiveAction?: string;\n negativeAction?: string;\n}\n\nexport interface Config {\n geolocation?: GeolocationConfig;\n activity?: ActivityConfig;\n heartbeat?: HeartbeatConfig;\n http?: HttpConfig;\n persistence?: PersistenceConfig;\n app?: AppConfig;\n notification?: NotificationConfig;\n geofence?: GeofenceConfig;\n logger?: LoggerConfig;\n backgroundPermissionRationale?: BackgroundPermissionRationale;\n /**\n * Android only\n * @default 'auto'\n */\n locationProvider?: LocationProviderSetting;\n}\n\nexport interface ReadyOptions {\n config?: Config;\n /**\n * true: config = defaults + given config (every launch). false: given config applied only on the very first\n * ready(); afterwards persisted config wins.\n * @default true\n */\n reset?: boolean;\n}\n\nexport interface State {\n enabled: boolean;\n trackingMode: TrackingMode;\n isMoving: boolean;\n odometer: number;\n backend: LocationBackend;\n lastRecordAt: string | null;\n /** fully populated with defaults */\n config: Config;\n}\n\n/* ================= RECORDS (snake_case = identical to wire format) ================= */\n\nexport interface Coords {\n latitude: number;\n longitude: number;\n accuracy: number;\n altitude: number | null;\n altitude_accuracy: number | null;\n speed: number | null;\n speed_accuracy: number | null;\n heading: number | null;\n heading_accuracy: number | null;\n}\n\nexport interface ProviderState {\n enabled: boolean;\n gps: boolean;\n network: boolean;\n permission: 'always' | 'when_in_use' | 'denied';\n accuracy: 'precise' | 'approximate' | 'none';\n backend: LocationBackend;\n}\n\nexport interface Location {\n uuid: string;\n event: RecordEvent;\n /** fix time (ISO-8601 UTC ms); null if no location ever known */\n timestamp: string | null;\n /** record creation time */\n recorded_at: string;\n /** only present in HTTP bodies */\n sent_at?: string;\n elapsed_realtime_ms: number;\n /** -1 if unavailable */\n boot_count: number;\n is_moving: boolean;\n odometer: number;\n mock: boolean;\n coords: Coords | null;\n activity: { type: ActivityType; confidence: number };\n /** level 0..1, -1 unknown */\n battery: { level: number; is_charging: boolean };\n backend: LocationBackend | null;\n extras?: Record<string, unknown>;\n /** event 'geofence' only */\n geofence?: { identifier: string; action: GeofenceAction; extras?: Record<string, unknown> };\n /** provider state when the record was created; the new state for event 'providerchange' */\n provider?: ProviderState;\n /**\n * tracking_start: start|start_geofences|boot|restore|package_replaced|resume_notification;\n * tracking_stop: stop|stop_on_stationary|stop_after_elapsed|terminate|permission_denied|service_start_failed|reboot|package_replaced\n */\n reason?: string;\n /** event 'heartbeat' only, optional: how the heartbeat is scheduled */\n heartbeat?: HeartbeatMeta;\n}\n\n/** Scheduling metadata of a `heartbeat` record (snake_case = wire format). */\nexport interface HeartbeatMeta {\n strategy: 'exact' | 'listener_with_backup' | 'idle_paced';\n /** heartbeat.minInterval (s) when the heartbeat was created */\n min_interval: number;\n /** heartbeat.maxInterval (s) when the heartbeat was created */\n max_interval: number;\n /** when the next heartbeat is expected (ISO-8601 UTC ms); null if unknown */\n next_at: string | null;\n /** the app is exempt from battery optimization */\n battery_exempt: boolean;\n /** the device was in deep Doze */\n device_idle: boolean;\n}\n\nexport type LocationRecord = Location;\n\nexport interface InsertLocationInput {\n coords: Pick<Coords, 'latitude' | 'longitude'> & Partial<Coords>;\n timestamp?: string;\n event?: RecordEvent;\n is_moving?: boolean;\n extras?: Record<string, unknown>;\n}\n\n/* ================= GEOFENCES ================= */\n\n/**\n * Either (latitude, longitude, radius) = circle, or vertices = polygon. For polygons, getGeofences() also returns\n * the computed enclosing circle.\n */\nexport interface Geofence {\n identifier: string;\n latitude?: number;\n longitude?: number;\n /** m */\n radius?: number;\n /** [[lat,lng], ...] >= 3 points */\n vertices?: [number, number][];\n /** @default true */\n notifyOnEntry?: boolean;\n /** @default true */\n notifyOnExit?: boolean;\n /** @default false */\n notifyOnDwell?: boolean;\n /**\n * ms\n * @default 30000\n */\n loiteringDelay?: number;\n extras?: Record<string, unknown>;\n}\n\n/* ================= EVENTS ================= */\n\nexport interface MotionChangeEvent {\n isMoving: boolean;\n location: Location;\n}\nexport interface ActivityChangeEvent {\n activity: ActivityType;\n confidence: number;\n}\nexport interface HeartbeatEvent {\n location: Location;\n}\nexport interface GeofenceEvent {\n identifier: string;\n action: GeofenceAction;\n location: Location;\n extras?: Record<string, unknown>;\n}\nexport interface GeofencesChangeEvent {\n on: Geofence[];\n off: string[];\n}\nexport interface HttpEvent {\n success: boolean;\n status: number;\n responseText: string;\n uuids: string[];\n}\nexport interface ConnectivityChangeEvent {\n connected: boolean;\n type: ConnectivityType;\n}\nexport interface PowerSaveChangeEvent {\n isPowerSaveMode: boolean;\n}\nexport interface EnabledChangeEvent {\n enabled: boolean;\n}\nexport interface NotificationActionEvent {\n id: string;\n}\nexport interface AuthorizationEvent {\n success: boolean;\n status: number;\n error?: string;\n response?: Record<string, unknown>;\n}\nexport interface LocationTrackingEventMap {\n location: Location;\n motionchange: MotionChangeEvent;\n activitychange: ActivityChangeEvent;\n providerchange: ProviderState;\n heartbeat: HeartbeatEvent;\n geofence: GeofenceEvent;\n geofenceschange: GeofencesChangeEvent;\n http: HttpEvent;\n connectivitychange: ConnectivityChangeEvent;\n powersavechange: PowerSaveChangeEvent;\n enabledchange: EnabledChangeEvent;\n notificationaction: NotificationActionEvent;\n authorization: AuthorizationEvent;\n}\nexport type LocationTrackingEventName = keyof LocationTrackingEventMap;\n\n/* ================= MISC ================= */\n\nexport interface CurrentPositionOptions {\n /** @default 3 */\n samples?: number;\n /**\n * ms\n * @default geolocation.locationTimeout\n */\n timeout?: number;\n /**\n * ms\n * @default 0\n */\n maximumAge?: number;\n /** @default 'high' */\n desiredAccuracy?: DesiredAccuracy;\n /** @default true */\n persist?: boolean;\n extras?: Record<string, unknown>;\n}\n\nexport interface WatchPositionOptions {\n /**\n * ms\n * @default 1000\n */\n interval?: number;\n /** @default 'high' */\n desiredAccuracy?: DesiredAccuracy;\n /** @default false */\n persist?: boolean;\n extras?: Record<string, unknown>;\n}\n\nexport type WatchPositionCallback = (location: Location | null, error?: { code: ErrorCode; message: string }) => void;\n\nexport interface HeartbeatStatus {\n enabled: boolean;\n minInterval: number;\n maxInterval: number;\n lastRecordAt: string | null;\n lastHeartbeatAt: string | null;\n nextHeartbeatAt: string | null;\n strategy: HeartbeatStrategy;\n canScheduleExactAlarms: boolean;\n isIgnoringBatteryOptimizations: boolean;\n isDeviceIdleMode: boolean;\n isPowerSaveMode: boolean;\n pendingHeartbeats: number;\n}\n\nexport interface BatteryOptimizationStatus {\n isIgnoringBatteryOptimizations: boolean;\n canScheduleExactAlarms: boolean;\n isDeviceIdleMode: boolean;\n}\n\nexport interface PowerManagerInfo {\n manufacturer: string;\n available: boolean;\n}\n\nexport interface DeviceInfo {\n platform: 'android' | 'web';\n manufacturer: string;\n model: string;\n brand: string;\n osVersion: string;\n sdkInt: number;\n pluginVersion: string;\n gmsAvailable: boolean;\n hmsAvailable: boolean;\n backend: LocationBackend;\n packagedProviders: string[];\n}\n\nexport interface Sensors {\n accelerometer: boolean;\n gyroscope: boolean;\n magnetometer: boolean;\n significantMotion: boolean;\n stepCounter: boolean;\n stepDetector: boolean;\n barometer: boolean;\n}\n\nexport interface PermissionStatus {\n location: PermissionState;\n backgroundLocation: PermissionState;\n activityRecognition: PermissionState;\n notifications: PermissionState;\n}\n\nexport interface LogQuery {\n start?: number;\n end?: number;\n level?: LogLevel;\n limit?: number;\n order?: 'asc' | 'desc';\n}\n\nexport interface LocationTrackingPlugin {\n /** Loads persisted config and state. Must resolve before most other methods (see NOT_READY rule). */\n ready(options?: ReadyOptions): Promise<State>;\n /** deep merge; arrays replaced; null resets key to default */\n setConfig(options: { config: Config }): Promise<State>;\n /** Resets the config to defaults, then applies the given config. */\n reset(options?: { config?: Config }): Promise<State>;\n getState(): Promise<State>;\n /** Starts location tracking (mode 'location'). */\n start(): Promise<State>;\n /** Starts geofence-only tracking (mode 'geofences'). */\n startGeofences(): Promise<State>;\n stop(): Promise<State>;\n /** Forces the motion state to moving or stationary. */\n changePace(options: { isMoving: boolean }): Promise<void>;\n\n getCurrentPosition(options?: CurrentPositionOptions): Promise<Location>;\n watchPosition(options: WatchPositionOptions, callback: WatchPositionCallback): Promise<CallbackID>;\n clearWatch(options: { id: CallbackID }): Promise<void>;\n\n getOdometer(): Promise<{ odometer: number }>;\n setOdometer(options: { odometer: number }): Promise<{ odometer: number }>;\n resetOdometer(): Promise<{ odometer: number }>;\n\n getLocations(options?: { limit?: number }): Promise<{ locations: Location[] }>;\n getCount(): Promise<{ count: number }>;\n insertLocation(options: { location: InsertLocationInput }): Promise<{ uuid: string }>;\n destroyLocations(): Promise<{ count: number }>;\n destroyLocation(options: { uuid: string }): Promise<{ deleted: boolean }>;\n /** uploads whole queue now; resolves with uploaded records */\n sync(): Promise<{ locations: Location[] }>;\n\n addGeofence(options: { geofence: Geofence }): Promise<void>;\n addGeofences(options: { geofences: Geofence[] }): Promise<void>;\n removeGeofence(options: { identifier: string }): Promise<void>;\n /** identifiers omitted (or null) = remove all; an empty array removes nothing */\n removeGeofences(options?: { identifiers?: string[] }): Promise<void>;\n getGeofences(): Promise<{ geofences: Geofence[] }>;\n getGeofence(options: { identifier: string }): Promise<{ geofence: Geofence | null }>;\n geofenceExists(options: { identifier: string }): Promise<{ exists: boolean }>;\n\n getHeartbeatStatus(): Promise<HeartbeatStatus>;\n\n getProviderState(): Promise<ProviderState>;\n isPowerSaveMode(): Promise<{ isPowerSaveMode: boolean }>;\n getBatteryOptimizationStatus(): Promise<BatteryOptimizationStatus>;\n openBatteryOptimizationSettings(): Promise<{ opened: boolean }>;\n getPowerManagerInfo(): Promise<PowerManagerInfo>;\n openPowerManagerSettings(): Promise<{ opened: boolean }>;\n openLocationSettings(): Promise<{ opened: boolean }>;\n openAppSettings(): Promise<{ opened: boolean }>;\n getDeviceInfo(): Promise<DeviceInfo>;\n getSensors(): Promise<Sensors>;\n\n checkPermissions(): Promise<PermissionStatus>;\n /** default all four, order: location, notifications, activityRecognition, backgroundLocation */\n requestPermissions(options?: { permissions?: PermissionType[] }): Promise<PermissionStatus>;\n\n log(options: { level: Exclude<LogLevel, 'off'>; message: string }): Promise<void>;\n getLog(options?: LogQuery): Promise<{ log: string }>;\n destroyLog(): Promise<void>;\n uploadLog(options: {\n url: string;\n headers?: Record<string, string>;\n params?: Record<string, unknown>;\n }): Promise<{ success: boolean; status: number }>;\n emailLog(options: { email: string; subject?: string }): Promise<void>;\n\n addListener(eventName: 'location', listenerFunc: (e: Location) => void): Promise<PluginListenerHandle>;\n addListener(eventName: 'motionchange', listenerFunc: (e: MotionChangeEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'activitychange',\n listenerFunc: (e: ActivityChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'providerchange', listenerFunc: (e: ProviderState) => void): Promise<PluginListenerHandle>;\n addListener(eventName: 'heartbeat', listenerFunc: (e: HeartbeatEvent) => void): Promise<PluginListenerHandle>;\n addListener(eventName: 'geofence', listenerFunc: (e: GeofenceEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'geofenceschange',\n listenerFunc: (e: GeofencesChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'http', listenerFunc: (e: HttpEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'connectivitychange',\n listenerFunc: (e: ConnectivityChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'powersavechange',\n listenerFunc: (e: PowerSaveChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'enabledchange', listenerFunc: (e: EnabledChangeEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'notificationaction',\n listenerFunc: (e: NotificationActionEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'authorization', listenerFunc: (e: AuthorizationEvent) => void): Promise<PluginListenerHandle>;\n removeAllListeners(): Promise<void>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/definitions.ts"],"names":[],"mappings":"","sourcesContent":["import type { PermissionState, PluginListenerHandle } from '@capacitor/core';\n\nexport type CallbackID = string;\nexport type DesiredAccuracy = 'high' | 'balanced' | 'low' | 'passive';\nexport type LocationProviderSetting = 'auto' | 'gms' | 'hms' | 'android';\nexport type LocationBackend = 'gms' | 'hms' | 'android' | 'web';\nexport type TrackingMode = 'location' | 'geofences';\nexport type LogLevel = 'off' | 'error' | 'warn' | 'info' | 'debug' | 'verbose';\nexport type ActivityType = 'still' | 'on_foot' | 'walking' | 'running' | 'on_bicycle' | 'in_vehicle' | 'unknown';\nexport type RecordEvent =\n | 'location'\n | 'motionchange'\n | 'current_position'\n | 'watch_position'\n | 'heartbeat'\n | 'geofence'\n | 'tracking_start'\n | 'tracking_stop'\n | 'providerchange';\nexport type GeofenceAction = 'ENTER' | 'EXIT' | 'DWELL';\nexport type HttpMethod = 'POST' | 'PUT' | 'PATCH';\nexport type NotificationPriority = 'min' | 'low' | 'default' | 'high' | 'max';\nexport type PermissionType = 'location' | 'backgroundLocation' | 'activityRecognition' | 'notifications';\nexport type ConnectivityType = 'wifi' | 'cellular' | 'ethernet' | 'other' | 'none';\nexport type HeartbeatStrategy = 'exact' | 'listener_with_backup' | 'idle_paced' | 'disabled';\n/** Rejection `code` of every failed promise. */\nexport type ErrorCode =\n | 'NOT_READY'\n | 'PERMISSION_DENIED'\n | 'LOCATION_DISABLED'\n | 'TIMEOUT'\n | 'UNAVAILABLE'\n | 'INVALID_ARGUMENT'\n | 'NOT_FOUND'\n | 'NO_URL'\n | 'HTTP_ERROR'\n | 'NETWORK_ERROR'\n | 'TOO_MANY_GEOFENCES'\n | 'NO_ACTIVITY'\n | 'IO_ERROR'\n | 'UNIMPLEMENTED'\n | 'INTERNAL';\n\n/* ================= CONFIG (all optional; defaults shown) ================= */\n\nexport interface LocationFilterConfig {\n /** @default false */\n useKalman?: boolean;\n /**\n * Reject fixes with accuracy worse than this (m).\n * @default 100\n */\n trackingAccuracyThreshold?: number;\n /**\n * Reject fixes implying speed above this (m/s); 0 = off.\n * @default 80\n */\n maxImpliedSpeed?: number;\n /**\n * Odometer ignores fixes worse than this (m).\n * @default 20\n */\n odometerAccuracyThreshold?: number;\n /** @default false */\n allowIdenticalLocations?: boolean;\n /**\n * Drop mock fixes entirely (otherwise they are kept with mock:true).\n * @default false\n */\n rejectMockLocations?: boolean;\n}\n\nexport interface GeolocationConfig {\n /** @default 'high' */\n desiredAccuracy?: DesiredAccuracy;\n /**\n * meters\n * @default 10\n */\n distanceFilter?: number;\n /**\n * ms\n * @default 1000\n */\n locationUpdateInterval?: number;\n /**\n * ms\n * @default 500\n */\n fastestLocationUpdateInterval?: number;\n /** @default false */\n disableElasticity?: boolean;\n /** @default 1 */\n elasticityMultiplier?: number;\n /**\n * meters\n * @default 25\n */\n stationaryRadius?: number;\n /**\n * minutes\n * @default 5\n */\n stopTimeout?: number;\n /**\n * minutes, 0 = off\n * @default 0\n */\n stopAfterElapsedMinutes?: number;\n /** @default false */\n stopOnStationary?: boolean;\n /**\n * default getCurrentPosition timeout, ms\n * @default 30000\n */\n locationTimeout?: number;\n filter?: LocationFilterConfig;\n}\n\nexport interface ActivityConfig {\n /** @default false */\n disableMotionActivityUpdates?: boolean;\n /**\n * ms\n * @default 10000\n */\n activityRecognitionInterval?: number;\n /**\n * 0-100\n * @default 75\n */\n minimumActivityRecognitionConfidence?: number;\n /**\n * ms\n * @default 0\n */\n motionTriggerDelay?: number;\n /** @default false */\n disableStopDetection?: boolean;\n}\n\nexport interface HeartbeatConfig {\n /** @default true */\n enabled?: boolean;\n /**\n * seconds, min 60\n * @default 180\n */\n minInterval?: number;\n /**\n * seconds, >= minInterval\n * @default 300\n */\n maxInterval?: number;\n /**\n * seconds, 0..60. After a heartbeat is queued, keep the phone awake until its upload has finished, or at most this\n * long, so it reaches the server on time while tracking is on. 0 = do not keep the phone awake.\n * @default 10\n */\n uploadKeepAwake?: number;\n}\n\nexport interface AuthorizationConfig {\n /** @default 'JWT' */\n strategy?: 'JWT';\n accessToken?: string;\n refreshToken?: string;\n refreshUrl?: string;\n /**\n * String values may contain `{refreshToken}`.\n * @default {}\n */\n refreshPayload?: Record<string, string>;\n refreshHeaders?: Record<string, string>;\n /** @default 'json' */\n refreshPayloadEncoding?: 'json' | 'form';\n /**\n * access-token expiry, epoch ms; -1 = unknown\n * @default -1\n */\n expires?: number;\n}\n\nexport interface HttpConfig {\n /** No url => nothing is uploaded (records stay queued). */\n url?: string | null;\n /** @default 'POST' */\n method?: HttpMethod;\n /** @default {} */\n headers?: Record<string, string>;\n /**\n * merged into the ROOT of every request body\n * @default {}\n */\n params?: Record<string, unknown>;\n /** @default true */\n autoSync?: boolean;\n /**\n * upload when queue >= threshold; 0 = every record\n * @default 0\n */\n autoSyncThreshold?: number;\n /**\n * s; upload normal records once the oldest queued one is this old; 0 = off\n * @default 0\n */\n syncInterval?: number;\n /** @default false */\n batchSync?: boolean;\n /** @default 100 */\n maxBatchSize?: number;\n /** @default false */\n disableAutoSyncOnCellular?: boolean;\n /**\n * '.' = no wrapping\n * @default 'location'\n */\n rootProperty?: string;\n /** JSON text with `<%= name %>` placeholders */\n locationTemplate?: string | null;\n /** used for event 'geofence'; falls back to locationTemplate */\n geofenceTemplate?: string | null;\n /**\n * ms\n * @default 60000\n */\n timeout?: number;\n /**\n * seconds, >= 0. The longest wait that a `Retry-After` header of a 429 or 503 answer can impose on automatic uploads.\n * @default 3600\n */\n maxRetryAfter?: number;\n authorization?: AuthorizationConfig | null;\n}\n\nexport interface PersistenceConfig {\n /** @default 7 */\n maxDaysToPersist?: number;\n /**\n * -1 = unlimited\n * @default -1\n */\n maxRecordsToPersist?: number;\n /**\n * merged into `extras` of every record at creation time\n * @default {}\n */\n extras?: Record<string, unknown>;\n}\n\nexport interface AppConfig {\n /** @default true */\n stopOnTerminate?: boolean;\n /** @default false */\n startOnBoot?: boolean;\n}\n\nexport interface NotificationActionButton {\n id: string;\n label: string;\n}\n\nexport interface NotificationConfig {\n /** @default app label */\n title?: string;\n /** @default 'Location tracking is active' */\n text?: string;\n /**\n * 'drawable/name' | 'mipmap/name'\n * @default plugin icon 'drawable/lt_ic_notification'\n */\n smallIcon?: string;\n largeIcon?: string;\n /** '#RRGGBB' */\n color?: string;\n /** @default 'default' */\n priority?: NotificationPriority;\n /** @default 'location_tracking' */\n channelId?: string;\n /** @default 'Location tracking' */\n channelName?: string;\n /** max 3; tap => 'notificationaction' event */\n actions?: NotificationActionButton[];\n /** notification that resumes tracking when Android refuses to restore it from the background (Android 14+) */\n resume?: ResumeNotificationConfig;\n}\n\n/**\n * Posted when Android refuses to restore tracking from the background (after a reboot, an app update or a process\n * restart), typically on Android 14+ without \"Allow all the time\". A tap resumes the session\n * (`tracking_start` reason `resume_notification`). Uses the tracking notification's small icon and color.\n */\nexport interface ResumeNotificationConfig {\n /** @default false */\n enabled?: boolean;\n /** @default app label */\n title?: string;\n /** @default 'Location tracking is paused. Tap to resume.' */\n text?: string;\n /** @default 'Paused location tracking' */\n channelName?: string;\n}\n\nexport interface GeofenceConfig {\n /** @default true */\n initialTriggerEntry?: boolean;\n}\n\nexport interface LoggerConfig {\n /** @default 'info' */\n logLevel?: LogLevel;\n /** @default 3 */\n logMaxDays?: number;\n}\n\nexport interface BackgroundPermissionRationale {\n /** defaults from plugin string resources */\n title?: string;\n message?: string;\n positiveAction?: string;\n negativeAction?: string;\n}\n\nexport interface Config {\n geolocation?: GeolocationConfig;\n activity?: ActivityConfig;\n heartbeat?: HeartbeatConfig;\n http?: HttpConfig;\n persistence?: PersistenceConfig;\n app?: AppConfig;\n notification?: NotificationConfig;\n geofence?: GeofenceConfig;\n logger?: LoggerConfig;\n backgroundPermissionRationale?: BackgroundPermissionRationale;\n /**\n * Android only\n * @default 'auto'\n */\n locationProvider?: LocationProviderSetting;\n}\n\nexport interface ReadyOptions {\n config?: Config;\n /**\n * true: config = defaults + given config (every launch). false: given config applied only on the very first\n * ready(); afterwards persisted config wins.\n * @default true\n */\n reset?: boolean;\n}\n\nexport interface State {\n enabled: boolean;\n trackingMode: TrackingMode;\n isMoving: boolean;\n odometer: number;\n backend: LocationBackend;\n lastRecordAt: string | null;\n /** reason of the last `tracking_stop` record (the `tracking_stop` reasons of `Location.reason`); null if none */\n lastStopReason: string | null;\n /** when tracking stopped for `lastStopReason` (ISO-8601 UTC ms); null if none */\n lastStopAt: string | null;\n /**\n * fully populated with defaults. On Android the `http.authorization` secrets (`accessToken`, `refreshToken`, the\n * values of `refreshPayload` and `refreshHeaders`) are masked: `***`, or `***` plus the last 4 characters for values\n * longer than 8 characters; a `refreshPayload` value that contains `{refreshToken}` is shown. Passing a masked value\n * back to `setConfig` keeps the stored one. The web stub returns them as given.\n */\n config: Config;\n /**\n * `ready()`, `setConfig()` and `reset()` only: what the given config contains that was accepted but is probably\n * wrong (for example an `http://` upload URL).\n */\n warnings?: string[];\n}\n\n/* ================= RECORDS (snake_case = identical to wire format) ================= */\n\nexport interface Coords {\n latitude: number;\n longitude: number;\n accuracy: number;\n altitude: number | null;\n altitude_accuracy: number | null;\n speed: number | null;\n speed_accuracy: number | null;\n heading: number | null;\n heading_accuracy: number | null;\n}\n\nexport interface ProviderState {\n enabled: boolean;\n gps: boolean;\n network: boolean;\n permission: 'always' | 'when_in_use' | 'denied';\n accuracy: 'precise' | 'approximate' | 'none';\n backend: LocationBackend;\n}\n\nexport interface Location {\n uuid: string;\n event: RecordEvent;\n /** fix time (ISO-8601 UTC ms); null if no location ever known */\n timestamp: string | null;\n /** record creation time */\n recorded_at: string;\n /** only present in HTTP bodies */\n sent_at?: string;\n elapsed_realtime_ms: number;\n /** -1 if unavailable */\n boot_count: number;\n is_moving: boolean;\n odometer: number;\n mock: boolean;\n coords: Coords | null;\n activity: { type: ActivityType; confidence: number };\n /**\n * level 0..1, -1 unknown. Heartbeat records also carry `temperature` (°C), `health` and `plugged` when the device\n * reports them.\n */\n battery: {\n level: number;\n is_charging: boolean;\n temperature?: number;\n health?: 'good' | 'overheat' | 'dead' | 'over_voltage' | 'cold' | 'failure' | 'unknown';\n plugged?: 'ac' | 'usb' | 'wireless' | 'dock' | 'none' | 'other';\n };\n backend: LocationBackend | null;\n extras?: Record<string, unknown>;\n /** event 'geofence' only */\n geofence?: { identifier: string; action: GeofenceAction; extras?: Record<string, unknown> };\n /** provider state when the record was created; the new state for event 'providerchange' */\n provider?: ProviderState;\n /**\n * tracking_start: start|start_geofences|boot|restore|package_replaced|resume_notification;\n * tracking_stop: stop|stop_on_stationary|stop_after_elapsed|terminate|permission_denied|service_start_failed|reboot|package_replaced|user_stopped\n */\n reason?: string;\n /** event 'tracking_stop' with reason 'user_stopped' only: when the user stopped the app (ISO-8601 UTC ms) */\n stopped_at?: string;\n /** event 'heartbeat' only, optional: how the heartbeat is scheduled */\n heartbeat?: HeartbeatMeta;\n /** connection type when the record was created */\n network?: ConnectivityType;\n /** the device id on every record; more readings on 'heartbeat' and 'tracking_start' records (see `DeviceReadings`) */\n device?: DeviceReadings;\n}\n\n/**\n * The `device` object of records; a reading is present only when the device provides it.\n * Every record: `device_id`.\n * Heartbeat records: `background_restricted`, `standby_bucket`, `disk_free_bytes`, `thermal_status`.\n * `tracking_start` records: `manufacturer`, `model`, `os_version`, `sdk_int`, `low_ram_device`, `ram_total_bytes`.\n */\nexport interface DeviceReadings {\n /**\n * the device id: on Android, `Settings.Secure.ANDROID_ID`; other platforms will fill it with their own id.\n * Absent in records queued by an older version. Declare \"Device or other IDs\" in Google Play's Data safety form.\n */\n device_id?: string;\n /** the user set the app's battery use to \"Restricted\" (Android 9+) */\n background_restricted?: boolean;\n /** App Standby bucket (Android 9+) */\n standby_bucket?: 'exempted' | 'active' | 'working_set' | 'frequent' | 'rare' | 'restricted';\n /** free space on the storage that holds the app's files */\n disk_free_bytes?: number;\n /** Android 10+ */\n thermal_status?: 'none' | 'light' | 'moderate' | 'severe' | 'critical' | 'emergency' | 'shutdown' | 'unknown';\n manufacturer?: string;\n model?: string;\n /** Android version, e.g. \"14\" */\n os_version?: string;\n sdk_int?: number;\n low_ram_device?: boolean;\n ram_total_bytes?: number;\n}\n\n/** Scheduling metadata of a `heartbeat` record (snake_case = wire format). */\nexport interface HeartbeatMeta {\n strategy: 'exact' | 'listener_with_backup' | 'idle_paced';\n /** heartbeat.minInterval (s) when the heartbeat was created */\n min_interval: number;\n /** heartbeat.maxInterval (s) when the heartbeat was created */\n max_interval: number;\n /** when the next heartbeat is expected (ISO-8601 UTC ms); null if unknown */\n next_at: string | null;\n /** the app is exempt from battery optimization */\n battery_exempt: boolean;\n /** the device was in deep Doze */\n device_idle: boolean;\n}\n\nexport type LocationRecord = Location;\n\nexport interface InsertLocationInput {\n /** `accuracy` (m) is required and must be greater than 0; otherwise the call rejects with `INVALID_ARGUMENT`. */\n coords: Pick<Coords, 'latitude' | 'longitude' | 'accuracy'> & Partial<Coords>;\n timestamp?: string;\n event?: RecordEvent;\n is_moving?: boolean;\n extras?: Record<string, unknown>;\n}\n\n/* ================= GEOFENCES ================= */\n\n/**\n * Either (latitude, longitude, radius) = circle, or vertices = polygon. For polygons, getGeofences() also returns\n * the computed enclosing circle.\n */\nexport interface Geofence {\n identifier: string;\n latitude?: number;\n longitude?: number;\n /** m */\n radius?: number;\n /** [[lat,lng], ...] >= 3 points */\n vertices?: [number, number][];\n /** @default true */\n notifyOnEntry?: boolean;\n /** @default true */\n notifyOnExit?: boolean;\n /** @default false */\n notifyOnDwell?: boolean;\n /**\n * ms\n * @default 30000\n */\n loiteringDelay?: number;\n extras?: Record<string, unknown>;\n}\n\n/* ================= EVENTS ================= */\n\nexport interface MotionChangeEvent {\n isMoving: boolean;\n location: Location;\n}\nexport interface ActivityChangeEvent {\n activity: ActivityType;\n confidence: number;\n}\nexport interface HeartbeatEvent {\n location: Location;\n}\nexport interface GeofenceEvent {\n identifier: string;\n action: GeofenceAction;\n location: Location;\n extras?: Record<string, unknown>;\n}\nexport interface GeofencesChangeEvent {\n on: Geofence[];\n off: string[];\n}\nexport interface HttpEvent {\n success: boolean;\n status: number;\n responseText: string;\n uuids: string[];\n}\nexport interface ConnectivityChangeEvent {\n connected: boolean;\n type: ConnectivityType;\n}\nexport interface PowerSaveChangeEvent {\n isPowerSaveMode: boolean;\n}\nexport interface EnabledChangeEvent {\n enabled: boolean;\n /**\n * why: a `tracking_start` reason when tracking was switched on (start, start_geofences, resume_notification), a\n * `tracking_stop` reason when it was switched off; the same values as `Location.reason`\n */\n reason: string | null;\n}\n/** The location request failed (no permission, Play services or HMS Core refused it, no usable provider). */\nexport interface LocationErrorEvent {\n code: ErrorCode;\n message: string;\n backend: LocationBackend;\n /** the plugin requests location updates again after this many ms; null if it does not */\n retryInMs: number | null;\n}\n/** A record could not be stored because the device storage is full. */\nexport interface StorageFullEvent {\n uuid: string;\n event: RecordEvent;\n diskFreeBytes: number | null;\n}\nexport interface NotificationActionEvent {\n id: string;\n}\nexport interface AuthorizationEvent {\n success: boolean;\n status: number;\n error?: string;\n response?: Record<string, unknown>;\n}\nexport interface LocationTrackingEventMap {\n location: Location;\n motionchange: MotionChangeEvent;\n activitychange: ActivityChangeEvent;\n providerchange: ProviderState;\n heartbeat: HeartbeatEvent;\n geofence: GeofenceEvent;\n geofenceschange: GeofencesChangeEvent;\n http: HttpEvent;\n connectivitychange: ConnectivityChangeEvent;\n powersavechange: PowerSaveChangeEvent;\n enabledchange: EnabledChangeEvent;\n notificationaction: NotificationActionEvent;\n authorization: AuthorizationEvent;\n locationerror: LocationErrorEvent;\n storagefull: StorageFullEvent;\n}\nexport type LocationTrackingEventName = keyof LocationTrackingEventMap;\n\n/* ================= MISC ================= */\n\nexport interface CurrentPositionOptions {\n /** @default 3 */\n samples?: number;\n /**\n * ms\n * @default geolocation.locationTimeout\n */\n timeout?: number;\n /**\n * ms\n * @default 0\n */\n maximumAge?: number;\n /** @default 'high' */\n desiredAccuracy?: DesiredAccuracy;\n /** @default true */\n persist?: boolean;\n extras?: Record<string, unknown>;\n}\n\nexport interface WatchPositionOptions {\n /**\n * ms\n * @default 1000\n */\n interval?: number;\n /** @default 'high' */\n desiredAccuracy?: DesiredAccuracy;\n /** @default false */\n persist?: boolean;\n extras?: Record<string, unknown>;\n}\n\nexport type WatchPositionCallback = (location: Location | null, error?: { code: ErrorCode; message: string }) => void;\n\nexport interface HeartbeatStatus {\n enabled: boolean;\n minInterval: number;\n maxInterval: number;\n lastRecordAt: string | null;\n lastHeartbeatAt: string | null;\n nextHeartbeatAt: string | null;\n strategy: HeartbeatStrategy;\n canScheduleExactAlarms: boolean;\n isIgnoringBatteryOptimizations: boolean;\n isDeviceIdleMode: boolean;\n isPowerSaveMode: boolean;\n pendingHeartbeats: number;\n}\n\nexport interface BatteryOptimizationStatus {\n isIgnoringBatteryOptimizations: boolean;\n canScheduleExactAlarms: boolean;\n isDeviceIdleMode: boolean;\n}\n\nexport interface PowerManagerInfo {\n manufacturer: string;\n available: boolean;\n}\n\nexport interface DeviceInfo {\n platform: 'android' | 'web';\n manufacturer: string;\n model: string;\n brand: string;\n osVersion: string;\n sdkInt: number;\n pluginVersion: string;\n gmsAvailable: boolean;\n hmsAvailable: boolean;\n backend: LocationBackend;\n packagedProviders: string[];\n /** why a better location backend is not used (for example \"gms: unavailable (status 2)\"); null when none is better */\n backendFallbackReason: string | null;\n /** raw GoogleApiAvailability result (0 = success); null if GMS is not packaged or not checked yet */\n gmsStatus: number | null;\n /** raw HuaweiApiAvailability result (0 = success); null if HMS is not packaged or not checked yet */\n hmsStatus: number | null;\n /** true when HMS Core is older than 6.3.0.301; null if HMS is not packaged */\n hmsCoreOutdated: boolean | null;\n /** last LocationAvailability reported by GMS or HMS; only a hint (it can be wrong both ways); null if none */\n locationAvailableHint: boolean | null;\n /** number of CPU cores */\n cpuCores: number;\n /** CPU types (Build.SUPPORTED_ABIS), e.g. [\"arm64-v8a\"] */\n supportedAbis: string[];\n}\n\nexport interface Sensors {\n accelerometer: boolean;\n gyroscope: boolean;\n magnetometer: boolean;\n significantMotion: boolean;\n stepCounter: boolean;\n stepDetector: boolean;\n barometer: boolean;\n}\n\nexport interface PermissionStatus {\n location: PermissionState;\n backgroundLocation: PermissionState;\n activityRecognition: PermissionState;\n notifications: PermissionState;\n}\n\nexport interface LogQuery {\n start?: number;\n end?: number;\n level?: LogLevel;\n limit?: number;\n order?: 'asc' | 'desc';\n}\n\nexport interface LocationTrackingPlugin {\n /** Loads persisted config and state. Must resolve before most other methods (see NOT_READY rule). */\n ready(options?: ReadyOptions): Promise<State>;\n /** deep merge; arrays replaced; null resets key to default */\n setConfig(options: { config: Config }): Promise<State>;\n /** Resets the config to defaults, then applies the given config. */\n reset(options?: { config?: Config }): Promise<State>;\n getState(): Promise<State>;\n /** Starts location tracking (mode 'location'). */\n start(): Promise<State>;\n /** Starts geofence-only tracking (mode 'geofences'). */\n startGeofences(): Promise<State>;\n stop(): Promise<State>;\n /** Forces the motion state to moving or stationary. */\n changePace(options: { isMoving: boolean }): Promise<void>;\n\n getCurrentPosition(options?: CurrentPositionOptions): Promise<Location>;\n watchPosition(options: WatchPositionOptions, callback: WatchPositionCallback): Promise<CallbackID>;\n clearWatch(options: { id: CallbackID }): Promise<void>;\n\n getOdometer(): Promise<{ odometer: number }>;\n setOdometer(options: { odometer: number }): Promise<{ odometer: number }>;\n resetOdometer(): Promise<{ odometer: number }>;\n\n getLocations(options?: { limit?: number }): Promise<{ locations: Location[] }>;\n getCount(): Promise<{ count: number }>;\n insertLocation(options: { location: InsertLocationInput }): Promise<{ uuid: string }>;\n destroyLocations(): Promise<{ count: number }>;\n destroyLocation(options: { uuid: string }): Promise<{ deleted: boolean }>;\n /** uploads whole queue now; resolves with uploaded records */\n sync(): Promise<{ locations: Location[] }>;\n\n addGeofence(options: { geofence: Geofence }): Promise<void>;\n addGeofences(options: { geofences: Geofence[] }): Promise<void>;\n removeGeofence(options: { identifier: string }): Promise<void>;\n /** identifiers omitted (or null) = remove all; an empty array removes nothing */\n removeGeofences(options?: { identifiers?: string[] }): Promise<void>;\n getGeofences(): Promise<{ geofences: Geofence[] }>;\n getGeofence(options: { identifier: string }): Promise<{ geofence: Geofence | null }>;\n geofenceExists(options: { identifier: string }): Promise<{ exists: boolean }>;\n\n getHeartbeatStatus(): Promise<HeartbeatStatus>;\n\n getProviderState(): Promise<ProviderState>;\n isPowerSaveMode(): Promise<{ isPowerSaveMode: boolean }>;\n getBatteryOptimizationStatus(): Promise<BatteryOptimizationStatus>;\n openBatteryOptimizationSettings(): Promise<{ opened: boolean }>;\n getPowerManagerInfo(): Promise<PowerManagerInfo>;\n openPowerManagerSettings(): Promise<{ opened: boolean }>;\n openLocationSettings(): Promise<{ opened: boolean }>;\n openAppSettings(): Promise<{ opened: boolean }>;\n getDeviceInfo(): Promise<DeviceInfo>;\n getSensors(): Promise<Sensors>;\n\n checkPermissions(): Promise<PermissionStatus>;\n /** default all four, order: location, notifications, activityRecognition, backgroundLocation */\n requestPermissions(options?: { permissions?: PermissionType[] }): Promise<PermissionStatus>;\n\n log(options: { level: Exclude<LogLevel, 'off'>; message: string }): Promise<void>;\n getLog(options?: LogQuery): Promise<{ log: string }>;\n destroyLog(): Promise<void>;\n uploadLog(options: {\n url: string;\n headers?: Record<string, string>;\n params?: Record<string, unknown>;\n }): Promise<{ success: boolean; status: number }>;\n emailLog(options: { email: string; subject?: string }): Promise<void>;\n\n addListener(eventName: 'location', listenerFunc: (e: Location) => void): Promise<PluginListenerHandle>;\n addListener(eventName: 'motionchange', listenerFunc: (e: MotionChangeEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'activitychange',\n listenerFunc: (e: ActivityChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'providerchange', listenerFunc: (e: ProviderState) => void): Promise<PluginListenerHandle>;\n addListener(eventName: 'heartbeat', listenerFunc: (e: HeartbeatEvent) => void): Promise<PluginListenerHandle>;\n addListener(eventName: 'geofence', listenerFunc: (e: GeofenceEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'geofenceschange',\n listenerFunc: (e: GeofencesChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'http', listenerFunc: (e: HttpEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'connectivitychange',\n listenerFunc: (e: ConnectivityChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'powersavechange',\n listenerFunc: (e: PowerSaveChangeEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'enabledchange', listenerFunc: (e: EnabledChangeEvent) => void): Promise<PluginListenerHandle>;\n addListener(\n eventName: 'notificationaction',\n listenerFunc: (e: NotificationActionEvent) => void,\n ): Promise<PluginListenerHandle>;\n addListener(eventName: 'authorization', listenerFunc: (e: AuthorizationEvent) => void): Promise<PluginListenerHandle>;\n addListener(eventName: 'locationerror', listenerFunc: (e: LocationErrorEvent) => void): Promise<PluginListenerHandle>;\n addListener(eventName: 'storagefull', listenerFunc: (e: StorageFullEvent) => void): Promise<PluginListenerHandle>;\n removeAllListeners(): Promise<void>;\n}\n"]}
|
package/dist/esm/events.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { PluginListenerHandle } from '@capacitor/core';
|
|
2
|
-
import type { ActivityChangeEvent, AuthorizationEvent, ConnectivityChangeEvent, EnabledChangeEvent, GeofenceEvent, GeofencesChangeEvent, HeartbeatEvent, HttpEvent, Location, LocationTrackingEventMap, LocationTrackingEventName, MotionChangeEvent, NotificationActionEvent, PowerSaveChangeEvent, ProviderState } from './definitions';
|
|
2
|
+
import type { ActivityChangeEvent, AuthorizationEvent, ConnectivityChangeEvent, EnabledChangeEvent, GeofenceEvent, GeofencesChangeEvent, HeartbeatEvent, HttpEvent, Location, LocationErrorEvent, LocationTrackingEventMap, LocationTrackingEventName, MotionChangeEvent, NotificationActionEvent, PowerSaveChangeEvent, ProviderState, StorageFullEvent } from './definitions';
|
|
3
3
|
/** Names of every event emitted by the plugin. */
|
|
4
4
|
export declare const Events: {
|
|
5
5
|
readonly LOCATION: "location";
|
|
@@ -15,6 +15,8 @@ export declare const Events: {
|
|
|
15
15
|
readonly ENABLEDCHANGE: "enabledchange";
|
|
16
16
|
readonly NOTIFICATIONACTION: "notificationaction";
|
|
17
17
|
readonly AUTHORIZATION: "authorization";
|
|
18
|
+
readonly LOCATIONERROR: "locationerror";
|
|
19
|
+
readonly STORAGEFULL: "storagefull";
|
|
18
20
|
};
|
|
19
21
|
/**
|
|
20
22
|
* Subscribes to any plugin event with a typed payload. Call `remove()` on the resolved handle to unsubscribe.
|
|
@@ -42,9 +44,13 @@ export declare const onHttp: (cb: (e: HttpEvent) => void) => Promise<PluginListe
|
|
|
42
44
|
export declare const onConnectivityChange: (cb: (e: ConnectivityChangeEvent) => void) => Promise<PluginListenerHandle>;
|
|
43
45
|
/** Battery-saver mode changes. */
|
|
44
46
|
export declare const onPowerSaveChange: (cb: (e: PowerSaveChangeEvent) => void) => Promise<PluginListenerHandle>;
|
|
45
|
-
/** Tracking enabled / disabled. */
|
|
47
|
+
/** Tracking enabled / disabled, with the reason (the same values as the tracking_start / tracking_stop records). */
|
|
46
48
|
export declare const onEnabledChange: (cb: (e: EnabledChangeEvent) => void) => Promise<PluginListenerHandle>;
|
|
47
49
|
/** Taps on the foreground notification's action buttons. */
|
|
48
50
|
export declare const onNotificationAction: (cb: (e: NotificationActionEvent) => void) => Promise<PluginListenerHandle>;
|
|
49
51
|
/** JWT refresh results. */
|
|
50
52
|
export declare const onAuthorization: (cb: (e: AuthorizationEvent) => void) => Promise<PluginListenerHandle>;
|
|
53
|
+
/** The location request failed; the plugin requests updates again after `retryInMs`. */
|
|
54
|
+
export declare const onLocationError: (cb: (e: LocationErrorEvent) => void) => Promise<PluginListenerHandle>;
|
|
55
|
+
/** A record could not be stored because the device storage is full. */
|
|
56
|
+
export declare const onStorageFull: (cb: (e: StorageFullEvent) => void) => Promise<PluginListenerHandle>;
|
package/dist/esm/events.js
CHANGED
|
@@ -14,6 +14,8 @@ export const Events = {
|
|
|
14
14
|
ENABLEDCHANGE: 'enabledchange',
|
|
15
15
|
NOTIFICATIONACTION: 'notificationaction',
|
|
16
16
|
AUTHORIZATION: 'authorization',
|
|
17
|
+
LOCATIONERROR: 'locationerror',
|
|
18
|
+
STORAGEFULL: 'storagefull',
|
|
17
19
|
};
|
|
18
20
|
/**
|
|
19
21
|
* Subscribes to any plugin event with a typed payload. Call `remove()` on the resolved handle to unsubscribe.
|
|
@@ -43,10 +45,14 @@ export const onHttp = (cb) => on('http', cb);
|
|
|
43
45
|
export const onConnectivityChange = (cb) => on('connectivitychange', cb);
|
|
44
46
|
/** Battery-saver mode changes. */
|
|
45
47
|
export const onPowerSaveChange = (cb) => on('powersavechange', cb);
|
|
46
|
-
/** Tracking enabled / disabled. */
|
|
48
|
+
/** Tracking enabled / disabled, with the reason (the same values as the tracking_start / tracking_stop records). */
|
|
47
49
|
export const onEnabledChange = (cb) => on('enabledchange', cb);
|
|
48
50
|
/** Taps on the foreground notification's action buttons. */
|
|
49
51
|
export const onNotificationAction = (cb) => on('notificationaction', cb);
|
|
50
52
|
/** JWT refresh results. */
|
|
51
53
|
export const onAuthorization = (cb) => on('authorization', cb);
|
|
54
|
+
/** The location request failed; the plugin requests updates again after `retryInMs`. */
|
|
55
|
+
export const onLocationError = (cb) => on('locationerror', cb);
|
|
56
|
+
/** A record could not be stored because the device storage is full. */
|
|
57
|
+
export const onStorageFull = (cb) => on('storagefull', cb);
|
|
52
58
|
//# sourceMappingURL=events.js.map
|
package/dist/esm/events.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"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","sourcesContent":["// Owned by Unit 1 (TS wrapper + web).\nimport type { PluginListenerHandle } from '@capacitor/core';\n\nimport type {\n ActivityChangeEvent,\n AuthorizationEvent,\n ConnectivityChangeEvent,\n EnabledChangeEvent,\n GeofenceEvent,\n GeofencesChangeEvent,\n HeartbeatEvent,\n HttpEvent,\n Location,\n LocationErrorEvent,\n LocationTrackingEventMap,\n LocationTrackingEventName,\n MotionChangeEvent,\n NotificationActionEvent,\n PowerSaveChangeEvent,\n ProviderState,\n StorageFullEvent,\n} from './definitions';\nimport { LocationTracking } from './plugin';\n\n/** Names of every event emitted by the plugin. */\nexport const Events = {\n LOCATION: 'location',\n MOTIONCHANGE: 'motionchange',\n ACTIVITYCHANGE: 'activitychange',\n PROVIDERCHANGE: 'providerchange',\n HEARTBEAT: 'heartbeat',\n GEOFENCE: 'geofence',\n GEOFENCESCHANGE: 'geofenceschange',\n HTTP: 'http',\n CONNECTIVITYCHANGE: 'connectivitychange',\n POWERSAVECHANGE: 'powersavechange',\n ENABLEDCHANGE: 'enabledchange',\n NOTIFICATIONACTION: 'notificationaction',\n AUTHORIZATION: 'authorization',\n LOCATIONERROR: 'locationerror',\n STORAGEFULL: 'storagefull',\n} as const;\n\ninterface UntypedListenerTarget {\n addListener(eventName: string, listenerFunc: (event: any) => void): Promise<PluginListenerHandle>;\n}\n\n/**\n * Subscribes to any plugin event with a typed payload. Call `remove()` on the resolved handle to unsubscribe.\n * The helpers below are standalone functions on purpose: Capacitor's plugin proxy turns unknown properties of\n * `LocationTracking` into native calls, so nothing is attached to it.\n */\nexport function on<K extends LocationTrackingEventName>(\n name: K,\n callback: (event: LocationTrackingEventMap[K]) => void,\n): Promise<PluginListenerHandle> {\n return (LocationTracking as unknown as UntypedListenerTarget).addListener(name, callback);\n}\n\n/** Every recorded location, including persisted `current_position` / `watch_position` fixes and motion changes. */\nexport const onLocation = (cb: (e: Location) => void): Promise<PluginListenerHandle> => on('location', cb);\n/** Moving / stationary transitions, with the fix at the moment of the change. */\nexport const onMotionChange = (cb: (e: MotionChangeEvent) => void): Promise<PluginListenerHandle> =>\n on('motionchange', cb);\n/** Detected activity (still, walking, in_vehicle, ...). */\nexport const onActivityChange = (cb: (e: ActivityChangeEvent) => void): Promise<PluginListenerHandle> =>\n on('activitychange', cb);\n/** Location services or permission changes. */\nexport const onProviderChange = (cb: (e: ProviderState) => void): Promise<PluginListenerHandle> =>\n on('providerchange', cb);\n/** Heartbeat records, created when no record was made for `heartbeat.minInterval` seconds while tracking. */\nexport const onHeartbeat = (cb: (e: HeartbeatEvent) => void): Promise<PluginListenerHandle> => on('heartbeat', cb);\n/** Geofence ENTER / EXIT / DWELL transitions. */\nexport const onGeofence = (cb: (e: GeofenceEvent) => void): Promise<PluginListenerHandle> => on('geofence', cb);\n/** Geofences added to or removed from monitoring. */\nexport const onGeofencesChange = (cb: (e: GeofencesChangeEvent) => void): Promise<PluginListenerHandle> =>\n on('geofenceschange', cb);\n/** Result of every HTTP upload request. */\nexport const onHttp = (cb: (e: HttpEvent) => void): Promise<PluginListenerHandle> => on('http', cb);\n/** Network connectivity changes. */\nexport const onConnectivityChange = (cb: (e: ConnectivityChangeEvent) => void): Promise<PluginListenerHandle> =>\n on('connectivitychange', cb);\n/** Battery-saver mode changes. */\nexport const onPowerSaveChange = (cb: (e: PowerSaveChangeEvent) => void): Promise<PluginListenerHandle> =>\n on('powersavechange', cb);\n/** Tracking enabled / disabled, with the reason (the same values as the tracking_start / tracking_stop records). */\nexport const onEnabledChange = (cb: (e: EnabledChangeEvent) => void): Promise<PluginListenerHandle> =>\n on('enabledchange', cb);\n/** Taps on the foreground notification's action buttons. */\nexport const onNotificationAction = (cb: (e: NotificationActionEvent) => void): Promise<PluginListenerHandle> =>\n on('notificationaction', cb);\n/** JWT refresh results. */\nexport const onAuthorization = (cb: (e: AuthorizationEvent) => void): Promise<PluginListenerHandle> =>\n on('authorization', cb);\n/** The location request failed; the plugin requests updates again after `retryInMs`. */\nexport const onLocationError = (cb: (e: LocationErrorEvent) => void): Promise<PluginListenerHandle> =>\n on('locationerror', cb);\n/** A record could not be stored because the device storage is full. */\nexport const onStorageFull = (cb: (e: StorageFullEvent) => void): Promise<PluginListenerHandle> =>\n on('storagefull', cb);\n"]}
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export * from './definitions';
|
|
2
2
|
export { LocationTracking } from './plugin';
|
|
3
|
-
export { Events, on, onActivityChange, onAuthorization, onConnectivityChange, onEnabledChange, onGeofence, onGeofencesChange, onHeartbeat, onHttp, onLocation, onMotionChange, onNotificationAction, onPowerSaveChange, onProviderChange, } from './events';
|
|
3
|
+
export { Events, on, onActivityChange, onAuthorization, onConnectivityChange, onEnabledChange, onGeofence, onGeofencesChange, onHeartbeat, onHttp, onLocation, onLocationError, onMotionChange, onNotificationAction, onPowerSaveChange, onProviderChange, onStorageFull, } from './events';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Owned by Unit 1 (TS wrapper + web).
|
|
2
2
|
export * from './definitions';
|
|
3
3
|
export { LocationTracking } from './plugin';
|
|
4
|
-
export { Events, on, onActivityChange, onAuthorization, onConnectivityChange, onEnabledChange, onGeofence, onGeofencesChange, onHeartbeat, onHttp, onLocation, onMotionChange, onNotificationAction, onPowerSaveChange, onProviderChange, } from './events';
|
|
4
|
+
export { Events, on, onActivityChange, onAuthorization, onConnectivityChange, onEnabledChange, onGeofence, onGeofencesChange, onHeartbeat, onHttp, onLocation, onLocationError, onMotionChange, onNotificationAction, onPowerSaveChange, onProviderChange, onStorageFull, } from './events';
|
|
5
5
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EACL,MAAM,EACN,EAAE,EACF,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,MAAM,EACN,UAAU,EACV,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,cAAc,eAAe,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,EACL,MAAM,EACN,EAAE,EACF,gBAAgB,EAChB,eAAe,EACf,oBAAoB,EACpB,eAAe,EACf,UAAU,EACV,iBAAiB,EACjB,WAAW,EACX,MAAM,EACN,UAAU,EACV,eAAe,EACf,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,GACd,MAAM,UAAU,CAAC","sourcesContent":["// Owned by Unit 1 (TS wrapper + web).\nexport * from './definitions';\nexport { LocationTracking } from './plugin';\nexport {\n Events,\n on,\n onActivityChange,\n onAuthorization,\n onConnectivityChange,\n onEnabledChange,\n onGeofence,\n onGeofencesChange,\n onHeartbeat,\n onHttp,\n onLocation,\n onLocationError,\n onMotionChange,\n onNotificationAction,\n onPowerSaveChange,\n onProviderChange,\n onStorageFull,\n} from './events';\n"]}
|
package/dist/esm/web/config.js
CHANGED
|
@@ -48,6 +48,7 @@ export function defaultConfig() {
|
|
|
48
48
|
enabled: true,
|
|
49
49
|
minInterval: 180,
|
|
50
50
|
maxInterval: 300,
|
|
51
|
+
uploadKeepAwake: 10,
|
|
51
52
|
},
|
|
52
53
|
http: {
|
|
53
54
|
url: null,
|
|
@@ -64,6 +65,7 @@ export function defaultConfig() {
|
|
|
64
65
|
locationTemplate: null,
|
|
65
66
|
geofenceTemplate: null,
|
|
66
67
|
timeout: 60000,
|
|
68
|
+
maxRetryAfter: 3600,
|
|
67
69
|
authorization: null,
|
|
68
70
|
},
|
|
69
71
|
persistence: {
|
|
@@ -197,6 +199,9 @@ function clamp(config) {
|
|
|
197
199
|
heartbeat.maxInterval < heartbeat.minInterval) {
|
|
198
200
|
heartbeat.maxInterval = heartbeat.minInterval;
|
|
199
201
|
}
|
|
202
|
+
if (typeof heartbeat.uploadKeepAwake === 'number') {
|
|
203
|
+
heartbeat.uploadKeepAwake = Math.min(60, Math.max(0, heartbeat.uploadKeepAwake));
|
|
204
|
+
}
|
|
200
205
|
}
|
|
201
206
|
const activity = config.activity;
|
|
202
207
|
if (activity && typeof activity.minimumActivityRecognitionConfidence === 'number') {
|
|
@@ -209,6 +214,9 @@ function clamp(config) {
|
|
|
209
214
|
if (http && typeof http.syncInterval === 'number' && http.syncInterval < 0) {
|
|
210
215
|
http.syncInterval = 0;
|
|
211
216
|
}
|
|
217
|
+
if (http && typeof http.maxRetryAfter === 'number' && http.maxRetryAfter < 0) {
|
|
218
|
+
http.maxRetryAfter = 0;
|
|
219
|
+
}
|
|
212
220
|
const notification = config.notification;
|
|
213
221
|
if (notification && Array.isArray(notification.actions) && notification.actions.length > 3) {
|
|
214
222
|
notification.actions = notification.actions.slice(0, 3);
|
|
@@ -237,6 +245,8 @@ export function webState(config) {
|
|
|
237
245
|
odometer: 0,
|
|
238
246
|
backend: 'web',
|
|
239
247
|
lastRecordAt: null,
|
|
248
|
+
lastStopReason: null,
|
|
249
|
+
lastStopAt: null,
|
|
240
250
|
config: cloneJson(config),
|
|
241
251
|
};
|
|
242
252
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/web/config.ts"],"names":[],"mappings":"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","sourcesContent":["// Owned by Unit 1 (TS wrapper + web).\nimport type { AuthorizationConfig, Config, State } from '../definitions';\n\ntype JsonObject = Record<string, unknown>;\n\n/** Never copied: assigning `__proto__` would change the target's prototype instead of adding a key. */\nconst PROTO_KEY = '__proto__';\n\n/** Free-form maps. They are config values, not sections: a new value replaces the old one instead of merging. */\nconst MAP_VALUES = [\n 'http.headers',\n 'http.params',\n 'persistence.extras',\n 'http.authorization.refreshPayload',\n 'http.authorization.refreshHeaders',\n];\n\n/** Sections whose own default is `null`. `null` resets them to `null`; setting them fills in their field defaults. */\nconst NULLABLE_SECTIONS = ['http.authorization'];\n\n/**\n * Every documented `@default` of {@link Config}, mirroring the Android `Config` model.\n * Keys without a default (for example `notification.title`, which falls back to the app label) are left out.\n */\nexport function defaultConfig(): Config {\n return {\n geolocation: {\n desiredAccuracy: 'high',\n distanceFilter: 10,\n locationUpdateInterval: 1000,\n fastestLocationUpdateInterval: 500,\n disableElasticity: false,\n elasticityMultiplier: 1,\n stationaryRadius: 25,\n stopTimeout: 5,\n stopAfterElapsedMinutes: 0,\n stopOnStationary: false,\n locationTimeout: 30000,\n filter: {\n useKalman: false,\n trackingAccuracyThreshold: 100,\n maxImpliedSpeed: 80,\n odometerAccuracyThreshold: 20,\n allowIdenticalLocations: false,\n rejectMockLocations: false,\n },\n },\n activity: {\n disableMotionActivityUpdates: false,\n activityRecognitionInterval: 10000,\n minimumActivityRecognitionConfidence: 75,\n motionTriggerDelay: 0,\n disableStopDetection: false,\n },\n heartbeat: {\n enabled: true,\n minInterval: 180,\n maxInterval: 300,\n },\n http: {\n url: null,\n method: 'POST',\n headers: {},\n params: {},\n autoSync: true,\n autoSyncThreshold: 0,\n syncInterval: 0,\n batchSync: false,\n maxBatchSize: 100,\n disableAutoSyncOnCellular: false,\n rootProperty: 'location',\n locationTemplate: null,\n geofenceTemplate: null,\n timeout: 60000,\n authorization: null,\n },\n persistence: {\n maxDaysToPersist: 7,\n maxRecordsToPersist: -1,\n extras: {},\n },\n app: {\n stopOnTerminate: true,\n startOnBoot: false,\n },\n notification: {\n text: 'Location tracking is active',\n smallIcon: 'drawable/lt_ic_notification',\n priority: 'default',\n channelId: 'location_tracking',\n channelName: 'Location tracking',\n actions: [],\n resume: {\n enabled: false,\n text: 'Location tracking is paused. Tap to resume.',\n channelName: 'Paused location tracking',\n },\n },\n geofence: {\n initialTriggerEntry: true,\n },\n logger: {\n logLevel: 'info',\n logMaxDays: 3,\n },\n backgroundPermissionRationale: {},\n locationProvider: 'auto',\n };\n}\n\n/** Field defaults of `http.authorization`, applied once it is set (the section itself defaults to `null`). */\nfunction defaultAuthorization(): AuthorizationConfig {\n return {\n strategy: 'JWT',\n refreshPayload: {},\n refreshHeaders: {},\n refreshPayloadEncoding: 'json',\n expires: -1,\n };\n}\n\ninterface DefaultTrees {\n /** The real defaults (`http.authorization` is `null`). */\n values: JsonObject;\n /** The defaults with nullable sections filled in, used to find sections and the defaults of their fields. */\n sections: JsonObject;\n}\n\nfunction defaultTrees(): DefaultTrees {\n const sections = defaultConfig() as unknown as JsonObject;\n (sections.http as JsonObject).authorization = defaultAuthorization();\n return { values: defaultConfig() as unknown as JsonObject, sections };\n}\n\nexport function isPlainObject(value: unknown): value is JsonObject {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n\n/** Deep copy of JSON-like data (plain objects, arrays and primitives). */\nexport function cloneJson<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map((item) => cloneJson(item)) as unknown as T;\n }\n if (isPlainObject(value)) {\n const copy: JsonObject = {};\n for (const key of Object.keys(value)) {\n if (key !== PROTO_KEY) {\n copy[key] = cloneJson(value[key]);\n }\n }\n return copy as T;\n }\n return value;\n}\n\nfunction lookup(tree: JsonObject, path: string[]): unknown {\n let node: unknown = tree;\n for (const key of path) {\n if (!isPlainObject(node)) {\n return undefined;\n }\n node = node[key];\n }\n return node;\n}\n\nfunction hasValue(patch: JsonObject): boolean {\n return Object.keys(patch).some((key) => patch[key] !== undefined && patch[key] !== null);\n}\n\nfunction mergeInto(target: JsonObject, patch: JsonObject, path: string[], trees: DefaultTrees): void {\n for (const key of Object.keys(patch)) {\n const value = patch[key];\n if (value === undefined || key === PROTO_KEY) {\n continue;\n }\n const childPath = path.concat(key);\n const dotted = childPath.join('.');\n const sectionDefaults = lookup(trees.sections, childPath);\n const isSection = isPlainObject(sectionDefaults) && MAP_VALUES.indexOf(dotted) < 0;\n\n if (value === null) {\n // null resets the key to its default (fields of a null section use the section's field defaults);\n // keys without a default are removed.\n const own = lookup(trees.values, childPath);\n const reset = own !== undefined ? own : sectionDefaults;\n if (reset === undefined) {\n delete target[key];\n } else {\n target[key] = cloneJson(reset);\n }\n } else if (isSection) {\n // A section only accepts an object; anything else is ignored so the section stays fully populated.\n const current = target[key];\n // A null section is only switched on by a patch that sets something.\n const staysNull = NULLABLE_SECTIONS.indexOf(dotted) >= 0 && current === null && !hasValue(value as JsonObject);\n if (isPlainObject(value) && !staysNull) {\n const base = isPlainObject(current) ? current : (cloneJson(sectionDefaults) as JsonObject);\n mergeInto(base, value as JsonObject, childPath, trees);\n target[key] = base;\n }\n } else {\n // Arrays, maps and scalar values are replaced.\n target[key] = cloneJson(value);\n }\n }\n}\n\n/** The same clamps the Android config validator applies. */\nfunction clamp(config: Config): void {\n const heartbeat = config.heartbeat;\n if (heartbeat) {\n if (typeof heartbeat.minInterval === 'number' && heartbeat.minInterval < 60) {\n heartbeat.minInterval = 60;\n }\n if (\n typeof heartbeat.minInterval === 'number' &&\n typeof heartbeat.maxInterval === 'number' &&\n heartbeat.maxInterval < heartbeat.minInterval\n ) {\n heartbeat.maxInterval = heartbeat.minInterval;\n }\n }\n const activity = config.activity;\n if (activity && typeof activity.minimumActivityRecognitionConfidence === 'number') {\n activity.minimumActivityRecognitionConfidence = Math.min(\n 100,\n Math.max(0, activity.minimumActivityRecognitionConfidence),\n );\n }\n const http = config.http;\n if (http && typeof http.maxBatchSize === 'number' && http.maxBatchSize < 1) {\n http.maxBatchSize = 1;\n }\n if (http && typeof http.syncInterval === 'number' && http.syncInterval < 0) {\n http.syncInterval = 0;\n }\n const notification = config.notification;\n if (notification && Array.isArray(notification.actions) && notification.actions.length > 3) {\n notification.actions = notification.actions.slice(0, 3);\n }\n}\n\n/**\n * Returns `base` deep-merged with `patch`, without changing either.\n * - Sections are merged key by key; arrays, maps (`headers`, `params`, `extras`, ...) and scalars are replaced.\n * - `null` resets a key to its default (`http.authorization` resets to `null`); `undefined` is ignored.\n */\nexport function mergeConfig(base: Config, patch: Config | undefined): Config {\n const result = cloneJson(base) as unknown as JsonObject;\n if (patch) {\n mergeInto(result, patch as unknown as JsonObject, [], defaultTrees());\n }\n const config = result as unknown as Config;\n clamp(config);\n return config;\n}\n\n/** The web `State`: tracking is never enabled on web, and nothing is recorded or persisted. */\nexport function webState(config: Config): State {\n return {\n enabled: false,\n trackingMode: 'location',\n isMoving: false,\n odometer: 0,\n backend: 'web',\n lastRecordAt: null,\n config: cloneJson(config),\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/web/config.ts"],"names":[],"mappings":"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","sourcesContent":["// Owned by Unit 1 (TS wrapper + web).\nimport type { AuthorizationConfig, Config, State } from '../definitions';\n\ntype JsonObject = Record<string, unknown>;\n\n/** Never copied: assigning `__proto__` would change the target's prototype instead of adding a key. */\nconst PROTO_KEY = '__proto__';\n\n/** Free-form maps. They are config values, not sections: a new value replaces the old one instead of merging. */\nconst MAP_VALUES = [\n 'http.headers',\n 'http.params',\n 'persistence.extras',\n 'http.authorization.refreshPayload',\n 'http.authorization.refreshHeaders',\n];\n\n/** Sections whose own default is `null`. `null` resets them to `null`; setting them fills in their field defaults. */\nconst NULLABLE_SECTIONS = ['http.authorization'];\n\n/**\n * Every documented `@default` of {@link Config}, mirroring the Android `Config` model.\n * Keys without a default (for example `notification.title`, which falls back to the app label) are left out.\n */\nexport function defaultConfig(): Config {\n return {\n geolocation: {\n desiredAccuracy: 'high',\n distanceFilter: 10,\n locationUpdateInterval: 1000,\n fastestLocationUpdateInterval: 500,\n disableElasticity: false,\n elasticityMultiplier: 1,\n stationaryRadius: 25,\n stopTimeout: 5,\n stopAfterElapsedMinutes: 0,\n stopOnStationary: false,\n locationTimeout: 30000,\n filter: {\n useKalman: false,\n trackingAccuracyThreshold: 100,\n maxImpliedSpeed: 80,\n odometerAccuracyThreshold: 20,\n allowIdenticalLocations: false,\n rejectMockLocations: false,\n },\n },\n activity: {\n disableMotionActivityUpdates: false,\n activityRecognitionInterval: 10000,\n minimumActivityRecognitionConfidence: 75,\n motionTriggerDelay: 0,\n disableStopDetection: false,\n },\n heartbeat: {\n enabled: true,\n minInterval: 180,\n maxInterval: 300,\n uploadKeepAwake: 10,\n },\n http: {\n url: null,\n method: 'POST',\n headers: {},\n params: {},\n autoSync: true,\n autoSyncThreshold: 0,\n syncInterval: 0,\n batchSync: false,\n maxBatchSize: 100,\n disableAutoSyncOnCellular: false,\n rootProperty: 'location',\n locationTemplate: null,\n geofenceTemplate: null,\n timeout: 60000,\n maxRetryAfter: 3600,\n authorization: null,\n },\n persistence: {\n maxDaysToPersist: 7,\n maxRecordsToPersist: -1,\n extras: {},\n },\n app: {\n stopOnTerminate: true,\n startOnBoot: false,\n },\n notification: {\n text: 'Location tracking is active',\n smallIcon: 'drawable/lt_ic_notification',\n priority: 'default',\n channelId: 'location_tracking',\n channelName: 'Location tracking',\n actions: [],\n resume: {\n enabled: false,\n text: 'Location tracking is paused. Tap to resume.',\n channelName: 'Paused location tracking',\n },\n },\n geofence: {\n initialTriggerEntry: true,\n },\n logger: {\n logLevel: 'info',\n logMaxDays: 3,\n },\n backgroundPermissionRationale: {},\n locationProvider: 'auto',\n };\n}\n\n/** Field defaults of `http.authorization`, applied once it is set (the section itself defaults to `null`). */\nfunction defaultAuthorization(): AuthorizationConfig {\n return {\n strategy: 'JWT',\n refreshPayload: {},\n refreshHeaders: {},\n refreshPayloadEncoding: 'json',\n expires: -1,\n };\n}\n\ninterface DefaultTrees {\n /** The real defaults (`http.authorization` is `null`). */\n values: JsonObject;\n /** The defaults with nullable sections filled in, used to find sections and the defaults of their fields. */\n sections: JsonObject;\n}\n\nfunction defaultTrees(): DefaultTrees {\n const sections = defaultConfig() as unknown as JsonObject;\n (sections.http as JsonObject).authorization = defaultAuthorization();\n return { values: defaultConfig() as unknown as JsonObject, sections };\n}\n\nexport function isPlainObject(value: unknown): value is JsonObject {\n return Object.prototype.toString.call(value) === '[object Object]';\n}\n\n/** Deep copy of JSON-like data (plain objects, arrays and primitives). */\nexport function cloneJson<T>(value: T): T {\n if (Array.isArray(value)) {\n return value.map((item) => cloneJson(item)) as unknown as T;\n }\n if (isPlainObject(value)) {\n const copy: JsonObject = {};\n for (const key of Object.keys(value)) {\n if (key !== PROTO_KEY) {\n copy[key] = cloneJson(value[key]);\n }\n }\n return copy as T;\n }\n return value;\n}\n\nfunction lookup(tree: JsonObject, path: string[]): unknown {\n let node: unknown = tree;\n for (const key of path) {\n if (!isPlainObject(node)) {\n return undefined;\n }\n node = node[key];\n }\n return node;\n}\n\nfunction hasValue(patch: JsonObject): boolean {\n return Object.keys(patch).some((key) => patch[key] !== undefined && patch[key] !== null);\n}\n\nfunction mergeInto(target: JsonObject, patch: JsonObject, path: string[], trees: DefaultTrees): void {\n for (const key of Object.keys(patch)) {\n const value = patch[key];\n if (value === undefined || key === PROTO_KEY) {\n continue;\n }\n const childPath = path.concat(key);\n const dotted = childPath.join('.');\n const sectionDefaults = lookup(trees.sections, childPath);\n const isSection = isPlainObject(sectionDefaults) && MAP_VALUES.indexOf(dotted) < 0;\n\n if (value === null) {\n // null resets the key to its default (fields of a null section use the section's field defaults);\n // keys without a default are removed.\n const own = lookup(trees.values, childPath);\n const reset = own !== undefined ? own : sectionDefaults;\n if (reset === undefined) {\n delete target[key];\n } else {\n target[key] = cloneJson(reset);\n }\n } else if (isSection) {\n // A section only accepts an object; anything else is ignored so the section stays fully populated.\n const current = target[key];\n // A null section is only switched on by a patch that sets something.\n const staysNull = NULLABLE_SECTIONS.indexOf(dotted) >= 0 && current === null && !hasValue(value as JsonObject);\n if (isPlainObject(value) && !staysNull) {\n const base = isPlainObject(current) ? current : (cloneJson(sectionDefaults) as JsonObject);\n mergeInto(base, value as JsonObject, childPath, trees);\n target[key] = base;\n }\n } else {\n // Arrays, maps and scalar values are replaced.\n target[key] = cloneJson(value);\n }\n }\n}\n\n/** The same clamps the Android config validator applies. */\nfunction clamp(config: Config): void {\n const heartbeat = config.heartbeat;\n if (heartbeat) {\n if (typeof heartbeat.minInterval === 'number' && heartbeat.minInterval < 60) {\n heartbeat.minInterval = 60;\n }\n if (\n typeof heartbeat.minInterval === 'number' &&\n typeof heartbeat.maxInterval === 'number' &&\n heartbeat.maxInterval < heartbeat.minInterval\n ) {\n heartbeat.maxInterval = heartbeat.minInterval;\n }\n if (typeof heartbeat.uploadKeepAwake === 'number') {\n heartbeat.uploadKeepAwake = Math.min(60, Math.max(0, heartbeat.uploadKeepAwake));\n }\n }\n const activity = config.activity;\n if (activity && typeof activity.minimumActivityRecognitionConfidence === 'number') {\n activity.minimumActivityRecognitionConfidence = Math.min(\n 100,\n Math.max(0, activity.minimumActivityRecognitionConfidence),\n );\n }\n const http = config.http;\n if (http && typeof http.maxBatchSize === 'number' && http.maxBatchSize < 1) {\n http.maxBatchSize = 1;\n }\n if (http && typeof http.syncInterval === 'number' && http.syncInterval < 0) {\n http.syncInterval = 0;\n }\n if (http && typeof http.maxRetryAfter === 'number' && http.maxRetryAfter < 0) {\n http.maxRetryAfter = 0;\n }\n const notification = config.notification;\n if (notification && Array.isArray(notification.actions) && notification.actions.length > 3) {\n notification.actions = notification.actions.slice(0, 3);\n }\n}\n\n/**\n * Returns `base` deep-merged with `patch`, without changing either.\n * - Sections are merged key by key; arrays, maps (`headers`, `params`, `extras`, ...) and scalars are replaced.\n * - `null` resets a key to its default (`http.authorization` resets to `null`); `undefined` is ignored.\n */\nexport function mergeConfig(base: Config, patch: Config | undefined): Config {\n const result = cloneJson(base) as unknown as JsonObject;\n if (patch) {\n mergeInto(result, patch as unknown as JsonObject, [], defaultTrees());\n }\n const config = result as unknown as Config;\n clamp(config);\n return config;\n}\n\n/** The web `State`: tracking is never enabled on web, and nothing is recorded or persisted. */\nexport function webState(config: Config): State {\n return {\n enabled: false,\n trackingMode: 'location',\n isMoving: false,\n odometer: 0,\n backend: 'web',\n lastRecordAt: null,\n lastStopReason: null,\n lastStopAt: null,\n config: cloneJson(config),\n };\n}\n"]}
|
package/dist/esm/web/device.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { DeviceInfo } from '../definitions';
|
|
2
2
|
/** `npm version` copies the `package.json` version here (scripts/sync-version.mjs); a test checks it. */
|
|
3
|
-
export declare const PLUGIN_VERSION = "8.0
|
|
3
|
+
export declare const PLUGIN_VERSION = "8.1.0";
|
|
4
4
|
/**
|
|
5
5
|
* Best-effort `DeviceInfo` for a browser, parsed from `navigator.userAgent`.
|
|
6
6
|
* `brand` is the browser, `model` the device when the user agent names one (else `navigator.platform`),
|
package/dist/esm/web/device.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** `npm version` copies the `package.json` version here (scripts/sync-version.mjs); a test checks it. */
|
|
2
|
-
export const PLUGIN_VERSION = '8.0
|
|
2
|
+
export const PLUGIN_VERSION = '8.1.0';
|
|
3
3
|
/** Tokens after `Android x` that do not name a device ('K' is Chrome's reduced user agent). */
|
|
4
4
|
const NOT_A_MODEL = ['K', 'U', 'wv', 'Mobile', 'Tablet', 'HarmonyOS'];
|
|
5
5
|
/** The device model among the `;`-separated tokens that follow `Android x` in the user agent's comment. */
|
|
@@ -85,6 +85,13 @@ export function webDeviceInfo(userAgent, platform) {
|
|
|
85
85
|
hmsAvailable: false,
|
|
86
86
|
backend: 'web',
|
|
87
87
|
packagedProviders: [],
|
|
88
|
+
backendFallbackReason: null,
|
|
89
|
+
gmsStatus: null,
|
|
90
|
+
hmsStatus: null,
|
|
91
|
+
hmsCoreOutdated: null,
|
|
92
|
+
locationAvailableHint: null,
|
|
93
|
+
cpuCores: typeof navigator !== 'undefined' && navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 0,
|
|
94
|
+
supportedAbis: [],
|
|
88
95
|
};
|
|
89
96
|
}
|
|
90
97
|
//# sourceMappingURL=device.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../../src/web/device.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"device.js","sourceRoot":"","sources":["../../../src/web/device.ts"],"names":[],"mappings":"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","sourcesContent":["// Owned by Unit 1 (TS wrapper + web).\nimport type { DeviceInfo } from '../definitions';\n\n/** `npm version` copies the `package.json` version here (scripts/sync-version.mjs); a test checks it. */\nexport const PLUGIN_VERSION = '8.1.0';\n\n/** Tokens after `Android x` that do not name a device ('K' is Chrome's reduced user agent). */\nconst NOT_A_MODEL = ['K', 'U', 'wv', 'Mobile', 'Tablet', 'HarmonyOS'];\n\ninterface OsInfo {\n osVersion: string;\n manufacturer: string;\n model: string | undefined;\n}\n\n/** The device model among the `;`-separated tokens that follow `Android x` in the user agent's comment. */\nfunction androidModel(tokens: string[]): string | undefined {\n for (const token of tokens) {\n const model = token.replace(/\\s*Build\\/.*$/, '').trim();\n const skip =\n !model ||\n NOT_A_MODEL.indexOf(model) >= 0 ||\n /^[a-z]{2}(?:[-_][a-z]{2})?$/i.test(model) || // locale, e.g. en-us\n /^(?:rv:|HMSCore)/.test(model);\n if (!skip) {\n return model;\n }\n }\n return undefined;\n}\n\nfunction parseOs(ua: string): OsInfo {\n let match = /\\(([^)]*?)Android\\s*([\\d.]*)([^)]*)\\)/.exec(ua);\n if (match) {\n return {\n osVersion: match[2] ? `Android ${match[2]}` : 'Android',\n manufacturer: 'unknown',\n model: androidModel(match[3].split(';')),\n };\n }\n match = /(iPhone|iPad|iPod).*?OS (\\d+(?:_\\d+)*)/.exec(ua);\n if (match) {\n return { osVersion: `iOS ${match[2].replace(/_/g, '.')}`, manufacturer: 'Apple', model: match[1] };\n }\n match = /Mac OS X (\\d+(?:[_.]\\d+)*)/.exec(ua);\n if (match) {\n return { osVersion: `macOS ${match[1].replace(/_/g, '.')}`, manufacturer: 'Apple', model: 'Macintosh' };\n }\n match = /Windows NT (\\d+(?:\\.\\d+)*)/.exec(ua);\n if (match) {\n return { osVersion: `Windows ${match[1]}`, manufacturer: 'unknown', model: undefined };\n }\n match = /CrOS \\S+ (\\d+(?:\\.\\d+)*)/.exec(ua);\n if (match) {\n return { osVersion: `ChromeOS ${match[1]}`, manufacturer: 'unknown', model: undefined };\n }\n if (/Linux/.test(ua)) {\n return { osVersion: 'Linux', manufacturer: 'unknown', model: undefined };\n }\n return { osVersion: 'unknown', manufacturer: 'unknown', model: undefined };\n}\n\n/** Browser name and major version, e.g. `Chrome 120`. Order matters: many browsers also claim Chrome or Safari. */\nfunction parseBrowser(ua: string): string {\n const browsers: [string, RegExp][] = [\n ['Edge', /Edg(?:e|A|iOS)?\\/(\\d+)/],\n ['Opera', /(?:OPR|Opera)\\/(\\d+)/],\n ['Samsung Internet', /SamsungBrowser\\/(\\d+)/],\n ['Huawei Browser', /HuaweiBrowser\\/(\\d+)/],\n ['Firefox', /(?:Firefox|FxiOS)\\/(\\d+)/],\n ['Chrome', /(?:Chrome|CriOS)\\/(\\d+)/],\n ['Safari', /Version\\/(\\d+)[\\d.]*.*Safari\\//],\n ['Node.js', /Node\\.js\\/(\\d+)/],\n ];\n for (const [name, pattern] of browsers) {\n const match = pattern.exec(ua);\n if (match) {\n return `${name} ${match[1]}`;\n }\n }\n return 'unknown';\n}\n\n/**\n * Best-effort `DeviceInfo` for a browser, parsed from `navigator.userAgent`.\n * `brand` is the browser, `model` the device when the user agent names one (else `navigator.platform`),\n * `osVersion` includes the OS name, and `sdkInt` is -1 because there is no Android API level.\n */\nexport function webDeviceInfo(userAgent: string, platform?: string): DeviceInfo {\n const os = parseOs(userAgent);\n return {\n platform: 'web',\n manufacturer: os.manufacturer,\n model: os.model || platform || 'unknown',\n brand: parseBrowser(userAgent),\n osVersion: os.osVersion,\n sdkInt: -1,\n pluginVersion: PLUGIN_VERSION,\n gmsAvailable: false,\n hmsAvailable: false,\n backend: 'web',\n packagedProviders: [],\n backendFallbackReason: null,\n gmsStatus: null,\n hmsStatus: null,\n hmsCoreOutdated: null,\n locationAvailableHint: null,\n cpuCores: typeof navigator !== 'undefined' && navigator.hardwareConcurrency ? navigator.hardwareConcurrency : 0,\n supportedAbis: [],\n };\n}\n"]}
|
package/dist/esm/web.d.ts
CHANGED
|
@@ -1,13 +1,5 @@
|
|
|
1
1
|
import { WebPlugin } from '@capacitor/core';
|
|
2
2
|
import type { BatteryOptimizationStatus, CallbackID, Config, CurrentPositionOptions, DeviceInfo, Geofence, HeartbeatStatus, InsertLocationInput, Location, LocationTrackingPlugin, LogLevel, LogQuery, PermissionStatus, PermissionType, PowerManagerInfo, ProviderState, ReadyOptions, Sensors, State, WatchPositionCallback, WatchPositionOptions } from './definitions';
|
|
3
|
-
/**
|
|
4
|
-
* Web implementation. It covers `getCurrentPosition`, `watchPosition` and `clearWatch` (via `navigator.geolocation`),
|
|
5
|
-
* an in-memory config and state, permissions and device info. Nothing is persisted or uploaded, and tracking cannot
|
|
6
|
-
* be started. Every other method rejects with `UNIMPLEMENTED`.
|
|
7
|
-
*
|
|
8
|
-
* Like the Android bridge, methods other than `ready`, `getState`, `checkPermissions`, `requestPermissions` and
|
|
9
|
-
* `getDeviceInfo` reject with `NOT_READY` until `ready()` has resolved.
|
|
10
|
-
*/
|
|
11
3
|
export declare class LocationTrackingWeb extends WebPlugin implements LocationTrackingPlugin {
|
|
12
4
|
private config;
|
|
13
5
|
private isReady;
|
package/dist/esm/web.js
CHANGED
|
@@ -28,6 +28,15 @@ function configFromDefaults(options) {
|
|
|
28
28
|
* Like the Android bridge, methods other than `ready`, `getState`, `checkPermissions`, `requestPermissions` and
|
|
29
29
|
* `getDeviceInfo` reject with `NOT_READY` until `ready()` has resolved.
|
|
30
30
|
*/
|
|
31
|
+
/** The State of `ready`, `setConfig` and `reset`, with the `warnings` the Android plugin also returns. */
|
|
32
|
+
function withWarnings(state) {
|
|
33
|
+
var _a;
|
|
34
|
+
const url = (_a = state.config.http) === null || _a === void 0 ? void 0 : _a.url;
|
|
35
|
+
const warnings = typeof url === 'string' && /^http:\/\//i.test(url.trim())
|
|
36
|
+
? ["http.url uses http://: Android 9+ blocks cleartext traffic unless the app's network security config allows it"]
|
|
37
|
+
: [];
|
|
38
|
+
return Object.assign(Object.assign({}, state), { warnings });
|
|
39
|
+
}
|
|
31
40
|
export class LocationTrackingWeb extends WebPlugin {
|
|
32
41
|
constructor() {
|
|
33
42
|
super(...arguments);
|
|
@@ -44,7 +53,7 @@ export class LocationTrackingWeb extends WebPlugin {
|
|
|
44
53
|
this.config = config;
|
|
45
54
|
}
|
|
46
55
|
this.isReady = true;
|
|
47
|
-
return webState(this.config);
|
|
56
|
+
return withWarnings(webState(this.config));
|
|
48
57
|
}
|
|
49
58
|
async setConfig(options) {
|
|
50
59
|
this.requireReady();
|
|
@@ -52,12 +61,12 @@ export class LocationTrackingWeb extends WebPlugin {
|
|
|
52
61
|
throw webError('INVALID_ARGUMENT', 'config must be an object.');
|
|
53
62
|
}
|
|
54
63
|
this.config = mergeConfig(this.config, options.config);
|
|
55
|
-
return webState(this.config);
|
|
64
|
+
return withWarnings(webState(this.config));
|
|
56
65
|
}
|
|
57
66
|
async reset(options) {
|
|
58
67
|
this.requireReady();
|
|
59
68
|
this.config = configFromDefaults(options);
|
|
60
|
-
return webState(this.config);
|
|
69
|
+
return withWarnings(webState(this.config));
|
|
61
70
|
}
|
|
62
71
|
async getState() {
|
|
63
72
|
return webState(this.config);
|