react-native-nitro-location-tracking 0.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/LICENSE +20 -0
- package/NitroLocationTracking.podspec +29 -0
- package/README.md +39 -0
- package/android/CMakeLists.txt +24 -0
- package/android/build.gradle +122 -0
- package/android/src/main/AndroidManifest.xml +18 -0
- package/android/src/main/cpp/cpp-adapter.cpp +6 -0
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/ConnectionManager.kt +137 -0
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/LocationEngine.kt +93 -0
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/LocationForegroundService.kt +65 -0
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/NativeDBWriter.kt +80 -0
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/NitroLocationTracking.kt +180 -0
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/NitroLocationTrackingPackage.kt +22 -0
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/NotificationService.kt +75 -0
- package/ios/ConnectionManager.swift +144 -0
- package/ios/LocationEngine.swift +146 -0
- package/ios/NativeDBWriter.swift +121 -0
- package/ios/NitroLocationTracking.swift +127 -0
- package/ios/NotificationService.swift +31 -0
- package/lib/module/LocationSmoother.js +33 -0
- package/lib/module/LocationSmoother.js.map +1 -0
- package/lib/module/NitroLocationTracking.nitro.js +4 -0
- package/lib/module/NitroLocationTracking.nitro.js.map +1 -0
- package/lib/module/bearing.js +19 -0
- package/lib/module/bearing.js.map +1 -0
- package/lib/module/db.js +234 -0
- package/lib/module/db.js.map +1 -0
- package/lib/module/index.js +68 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/LocationSmoother.d.ts +19 -0
- package/lib/typescript/src/LocationSmoother.d.ts.map +1 -0
- package/lib/typescript/src/NitroLocationTracking.nitro.d.ts +59 -0
- package/lib/typescript/src/NitroLocationTracking.nitro.d.ts.map +1 -0
- package/lib/typescript/src/bearing.d.ts +9 -0
- package/lib/typescript/src/bearing.d.ts.map +1 -0
- package/lib/typescript/src/db.d.ts +1 -0
- package/lib/typescript/src/db.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +21 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/nitro.json +17 -0
- package/nitrogen/generated/android/c++/JAccuracyLevel.hpp +61 -0
- package/nitrogen/generated/android/c++/JConnectionConfig.hpp +81 -0
- package/nitrogen/generated/android/c++/JConnectionState.hpp +61 -0
- package/nitrogen/generated/android/c++/JFunc_void_ConnectionState.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_LocationData.hpp +77 -0
- package/nitrogen/generated/android/c++/JFunc_void_bool.hpp +75 -0
- package/nitrogen/generated/android/c++/JFunc_void_std__string.hpp +76 -0
- package/nitrogen/generated/android/c++/JHybridNitroLocationTrackingSpec.cpp +179 -0
- package/nitrogen/generated/android/c++/JHybridNitroLocationTrackingSpec.hpp +83 -0
- package/nitrogen/generated/android/c++/JLocationConfig.hpp +91 -0
- package/nitrogen/generated/android/c++/JLocationData.hpp +81 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/AccuracyLevel.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/ConnectionConfig.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/ConnectionState.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/Func_void_ConnectionState.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/Func_void_LocationData.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/Func_void_bool.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/Func_void_std__string.kt +80 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/HybridNitroLocationTrackingSpec.kt +146 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/LocationConfig.kt +62 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/LocationData.kt +56 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/nitrolocationtrackingOnLoad.kt +35 -0
- package/nitrogen/generated/android/nitrolocationtracking+autolinking.cmake +81 -0
- package/nitrogen/generated/android/nitrolocationtracking+autolinking.gradle +27 -0
- package/nitrogen/generated/android/nitrolocationtrackingOnLoad.cpp +52 -0
- package/nitrogen/generated/android/nitrolocationtrackingOnLoad.hpp +25 -0
- package/nitrogen/generated/ios/NitroLocationTracking+autolinking.rb +60 -0
- package/nitrogen/generated/ios/NitroLocationTracking-Swift-Cxx-Bridge.cpp +73 -0
- package/nitrogen/generated/ios/NitroLocationTracking-Swift-Cxx-Bridge.hpp +231 -0
- package/nitrogen/generated/ios/NitroLocationTracking-Swift-Cxx-Umbrella.hpp +61 -0
- package/nitrogen/generated/ios/NitroLocationTrackingAutolinking.mm +33 -0
- package/nitrogen/generated/ios/NitroLocationTrackingAutolinking.swift +26 -0
- package/nitrogen/generated/ios/c++/HybridNitroLocationTrackingSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridNitroLocationTrackingSpecSwift.hpp +206 -0
- package/nitrogen/generated/ios/swift/AccuracyLevel.swift +44 -0
- package/nitrogen/generated/ios/swift/ConnectionConfig.swift +59 -0
- package/nitrogen/generated/ios/swift/ConnectionState.swift +44 -0
- package/nitrogen/generated/ios/swift/Func_void_ConnectionState.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_LocationData.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_bool.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridNitroLocationTrackingSpec.swift +72 -0
- package/nitrogen/generated/ios/swift/HybridNitroLocationTrackingSpec_cxx.swift +362 -0
- package/nitrogen/generated/ios/swift/LocationConfig.swift +69 -0
- package/nitrogen/generated/ios/swift/LocationData.swift +59 -0
- package/nitrogen/generated/shared/c++/AccuracyLevel.hpp +80 -0
- package/nitrogen/generated/shared/c++/ConnectionConfig.hpp +107 -0
- package/nitrogen/generated/shared/c++/ConnectionState.hpp +80 -0
- package/nitrogen/generated/shared/c++/HybridNitroLocationTrackingSpec.cpp +38 -0
- package/nitrogen/generated/shared/c++/HybridNitroLocationTrackingSpec.hpp +92 -0
- package/nitrogen/generated/shared/c++/LocationConfig.hpp +117 -0
- package/nitrogen/generated/shared/c++/LocationData.hpp +107 -0
- package/package.json +174 -0
- package/src/LocationSmoother.ts +46 -0
- package/src/NitroLocationTracking.nitro.ts +79 -0
- package/src/bearing.ts +22 -0
- package/src/db.ts +232 -0
- package/src/index.tsx +92 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
+
|
|
3
|
+
// ─── Enums ───────────────────────────────────────────
|
|
4
|
+
|
|
5
|
+
export type AccuracyLevel = 'high' | 'balanced' | 'low';
|
|
6
|
+
export type ConnectionState = 'connected' | 'disconnected' | 'reconnecting';
|
|
7
|
+
|
|
8
|
+
// ─── Types ───────────────────────────────────────────
|
|
9
|
+
|
|
10
|
+
export interface LocationData {
|
|
11
|
+
latitude: number;
|
|
12
|
+
longitude: number;
|
|
13
|
+
altitude: number;
|
|
14
|
+
speed: number; // m/s
|
|
15
|
+
bearing: number; // degrees
|
|
16
|
+
accuracy: number; // meters
|
|
17
|
+
timestamp: number; // unix ms
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export interface LocationConfig {
|
|
21
|
+
desiredAccuracy: AccuracyLevel;
|
|
22
|
+
distanceFilter: number; // meters
|
|
23
|
+
intervalMs: number; // Android only
|
|
24
|
+
fastestIntervalMs: number; // Android only
|
|
25
|
+
stopTimeout: number; // minutes before declaring stopped
|
|
26
|
+
stopOnTerminate: boolean; // keep tracking after app close (Android)
|
|
27
|
+
startOnBoot: boolean; // restart tracking after reboot (Android)
|
|
28
|
+
foregroundNotificationTitle: string;
|
|
29
|
+
foregroundNotificationText: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface ConnectionConfig {
|
|
33
|
+
wsUrl: string;
|
|
34
|
+
restUrl: string;
|
|
35
|
+
authToken: string;
|
|
36
|
+
reconnectIntervalMs: number;
|
|
37
|
+
maxReconnectAttempts: number;
|
|
38
|
+
batchSize: number; // locations per batch upload
|
|
39
|
+
syncIntervalMs: number; // how often to flush queue
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type LocationCallback = (location: LocationData) => void;
|
|
43
|
+
export type ConnectionStateCallback = (state: ConnectionState) => void;
|
|
44
|
+
export type MessageCallback = (message: string) => void;
|
|
45
|
+
|
|
46
|
+
// ─── Hybrid Object ──────────────────────────────────
|
|
47
|
+
|
|
48
|
+
export interface NitroLocationTracking
|
|
49
|
+
extends HybridObject<{ ios: 'swift'; android: 'kotlin' }> {
|
|
50
|
+
// === Location Engine ===
|
|
51
|
+
configure(config: LocationConfig): void;
|
|
52
|
+
startTracking(): void;
|
|
53
|
+
stopTracking(): void;
|
|
54
|
+
getCurrentLocation(): Promise<LocationData>;
|
|
55
|
+
isTracking(): boolean;
|
|
56
|
+
|
|
57
|
+
onLocation(callback: LocationCallback): void;
|
|
58
|
+
onMotionChange(callback: (isMoving: boolean) => void): void;
|
|
59
|
+
|
|
60
|
+
// === Connection Manager ===
|
|
61
|
+
configureConnection(config: ConnectionConfig): void;
|
|
62
|
+
connectWebSocket(): void;
|
|
63
|
+
disconnectWebSocket(): void;
|
|
64
|
+
sendMessage(message: string): void;
|
|
65
|
+
getConnectionState(): ConnectionState;
|
|
66
|
+
|
|
67
|
+
onConnectionStateChange(callback: ConnectionStateCallback): void;
|
|
68
|
+
onMessage(callback: MessageCallback): void;
|
|
69
|
+
|
|
70
|
+
// === Sync Control ===
|
|
71
|
+
forceSync(): Promise<boolean>;
|
|
72
|
+
|
|
73
|
+
// === Notifications ===
|
|
74
|
+
showLocalNotification(title: string, body: string): void;
|
|
75
|
+
updateForegroundNotification(title: string, body: string): void;
|
|
76
|
+
|
|
77
|
+
// === Lifecycle ===
|
|
78
|
+
destroy(): void;
|
|
79
|
+
}
|
package/src/bearing.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export function shortestRotation(from: number, to: number): number {
|
|
2
|
+
let diff = to - from;
|
|
3
|
+
while (diff > 180) diff -= 360;
|
|
4
|
+
while (diff < -180) diff += 360;
|
|
5
|
+
return from + diff;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function calculateBearing(
|
|
9
|
+
from: { latitude: number; longitude: number },
|
|
10
|
+
to: { latitude: number; longitude: number }
|
|
11
|
+
): number {
|
|
12
|
+
const toRad = (d: number) => (d * Math.PI) / 180;
|
|
13
|
+
const toDeg = (r: number) => (r * 180) / Math.PI;
|
|
14
|
+
const dLon = toRad(to.longitude - from.longitude);
|
|
15
|
+
const lat1 = toRad(from.latitude);
|
|
16
|
+
const lat2 = toRad(to.latitude);
|
|
17
|
+
const y = Math.sin(dLon) * Math.cos(lat2);
|
|
18
|
+
const x =
|
|
19
|
+
Math.cos(lat1) * Math.sin(lat2) -
|
|
20
|
+
Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
|
|
21
|
+
return (toDeg(Math.atan2(y, x)) + 360) % 360;
|
|
22
|
+
}
|
package/src/db.ts
ADDED
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
// import { open } from 'react-native-nitro-sqlite'
|
|
2
|
+
|
|
3
|
+
// // Open the SAME database that native module writes to
|
|
4
|
+
// export const db = open({ name: 'nitro_location.db' })
|
|
5
|
+
|
|
6
|
+
// // Enable WAL for safe concurrent access with native writer
|
|
7
|
+
// db.execute('PRAGMA journal_mode = WAL')
|
|
8
|
+
|
|
9
|
+
// // ─── Additional Tables (JS-managed) ────────────────
|
|
10
|
+
|
|
11
|
+
// db.execute(`
|
|
12
|
+
// CREATE TABLE IF NOT EXISTS rides (
|
|
13
|
+
// id TEXT PRIMARY KEY,
|
|
14
|
+
// driver_id TEXT,
|
|
15
|
+
// rider_id TEXT,
|
|
16
|
+
// status TEXT DEFAULT 'pending',
|
|
17
|
+
// pickup_lat REAL, pickup_lng REAL,
|
|
18
|
+
// dropoff_lat REAL, dropoff_lng REAL,
|
|
19
|
+
// pickup_address TEXT, dropoff_address TEXT,
|
|
20
|
+
// fare_amount REAL,
|
|
21
|
+
// distance_km REAL,
|
|
22
|
+
// duration_minutes REAL,
|
|
23
|
+
// started_at INTEGER,
|
|
24
|
+
// completed_at INTEGER,
|
|
25
|
+
// created_at INTEGER DEFAULT (strftime('%s','now') * 1000)
|
|
26
|
+
// )
|
|
27
|
+
// `)
|
|
28
|
+
|
|
29
|
+
// db.execute(`
|
|
30
|
+
// CREATE TABLE IF NOT EXISTS earnings (
|
|
31
|
+
// id TEXT PRIMARY KEY,
|
|
32
|
+
// date TEXT UNIQUE,
|
|
33
|
+
// ride_count INTEGER DEFAULT 0,
|
|
34
|
+
// total_amount REAL DEFAULT 0,
|
|
35
|
+
// total_distance REAL DEFAULT 0,
|
|
36
|
+
// online_hours REAL DEFAULT 0
|
|
37
|
+
// )
|
|
38
|
+
// `)
|
|
39
|
+
|
|
40
|
+
// db.execute(`
|
|
41
|
+
// CREATE TABLE IF NOT EXISTS settings (
|
|
42
|
+
// key TEXT PRIMARY KEY,
|
|
43
|
+
// value TEXT
|
|
44
|
+
// )
|
|
45
|
+
// `)
|
|
46
|
+
|
|
47
|
+
// // ─── Query Helpers — Locations ──────────────────────
|
|
48
|
+
|
|
49
|
+
// export function getRecentLocations(limit = 100) {
|
|
50
|
+
// return db.execute(
|
|
51
|
+
// 'SELECT * FROM locations ORDER BY timestamp DESC LIMIT ?',
|
|
52
|
+
// [limit]
|
|
53
|
+
// )
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
// export function getRideLocations(rideId: string) {
|
|
57
|
+
// return db.execute(
|
|
58
|
+
// `
|
|
59
|
+
// SELECT latitude, longitude, speed, bearing, timestamp
|
|
60
|
+
// FROM locations WHERE ride_id = ? ORDER BY timestamp ASC
|
|
61
|
+
// `,
|
|
62
|
+
// [rideId]
|
|
63
|
+
// )
|
|
64
|
+
// }
|
|
65
|
+
|
|
66
|
+
// export function getLocationsBetween(startMs: number, endMs: number) {
|
|
67
|
+
// return db.execute(
|
|
68
|
+
// `
|
|
69
|
+
// SELECT * FROM locations
|
|
70
|
+
// WHERE timestamp BETWEEN ? AND ? ORDER BY timestamp ASC
|
|
71
|
+
// `,
|
|
72
|
+
// [startMs, endMs]
|
|
73
|
+
// )
|
|
74
|
+
// }
|
|
75
|
+
|
|
76
|
+
// export function getUnsyncedCount(): number {
|
|
77
|
+
// return db.execute(
|
|
78
|
+
// 'SELECT COUNT(*) as count FROM locations WHERE synced = 0'
|
|
79
|
+
// ).rows.item(0)!.count as number
|
|
80
|
+
// }
|
|
81
|
+
|
|
82
|
+
// // ─── Query Helpers — Analytics ──────────────────────
|
|
83
|
+
|
|
84
|
+
// export function getTodayStats() {
|
|
85
|
+
// const today = new Date().toISOString().split('T')[0]!
|
|
86
|
+
// return db.execute(
|
|
87
|
+
// `
|
|
88
|
+
// SELECT COUNT(*) as trips,
|
|
89
|
+
// COALESCE(SUM(fare_amount), 0) as earnings,
|
|
90
|
+
// COALESCE(SUM(distance_km), 0) as distance,
|
|
91
|
+
// COALESCE(SUM(duration_minutes), 0) as minutes
|
|
92
|
+
// FROM rides
|
|
93
|
+
// WHERE date(started_at / 1000, 'unixepoch') = ?
|
|
94
|
+
// AND status = 'completed'
|
|
95
|
+
// `,
|
|
96
|
+
// [today]
|
|
97
|
+
// )
|
|
98
|
+
// }
|
|
99
|
+
|
|
100
|
+
// export function getWeeklyEarnings() {
|
|
101
|
+
// return db.execute(
|
|
102
|
+
// `
|
|
103
|
+
// SELECT date(started_at / 1000, 'unixepoch') as day,
|
|
104
|
+
// COUNT(*) as trips, SUM(fare_amount) as earnings,
|
|
105
|
+
// SUM(distance_km) as distance
|
|
106
|
+
// FROM rides WHERE started_at > ? AND status = 'completed'
|
|
107
|
+
// GROUP BY day ORDER BY day ASC
|
|
108
|
+
// `,
|
|
109
|
+
// [Date.now() - 7 * 86400000]
|
|
110
|
+
// )
|
|
111
|
+
// }
|
|
112
|
+
|
|
113
|
+
// export function getSpeedHistory(lastHours = 1) {
|
|
114
|
+
// return db.execute(
|
|
115
|
+
// `
|
|
116
|
+
// SELECT CAST(timestamp / 60000 AS INTEGER) * 60000 as minute,
|
|
117
|
+
// AVG(speed) as avg_speed, MAX(speed) as max_speed
|
|
118
|
+
// FROM locations WHERE timestamp > ?
|
|
119
|
+
// GROUP BY minute ORDER BY minute ASC
|
|
120
|
+
// `,
|
|
121
|
+
// [Date.now() - lastHours * 3600000]
|
|
122
|
+
// )
|
|
123
|
+
// }
|
|
124
|
+
|
|
125
|
+
// export function getPickupHeatmap(limit = 50) {
|
|
126
|
+
// return db.execute(
|
|
127
|
+
// `
|
|
128
|
+
// SELECT ROUND(pickup_lat, 3) as lat, ROUND(pickup_lng, 3) as lng,
|
|
129
|
+
// COUNT(*) as ride_count
|
|
130
|
+
// FROM rides WHERE status = 'completed'
|
|
131
|
+
// GROUP BY lat, lng ORDER BY ride_count DESC LIMIT ?
|
|
132
|
+
// `,
|
|
133
|
+
// [limit]
|
|
134
|
+
// )
|
|
135
|
+
// }
|
|
136
|
+
|
|
137
|
+
// export function getPeakHours() {
|
|
138
|
+
// return db.execute(`
|
|
139
|
+
// SELECT CAST(strftime('%H', started_at / 1000, 'unixepoch') AS INTEGER) as hour,
|
|
140
|
+
// COUNT(*) as trips, AVG(fare_amount) as avg_fare
|
|
141
|
+
// FROM rides WHERE status = 'completed'
|
|
142
|
+
// GROUP BY hour ORDER BY hour ASC
|
|
143
|
+
// `)
|
|
144
|
+
// }
|
|
145
|
+
|
|
146
|
+
// // ─── Query Helpers — Ride Management ────────────────
|
|
147
|
+
|
|
148
|
+
// export function createRide(ride: {
|
|
149
|
+
// id: string
|
|
150
|
+
// driverId?: string
|
|
151
|
+
// riderId?: string
|
|
152
|
+
// pickupLat: number
|
|
153
|
+
// pickupLng: number
|
|
154
|
+
// pickupAddress: string
|
|
155
|
+
// dropoffLat: number
|
|
156
|
+
// dropoffLng: number
|
|
157
|
+
// dropoffAddress: string
|
|
158
|
+
// }) {
|
|
159
|
+
// return db.execute(
|
|
160
|
+
// `
|
|
161
|
+
// INSERT INTO rides (id, driver_id, rider_id, status,
|
|
162
|
+
// pickup_lat, pickup_lng, pickup_address,
|
|
163
|
+
// dropoff_lat, dropoff_lng, dropoff_address, started_at)
|
|
164
|
+
// VALUES (?, ?, ?, 'active', ?, ?, ?, ?, ?, ?, ?)
|
|
165
|
+
// `,
|
|
166
|
+
// [
|
|
167
|
+
// ride.id,
|
|
168
|
+
// ride.driverId ?? null,
|
|
169
|
+
// ride.riderId ?? null,
|
|
170
|
+
// ride.pickupLat,
|
|
171
|
+
// ride.pickupLng,
|
|
172
|
+
// ride.pickupAddress,
|
|
173
|
+
// ride.dropoffLat,
|
|
174
|
+
// ride.dropoffLng,
|
|
175
|
+
// ride.dropoffAddress,
|
|
176
|
+
// Date.now(),
|
|
177
|
+
// ]
|
|
178
|
+
// )
|
|
179
|
+
// }
|
|
180
|
+
|
|
181
|
+
// export function completeRide(
|
|
182
|
+
// rideId: string,
|
|
183
|
+
// fare: number,
|
|
184
|
+
// distKm: number
|
|
185
|
+
// ) {
|
|
186
|
+
// const now = Date.now()
|
|
187
|
+
// db.execute(
|
|
188
|
+
// `
|
|
189
|
+
// UPDATE rides SET status = 'completed', fare_amount = ?,
|
|
190
|
+
// distance_km = ?, completed_at = ?,
|
|
191
|
+
// duration_minutes = (? - started_at) / 60000.0
|
|
192
|
+
// WHERE id = ?
|
|
193
|
+
// `,
|
|
194
|
+
// [fare, distKm, now, now, rideId]
|
|
195
|
+
// )
|
|
196
|
+
// }
|
|
197
|
+
|
|
198
|
+
// export function getRideHistory(limit = 20) {
|
|
199
|
+
// return db.execute(
|
|
200
|
+
// `
|
|
201
|
+
// SELECT * FROM rides WHERE status = 'completed'
|
|
202
|
+
// ORDER BY completed_at DESC LIMIT ?
|
|
203
|
+
// `,
|
|
204
|
+
// [limit]
|
|
205
|
+
// )
|
|
206
|
+
// }
|
|
207
|
+
|
|
208
|
+
// export function getRideWithLocations(rideId: string) {
|
|
209
|
+
// const ride = db.execute('SELECT * FROM rides WHERE id = ?', [rideId])
|
|
210
|
+
// const locs = db.execute(
|
|
211
|
+
// `
|
|
212
|
+
// SELECT latitude, longitude, speed, bearing, timestamp
|
|
213
|
+
// FROM locations WHERE ride_id = ? ORDER BY timestamp ASC
|
|
214
|
+
// `,
|
|
215
|
+
// [rideId]
|
|
216
|
+
// )
|
|
217
|
+
// return { ride: ride.rows.item(0), locations: locs.rows._array }
|
|
218
|
+
// }
|
|
219
|
+
|
|
220
|
+
// // ─── Settings Helper ────────────────────────────────
|
|
221
|
+
|
|
222
|
+
// export function getSetting(key: string): string | null {
|
|
223
|
+
// const r = db.execute('SELECT value FROM settings WHERE key = ?', [key])
|
|
224
|
+
// return r.rows.length > 0 ? (r.rows.item(0)!.value as string) : null
|
|
225
|
+
// }
|
|
226
|
+
|
|
227
|
+
// export function setSetting(key: string, value: string) {
|
|
228
|
+
// db.execute(
|
|
229
|
+
// 'INSERT OR REPLACE INTO settings (key, value) VALUES (?, ?)',
|
|
230
|
+
// [key, value]
|
|
231
|
+
// )
|
|
232
|
+
// }
|
package/src/index.tsx
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
2
|
+
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
|
+
import type {
|
|
4
|
+
NitroLocationTracking,
|
|
5
|
+
LocationData,
|
|
6
|
+
LocationConfig,
|
|
7
|
+
ConnectionConfig,
|
|
8
|
+
} from './NitroLocationTracking.nitro';
|
|
9
|
+
|
|
10
|
+
const NitroLocationModule =
|
|
11
|
+
NitroModules.createHybridObject<NitroLocationTracking>(
|
|
12
|
+
'NitroLocationTracking'
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
export default NitroLocationModule;
|
|
16
|
+
export { LocationSmoother } from './LocationSmoother';
|
|
17
|
+
export { shortestRotation, calculateBearing } from './bearing';
|
|
18
|
+
// export * from './db'
|
|
19
|
+
export type {
|
|
20
|
+
NitroLocationTracking,
|
|
21
|
+
LocationData,
|
|
22
|
+
LocationConfig,
|
|
23
|
+
ConnectionConfig,
|
|
24
|
+
} from './NitroLocationTracking.nitro';
|
|
25
|
+
|
|
26
|
+
export function useDriverLocation(config: LocationConfig) {
|
|
27
|
+
const [location, setLocation] = useState<LocationData | null>(null);
|
|
28
|
+
const [isMoving, setIsMoving] = useState(false);
|
|
29
|
+
const [isTracking, setIsTracking] = useState(false);
|
|
30
|
+
|
|
31
|
+
// Stabilize config by value so the effect doesn't re-run on every render
|
|
32
|
+
const configJson = JSON.stringify(config);
|
|
33
|
+
|
|
34
|
+
// Keep a ref to track whether we started, so cleanup only stops if we did
|
|
35
|
+
const trackingRef = useRef(false);
|
|
36
|
+
|
|
37
|
+
useEffect(() => {
|
|
38
|
+
const parsed = JSON.parse(configJson) as LocationConfig;
|
|
39
|
+
NitroLocationModule.configure(parsed);
|
|
40
|
+
NitroLocationModule.onLocation(setLocation);
|
|
41
|
+
NitroLocationModule.onMotionChange(setIsMoving);
|
|
42
|
+
return () => {
|
|
43
|
+
if (trackingRef.current) {
|
|
44
|
+
NitroLocationModule.stopTracking();
|
|
45
|
+
trackingRef.current = false;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
}, [configJson]);
|
|
49
|
+
|
|
50
|
+
return {
|
|
51
|
+
location,
|
|
52
|
+
isMoving,
|
|
53
|
+
isTracking,
|
|
54
|
+
startTracking: useCallback(() => {
|
|
55
|
+
NitroLocationModule.startTracking();
|
|
56
|
+
trackingRef.current = true;
|
|
57
|
+
setIsTracking(true);
|
|
58
|
+
}, []),
|
|
59
|
+
stopTracking: useCallback(() => {
|
|
60
|
+
NitroLocationModule.stopTracking();
|
|
61
|
+
trackingRef.current = false;
|
|
62
|
+
setIsTracking(false);
|
|
63
|
+
}, []),
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function useRideConnection(config: ConnectionConfig) {
|
|
68
|
+
const [connectionState, setConnectionState] = useState<
|
|
69
|
+
'connected' | 'disconnected' | 'reconnecting'
|
|
70
|
+
>('disconnected');
|
|
71
|
+
const [lastMessage, setLastMessage] = useState<string | null>(null);
|
|
72
|
+
|
|
73
|
+
useEffect(() => {
|
|
74
|
+
NitroLocationModule.configureConnection(config);
|
|
75
|
+
NitroLocationModule.onConnectionStateChange(setConnectionState);
|
|
76
|
+
NitroLocationModule.onMessage(setLastMessage);
|
|
77
|
+
return () => {
|
|
78
|
+
NitroLocationModule.disconnectWebSocket();
|
|
79
|
+
};
|
|
80
|
+
}, [config]);
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
connectionState,
|
|
84
|
+
lastMessage,
|
|
85
|
+
connect: useCallback(() => NitroLocationModule.connectWebSocket(), []),
|
|
86
|
+
disconnect: useCallback(
|
|
87
|
+
() => NitroLocationModule.disconnectWebSocket(),
|
|
88
|
+
[]
|
|
89
|
+
),
|
|
90
|
+
send: useCallback((m: string) => NitroLocationModule.sendMessage(m), []),
|
|
91
|
+
};
|
|
92
|
+
}
|