therms-device-tracker 1.0.0-rc.1
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/ARCHITECTURE.md +145 -0
- package/CHANGELOG.md +26 -0
- package/LICENSE +21 -0
- package/README.md +386 -0
- package/android/build.gradle +25 -0
- package/android/src/main/AndroidManifest.xml +23 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/ActivityRecognitionProvider.kt +109 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/GeofenceProvider.kt +184 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/GeofenceTransitionReceiver.kt +34 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/LocationProvider.kt +84 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/LocationStore.kt +150 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/ScheduleProvider.kt +55 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/SyncProvider.kt +292 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/ThermsDeviceTrackerModule.kt +726 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/ThermsDeviceTrackerModuleSharedObject.kt +23 -0
- package/android/src/main/java/expo/modules/thermsdevicetracker/ThermsLocationService.kt +129 -0
- package/app.plugin.js +1 -0
- package/build/DeviceSettings.d.ts +14 -0
- package/build/DeviceSettings.d.ts.map +1 -0
- package/build/DeviceSettings.js +24 -0
- package/build/DeviceSettings.js.map +1 -0
- package/build/Logger.d.ts +13 -0
- package/build/Logger.d.ts.map +1 -0
- package/build/Logger.js +27 -0
- package/build/Logger.js.map +1 -0
- package/build/NativeModule.d.ts +51 -0
- package/build/NativeModule.d.ts.map +1 -0
- package/build/NativeModule.js +159 -0
- package/build/NativeModule.js.map +1 -0
- package/build/ThermsDeviceTracker.types.d.ts +204 -0
- package/build/ThermsDeviceTracker.types.d.ts.map +1 -0
- package/build/ThermsDeviceTracker.types.js +34 -0
- package/build/ThermsDeviceTracker.types.js.map +1 -0
- package/build/ThermsDeviceTrackerModule.d.ts +43 -0
- package/build/ThermsDeviceTrackerModule.d.ts.map +1 -0
- package/build/ThermsDeviceTrackerModule.js +3 -0
- package/build/ThermsDeviceTrackerModule.js.map +1 -0
- package/build/ThermsDeviceTrackerModule.web.d.ts +47 -0
- package/build/ThermsDeviceTrackerModule.web.d.ts.map +1 -0
- package/build/ThermsDeviceTrackerModule.web.js +132 -0
- package/build/ThermsDeviceTrackerModule.web.js.map +1 -0
- package/build/ThermsDeviceTrackerModuleSharedObject.d.ts +46 -0
- package/build/ThermsDeviceTrackerModuleSharedObject.d.ts.map +1 -0
- package/build/ThermsDeviceTrackerModuleSharedObject.js +24 -0
- package/build/ThermsDeviceTrackerModuleSharedObject.js.map +1 -0
- package/build/index.d.ts +101 -0
- package/build/index.d.ts.map +1 -0
- package/build/index.js +221 -0
- package/build/index.js.map +1 -0
- package/build/plugin/index.d.ts +14 -0
- package/build/plugin/index.d.ts.map +1 -0
- package/build/plugin/index.js +83 -0
- package/build/plugin/index.js.map +1 -0
- package/build/tsconfig.tsbuildinfo +1 -0
- package/expo-module.config.json +9 -0
- package/ios/GeofenceManager.swift +221 -0
- package/ios/LocationProvider.swift +32 -0
- package/ios/LocationStore.swift +98 -0
- package/ios/MotionActivityProvider.swift +109 -0
- package/ios/ProviderMonitor.swift +33 -0
- package/ios/ScheduleManager.swift +33 -0
- package/ios/SyncManager.swift +186 -0
- package/ios/ThermsDeviceTracker.podspec +24 -0
- package/ios/ThermsDeviceTrackerModule.swift +632 -0
- package/ios/ThermsDeviceTrackerModuleSharedObject.swift +17 -0
- package/ios/ThermsGeofenceTests.swift +474 -0
- package/package.json +95 -0
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types and enums heavily inspired by patterns from react-native-background-geolocation
|
|
3
|
+
* for excellent naming, discoverability, and compound configuration.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* NOTE on plugin configuration (separate from runtime ThermsConfig):
|
|
7
|
+
* The config plugin (therms-device-tracker in app.json "plugins") accepts ThermsDeviceTrackerPluginProps.
|
|
8
|
+
* See plugin/src/index.ts (or build/plugin/index.d.ts after build) for the exported interface.
|
|
9
|
+
* One key prop finalized here: `iosBackgroundTaskIdentifier?: string` (enables BGTaskScheduler on iOS).
|
|
10
|
+
* Full docs + usage example in README.md (Installation + "iOS Background Sync with `iosBackgroundTaskIdentifier` + BGTaskScheduler").
|
|
11
|
+
* The plugin prop is not part of JS runtime config but is required for native bg periodic capability setup.
|
|
12
|
+
*/
|
|
13
|
+
export type LocationPoint = {
|
|
14
|
+
latitude: number;
|
|
15
|
+
longitude: number;
|
|
16
|
+
altitude?: number;
|
|
17
|
+
accuracy?: number;
|
|
18
|
+
speed?: number;
|
|
19
|
+
heading?: number;
|
|
20
|
+
timestamp: number;
|
|
21
|
+
};
|
|
22
|
+
export type MotionChangeEvent = {
|
|
23
|
+
isMoving: boolean;
|
|
24
|
+
location: LocationPoint | null;
|
|
25
|
+
};
|
|
26
|
+
export type ActivityType = 'still' | 'walking' | 'running' | 'cycling' | 'automotive' | 'unknown';
|
|
27
|
+
export type ActivityUpdate = {
|
|
28
|
+
type: ActivityType;
|
|
29
|
+
confidence: number;
|
|
30
|
+
timestamp: number;
|
|
31
|
+
};
|
|
32
|
+
export type PedometerData = {
|
|
33
|
+
steps: number;
|
|
34
|
+
distance?: number;
|
|
35
|
+
floorsAscended?: number;
|
|
36
|
+
floorsDescended?: number;
|
|
37
|
+
timestamp: number;
|
|
38
|
+
};
|
|
39
|
+
export interface GeoConfig {
|
|
40
|
+
desiredAccuracy?: 'high' | 'balanced' | 'low' | 'lowest';
|
|
41
|
+
distanceFilter?: number;
|
|
42
|
+
timeInterval?: number;
|
|
43
|
+
}
|
|
44
|
+
export interface MotionConfig {
|
|
45
|
+
enableActivityTracking?: boolean;
|
|
46
|
+
enableStepCounting?: boolean;
|
|
47
|
+
}
|
|
48
|
+
export interface BackgroundConfig {
|
|
49
|
+
enable?: boolean;
|
|
50
|
+
}
|
|
51
|
+
export interface NotificationConfig {
|
|
52
|
+
title?: string;
|
|
53
|
+
text?: string;
|
|
54
|
+
channelId?: string;
|
|
55
|
+
}
|
|
56
|
+
export interface ThermsConfig {
|
|
57
|
+
geolocation?: GeoConfig;
|
|
58
|
+
motion?: MotionConfig;
|
|
59
|
+
background?: BackgroundConfig;
|
|
60
|
+
notification?: NotificationConfig;
|
|
61
|
+
geofence?: GeofenceConfig;
|
|
62
|
+
schedule?: ScheduleConfig;
|
|
63
|
+
persistence?: PersistenceConfig;
|
|
64
|
+
sync?: SyncConfig;
|
|
65
|
+
ios?: {
|
|
66
|
+
activityType?: 'other' | 'automotive' | 'fitness' | 'otherNavigation';
|
|
67
|
+
pausesLocationUpdatesAutomatically?: boolean;
|
|
68
|
+
showsBackgroundLocationIndicator?: boolean;
|
|
69
|
+
};
|
|
70
|
+
android?: {
|
|
71
|
+
priority?: 'high' | 'balanced' | 'low';
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
export type TrackingOptions = ThermsConfig;
|
|
75
|
+
export type PermissionStatus = 'granted' | 'denied' | 'undetermined';
|
|
76
|
+
export type PermissionResponse = {
|
|
77
|
+
location: PermissionStatus;
|
|
78
|
+
backgroundLocation?: PermissionStatus;
|
|
79
|
+
motion?: PermissionStatus;
|
|
80
|
+
canAskAgain: boolean;
|
|
81
|
+
};
|
|
82
|
+
export type TrackingState = 'inactive' | 'active' | 'paused';
|
|
83
|
+
export type TrackingStatus = {
|
|
84
|
+
state: TrackingState;
|
|
85
|
+
isBackground: boolean;
|
|
86
|
+
sessionId?: string;
|
|
87
|
+
startedAt?: number;
|
|
88
|
+
};
|
|
89
|
+
export type ThermsDeviceTrackerModuleEvents = {
|
|
90
|
+
onLocationUpdate: (location: LocationPoint) => void;
|
|
91
|
+
onMotionChange: (event: MotionChangeEvent) => void;
|
|
92
|
+
onActivityUpdate: (activity: ActivityUpdate) => void;
|
|
93
|
+
onPedometerUpdate: (data: PedometerData) => void;
|
|
94
|
+
onTrackingStateChange: (status: TrackingStatus) => void;
|
|
95
|
+
onProviderChange: (event: ProviderChangeEvent) => void;
|
|
96
|
+
onGeofence: (event: GeofenceEvent) => void;
|
|
97
|
+
onGeofencesChange?: (event: {
|
|
98
|
+
on: Geofence[];
|
|
99
|
+
off: Geofence[];
|
|
100
|
+
}) => void;
|
|
101
|
+
onSchedule?: (event: any) => void;
|
|
102
|
+
onSync?: (event: SyncEvent) => void;
|
|
103
|
+
onError: (error: {
|
|
104
|
+
code: string;
|
|
105
|
+
message: string;
|
|
106
|
+
}) => void;
|
|
107
|
+
};
|
|
108
|
+
export type ProviderChangeEvent = {
|
|
109
|
+
enabled: boolean;
|
|
110
|
+
status: 'not_determined' | 'restricted' | 'denied' | 'always' | 'when_in_use';
|
|
111
|
+
accuracyAuthorization?: 'full' | 'reduced';
|
|
112
|
+
gps?: boolean;
|
|
113
|
+
network?: boolean;
|
|
114
|
+
};
|
|
115
|
+
export interface Geofence {
|
|
116
|
+
identifier: string;
|
|
117
|
+
latitude: number;
|
|
118
|
+
longitude: number;
|
|
119
|
+
radius: number;
|
|
120
|
+
notifyOnEntry?: boolean;
|
|
121
|
+
notifyOnExit?: boolean;
|
|
122
|
+
notifyOnDwell?: boolean;
|
|
123
|
+
loiteringDelay?: number;
|
|
124
|
+
extras?: Record<string, any>;
|
|
125
|
+
}
|
|
126
|
+
export type GeofenceEvent = {
|
|
127
|
+
identifier: string;
|
|
128
|
+
action: 'ENTER' | 'EXIT' | 'DWELL';
|
|
129
|
+
location?: LocationPoint;
|
|
130
|
+
extras?: Record<string, any>;
|
|
131
|
+
};
|
|
132
|
+
/**
|
|
133
|
+
* Sync event emitted by native bg HTTP sync (onSync).
|
|
134
|
+
*
|
|
135
|
+
* Always includes `state` (emitted by iOS SyncManager or Android SyncProvider/SyncWorker). 'warning' is Android-specific (interval clamp).
|
|
136
|
+
* `success` is optional: present on result emissions (success/error/noop), absent on
|
|
137
|
+
* lifecycle events (started/stopped/disabled) which may carry `url` or `reason` instead.
|
|
138
|
+
* Other fields populated for HTTP results per runtime shapes.
|
|
139
|
+
*
|
|
140
|
+
* Matches native emission shapes (onSync callback payloads from SyncManager/SyncProvider).
|
|
141
|
+
*
|
|
142
|
+
* Caveat: see platform docs in SyncManager.swift (iOS periodic/Timer vs BGTaskScheduler reqs)
|
|
143
|
+
* and SyncProvider.kt (Android live store prefer for batch).
|
|
144
|
+
*/
|
|
145
|
+
export type SyncEvent = {
|
|
146
|
+
state: 'started' | 'stopped' | 'disabled' | 'noop' | 'success' | 'error' | 'warning';
|
|
147
|
+
success?: boolean;
|
|
148
|
+
status?: number;
|
|
149
|
+
count?: number;
|
|
150
|
+
message?: string;
|
|
151
|
+
url?: string;
|
|
152
|
+
reason?: string;
|
|
153
|
+
};
|
|
154
|
+
export interface GeofenceConfig {
|
|
155
|
+
enabled?: boolean;
|
|
156
|
+
proximityRadius?: number;
|
|
157
|
+
}
|
|
158
|
+
export interface ScheduleConfig {
|
|
159
|
+
enabled?: boolean;
|
|
160
|
+
schedule?: any;
|
|
161
|
+
}
|
|
162
|
+
export interface PersistenceConfig {
|
|
163
|
+
enabled?: boolean;
|
|
164
|
+
maxDaysToPersist?: number;
|
|
165
|
+
}
|
|
166
|
+
export interface SyncConfig {
|
|
167
|
+
enabled?: boolean;
|
|
168
|
+
url: string;
|
|
169
|
+
method?: 'POST' | 'PUT' | 'PATCH';
|
|
170
|
+
headers?: Record<string, string>;
|
|
171
|
+
batch?: boolean;
|
|
172
|
+
interval?: number;
|
|
173
|
+
maxBatchSize?: number;
|
|
174
|
+
}
|
|
175
|
+
export declare const Event: {
|
|
176
|
+
readonly Location: "onLocationUpdate";
|
|
177
|
+
readonly MotionChange: "onMotionChange";
|
|
178
|
+
readonly ActivityChange: "onActivityUpdate";
|
|
179
|
+
readonly Pedometer: "onPedometerUpdate";
|
|
180
|
+
readonly TrackingStateChange: "onTrackingStateChange";
|
|
181
|
+
readonly ProviderChange: "onProviderChange";
|
|
182
|
+
readonly Geofence: "onGeofence";
|
|
183
|
+
readonly GeofencesChange: "onGeofencesChange";
|
|
184
|
+
readonly Schedule: "onSchedule";
|
|
185
|
+
readonly Sync: "onSync";
|
|
186
|
+
readonly Error: "onError";
|
|
187
|
+
};
|
|
188
|
+
export declare const DesiredAccuracy: {
|
|
189
|
+
readonly High: "high";
|
|
190
|
+
readonly Balanced: "balanced";
|
|
191
|
+
readonly Low: "low";
|
|
192
|
+
readonly Lowest: "lowest";
|
|
193
|
+
};
|
|
194
|
+
export declare const ActivityTypeEnum: {
|
|
195
|
+
readonly Still: "still";
|
|
196
|
+
readonly Walking: "walking";
|
|
197
|
+
readonly Running: "running";
|
|
198
|
+
readonly Cycling: "cycling";
|
|
199
|
+
readonly Automotive: "automotive";
|
|
200
|
+
readonly Unknown: "unknown";
|
|
201
|
+
};
|
|
202
|
+
export type LocationsResult = LocationPoint[];
|
|
203
|
+
export type GeofencesResult = Geofence[];
|
|
204
|
+
//# sourceMappingURL=ThermsDeviceTracker.types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThermsDeviceTracker.types.d.ts","sourceRoot":"","sources":["../src/ThermsDeviceTracker.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types and enums heavily inspired by patterns from react-native-background-geolocation
|
|
3
|
+
* for excellent naming, discoverability, and compound configuration.
|
|
4
|
+
*/
|
|
5
|
+
// Event name constants (reference style)
|
|
6
|
+
export const Event = {
|
|
7
|
+
Location: 'onLocationUpdate',
|
|
8
|
+
MotionChange: 'onMotionChange',
|
|
9
|
+
ActivityChange: 'onActivityUpdate',
|
|
10
|
+
Pedometer: 'onPedometerUpdate',
|
|
11
|
+
TrackingStateChange: 'onTrackingStateChange',
|
|
12
|
+
ProviderChange: 'onProviderChange',
|
|
13
|
+
Geofence: 'onGeofence',
|
|
14
|
+
GeofencesChange: 'onGeofencesChange',
|
|
15
|
+
Schedule: 'onSchedule',
|
|
16
|
+
Sync: 'onSync',
|
|
17
|
+
Error: 'onError',
|
|
18
|
+
};
|
|
19
|
+
// Enums as namespaces (reference pattern)
|
|
20
|
+
export const DesiredAccuracy = {
|
|
21
|
+
High: 'high',
|
|
22
|
+
Balanced: 'balanced',
|
|
23
|
+
Low: 'low',
|
|
24
|
+
Lowest: 'lowest',
|
|
25
|
+
};
|
|
26
|
+
export const ActivityTypeEnum = {
|
|
27
|
+
Still: 'still',
|
|
28
|
+
Walking: 'walking',
|
|
29
|
+
Running: 'running',
|
|
30
|
+
Cycling: 'cycling',
|
|
31
|
+
Automotive: 'automotive',
|
|
32
|
+
Unknown: 'unknown',
|
|
33
|
+
};
|
|
34
|
+
//# sourceMappingURL=ThermsDeviceTracker.types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThermsDeviceTracker.types.js","sourceRoot":"","sources":["../src/ThermsDeviceTracker.types.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAmNH,yCAAyC;AACzC,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,QAAQ,EAAE,kBAAkB;IAC5B,YAAY,EAAE,gBAAgB;IAC9B,cAAc,EAAE,kBAAkB;IAClC,SAAS,EAAE,mBAAmB;IAC9B,mBAAmB,EAAE,uBAAuB;IAC5C,cAAc,EAAE,kBAAkB;IAClC,QAAQ,EAAE,YAAY;IACtB,eAAe,EAAE,mBAAmB;IACpC,QAAQ,EAAE,YAAY;IACtB,IAAI,EAAE,QAAQ;IACd,KAAK,EAAE,SAAS;CACR,CAAC;AAEX,0CAA0C;AAC1C,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B,IAAI,EAAE,MAAM;IACZ,QAAQ,EAAE,UAAU;IACpB,GAAG,EAAE,KAAK;IACV,MAAM,EAAE,QAAQ;CACR,CAAC;AAEX,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,KAAK,EAAE,OAAO;IACd,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,SAAS;IAClB,UAAU,EAAE,YAAY;IACxB,OAAO,EAAE,SAAS;CACV,CAAC","sourcesContent":["/**\n * Types and enums heavily inspired by patterns from react-native-background-geolocation\n * for excellent naming, discoverability, and compound configuration.\n */\n\n/**\n * NOTE on plugin configuration (separate from runtime ThermsConfig):\n * The config plugin (therms-device-tracker in app.json \"plugins\") accepts ThermsDeviceTrackerPluginProps.\n * See plugin/src/index.ts (or build/plugin/index.d.ts after build) for the exported interface.\n * One key prop finalized here: `iosBackgroundTaskIdentifier?: string` (enables BGTaskScheduler on iOS).\n * Full docs + usage example in README.md (Installation + \"iOS Background Sync with `iosBackgroundTaskIdentifier` + BGTaskScheduler\").\n * The plugin prop is not part of JS runtime config but is required for native bg periodic capability setup.\n */\n\nexport type LocationPoint = {\n latitude: number;\n longitude: number;\n altitude?: number;\n accuracy?: number;\n speed?: number;\n heading?: number;\n timestamp: number;\n};\n\n// Motion-aware event (inspired by reference's onMotionChange)\nexport type MotionChangeEvent = {\n isMoving: boolean;\n location: LocationPoint | null;\n};\n\nexport type ActivityType = 'still' | 'walking' | 'running' | 'cycling' | 'automotive' | 'unknown';\n\nexport type ActivityUpdate = {\n type: ActivityType;\n confidence: number; // 0-1\n timestamp: number;\n};\n\nexport type PedometerData = {\n steps: number;\n distance?: number;\n floorsAscended?: number;\n floorsDescended?: number;\n timestamp: number;\n};\n\n// Compound config (reference-style)\nexport interface GeoConfig {\n desiredAccuracy?: 'high' | 'balanced' | 'low' | 'lowest';\n distanceFilter?: number;\n timeInterval?: number;\n}\n\nexport interface MotionConfig {\n enableActivityTracking?: boolean;\n enableStepCounting?: boolean;\n}\n\nexport interface BackgroundConfig {\n enable?: boolean;\n}\n\nexport interface NotificationConfig {\n title?: string;\n text?: string;\n channelId?: string;\n}\n\nexport interface ThermsConfig {\n geolocation?: GeoConfig;\n motion?: MotionConfig;\n background?: BackgroundConfig;\n notification?: NotificationConfig;\n geofence?: GeofenceConfig;\n schedule?: ScheduleConfig;\n persistence?: PersistenceConfig;\n // Opt-in native bg sync (see SyncConfig). Disabled by default for backward compat.\n // Uses platform bg HTTP (iOS URLSession+Timer/BGTask; Android WorkManager). Emits onSync.\n sync?: SyncConfig;\n // iOS/Android specific passthrough\n ios?: {\n activityType?: 'other' | 'automotive' | 'fitness' | 'otherNavigation';\n pausesLocationUpdatesAutomatically?: boolean;\n showsBackgroundLocationIndicator?: boolean;\n };\n android?: {\n priority?: 'high' | 'balanced' | 'low';\n };\n}\n\n// Legacy alias for backward compat during refactor\nexport type TrackingOptions = ThermsConfig;\n\nexport type PermissionStatus = 'granted' | 'denied' | 'undetermined';\n\nexport type PermissionResponse = {\n location: PermissionStatus;\n backgroundLocation?: PermissionStatus;\n motion?: PermissionStatus;\n canAskAgain: boolean;\n};\n\nexport type TrackingState = 'inactive' | 'active' | 'paused';\n\nexport type TrackingStatus = {\n state: TrackingState;\n isBackground: boolean;\n sessionId?: string;\n startedAt?: number;\n};\n\n// Rich events (inspired by reference)\nexport type ThermsDeviceTrackerModuleEvents = {\n onLocationUpdate: (location: LocationPoint) => void;\n onMotionChange: (event: MotionChangeEvent) => void;\n onActivityUpdate: (activity: ActivityUpdate) => void;\n onPedometerUpdate: (data: PedometerData) => void;\n onTrackingStateChange: (status: TrackingStatus) => void;\n onProviderChange: (event: ProviderChangeEvent) => void;\n onGeofence: (event: GeofenceEvent) => void;\n onGeofencesChange?: (event: { on: Geofence[]; off: Geofence[] }) => void;\n onSchedule?: (event: any) => void;\n onSync?: (event: SyncEvent) => void;\n onError: (error: { code: string; message: string }) => void;\n};\n\nexport type ProviderChangeEvent = {\n enabled: boolean; // location services / GPS enabled\n status: 'not_determined' | 'restricted' | 'denied' | 'always' | 'when_in_use';\n accuracyAuthorization?: 'full' | 'reduced'; // iOS 14+\n // Optional provider details\n gps?: boolean;\n network?: boolean;\n};\n\n// Geofencing (reference: addGeofence, onGeofence)\nexport interface Geofence {\n identifier: string;\n latitude: number;\n longitude: number;\n radius: number; // meters\n notifyOnEntry?: boolean;\n notifyOnExit?: boolean;\n notifyOnDwell?: boolean;\n loiteringDelay?: number; // ms\n extras?: Record<string, any>;\n}\n\nexport type GeofenceEvent = {\n identifier: string;\n action: 'ENTER' | 'EXIT' | 'DWELL';\n location?: LocationPoint;\n extras?: Record<string, any>;\n};\n\n/**\n * Sync event emitted by native bg HTTP sync (onSync).\n *\n * Always includes `state` (emitted by iOS SyncManager or Android SyncProvider/SyncWorker). 'warning' is Android-specific (interval clamp).\n * `success` is optional: present on result emissions (success/error/noop), absent on\n * lifecycle events (started/stopped/disabled) which may carry `url` or `reason` instead.\n * Other fields populated for HTTP results per runtime shapes.\n *\n * Matches native emission shapes (onSync callback payloads from SyncManager/SyncProvider).\n *\n * Caveat: see platform docs in SyncManager.swift (iOS periodic/Timer vs BGTaskScheduler reqs)\n * and SyncProvider.kt (Android live store prefer for batch).\n */\nexport type SyncEvent = {\n state: 'started' | 'stopped' | 'disabled' | 'noop' | 'success' | 'error' | 'warning';\n success?: boolean;\n status?: number;\n count?: number; // items attempted/sent in batch or immediate\n message?: string;\n url?: string;\n reason?: string;\n // additional fields (e.g. for future) possible but not required\n};\n\n// Config extensions for geofence/schedule/persistence sections\nexport interface GeofenceConfig {\n enabled?: boolean;\n proximityRadius?: number; // optimization hint in meters\n}\n\nexport interface ScheduleConfig {\n enabled?: boolean;\n // Reference often uses string[] schedules or start/stop; keep flexible object for now\n schedule?: any;\n}\n\nexport interface PersistenceConfig {\n enabled?: boolean;\n maxDaysToPersist?: number;\n}\n\n// Opt-in native background HTTP sync (periodic batch or immediate).\n// Uses OS APIs (URLSession bg / WorkManager) for battery efficiency vs. JS headless.\n// Data sourced from LocationStore via SyncDataSource (live getAll at execution for batch).\n// Emits to onSync listener (via native callback seam).\nexport interface SyncConfig {\n enabled?: boolean;\n url: string;\n method?: 'POST' | 'PUT' | 'PATCH';\n headers?: Record<string, string>;\n // batch: true (default) + interval for periodic batch sync; false for more immediate (on data updates).\n // When omitted, native treats as batch (defaults to true). Immediate triggers are driven by the caller\n // (location delivery paths check `batch != true` and call syncNow).\n batch?: boolean;\n interval?: number; // seconds, for periodic/batch mode. NOTE: Android WorkManager enforces >=15min for periodic batch; shorter values are clamped and a \"warning\" state is emitted via onSync. iOS Timer path (demo) accepts any; BGTaskScheduler has its own scheduling.\n maxBatchSize?: number; // cap items per payload (reuse store bounds)\n // Future: auth passthrough, retry policy, body shape, etc.\n}\n\n// Event name constants (reference style)\nexport const Event = {\n Location: 'onLocationUpdate',\n MotionChange: 'onMotionChange',\n ActivityChange: 'onActivityUpdate',\n Pedometer: 'onPedometerUpdate',\n TrackingStateChange: 'onTrackingStateChange',\n ProviderChange: 'onProviderChange',\n Geofence: 'onGeofence',\n GeofencesChange: 'onGeofencesChange',\n Schedule: 'onSchedule',\n Sync: 'onSync',\n Error: 'onError',\n} as const;\n\n// Enums as namespaces (reference pattern)\nexport const DesiredAccuracy = {\n High: 'high',\n Balanced: 'balanced',\n Low: 'low',\n Lowest: 'lowest',\n} as const;\n\nexport const ActivityTypeEnum = {\n Still: 'still',\n Walking: 'walking',\n Running: 'running',\n Cycling: 'cycling',\n Automotive: 'automotive',\n Unknown: 'unknown',\n} as const;\n\n// Persistence response helpers (reference-inspired)\nexport type LocationsResult = LocationPoint[];\n\nexport type GeofencesResult = Geofence[];\n"]}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { NativeModule } from 'expo';
|
|
2
|
+
import type { ThermsDeviceTrackerModuleEvents, TrackingOptions, PermissionResponse, LocationPoint, ActivityUpdate, TrackingStatus, PedometerData, Geofence, GeofenceEvent } from './ThermsDeviceTracker.types';
|
|
3
|
+
import type { ThermsTracker } from './ThermsDeviceTrackerModuleSharedObject';
|
|
4
|
+
declare class ThermsDeviceTrackerModule extends NativeModule<ThermsDeviceTrackerModuleEvents> {
|
|
5
|
+
readonly name: string;
|
|
6
|
+
getPermissionsAsync(): Promise<PermissionResponse>;
|
|
7
|
+
requestPermissionsAsync(options?: {
|
|
8
|
+
background?: boolean;
|
|
9
|
+
}): Promise<PermissionResponse>;
|
|
10
|
+
startTrackingAsync(options?: TrackingOptions): Promise<void>;
|
|
11
|
+
stopTrackingAsync(): Promise<void>;
|
|
12
|
+
getCurrentLocationAsync(): Promise<LocationPoint | null>;
|
|
13
|
+
getLastKnownLocation(): LocationPoint | null;
|
|
14
|
+
getCurrentActivity(): ActivityUpdate | null;
|
|
15
|
+
getTrackingStatus(): TrackingStatus;
|
|
16
|
+
getCurrentSessionHistory(): Promise<{
|
|
17
|
+
locations: LocationPoint[];
|
|
18
|
+
activities: ActivityUpdate[];
|
|
19
|
+
pedometer?: PedometerData[];
|
|
20
|
+
}>;
|
|
21
|
+
clearCurrentSessionHistory(): Promise<void>;
|
|
22
|
+
getProviderState?(): any;
|
|
23
|
+
addGeofence?(geofence: Geofence): Promise<void> | void;
|
|
24
|
+
addGeofences?(geofences: Geofence[]): Promise<void> | void;
|
|
25
|
+
removeGeofence?(identifier: string): Promise<void> | void;
|
|
26
|
+
removeGeofences?(identifiers?: string[]): Promise<void> | void;
|
|
27
|
+
getGeofences?(): Promise<Geofence[]>;
|
|
28
|
+
startGeofences?(): Promise<void> | void;
|
|
29
|
+
onGeofence?(event: GeofenceEvent): void;
|
|
30
|
+
getLocations?(): Promise<any>;
|
|
31
|
+
getCount?(): Promise<number>;
|
|
32
|
+
destroyLocations?(): Promise<void>;
|
|
33
|
+
destroyLocation?(uuid?: string): Promise<void>;
|
|
34
|
+
insertLocation?(location: LocationPoint | Record<string, any>): Promise<void>;
|
|
35
|
+
startSchedule?(): Promise<void> | void;
|
|
36
|
+
stopSchedule?(): Promise<void> | void;
|
|
37
|
+
startSync?(): Promise<void> | void;
|
|
38
|
+
stopSync?(): Promise<void> | void;
|
|
39
|
+
ThermsTracker: typeof ThermsTracker;
|
|
40
|
+
}
|
|
41
|
+
declare const _default: ThermsDeviceTrackerModule;
|
|
42
|
+
export default _default;
|
|
43
|
+
//# sourceMappingURL=ThermsDeviceTrackerModule.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThermsDeviceTrackerModule.d.ts","sourceRoot":"","sources":["../src/ThermsDeviceTrackerModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,MAAM,CAAC;AAEzD,OAAO,KAAK,EACV,+BAA+B,EAC/B,eAAe,EACf,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,cAAc,EACd,aAAa,EACb,QAAQ,EACR,aAAa,EACd,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yCAAyC,CAAC;AAE7E,OAAO,OAAO,yBAA0B,SAAQ,YAAY,CAAC,+BAA+B,CAAC;IAC3F,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAEtB,mBAAmB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAClD,uBAAuB,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;IAExF,kBAAkB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAC5D,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IAElC,uBAAuB,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IACxD,oBAAoB,IAAI,aAAa,GAAG,IAAI;IAC5C,kBAAkB,IAAI,cAAc,GAAG,IAAI;IAC3C,iBAAiB,IAAI,cAAc;IAEnC,wBAAwB,IAAI,OAAO,CAAC;QAClC,SAAS,EAAE,aAAa,EAAE,CAAC;QAC3B,UAAU,EAAE,cAAc,EAAE,CAAC;QAC7B,SAAS,CAAC,EAAE,aAAa,EAAE,CAAC;KAC7B,CAAC;IACF,0BAA0B,IAAI,OAAO,CAAC,IAAI,CAAC;IAE3C,gBAAgB,CAAC,IAAI,GAAG;IAGxB,WAAW,CAAC,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IACtD,YAAY,CAAC,CAAC,SAAS,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAC1D,cAAc,CAAC,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IACzD,eAAe,CAAC,CAAC,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAC9D,YAAY,CAAC,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;IACpC,cAAc,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAEvC,UAAU,CAAC,CAAC,KAAK,EAAE,aAAa,GAAG,IAAI;IAGvC,YAAY,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC;IAC7B,QAAQ,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC;IAC5B,gBAAgB,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC;IAClC,eAAe,CAAC,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9C,cAAc,CAAC,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;IAG7E,aAAa,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IACtC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAIrC,SAAS,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAClC,QAAQ,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;IAEjC,aAAa,EAAE,OAAO,aAAa,CAAC;CACrC;;AAED,wBAAqF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThermsDeviceTrackerModule.js","sourceRoot":"","sources":["../src/ThermsDeviceTrackerModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,MAAM,CAAC;AAmEzD,eAAe,mBAAmB,CAA4B,qBAAqB,CAAC,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from 'expo';\n\nimport type {\n ThermsDeviceTrackerModuleEvents,\n TrackingOptions,\n PermissionResponse,\n LocationPoint,\n ActivityUpdate,\n TrackingStatus,\n PedometerData,\n Geofence,\n GeofenceEvent,\n} from './ThermsDeviceTracker.types';\nimport type { ThermsTracker } from './ThermsDeviceTrackerModuleSharedObject';\n\ndeclare class ThermsDeviceTrackerModule extends NativeModule<ThermsDeviceTrackerModuleEvents> {\n readonly name: string;\n\n getPermissionsAsync(): Promise<PermissionResponse>;\n requestPermissionsAsync(options?: { background?: boolean }): Promise<PermissionResponse>;\n\n startTrackingAsync(options?: TrackingOptions): Promise<void>;\n stopTrackingAsync(): Promise<void>;\n\n getCurrentLocationAsync(): Promise<LocationPoint | null>;\n getLastKnownLocation(): LocationPoint | null;\n getCurrentActivity(): ActivityUpdate | null;\n getTrackingStatus(): TrackingStatus;\n\n getCurrentSessionHistory(): Promise<{\n locations: LocationPoint[];\n activities: ActivityUpdate[];\n pedometer?: PedometerData[];\n }>;\n clearCurrentSessionHistory(): Promise<void>;\n\n getProviderState?(): any;\n\n // Geofencing\n addGeofence?(geofence: Geofence): Promise<void> | void;\n addGeofences?(geofences: Geofence[]): Promise<void> | void;\n removeGeofence?(identifier: string): Promise<void> | void;\n removeGeofences?(identifiers?: string[]): Promise<void> | void;\n getGeofences?(): Promise<Geofence[]>;\n startGeofences?(): Promise<void> | void;\n\n onGeofence?(event: GeofenceEvent): void;\n\n // Persistence\n getLocations?(): Promise<any>;\n getCount?(): Promise<number>;\n destroyLocations?(): Promise<void>;\n destroyLocation?(uuid?: string): Promise<void>;\n insertLocation?(location: LocationPoint | Record<string, any>): Promise<void>;\n\n // Scheduler\n startSchedule?(): Promise<void> | void;\n stopSchedule?(): Promise<void> | void;\n\n // Background native HTTP sync (opt-in via config; explicit start/stop for control).\n // Implementations (native): use onSync callback for events. See types SyncConfig.\n startSync?(): Promise<void> | void;\n stopSync?(): Promise<void> | void;\n\n ThermsTracker: typeof ThermsTracker;\n}\n\nexport default requireNativeModule<ThermsDeviceTrackerModule>('ThermsDeviceTracker');\n"]}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { NativeModule } from 'expo';
|
|
2
|
+
import { ThermsDeviceTrackerModuleEvents, LocationPoint, ActivityUpdate, TrackingStatus, PermissionResponse, TrackingOptions } from './ThermsDeviceTracker.types';
|
|
3
|
+
declare class ThermsDeviceTrackerModule extends NativeModule<ThermsDeviceTrackerModuleEvents> {
|
|
4
|
+
private watchId;
|
|
5
|
+
private isTracking;
|
|
6
|
+
private lastLocation;
|
|
7
|
+
private sessionLocations;
|
|
8
|
+
getPermissionsAsync(): Promise<PermissionResponse>;
|
|
9
|
+
requestPermissionsAsync(): Promise<PermissionResponse>;
|
|
10
|
+
startTrackingAsync(options?: TrackingOptions): Promise<void>;
|
|
11
|
+
stopTrackingAsync(): Promise<void>;
|
|
12
|
+
getCurrentLocationAsync(): Promise<LocationPoint | null>;
|
|
13
|
+
getLastKnownLocation(): LocationPoint | null;
|
|
14
|
+
getCurrentActivity(): ActivityUpdate | null;
|
|
15
|
+
getTrackingStatus(): TrackingStatus;
|
|
16
|
+
getCurrentSessionHistory(): Promise<{
|
|
17
|
+
locations: LocationPoint[];
|
|
18
|
+
activities: never[];
|
|
19
|
+
}>;
|
|
20
|
+
clearCurrentSessionHistory(): Promise<void>;
|
|
21
|
+
addGeofence(_geofence: any): Promise<void>;
|
|
22
|
+
addGeofences(_geofences: any[]): Promise<void>;
|
|
23
|
+
removeGeofence(_id: string): Promise<void>;
|
|
24
|
+
removeGeofences(_ids?: string[]): Promise<void>;
|
|
25
|
+
getGeofences(): Promise<any[]>;
|
|
26
|
+
startGeofences(): Promise<void>;
|
|
27
|
+
getLocations(): Promise<any>;
|
|
28
|
+
getCount(): Promise<number>;
|
|
29
|
+
destroyLocations(): Promise<void>;
|
|
30
|
+
destroyLocation(_uuid?: string): Promise<void>;
|
|
31
|
+
insertLocation(loc: any): Promise<void>;
|
|
32
|
+
startSchedule(): Promise<void>;
|
|
33
|
+
stopSchedule(): Promise<void>;
|
|
34
|
+
startSync(): Promise<void>;
|
|
35
|
+
stopSync(): Promise<void>;
|
|
36
|
+
setConfig(_config?: any): Promise<void>;
|
|
37
|
+
getProviderState(): {
|
|
38
|
+
enabled: boolean;
|
|
39
|
+
status: string;
|
|
40
|
+
gps: boolean;
|
|
41
|
+
network: boolean;
|
|
42
|
+
};
|
|
43
|
+
private emitStateChange;
|
|
44
|
+
}
|
|
45
|
+
declare const _default: typeof ThermsDeviceTrackerModule;
|
|
46
|
+
export default _default;
|
|
47
|
+
//# sourceMappingURL=ThermsDeviceTrackerModule.web.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThermsDeviceTrackerModule.web.d.ts","sourceRoot":"","sources":["../src/ThermsDeviceTrackerModule.web.ts"],"names":[],"mappings":"AAAA,OAAO,EAAqB,YAAY,EAAE,MAAM,MAAM,CAAC;AAEvD,OAAO,EACL,+BAA+B,EAC/B,aAAa,EACb,cAAc,EACd,cAAc,EACd,kBAAkB,EAClB,eAAe,EAChB,MAAM,6BAA6B,CAAC;AAErC,cAAM,yBAA0B,SAAQ,YAAY,CAAC,+BAA+B,CAAC;IACnF,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,gBAAgB,CAAuB;IAEzC,mBAAmB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAWlD,uBAAuB,IAAI,OAAO,CAAC,kBAAkB,CAAC;IAItD,kBAAkB,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;IAuC5D,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;IASlC,uBAAuB,IAAI,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC;IAI9D,oBAAoB,IAAI,aAAa,GAAG,IAAI;IAI5C,kBAAkB,IAAI,cAAc,GAAG,IAAI;IAK3C,iBAAiB,IAAI,cAAc;IAO7B,wBAAwB;;;;IAOxB,0BAA0B;IAM1B,WAAW,CAAC,SAAS,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1C,YAAY,CAAC,UAAU,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9C,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1C,eAAe,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/C,YAAY,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IAG9B,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC;IAG/B,YAAY,IAAI,OAAO,CAAC,GAAG,CAAC;IAG5B,QAAQ,IAAI,OAAO,CAAC,MAAM,CAAC;IAG3B,gBAAgB,IAAI,OAAO,CAAC,IAAI,CAAC;IAGjC,eAAe,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9C,cAAc,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAKvC,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAC9B,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAO7B,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC;IAC1B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAIzB,SAAS,CAAC,OAAO,CAAC,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAG7C,gBAAgB;;;;;;IAIhB,OAAO,CAAC,eAAe;CAGxB;;AAED,wBAAyF"}
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { registerWebModule, NativeModule } from 'expo';
|
|
2
|
+
class ThermsDeviceTrackerModule extends NativeModule {
|
|
3
|
+
watchId = null;
|
|
4
|
+
isTracking = false;
|
|
5
|
+
lastLocation = null;
|
|
6
|
+
sessionLocations = [];
|
|
7
|
+
async getPermissionsAsync() {
|
|
8
|
+
// Browser geolocation permission is implicit on first use; no real background/motion distinction.
|
|
9
|
+
// Return full PermissionResponse shape for consistency with native (location + bg + motion + canAskAgain).
|
|
10
|
+
return {
|
|
11
|
+
location: 'undetermined',
|
|
12
|
+
backgroundLocation: 'undetermined',
|
|
13
|
+
motion: 'undetermined',
|
|
14
|
+
canAskAgain: true,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
async requestPermissionsAsync() {
|
|
18
|
+
return this.getPermissionsAsync();
|
|
19
|
+
}
|
|
20
|
+
async startTrackingAsync(options) {
|
|
21
|
+
if (!('geolocation' in navigator)) {
|
|
22
|
+
this.emit('onError', { code: 'unavailable', message: 'Geolocation not supported' });
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
this.isTracking = true;
|
|
26
|
+
this.sessionLocations = [];
|
|
27
|
+
this.emitStateChange();
|
|
28
|
+
this.watchId = navigator.geolocation.watchPosition((pos) => {
|
|
29
|
+
const point = {
|
|
30
|
+
latitude: pos.coords.latitude,
|
|
31
|
+
longitude: pos.coords.longitude,
|
|
32
|
+
altitude: pos.coords.altitude ?? undefined,
|
|
33
|
+
accuracy: pos.coords.accuracy ?? undefined,
|
|
34
|
+
speed: pos.coords.speed ?? undefined,
|
|
35
|
+
heading: pos.coords.heading ?? undefined,
|
|
36
|
+
timestamp: pos.timestamp,
|
|
37
|
+
};
|
|
38
|
+
this.lastLocation = point;
|
|
39
|
+
this.sessionLocations.push(point);
|
|
40
|
+
this.emit('onLocationUpdate', point);
|
|
41
|
+
this.emitStateChange();
|
|
42
|
+
}, (err) => {
|
|
43
|
+
this.emit('onError', { code: 'position_error', message: err.message });
|
|
44
|
+
}, {
|
|
45
|
+
enableHighAccuracy: (options?.geolocation?.desiredAccuracy ??
|
|
46
|
+
options?.accuracy ??
|
|
47
|
+
'balanced') !== 'low',
|
|
48
|
+
maximumAge: 10000,
|
|
49
|
+
timeout: 20000,
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
async stopTrackingAsync() {
|
|
53
|
+
if (this.watchId != null) {
|
|
54
|
+
navigator.geolocation.clearWatch(this.watchId);
|
|
55
|
+
this.watchId = null;
|
|
56
|
+
}
|
|
57
|
+
this.isTracking = false;
|
|
58
|
+
this.emitStateChange();
|
|
59
|
+
}
|
|
60
|
+
async getCurrentLocationAsync() {
|
|
61
|
+
return this.lastLocation;
|
|
62
|
+
}
|
|
63
|
+
getLastKnownLocation() {
|
|
64
|
+
return this.lastLocation;
|
|
65
|
+
}
|
|
66
|
+
getCurrentActivity() {
|
|
67
|
+
// Web: no reliable activity without extra sensors / permissions
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
getTrackingStatus() {
|
|
71
|
+
return {
|
|
72
|
+
state: this.isTracking ? 'active' : 'inactive',
|
|
73
|
+
isBackground: false,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
async getCurrentSessionHistory() {
|
|
77
|
+
return {
|
|
78
|
+
locations: this.sessionLocations,
|
|
79
|
+
activities: [],
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async clearCurrentSessionHistory() {
|
|
83
|
+
this.sessionLocations = [];
|
|
84
|
+
}
|
|
85
|
+
// Geofencing stubs (web limited; no native GeofencingClient / CLCircularRegion).
|
|
86
|
+
// Methods match optional signatures in ThermsDeviceTrackerModule.ts + native delegation.
|
|
87
|
+
async addGeofence(_geofence) { }
|
|
88
|
+
async addGeofences(_geofences) { }
|
|
89
|
+
async removeGeofence(_id) { }
|
|
90
|
+
async removeGeofences(_ids) { }
|
|
91
|
+
async getGeofences() {
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
async startGeofences() { }
|
|
95
|
+
// Persistence stubs (in-memory only on web; no SharedPreferences/UserDefaults backing).
|
|
96
|
+
async getLocations() {
|
|
97
|
+
return { locations: this.sessionLocations, activities: [] };
|
|
98
|
+
}
|
|
99
|
+
async getCount() {
|
|
100
|
+
return this.sessionLocations.length;
|
|
101
|
+
}
|
|
102
|
+
async destroyLocations() {
|
|
103
|
+
this.sessionLocations = [];
|
|
104
|
+
}
|
|
105
|
+
async destroyLocation(_uuid) { }
|
|
106
|
+
async insertLocation(loc) {
|
|
107
|
+
if (loc)
|
|
108
|
+
this.sessionLocations.push(loc);
|
|
109
|
+
}
|
|
110
|
+
// Scheduler stubs (no-op; Android uses Handler timer demo, iOS ScheduleManager).
|
|
111
|
+
async startSchedule() { }
|
|
112
|
+
async stopSchedule() { }
|
|
113
|
+
// Background sync stubs (no-op on web; no WorkManager / URLSession bg HTTP).
|
|
114
|
+
// - Use ThermsDeviceTracker.onSync(...) for events (works via NativeModule base on all platforms).
|
|
115
|
+
// - Real impls only on native (SyncManager/SyncProvider); config-driven from ready/start or explicit start/stopSync.
|
|
116
|
+
// - See SyncConfig in ThermsDeviceTracker.types.ts and bg sync notes in ARCHITECTURE.md / native headers.
|
|
117
|
+
// - startSync/stopSync are safe no-ops here; do not emit onSync lifecycle (native-only seam).
|
|
118
|
+
async startSync() { }
|
|
119
|
+
async stopSync() { }
|
|
120
|
+
// Internal seam for NativeModule.start() (calls setConfig if present before startTrackingAsync).
|
|
121
|
+
// Web ignores sync/etc config (no-op support); options handled in startTrackingAsync.
|
|
122
|
+
async setConfig(_config) { }
|
|
123
|
+
// Provider state stub (parity with Android getProviderState / iOS equivalent; used by getProviderState).
|
|
124
|
+
getProviderState() {
|
|
125
|
+
return { enabled: false, status: 'denied', gps: false, network: true };
|
|
126
|
+
}
|
|
127
|
+
emitStateChange() {
|
|
128
|
+
this.emit('onTrackingStateChange', this.getTrackingStatus());
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
export default registerWebModule(ThermsDeviceTrackerModule, 'ThermsDeviceTrackerModule');
|
|
132
|
+
//# sourceMappingURL=ThermsDeviceTrackerModule.web.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThermsDeviceTrackerModule.web.js","sourceRoot":"","sources":["../src/ThermsDeviceTrackerModule.web.ts"],"names":[],"mappings":"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","sourcesContent":["import { registerWebModule, NativeModule } from 'expo';\n\nimport {\n ThermsDeviceTrackerModuleEvents,\n LocationPoint,\n ActivityUpdate,\n TrackingStatus,\n PermissionResponse,\n TrackingOptions,\n} from './ThermsDeviceTracker.types';\n\nclass ThermsDeviceTrackerModule extends NativeModule<ThermsDeviceTrackerModuleEvents> {\n private watchId: number | null = null;\n private isTracking = false;\n private lastLocation: LocationPoint | null = null;\n private sessionLocations: LocationPoint[] = [];\n\n async getPermissionsAsync(): Promise<PermissionResponse> {\n // Browser geolocation permission is implicit on first use; no real background/motion distinction.\n // Return full PermissionResponse shape for consistency with native (location + bg + motion + canAskAgain).\n return {\n location: 'undetermined',\n backgroundLocation: 'undetermined',\n motion: 'undetermined',\n canAskAgain: true,\n };\n }\n\n async requestPermissionsAsync(): Promise<PermissionResponse> {\n return this.getPermissionsAsync();\n }\n\n async startTrackingAsync(options?: TrackingOptions): Promise<void> {\n if (!('geolocation' in navigator)) {\n this.emit('onError', { code: 'unavailable', message: 'Geolocation not supported' });\n return;\n }\n this.isTracking = true;\n this.sessionLocations = [];\n this.emitStateChange();\n\n this.watchId = navigator.geolocation.watchPosition(\n (pos) => {\n const point: LocationPoint = {\n latitude: pos.coords.latitude,\n longitude: pos.coords.longitude,\n altitude: pos.coords.altitude ?? undefined,\n accuracy: pos.coords.accuracy ?? undefined,\n speed: pos.coords.speed ?? undefined,\n heading: pos.coords.heading ?? undefined,\n timestamp: pos.timestamp,\n };\n this.lastLocation = point;\n this.sessionLocations.push(point);\n this.emit('onLocationUpdate', point);\n this.emitStateChange();\n },\n (err) => {\n this.emit('onError', { code: 'position_error', message: err.message });\n },\n {\n enableHighAccuracy:\n ((options as any)?.geolocation?.desiredAccuracy ??\n (options as any)?.accuracy ??\n 'balanced') !== 'low',\n maximumAge: 10000,\n timeout: 20000,\n }\n );\n }\n\n async stopTrackingAsync(): Promise<void> {\n if (this.watchId != null) {\n navigator.geolocation.clearWatch(this.watchId);\n this.watchId = null;\n }\n this.isTracking = false;\n this.emitStateChange();\n }\n\n async getCurrentLocationAsync(): Promise<LocationPoint | null> {\n return this.lastLocation;\n }\n\n getLastKnownLocation(): LocationPoint | null {\n return this.lastLocation;\n }\n\n getCurrentActivity(): ActivityUpdate | null {\n // Web: no reliable activity without extra sensors / permissions\n return null;\n }\n\n getTrackingStatus(): TrackingStatus {\n return {\n state: this.isTracking ? 'active' : 'inactive',\n isBackground: false,\n };\n }\n\n async getCurrentSessionHistory() {\n return {\n locations: this.sessionLocations,\n activities: [],\n };\n }\n\n async clearCurrentSessionHistory() {\n this.sessionLocations = [];\n }\n\n // Geofencing stubs (web limited; no native GeofencingClient / CLCircularRegion).\n // Methods match optional signatures in ThermsDeviceTrackerModule.ts + native delegation.\n async addGeofence(_geofence: any): Promise<void> {}\n async addGeofences(_geofences: any[]): Promise<void> {}\n async removeGeofence(_id: string): Promise<void> {}\n async removeGeofences(_ids?: string[]): Promise<void> {}\n async getGeofences(): Promise<any[]> {\n return [];\n }\n async startGeofences(): Promise<void> {}\n\n // Persistence stubs (in-memory only on web; no SharedPreferences/UserDefaults backing).\n async getLocations(): Promise<any> {\n return { locations: this.sessionLocations, activities: [] };\n }\n async getCount(): Promise<number> {\n return this.sessionLocations.length;\n }\n async destroyLocations(): Promise<void> {\n this.sessionLocations = [];\n }\n async destroyLocation(_uuid?: string): Promise<void> {}\n async insertLocation(loc: any): Promise<void> {\n if (loc) this.sessionLocations.push(loc);\n }\n\n // Scheduler stubs (no-op; Android uses Handler timer demo, iOS ScheduleManager).\n async startSchedule(): Promise<void> {}\n async stopSchedule(): Promise<void> {}\n\n // Background sync stubs (no-op on web; no WorkManager / URLSession bg HTTP).\n // - Use ThermsDeviceTracker.onSync(...) for events (works via NativeModule base on all platforms).\n // - Real impls only on native (SyncManager/SyncProvider); config-driven from ready/start or explicit start/stopSync.\n // - See SyncConfig in ThermsDeviceTracker.types.ts and bg sync notes in ARCHITECTURE.md / native headers.\n // - startSync/stopSync are safe no-ops here; do not emit onSync lifecycle (native-only seam).\n async startSync(): Promise<void> {}\n async stopSync(): Promise<void> {}\n\n // Internal seam for NativeModule.start() (calls setConfig if present before startTrackingAsync).\n // Web ignores sync/etc config (no-op support); options handled in startTrackingAsync.\n async setConfig(_config?: any): Promise<void> {}\n\n // Provider state stub (parity with Android getProviderState / iOS equivalent; used by getProviderState).\n getProviderState() {\n return { enabled: false, status: 'denied', gps: false, network: true };\n }\n\n private emitStateChange() {\n this.emit('onTrackingStateChange', this.getTrackingStatus());\n }\n}\n\nexport default registerWebModule(ThermsDeviceTrackerModule, 'ThermsDeviceTrackerModule');\n"]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { SharedObject } from 'expo-modules-core';
|
|
2
|
+
import type { LocationPoint, ActivityUpdate, TrackingStatus } from './ThermsDeviceTracker.types';
|
|
3
|
+
/**
|
|
4
|
+
* ThermsTracker is a lightweight SharedObject handle providing on-demand live access
|
|
5
|
+
* to the module's shared (singleton) tracking state.
|
|
6
|
+
*
|
|
7
|
+
* IMPORTANT: This is NOT a "stateful independent instance" per SharedObject docs pattern.
|
|
8
|
+
* - Tracking session state (location, activity, isTracking, stats) is owned by the single
|
|
9
|
+
* ThermsDeviceTracker native module (one CLLocationManager / FusedLocation + session buffers).
|
|
10
|
+
* - All ThermsTracker instances (from `new` or the hook) proxy / reflect the same underlying state.
|
|
11
|
+
* - This is intentional: the module exposes a single tracking session, matching real-world
|
|
12
|
+
* device tracking semantics (you don't run multiple independent trackers in one app process).
|
|
13
|
+
* - Properties are read live when accessed from JS (polling snapshots); use events (via useEvent
|
|
14
|
+
* or ThermsDeviceTracker.onXXX) for push updates and re-renders.
|
|
15
|
+
*
|
|
16
|
+
* The handle enables `useReleasingSharedObject` lifecycle + a clean `tracker.xxx` API surface.
|
|
17
|
+
* Keep the public surface: isTracking, trackingStatus, lastLocation, currentActivity, sessionStats.
|
|
18
|
+
*/
|
|
19
|
+
export declare class ThermsTracker extends SharedObject {
|
|
20
|
+
readonly isTracking: boolean;
|
|
21
|
+
readonly trackingStatus: TrackingStatus;
|
|
22
|
+
readonly lastLocation?: LocationPoint;
|
|
23
|
+
readonly currentActivity?: ActivityUpdate;
|
|
24
|
+
readonly sessionStats?: {
|
|
25
|
+
startTime: number;
|
|
26
|
+
pointCount: number;
|
|
27
|
+
totalSteps?: number;
|
|
28
|
+
totalDistance?: number;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new ThermsTracker instance (lightweight handle to shared module state).
|
|
33
|
+
* You are responsible for releasing it from memory by calling `release()` when done.
|
|
34
|
+
*/
|
|
35
|
+
export declare function createThermsTracker(): ThermsTracker;
|
|
36
|
+
/**
|
|
37
|
+
* A hook that creates a ThermsTracker instance and automatically
|
|
38
|
+
* releases it when the component unmounts.
|
|
39
|
+
*
|
|
40
|
+
* All instances share the module's tracking state (intentional facade pattern).
|
|
41
|
+
*/
|
|
42
|
+
export declare function useThermsTracker(): ThermsTracker;
|
|
43
|
+
export { ThermsTracker as ThermsDeviceTrackerModuleSharedObject };
|
|
44
|
+
export declare const createThermsDeviceTrackerModuleSharedObject: typeof createThermsTracker;
|
|
45
|
+
export declare const useThermsDeviceTrackerModuleSharedObject: typeof useThermsTracker;
|
|
46
|
+
//# sourceMappingURL=ThermsDeviceTrackerModuleSharedObject.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThermsDeviceTrackerModuleSharedObject.d.ts","sourceRoot":"","sources":["../src/ThermsDeviceTrackerModuleSharedObject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAA4B,MAAM,mBAAmB,CAAC;AAE3E,OAAO,KAAK,EAAE,aAAa,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAGjG;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,OAAO,OAAO,aAAc,SAAQ,YAAY;IACrD,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,QAAQ,CAAC,cAAc,EAAE,cAAc,CAAC;IACxC,QAAQ,CAAC,YAAY,CAAC,EAAE,aAAa,CAAC;IACtC,QAAQ,CAAC,eAAe,CAAC,EAAE,cAAc,CAAC;IAC1C,QAAQ,CAAC,YAAY,CAAC,EAAE;QACtB,SAAS,EAAE,MAAM,CAAC;QAClB,UAAU,EAAE,MAAM,CAAC;QACnB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,aAAa,CAAC,EAAE,MAAM,CAAC;KACxB,CAAC;CACH;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,IAAI,aAAa,CAEnD;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,IAAI,aAAa,CAEhD;AAID,OAAO,EAAE,aAAa,IAAI,qCAAqC,EAAE,CAAC;AAClE,eAAO,MAAM,2CAA2C,4BAAsB,CAAC;AAC/E,eAAO,MAAM,wCAAwC,yBAAmB,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { useReleasingSharedObject } from 'expo-modules-core';
|
|
2
|
+
import ThermsDeviceTrackerModule from './ThermsDeviceTrackerModule';
|
|
3
|
+
/**
|
|
4
|
+
* Creates a new ThermsTracker instance (lightweight handle to shared module state).
|
|
5
|
+
* You are responsible for releasing it from memory by calling `release()` when done.
|
|
6
|
+
*/
|
|
7
|
+
export function createThermsTracker() {
|
|
8
|
+
return new ThermsDeviceTrackerModule.ThermsTracker();
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* A hook that creates a ThermsTracker instance and automatically
|
|
12
|
+
* releases it when the component unmounts.
|
|
13
|
+
*
|
|
14
|
+
* All instances share the module's tracking state (intentional facade pattern).
|
|
15
|
+
*/
|
|
16
|
+
export function useThermsTracker() {
|
|
17
|
+
return useReleasingSharedObject(() => new ThermsDeviceTrackerModule.ThermsTracker(), []);
|
|
18
|
+
}
|
|
19
|
+
// Legacy aliases (to be removed after migration)
|
|
20
|
+
// Note: the "ModuleSharedObject" name is historical; prefer ThermsTracker / useThermsTracker.
|
|
21
|
+
export { ThermsTracker as ThermsDeviceTrackerModuleSharedObject };
|
|
22
|
+
export const createThermsDeviceTrackerModuleSharedObject = createThermsTracker;
|
|
23
|
+
export const useThermsDeviceTrackerModuleSharedObject = useThermsTracker;
|
|
24
|
+
//# sourceMappingURL=ThermsDeviceTrackerModuleSharedObject.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ThermsDeviceTrackerModuleSharedObject.js","sourceRoot":"","sources":["../src/ThermsDeviceTrackerModuleSharedObject.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAG3E,OAAO,yBAAyB,MAAM,6BAA6B,CAAC;AA+BpE;;;GAGG;AACH,MAAM,UAAU,mBAAmB;IACjC,OAAO,IAAI,yBAAyB,CAAC,aAAa,EAAE,CAAC;AACvD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,wBAAwB,CAAC,GAAG,EAAE,CAAC,IAAI,yBAAyB,CAAC,aAAa,EAAE,EAAE,EAAE,CAAC,CAAC;AAC3F,CAAC;AAED,iDAAiD;AACjD,8FAA8F;AAC9F,OAAO,EAAE,aAAa,IAAI,qCAAqC,EAAE,CAAC;AAClE,MAAM,CAAC,MAAM,2CAA2C,GAAG,mBAAmB,CAAC;AAC/E,MAAM,CAAC,MAAM,wCAAwC,GAAG,gBAAgB,CAAC","sourcesContent":["import { SharedObject, useReleasingSharedObject } from 'expo-modules-core';\n\nimport type { LocationPoint, ActivityUpdate, TrackingStatus } from './ThermsDeviceTracker.types';\nimport ThermsDeviceTrackerModule from './ThermsDeviceTrackerModule';\n\n/**\n * ThermsTracker is a lightweight SharedObject handle providing on-demand live access\n * to the module's shared (singleton) tracking state.\n *\n * IMPORTANT: This is NOT a \"stateful independent instance\" per SharedObject docs pattern.\n * - Tracking session state (location, activity, isTracking, stats) is owned by the single\n * ThermsDeviceTracker native module (one CLLocationManager / FusedLocation + session buffers).\n * - All ThermsTracker instances (from `new` or the hook) proxy / reflect the same underlying state.\n * - This is intentional: the module exposes a single tracking session, matching real-world\n * device tracking semantics (you don't run multiple independent trackers in one app process).\n * - Properties are read live when accessed from JS (polling snapshots); use events (via useEvent\n * or ThermsDeviceTracker.onXXX) for push updates and re-renders.\n *\n * The handle enables `useReleasingSharedObject` lifecycle + a clean `tracker.xxx` API surface.\n * Keep the public surface: isTracking, trackingStatus, lastLocation, currentActivity, sessionStats.\n */\nexport declare class ThermsTracker extends SharedObject {\n readonly isTracking: boolean;\n readonly trackingStatus: TrackingStatus;\n readonly lastLocation?: LocationPoint;\n readonly currentActivity?: ActivityUpdate;\n readonly sessionStats?: {\n startTime: number;\n pointCount: number;\n totalSteps?: number;\n totalDistance?: number;\n };\n}\n\n/**\n * Creates a new ThermsTracker instance (lightweight handle to shared module state).\n * You are responsible for releasing it from memory by calling `release()` when done.\n */\nexport function createThermsTracker(): ThermsTracker {\n return new ThermsDeviceTrackerModule.ThermsTracker();\n}\n\n/**\n * A hook that creates a ThermsTracker instance and automatically\n * releases it when the component unmounts.\n *\n * All instances share the module's tracking state (intentional facade pattern).\n */\nexport function useThermsTracker(): ThermsTracker {\n return useReleasingSharedObject(() => new ThermsDeviceTrackerModule.ThermsTracker(), []);\n}\n\n// Legacy aliases (to be removed after migration)\n// Note: the \"ModuleSharedObject\" name is historical; prefer ThermsTracker / useThermsTracker.\nexport { ThermsTracker as ThermsDeviceTrackerModuleSharedObject };\nexport const createThermsDeviceTrackerModuleSharedObject = createThermsTracker;\nexport const useThermsDeviceTrackerModuleSharedObject = useThermsTracker;\n"]}
|