react-native-nitro-location-tracking 0.1.18 → 0.1.21
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 +117 -0
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/LocationEngine.kt +11 -1
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/MockLocationMonitor.kt +55 -82
- package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/NitroLocationTracking.kt +22 -0
- package/ios/LiveActivityManager.swift +116 -0
- package/ios/NitroLocationTracking.swift +54 -0
- package/ios/widget/CourierWidgetLiveActivity.swift +226 -0
- package/lib/module/index.js +10 -0
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/src/NitroLocationTracking.nitro.d.ts +3 -0
- package/lib/typescript/src/NitroLocationTracking.nitro.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +7 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/nitrogen/generated/android/c++/JHybridNitroLocationTrackingSpec.cpp +12 -0
- package/nitrogen/generated/android/c++/JHybridNitroLocationTrackingSpec.hpp +3 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/nitrolocationtracking/HybridNitroLocationTrackingSpec.kt +12 -0
- package/nitrogen/generated/ios/c++/HybridNitroLocationTrackingSpecSwift.hpp +18 -0
- package/nitrogen/generated/ios/swift/HybridNitroLocationTrackingSpec.swift +3 -0
- package/nitrogen/generated/ios/swift/HybridNitroLocationTrackingSpec_cxx.swift +33 -0
- package/nitrogen/generated/shared/c++/HybridNitroLocationTrackingSpec.cpp +3 -0
- package/nitrogen/generated/shared/c++/HybridNitroLocationTrackingSpec.hpp +3 -0
- package/package.json +1 -1
- package/src/NitroLocationTracking.nitro.ts +19 -0
- package/src/index.tsx +16 -0
package/README.md
CHANGED
|
@@ -14,6 +14,7 @@ A high-performance React Native location tracking library built with [Nitro Modu
|
|
|
14
14
|
- **Smooth map marker animations** via `LocationSmoother`
|
|
15
15
|
- **Bearing calculation** utilities for rotation/heading
|
|
16
16
|
- **Foreground notifications** (Android foreground service, iOS local notifications)
|
|
17
|
+
- **Live Activity / Dynamic Island** (iOS 16.2+) — show a delivery card on the Lock Screen and Dynamic Island that updates in real time
|
|
17
18
|
- **Permission helpers** for fine, background, and notification permissions
|
|
18
19
|
- **Built on Nitro Modules** for near-native performance via JSI
|
|
19
20
|
|
|
@@ -597,6 +598,117 @@ NitroLocationModule.onPermissionStatusChange((status) => {
|
|
|
597
598
|
| iOS | `locationManagerDidChangeAuthorization` delegate | Immediately when the user changes permission (system dialog, Settings, MDM) |
|
|
598
599
|
| Android | `ProcessLifecycleOwner` lifecycle observer | When the app returns to foreground after the user changes permission in Settings |
|
|
599
600
|
|
|
601
|
+
### Live Activity (iOS Dynamic Island & Lock Screen)
|
|
602
|
+
|
|
603
|
+
Show a live delivery card on the iOS Lock Screen and Dynamic Island that updates in real time as the order progresses. Android calls are safe no-ops.
|
|
604
|
+
|
|
605
|
+
#### iOS Prerequisites (one-time setup)
|
|
606
|
+
|
|
607
|
+
1. **Create a Widget Extension** in Xcode:
|
|
608
|
+
`File → New → Target → Widget Extension` — uncheck "Include Configuration App Intent"
|
|
609
|
+
|
|
610
|
+
2. **Copy the widget file** from the published package into your widget extension folder:
|
|
611
|
+
|
|
612
|
+
```sh
|
|
613
|
+
# from your project root
|
|
614
|
+
cp node_modules/react-native-nitro-location-tracking/ios/widget/CourierWidgetLiveActivity.swift \
|
|
615
|
+
ios/YourWidgetExtension/CourierWidgetLiveActivity.swift
|
|
616
|
+
```
|
|
617
|
+
|
|
618
|
+
Then in Xcode, add the copied file to the widget extension target's **Compile Sources**.
|
|
619
|
+
|
|
620
|
+
3. **Replace** the generated bundle file (`YourWidgetBundle.swift`) with:
|
|
621
|
+
|
|
622
|
+
```swift
|
|
623
|
+
import WidgetKit
|
|
624
|
+
import SwiftUI
|
|
625
|
+
|
|
626
|
+
@main
|
|
627
|
+
struct YourWidgetBundle: WidgetBundle {
|
|
628
|
+
var body: some Widget {
|
|
629
|
+
CourierWidgetLiveActivity()
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
4. **Delete** the other files Xcode generated (`YourWidget.swift`, `YourWidgetControl.swift`, `AppIntent.swift`).
|
|
635
|
+
|
|
636
|
+
5. **Add to your main app's `Info.plist`**:
|
|
637
|
+
|
|
638
|
+
```xml
|
|
639
|
+
<key>NSSupportsLiveActivities</key>
|
|
640
|
+
<true/>
|
|
641
|
+
```
|
|
642
|
+
|
|
643
|
+
6. **Verify embedding**: Main app target → **General** → **Frameworks, Libraries, and Embedded Content** → your `.appex` should be listed as **Embed Without Signing**.
|
|
644
|
+
|
|
645
|
+
7. On the device, go to **Settings → [Your App] → Live Activities** and make sure it is **ON**.
|
|
646
|
+
|
|
647
|
+
> Live Activities do not work in the iOS Simulator. Test on a real device running iOS 16.2+.
|
|
648
|
+
> Dynamic Island UI requires iPhone 14 Pro or later.
|
|
649
|
+
|
|
650
|
+
#### Usage
|
|
651
|
+
|
|
652
|
+
```tsx
|
|
653
|
+
import NitroLocation, {
|
|
654
|
+
isLiveActivitySupported,
|
|
655
|
+
} from 'react-native-nitro-location-tracking';
|
|
656
|
+
import type { LiveActivityState } from 'react-native-nitro-location-tracking';
|
|
657
|
+
|
|
658
|
+
// Guard — only call on iOS
|
|
659
|
+
if (!isLiveActivitySupported()) return;
|
|
660
|
+
|
|
661
|
+
// Start a Live Activity
|
|
662
|
+
try {
|
|
663
|
+
NitroLocation.startLiveActivity(
|
|
664
|
+
'ORD-9981', // orderId
|
|
665
|
+
'John Doe', // customerName
|
|
666
|
+
'42 Elm Street', // deliveryAddress
|
|
667
|
+
2, // orderCount
|
|
668
|
+
'picking_up', // status
|
|
669
|
+
'Picking up order', // statusText (localised label shown on widget)
|
|
670
|
+
18, // estimatedMinutes
|
|
671
|
+
4500 // distanceMeters
|
|
672
|
+
);
|
|
673
|
+
} catch (e) {
|
|
674
|
+
// Thrown when Live Activities are disabled in Settings
|
|
675
|
+
Alert.alert('Live Activity', String(e));
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
// Update as the delivery progresses
|
|
679
|
+
const nextState: LiveActivityState = {
|
|
680
|
+
status: 'on_the_way',
|
|
681
|
+
statusText: 'On the way',
|
|
682
|
+
estimatedMinutes: 12,
|
|
683
|
+
distanceMeters: 2800,
|
|
684
|
+
};
|
|
685
|
+
NitroLocation.updateLiveActivity(
|
|
686
|
+
nextState.status,
|
|
687
|
+
nextState.statusText,
|
|
688
|
+
nextState.estimatedMinutes,
|
|
689
|
+
nextState.distanceMeters
|
|
690
|
+
);
|
|
691
|
+
|
|
692
|
+
// End when delivered
|
|
693
|
+
NitroLocation.endLiveActivity();
|
|
694
|
+
```
|
|
695
|
+
|
|
696
|
+
**Status values and their meaning:**
|
|
697
|
+
|
|
698
|
+
| `status` | Widget emoji | Typical use |
|
|
699
|
+
| ------------- | ------------ | ------------------------------ |
|
|
700
|
+
| `picking_up` | 📦 | Courier heading to restaurant |
|
|
701
|
+
| `on_the_way` | 🚗 | En route to customer |
|
|
702
|
+
| `arriving` | 🏁 | Less than ~1 min away |
|
|
703
|
+
| `delivered` | ✅ | Order handed over |
|
|
704
|
+
|
|
705
|
+
**Platform behavior:**
|
|
706
|
+
|
|
707
|
+
| Platform | Behavior |
|
|
708
|
+
| -------- | -------- |
|
|
709
|
+
| iOS 16.2+ | Shows on Lock Screen; Dynamic Island on iPhone 14 Pro+ |
|
|
710
|
+
| Android | No-op — calls are safe to make cross-platform |
|
|
711
|
+
|
|
600
712
|
## API Reference
|
|
601
713
|
|
|
602
714
|
### Types
|
|
@@ -741,6 +853,9 @@ type PermissionStatus =
|
|
|
741
853
|
| `getLocationPermissionStatus()` | `PermissionStatus` | Check current location permission without prompting |
|
|
742
854
|
| `requestLocationPermission()` | `Promise<PermissionStatus>` | Request location permission and return the resulting status |
|
|
743
855
|
| `onPermissionStatusChange(callback)` | `void` | Register a callback that fires when location permission status changes |
|
|
856
|
+
| `startLiveActivity(orderId, customerName, deliveryAddress, orderCount, status, statusText, estimatedMinutes, distanceMeters)` | `void` | Start a Live Activity on the Lock Screen / Dynamic Island (iOS 16.2+ only; no-op on Android) |
|
|
857
|
+
| `updateLiveActivity(status, statusText, estimatedMinutes, distanceMeters)` | `void` | Push a state update to the running Live Activity |
|
|
858
|
+
| `endLiveActivity()` | `void` | End and dismiss the Live Activity immediately |
|
|
744
859
|
| `showLocalNotification(title, body)` | `void` | Show a local notification |
|
|
745
860
|
| `updateForegroundNotification(title, body)` | `void` | Update the foreground service notification |
|
|
746
861
|
| `destroy()` | `void` | Stop tracking and disconnect |
|
|
@@ -753,6 +868,8 @@ type PermissionStatus =
|
|
|
753
868
|
| `calculateBearing(from, to)` | Calculate bearing between two coordinates (degrees, 0-360) |
|
|
754
869
|
| `shortestRotation(from, to)` | Calculate shortest rotation path to avoid spinning |
|
|
755
870
|
| `requestLocationPermission()` | Request location + notification permissions (Android) |
|
|
871
|
+
| `isLiveActivitySupported()` | Returns `true` on iOS, `false` on Android |
|
|
872
|
+
| `LiveActivityState` | Type for `{ status, statusText, estimatedMinutes, distanceMeters }` passed to start/update |
|
|
756
873
|
|
|
757
874
|
### Pure C++ Math Engine
|
|
758
875
|
|
|
@@ -21,12 +21,14 @@ class LocationEngine(private val context: Context) {
|
|
|
21
21
|
|
|
22
22
|
var onLocation: ((LocationData) -> Unit)? = null
|
|
23
23
|
var onMotionChange: ((Boolean) -> Unit)? = null
|
|
24
|
+
var onMockLocationChanged: ((Boolean) -> Unit)? = null
|
|
24
25
|
var dbWriter: NativeDBWriter? = null
|
|
25
26
|
// var currentRideId: String? = null
|
|
26
27
|
var rejectMockLocations: Boolean = false
|
|
27
28
|
val speedMonitor = SpeedMonitor()
|
|
28
29
|
val tripCalculator = TripCalculator()
|
|
29
30
|
private var lastSpeed = 0f
|
|
31
|
+
private var lastMockState: Boolean? = null
|
|
30
32
|
private var tracking = false
|
|
31
33
|
var lastLocation: Location? = null
|
|
32
34
|
private set
|
|
@@ -116,8 +118,16 @@ class LocationEngine(private val context: Context) {
|
|
|
116
118
|
lastLocation = location
|
|
117
119
|
val data = locationToData(location)
|
|
118
120
|
|
|
121
|
+
// Check mock location state change and notify
|
|
122
|
+
val isMock = data.isMockLocation == true
|
|
123
|
+
if (isMock != lastMockState) {
|
|
124
|
+
lastMockState = isMock
|
|
125
|
+
Log.d(TAG, "Mock location state changed: $isMock")
|
|
126
|
+
onMockLocationChanged?.invoke(isMock)
|
|
127
|
+
}
|
|
128
|
+
|
|
119
129
|
// Skip mock locations if rejection is enabled
|
|
120
|
-
if (rejectMockLocations &&
|
|
130
|
+
if (rejectMockLocations && isMock) {
|
|
121
131
|
Log.d(TAG, "Rejecting mock location")
|
|
122
132
|
return
|
|
123
133
|
}
|
package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/MockLocationMonitor.kt
CHANGED
|
@@ -1,23 +1,26 @@
|
|
|
1
1
|
package com.margelo.nitro.nitrolocationtracking
|
|
2
2
|
|
|
3
3
|
import android.annotation.SuppressLint
|
|
4
|
-
import android.app.AppOpsManager
|
|
5
4
|
import android.content.Context
|
|
5
|
+
import android.location.Location
|
|
6
6
|
import android.os.Build
|
|
7
7
|
import android.os.Handler
|
|
8
8
|
import android.os.Looper
|
|
9
9
|
import android.provider.Settings
|
|
10
10
|
import android.util.Log
|
|
11
|
+
import com.google.android.gms.location.CurrentLocationRequest
|
|
12
|
+
import com.google.android.gms.location.LocationServices
|
|
13
|
+
import com.google.android.gms.location.Priority
|
|
11
14
|
|
|
12
15
|
/**
|
|
13
|
-
* Periodically
|
|
14
|
-
*
|
|
15
|
-
* mock location apps (e.g. Fake GPS, Mock Locations) at the system level.
|
|
16
|
+
* Periodically checks whether mock/fake GPS is actively being used on the device.
|
|
17
|
+
* Works independently of location tracking — can be used on login/verify screens.
|
|
16
18
|
*
|
|
17
|
-
*
|
|
19
|
+
* Detection strategy:
|
|
18
20
|
* - Pre-API 23: Settings.Secure.ALLOW_MOCK_LOCATION
|
|
19
|
-
* - API 23+:
|
|
20
|
-
*
|
|
21
|
+
* - API 23+: Requests a single location via FusedLocationProviderClient and checks
|
|
22
|
+
* Location.isMock / isFromMockProvider. This is the only reliable way to know
|
|
23
|
+
* if mock location is currently ACTIVE (not just if a mock app is installed).
|
|
21
24
|
*
|
|
22
25
|
* The callback fires only when the state changes (deduplicated).
|
|
23
26
|
*/
|
|
@@ -25,11 +28,11 @@ class MockLocationMonitor(private val context: Context) {
|
|
|
25
28
|
|
|
26
29
|
companion object {
|
|
27
30
|
private const val TAG = "MockLocationMonitor"
|
|
28
|
-
/** Default poll interval in milliseconds */
|
|
29
31
|
private const val DEFAULT_POLL_INTERVAL_MS = 3000L
|
|
30
32
|
}
|
|
31
33
|
|
|
32
34
|
private val mainHandler = Handler(Looper.getMainLooper())
|
|
35
|
+
private val fusedClient = LocationServices.getFusedLocationProviderClient(context)
|
|
33
36
|
private var callback: ((Boolean) -> Unit)? = null
|
|
34
37
|
private var lastState: Boolean? = null
|
|
35
38
|
private var polling = false
|
|
@@ -38,18 +41,15 @@ class MockLocationMonitor(private val context: Context) {
|
|
|
38
41
|
private val pollRunnable = object : Runnable {
|
|
39
42
|
override fun run() {
|
|
40
43
|
if (!polling) return
|
|
41
|
-
|
|
44
|
+
checkMockLocation()
|
|
42
45
|
mainHandler.postDelayed(this, pollIntervalMs)
|
|
43
46
|
}
|
|
44
47
|
}
|
|
45
48
|
|
|
46
49
|
fun setCallback(callback: (Boolean) -> Unit) {
|
|
47
50
|
this.callback = callback
|
|
48
|
-
//
|
|
49
|
-
|
|
50
|
-
lastState = current
|
|
51
|
-
callback.invoke(current)
|
|
52
|
-
// Start polling
|
|
51
|
+
// Kick off an immediate check
|
|
52
|
+
checkMockLocation()
|
|
53
53
|
startPolling()
|
|
54
54
|
}
|
|
55
55
|
|
|
@@ -66,93 +66,66 @@ class MockLocationMonitor(private val context: Context) {
|
|
|
66
66
|
Log.d(TAG, "Mock location polling stopped")
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
-
private fun
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
callback?.invoke(current)
|
|
69
|
+
private fun notifyIfChanged(isMock: Boolean) {
|
|
70
|
+
if (isMock != lastState) {
|
|
71
|
+
lastState = isMock
|
|
72
|
+
Log.d(TAG, "Mock location state changed: isMockEnabled=$isMock")
|
|
73
|
+
callback?.invoke(isMock)
|
|
75
74
|
}
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
@SuppressLint("DiscouragedPrivateApi")
|
|
82
|
-
fun isMockLocationActive(): Boolean {
|
|
83
|
-
// Pre-API 23: check the global mock location setting
|
|
77
|
+
@SuppressLint("MissingPermission")
|
|
78
|
+
private fun checkMockLocation() {
|
|
79
|
+
// Pre-API 23: use the global settings flag
|
|
84
80
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
85
81
|
@Suppress("DEPRECATION")
|
|
86
82
|
val mockSetting = Settings.Secure.getString(
|
|
87
83
|
context.contentResolver,
|
|
88
84
|
Settings.Secure.ALLOW_MOCK_LOCATION
|
|
89
85
|
)
|
|
90
|
-
|
|
86
|
+
notifyIfChanged(mockSetting == "1")
|
|
87
|
+
return
|
|
91
88
|
}
|
|
92
89
|
|
|
93
|
-
// API 23+:
|
|
94
|
-
// The previous approach only checked our own UID which always returned false
|
|
95
|
-
// since the mock location app (not ours) holds the permission.
|
|
90
|
+
// API 23+: request a current location and check isMock flag
|
|
96
91
|
try {
|
|
97
|
-
val
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
Int::class.javaPrimitiveType,
|
|
102
|
-
Int::class.javaPrimitiveType,
|
|
103
|
-
String::class.java
|
|
104
|
-
)
|
|
92
|
+
val request = CurrentLocationRequest.Builder()
|
|
93
|
+
.setPriority(Priority.PRIORITY_HIGH_ACCURACY)
|
|
94
|
+
.setMaxUpdateAgeMillis(5000)
|
|
95
|
+
.build()
|
|
105
96
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
97
|
+
fusedClient.getCurrentLocation(request, null)
|
|
98
|
+
.addOnSuccessListener { location: Location? ->
|
|
99
|
+
if (location != null) {
|
|
100
|
+
val isMock = isLocationMock(location)
|
|
101
|
+
mainHandler.post { notifyIfChanged(isMock) }
|
|
102
|
+
} else {
|
|
103
|
+
// No location available — try last location as fallback
|
|
104
|
+
fusedClient.lastLocation.addOnSuccessListener { lastLoc: Location? ->
|
|
105
|
+
if (lastLoc != null) {
|
|
106
|
+
val isMock = isLocationMock(lastLoc)
|
|
107
|
+
mainHandler.post { notifyIfChanged(isMock) }
|
|
108
|
+
}
|
|
109
|
+
}
|
|
119
110
|
}
|
|
120
|
-
} catch (_: Exception) {
|
|
121
|
-
// Some packages may not be queryable — skip
|
|
122
111
|
}
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
Log.w(TAG, "Could not check mock location app ops: ${e.message}")
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Fallback: check for known mock location app package names
|
|
129
|
-
try {
|
|
130
|
-
val pm = context.packageManager
|
|
131
|
-
val knownMockApps = listOf(
|
|
132
|
-
"com.lexa.fakegps",
|
|
133
|
-
"com.incorporateapps.fakegps.fre",
|
|
134
|
-
"com.fakegps.mock",
|
|
135
|
-
"com.lkr.fakegps",
|
|
136
|
-
"com.fake.gps.go.location.spoofer.free",
|
|
137
|
-
"com.theappninjas.gpsjoystick",
|
|
138
|
-
"com.evezzon.fgl",
|
|
139
|
-
"com.mock.location"
|
|
140
|
-
)
|
|
141
|
-
for (pkg in knownMockApps) {
|
|
142
|
-
try {
|
|
143
|
-
@Suppress("DEPRECATION")
|
|
144
|
-
pm.getApplicationInfo(pkg, 0)
|
|
145
|
-
Log.d(TAG, "Known mock location app detected: $pkg")
|
|
146
|
-
return true
|
|
147
|
-
} catch (_: Exception) {
|
|
148
|
-
// Not installed
|
|
112
|
+
.addOnFailureListener { e ->
|
|
113
|
+
Log.w(TAG, "Failed to get current location for mock check: ${e.message}")
|
|
149
114
|
}
|
|
150
|
-
|
|
115
|
+
} catch (e: SecurityException) {
|
|
116
|
+
Log.w(TAG, "No location permission for mock check: ${e.message}")
|
|
151
117
|
} catch (e: Exception) {
|
|
152
|
-
Log.w(TAG, "
|
|
118
|
+
Log.w(TAG, "Error checking mock location: ${e.message}")
|
|
153
119
|
}
|
|
120
|
+
}
|
|
154
121
|
|
|
155
|
-
|
|
122
|
+
private fun isLocationMock(location: Location): Boolean {
|
|
123
|
+
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
124
|
+
location.isMock
|
|
125
|
+
} else {
|
|
126
|
+
@Suppress("DEPRECATION")
|
|
127
|
+
location.isFromMockProvider
|
|
128
|
+
}
|
|
156
129
|
}
|
|
157
130
|
|
|
158
131
|
fun destroy() {
|
package/android/src/main/java/com/margelo/nitro/nitrolocationtracking/NitroLocationTracking.kt
CHANGED
|
@@ -548,6 +548,28 @@ class NitroLocationTracking : HybridNitroLocationTrackingSpec() {
|
|
|
548
548
|
return geofenceManager?.distanceTo(regionId, locationEngine?.lastLocation) ?: -1.0
|
|
549
549
|
}
|
|
550
550
|
|
|
551
|
+
// === Live Activity (Android no-op — Dynamic Island is iOS-only) ===
|
|
552
|
+
|
|
553
|
+
override fun startLiveActivity(
|
|
554
|
+
orderId: String,
|
|
555
|
+
customerName: String,
|
|
556
|
+
deliveryAddress: String,
|
|
557
|
+
orderCount: Double,
|
|
558
|
+
status: String,
|
|
559
|
+
statusText: String,
|
|
560
|
+
estimatedMinutes: Double,
|
|
561
|
+
distanceMeters: Double
|
|
562
|
+
) { /* no-op */ }
|
|
563
|
+
|
|
564
|
+
override fun updateLiveActivity(
|
|
565
|
+
status: String,
|
|
566
|
+
statusText: String,
|
|
567
|
+
estimatedMinutes: Double,
|
|
568
|
+
distanceMeters: Double
|
|
569
|
+
) { /* no-op */ }
|
|
570
|
+
|
|
571
|
+
override fun endLiveActivity() { /* no-op */ }
|
|
572
|
+
|
|
551
573
|
// === Notifications ===
|
|
552
574
|
|
|
553
575
|
override fun showLocalNotification(title: String, body: String) {
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
// Wraps ActivityKit so the rest of the module stays buildable on iOS < 16.2
|
|
4
|
+
// and on macOS/tvOS where ActivityKit is unavailable.
|
|
5
|
+
|
|
6
|
+
#if canImport(ActivityKit)
|
|
7
|
+
import ActivityKit
|
|
8
|
+
|
|
9
|
+
// ─── Activity Attributes ──────────────────────────────────────────────────────
|
|
10
|
+
|
|
11
|
+
public struct CourierActivityAttributes: ActivityAttributes {
|
|
12
|
+
// Custom activityType so the widget extension (different module) can match this activity.
|
|
13
|
+
public static var activityType: String { "CourierDeliveryActivity" }
|
|
14
|
+
|
|
15
|
+
public let orderId: String
|
|
16
|
+
public let customerName: String
|
|
17
|
+
public let deliveryAddress: String
|
|
18
|
+
public let orderCount: Int
|
|
19
|
+
|
|
20
|
+
public struct ContentState: Codable, Hashable {
|
|
21
|
+
public let status: String
|
|
22
|
+
public let statusText: String
|
|
23
|
+
public let estimatedMinutes: Int
|
|
24
|
+
public let distanceMeters: Double
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// ─── Manager ─────────────────────────────────────────────────────────────────
|
|
29
|
+
|
|
30
|
+
@available(iOS 16.2, *)
|
|
31
|
+
final class LiveActivityManager {
|
|
32
|
+
static let shared = LiveActivityManager()
|
|
33
|
+
|
|
34
|
+
private init() {
|
|
35
|
+
// Recover any activity that was alive before the app restarted.
|
|
36
|
+
currentActivity = Activity<CourierActivityAttributes>.activities.first
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private var currentActivity: Activity<CourierActivityAttributes>?
|
|
40
|
+
|
|
41
|
+
func start(
|
|
42
|
+
orderId: String,
|
|
43
|
+
customerName: String,
|
|
44
|
+
deliveryAddress: String,
|
|
45
|
+
orderCount: Int,
|
|
46
|
+
status: String,
|
|
47
|
+
statusText: String,
|
|
48
|
+
estimatedMinutes: Int,
|
|
49
|
+
distanceMeters: Double
|
|
50
|
+
) throws {
|
|
51
|
+
guard ActivityAuthorizationInfo().areActivitiesEnabled else {
|
|
52
|
+
let appName = Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
|
|
53
|
+
?? Bundle.main.object(forInfoDictionaryKey: "CFBundleName") as? String
|
|
54
|
+
?? "the app"
|
|
55
|
+
throw NSError(
|
|
56
|
+
domain: "com.nitro.liveactivity",
|
|
57
|
+
code: 1,
|
|
58
|
+
userInfo: [NSLocalizedDescriptionKey: "Live Activities are disabled. Enable them in Settings → \(appName) → Live Activities."]
|
|
59
|
+
)
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if let existing = currentActivity {
|
|
63
|
+
Task { await existing.end(nil, dismissalPolicy: .immediate) }
|
|
64
|
+
currentActivity = nil
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let attributes = CourierActivityAttributes(
|
|
68
|
+
orderId: orderId,
|
|
69
|
+
customerName: customerName,
|
|
70
|
+
deliveryAddress: deliveryAddress,
|
|
71
|
+
orderCount: orderCount
|
|
72
|
+
)
|
|
73
|
+
let content = ActivityContent(
|
|
74
|
+
state: CourierActivityAttributes.ContentState(
|
|
75
|
+
status: status,
|
|
76
|
+
statusText: statusText,
|
|
77
|
+
estimatedMinutes: estimatedMinutes,
|
|
78
|
+
distanceMeters: distanceMeters
|
|
79
|
+
),
|
|
80
|
+
staleDate: Date().addingTimeInterval(3600)
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
currentActivity = try Activity.request(attributes: attributes, content: content, pushType: nil)
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
func update(status: String, statusText: String, estimatedMinutes: Int, distanceMeters: Double) {
|
|
87
|
+
// Recover orphaned reference if the app was restarted between start and update.
|
|
88
|
+
if currentActivity == nil {
|
|
89
|
+
currentActivity = Activity<CourierActivityAttributes>.activities.first
|
|
90
|
+
}
|
|
91
|
+
guard let activity = currentActivity else { return }
|
|
92
|
+
|
|
93
|
+
let content = ActivityContent(
|
|
94
|
+
state: CourierActivityAttributes.ContentState(
|
|
95
|
+
status: status,
|
|
96
|
+
statusText: statusText,
|
|
97
|
+
estimatedMinutes: estimatedMinutes,
|
|
98
|
+
distanceMeters: distanceMeters
|
|
99
|
+
),
|
|
100
|
+
staleDate: Date().addingTimeInterval(3600)
|
|
101
|
+
)
|
|
102
|
+
Task { await activity.update(content) }
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
func end() {
|
|
106
|
+
// Recover orphaned reference if the app was restarted between start and end.
|
|
107
|
+
if currentActivity == nil {
|
|
108
|
+
currentActivity = Activity<CourierActivityAttributes>.activities.first
|
|
109
|
+
}
|
|
110
|
+
guard let activity = currentActivity else { return }
|
|
111
|
+
currentActivity = nil
|
|
112
|
+
Task { await activity.end(nil, dismissalPolicy: .immediate) }
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
#endif // canImport(ActivityKit)
|
|
@@ -329,6 +329,60 @@ class NitroLocationTracking: HybridNitroLocationTrackingSpec {
|
|
|
329
329
|
return geofenceManager.distanceTo(regionId: regionId, from: locationEngine.lastCLLocation)
|
|
330
330
|
}
|
|
331
331
|
|
|
332
|
+
// MARK: - Live Activity
|
|
333
|
+
|
|
334
|
+
func startLiveActivity(
|
|
335
|
+
orderId: String,
|
|
336
|
+
customerName: String,
|
|
337
|
+
deliveryAddress: String,
|
|
338
|
+
orderCount: Double,
|
|
339
|
+
status: String,
|
|
340
|
+
statusText: String,
|
|
341
|
+
estimatedMinutes: Double,
|
|
342
|
+
distanceMeters: Double
|
|
343
|
+
) throws {
|
|
344
|
+
#if canImport(ActivityKit)
|
|
345
|
+
if #available(iOS 16.2, *) {
|
|
346
|
+
try LiveActivityManager.shared.start(
|
|
347
|
+
orderId: orderId,
|
|
348
|
+
customerName: customerName,
|
|
349
|
+
deliveryAddress: deliveryAddress,
|
|
350
|
+
orderCount: Int(orderCount),
|
|
351
|
+
status: status,
|
|
352
|
+
statusText: statusText,
|
|
353
|
+
estimatedMinutes: Int(estimatedMinutes),
|
|
354
|
+
distanceMeters: distanceMeters
|
|
355
|
+
)
|
|
356
|
+
}
|
|
357
|
+
#endif
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
func updateLiveActivity(
|
|
361
|
+
status: String,
|
|
362
|
+
statusText: String,
|
|
363
|
+
estimatedMinutes: Double,
|
|
364
|
+
distanceMeters: Double
|
|
365
|
+
) throws {
|
|
366
|
+
#if canImport(ActivityKit)
|
|
367
|
+
if #available(iOS 16.2, *) {
|
|
368
|
+
LiveActivityManager.shared.update(
|
|
369
|
+
status: status,
|
|
370
|
+
statusText: statusText,
|
|
371
|
+
estimatedMinutes: Int(estimatedMinutes),
|
|
372
|
+
distanceMeters: distanceMeters
|
|
373
|
+
)
|
|
374
|
+
}
|
|
375
|
+
#endif
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
func endLiveActivity() throws {
|
|
379
|
+
#if canImport(ActivityKit)
|
|
380
|
+
if #available(iOS 16.2, *) {
|
|
381
|
+
LiveActivityManager.shared.end()
|
|
382
|
+
}
|
|
383
|
+
#endif
|
|
384
|
+
}
|
|
385
|
+
|
|
332
386
|
// MARK: - Notifications
|
|
333
387
|
|
|
334
388
|
func showLocalNotification(title: String, body: String) throws {
|
|
@@ -0,0 +1,226 @@
|
|
|
1
|
+
// CourierWidgetLiveActivity.swift
|
|
2
|
+
// react-native-nitro-location-tracking
|
|
3
|
+
//
|
|
4
|
+
// ─── HOW TO USE ──────────────────────────────────────────────────────────────
|
|
5
|
+
//
|
|
6
|
+
// 1. In Xcode, add a new Widget Extension target to your app:
|
|
7
|
+
// File → New → Target → Widget Extension
|
|
8
|
+
// Uncheck "Include Configuration App Intent"
|
|
9
|
+
//
|
|
10
|
+
// 2. Copy THIS file into the widget extension folder and add it to the
|
|
11
|
+
// widget extension target's "Compile Sources".
|
|
12
|
+
//
|
|
13
|
+
// 3. Delete the template files Xcode generated
|
|
14
|
+
// (WidgetName.swift, WidgetNameBundle.swift, Assets.xcassets is fine to keep).
|
|
15
|
+
//
|
|
16
|
+
// 4. Replace WidgetNameBundle.swift content with:
|
|
17
|
+
//
|
|
18
|
+
// import WidgetKit
|
|
19
|
+
// import SwiftUI
|
|
20
|
+
//
|
|
21
|
+
// @main
|
|
22
|
+
// struct YourWidgetBundle: WidgetBundle {
|
|
23
|
+
// var body: some Widget {
|
|
24
|
+
// CourierWidgetLiveActivity()
|
|
25
|
+
// }
|
|
26
|
+
// }
|
|
27
|
+
//
|
|
28
|
+
// 5. In your main app's Info.plist, add:
|
|
29
|
+
// <key>NSSupportsLiveActivities</key>
|
|
30
|
+
// <true/>
|
|
31
|
+
//
|
|
32
|
+
// 6. In Xcode, select your main app target → General →
|
|
33
|
+
// Frameworks, Libraries, and Embedded Content → verify the
|
|
34
|
+
// widget extension .appex is listed with "Embed Without Signing".
|
|
35
|
+
//
|
|
36
|
+
// Minimum deployment target: iOS 16.2
|
|
37
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
38
|
+
|
|
39
|
+
import ActivityKit
|
|
40
|
+
import WidgetKit
|
|
41
|
+
import SwiftUI
|
|
42
|
+
|
|
43
|
+
// MARK: - Attributes
|
|
44
|
+
// Must mirror CourierActivityAttributes in LiveActivityManager.swift exactly.
|
|
45
|
+
// The activityType string is what links the library's Activity.request() call
|
|
46
|
+
// to this widget extension across Swift module boundaries.
|
|
47
|
+
|
|
48
|
+
struct CourierActivityAttributes: ActivityAttributes {
|
|
49
|
+
static var activityType: String { "CourierDeliveryActivity" }
|
|
50
|
+
|
|
51
|
+
let orderId: String
|
|
52
|
+
let customerName: String
|
|
53
|
+
let deliveryAddress: String
|
|
54
|
+
let orderCount: Int
|
|
55
|
+
|
|
56
|
+
struct ContentState: Codable, Hashable {
|
|
57
|
+
let status: String // "picking_up" | "on_the_way" | "arriving" | "delivered"
|
|
58
|
+
let statusText: String // Localised label for the status
|
|
59
|
+
let estimatedMinutes: Int
|
|
60
|
+
let distanceMeters: Double
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// MARK: - Helpers
|
|
65
|
+
|
|
66
|
+
private func statusEmoji(_ status: String) -> String {
|
|
67
|
+
switch status {
|
|
68
|
+
case "picking_up": return "📦"
|
|
69
|
+
case "on_the_way": return "🚗"
|
|
70
|
+
case "arriving": return "🏁"
|
|
71
|
+
case "delivered": return "✅"
|
|
72
|
+
default: return "📍"
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
private func statusColor(_ status: String) -> Color {
|
|
77
|
+
switch status {
|
|
78
|
+
case "picking_up": return .orange
|
|
79
|
+
case "on_the_way": return .blue
|
|
80
|
+
case "arriving": return Color(red: 0.1, green: 0.7, blue: 0.3)
|
|
81
|
+
case "delivered": return .green
|
|
82
|
+
default: return .gray
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
private func distanceText(_ meters: Double) -> String {
|
|
87
|
+
meters >= 1000
|
|
88
|
+
? String(format: "%.1f km", meters / 1000)
|
|
89
|
+
: "\(Int(meters)) m"
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
private func safeDeliveryURL(orderId: String) -> URL? {
|
|
93
|
+
var components = URLComponents()
|
|
94
|
+
components.scheme = "nitrolocation"
|
|
95
|
+
components.host = "delivery"
|
|
96
|
+
components.path = "/\(orderId)"
|
|
97
|
+
return components.url
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// MARK: - Lock Screen / Banner
|
|
101
|
+
|
|
102
|
+
struct CourierLockScreenView: View {
|
|
103
|
+
let context: ActivityViewContext<CourierActivityAttributes>
|
|
104
|
+
|
|
105
|
+
var body: some View {
|
|
106
|
+
VStack(spacing: 8) {
|
|
107
|
+
HStack(alignment: .center) {
|
|
108
|
+
Text(statusEmoji(context.state.status))
|
|
109
|
+
.font(.title2)
|
|
110
|
+
VStack(alignment: .leading, spacing: 2) {
|
|
111
|
+
Text(context.state.statusText)
|
|
112
|
+
.font(.headline)
|
|
113
|
+
Text(context.attributes.customerName)
|
|
114
|
+
.font(.subheadline)
|
|
115
|
+
.foregroundStyle(.secondary)
|
|
116
|
+
}
|
|
117
|
+
Spacer()
|
|
118
|
+
VStack(alignment: .trailing, spacing: 2) {
|
|
119
|
+
if context.isStale {
|
|
120
|
+
Text("Updating…")
|
|
121
|
+
.font(.caption2)
|
|
122
|
+
.foregroundStyle(.orange)
|
|
123
|
+
} else {
|
|
124
|
+
Text("\(context.state.estimatedMinutes) min")
|
|
125
|
+
.font(.title3)
|
|
126
|
+
.fontWeight(.bold)
|
|
127
|
+
.foregroundStyle(statusColor(context.state.status))
|
|
128
|
+
}
|
|
129
|
+
Text(distanceText(context.state.distanceMeters))
|
|
130
|
+
.font(.caption)
|
|
131
|
+
.foregroundStyle(.secondary)
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
Divider()
|
|
136
|
+
|
|
137
|
+
HStack {
|
|
138
|
+
Image(systemName: "location.fill")
|
|
139
|
+
.font(.caption2)
|
|
140
|
+
.foregroundStyle(.secondary)
|
|
141
|
+
Text(context.attributes.deliveryAddress)
|
|
142
|
+
.font(.caption)
|
|
143
|
+
.foregroundStyle(.secondary)
|
|
144
|
+
.lineLimit(1)
|
|
145
|
+
Spacer()
|
|
146
|
+
Text(context.attributes.orderId)
|
|
147
|
+
.font(.caption2)
|
|
148
|
+
.foregroundStyle(.secondary)
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
.padding()
|
|
152
|
+
.activityBackgroundTint(Color(.systemBackground))
|
|
153
|
+
.activitySystemActionForegroundColor(.primary)
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
// MARK: - Widget
|
|
158
|
+
|
|
159
|
+
struct CourierWidgetLiveActivity: Widget {
|
|
160
|
+
var body: some WidgetConfiguration {
|
|
161
|
+
ActivityConfiguration(for: CourierActivityAttributes.self) { context in
|
|
162
|
+
CourierLockScreenView(context: context)
|
|
163
|
+
} dynamicIsland: { context in
|
|
164
|
+
DynamicIsland {
|
|
165
|
+
DynamicIslandExpandedRegion(.leading) {
|
|
166
|
+
HStack(spacing: 6) {
|
|
167
|
+
Text(statusEmoji(context.state.status))
|
|
168
|
+
.font(.title2)
|
|
169
|
+
VStack(alignment: .leading, spacing: 1) {
|
|
170
|
+
Text(context.state.statusText)
|
|
171
|
+
.font(.caption)
|
|
172
|
+
.fontWeight(.semibold)
|
|
173
|
+
Text(context.attributes.customerName)
|
|
174
|
+
.font(.caption2)
|
|
175
|
+
.foregroundStyle(.secondary)
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
.padding(.leading, 4)
|
|
179
|
+
}
|
|
180
|
+
DynamicIslandExpandedRegion(.trailing) {
|
|
181
|
+
VStack(alignment: .trailing, spacing: 1) {
|
|
182
|
+
Text("\(context.state.estimatedMinutes)")
|
|
183
|
+
.font(.title)
|
|
184
|
+
.fontWeight(.bold)
|
|
185
|
+
.foregroundStyle(statusColor(context.state.status))
|
|
186
|
+
Text("min")
|
|
187
|
+
.font(.caption2)
|
|
188
|
+
.foregroundStyle(.secondary)
|
|
189
|
+
}
|
|
190
|
+
.padding(.trailing, 4)
|
|
191
|
+
}
|
|
192
|
+
DynamicIslandExpandedRegion(.bottom) {
|
|
193
|
+
HStack {
|
|
194
|
+
Image(systemName: "location.fill")
|
|
195
|
+
.font(.caption2)
|
|
196
|
+
.foregroundStyle(.secondary)
|
|
197
|
+
Text(context.attributes.deliveryAddress)
|
|
198
|
+
.font(.caption)
|
|
199
|
+
.foregroundStyle(.secondary)
|
|
200
|
+
.lineLimit(1)
|
|
201
|
+
Spacer()
|
|
202
|
+
Text(distanceText(context.state.distanceMeters))
|
|
203
|
+
.font(.caption)
|
|
204
|
+
.fontWeight(.semibold)
|
|
205
|
+
}
|
|
206
|
+
.padding(.horizontal, 4)
|
|
207
|
+
.padding(.bottom, 4)
|
|
208
|
+
}
|
|
209
|
+
} compactLeading: {
|
|
210
|
+
Text(statusEmoji(context.state.status))
|
|
211
|
+
} compactTrailing: {
|
|
212
|
+
Text("\(context.state.estimatedMinutes)m")
|
|
213
|
+
.font(.caption2)
|
|
214
|
+
.fontWeight(.bold)
|
|
215
|
+
.foregroundStyle(statusColor(context.state.status))
|
|
216
|
+
} minimal: {
|
|
217
|
+
Text("\(context.state.estimatedMinutes)")
|
|
218
|
+
.font(.caption2)
|
|
219
|
+
.fontWeight(.bold)
|
|
220
|
+
.foregroundStyle(statusColor(context.state.status))
|
|
221
|
+
}
|
|
222
|
+
.widgetURL(safeDeliveryURL(orderId: context.attributes.orderId))
|
|
223
|
+
.keylineTint(statusColor(context.state.status))
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
package/lib/module/index.js
CHANGED
|
@@ -1,10 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
4
|
+
import { Platform } from 'react-native';
|
|
4
5
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
5
6
|
const NitroLocationModule = NitroModules.createHybridObject('NitroLocationTracking');
|
|
6
7
|
export const NitroLocationCalculations = NitroModules.createHybridObject('NitroLocationComplexLogicsCalculation');
|
|
7
8
|
export default NitroLocationModule;
|
|
9
|
+
|
|
10
|
+
// Live Activities are an iOS-only feature (Android calls are safe no-ops).
|
|
11
|
+
// Use this guard before calling startLiveActivity / updateLiveActivity / endLiveActivity.
|
|
12
|
+
export function isLiveActivitySupported() {
|
|
13
|
+
return Platform.OS === 'ios';
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// Convenience type for the mutable state passed to startLiveActivity / updateLiveActivity.
|
|
17
|
+
|
|
8
18
|
export { requestLocationPermission } from "./requestPermission.js";
|
|
9
19
|
export { LocationSmoother } from "./LocationSmoother.js";
|
|
10
20
|
export { shortestRotation, calculateBearing } from "./bearing.js";
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useState","useEffect","useCallback","useRef","NitroModules","NitroLocationModule","createHybridObject","NitroLocationCalculations","requestLocationPermission","LocationSmoother","shortestRotation","calculateBearing","useDriverLocation","config","location","setLocation","isMoving","setIsMoving","isTracking","setIsTracking","configJson","JSON","stringify","trackingRef","parsed","parse","configure","onLocation","onMotionChange","current","stopTracking","startTracking","useRideConnection","connectionState","setConnectionState","lastMessage","setLastMessage","configureConnection","onConnectionStateChange","onMessage","disconnectWebSocket","connect","connectWebSocket","disconnect","send","m","sendMessage"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAAA,SAASA,QAAQ,EAAEC,SAAS,EAAEC,WAAW,EAAEC,MAAM,QAAQ,OAAO;AAChE,SAASC,YAAY,QAAQ,4BAA4B;AAQzD,MAAMC,mBAAmB,GACvBD,YAAY,CAACE,kBAAkB,CAC7B,uBACF,CAAC;AAEH,OAAO,MAAMC,yBAAyB,GAAGH,YAAY,CAACE,kBAAkB,CAEtE,uCAAuC,CAAC;AAE1C,eAAeD,mBAAmB;
|
|
1
|
+
{"version":3,"names":["useState","useEffect","useCallback","useRef","Platform","NitroModules","NitroLocationModule","createHybridObject","NitroLocationCalculations","isLiveActivitySupported","OS","requestLocationPermission","LocationSmoother","shortestRotation","calculateBearing","useDriverLocation","config","location","setLocation","isMoving","setIsMoving","isTracking","setIsTracking","configJson","JSON","stringify","trackingRef","parsed","parse","configure","onLocation","onMotionChange","current","stopTracking","startTracking","useRideConnection","connectionState","setConnectionState","lastMessage","setLastMessage","configureConnection","onConnectionStateChange","onMessage","disconnectWebSocket","connect","connectWebSocket","disconnect","send","m","sendMessage"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -122,6 +122,9 @@ export interface NitroLocationTracking extends HybridObject<{
|
|
|
122
122
|
getDistanceToGeofence(regionId: string): number;
|
|
123
123
|
showLocalNotification(title: string, body: string): void;
|
|
124
124
|
updateForegroundNotification(title: string, body: string): void;
|
|
125
|
+
startLiveActivity(orderId: string, customerName: string, deliveryAddress: string, orderCount: number, status: string, statusText: string, estimatedMinutes: number, distanceMeters: number): void;
|
|
126
|
+
updateLiveActivity(status: string, statusText: string, estimatedMinutes: number, distanceMeters: number): void;
|
|
127
|
+
endLiveActivity(): void;
|
|
125
128
|
destroy(): void;
|
|
126
129
|
}
|
|
127
130
|
//# sourceMappingURL=NitroLocationTracking.nitro.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NitroLocationTracking.nitro.d.ts","sourceRoot":"","sources":["../../../src/NitroLocationTracking.nitro.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"NitroLocationTracking.nitro.d.ts","sourceRoot":"","sources":["../../../src/NitroLocationTracking.nitro.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,6 +2,13 @@ import type { NitroLocationTracking, LocationData, LocationConfig, ConnectionCon
|
|
|
2
2
|
declare const NitroLocationModule: NitroLocationTracking;
|
|
3
3
|
export declare const NitroLocationCalculations: import("./NitroLocationComplexLogicsCalculation.nitro").NitroLocationComplexLogicsCalculation;
|
|
4
4
|
export default NitroLocationModule;
|
|
5
|
+
export declare function isLiveActivitySupported(): boolean;
|
|
6
|
+
export type LiveActivityState = {
|
|
7
|
+
status: 'picking_up' | 'on_the_way' | 'arriving' | 'delivered';
|
|
8
|
+
statusText: string;
|
|
9
|
+
estimatedMinutes: number;
|
|
10
|
+
distanceMeters: number;
|
|
11
|
+
};
|
|
5
12
|
export { requestLocationPermission } from './requestPermission';
|
|
6
13
|
export { LocationSmoother } from './LocationSmoother';
|
|
7
14
|
export { shortestRotation, calculateBearing } from './bearing';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,gBAAgB,EACjB,MAAM,+BAA+B,CAAC;AAEvC,QAAA,MAAM,mBAAmB,uBAGtB,CAAC;AAEJ,eAAO,MAAM,yBAAyB,+FAEI,CAAC;AAE3C,eAAe,mBAAmB,CAAC;AAInC,wBAAgB,uBAAuB,IAAI,OAAO,CAEjD;AAGD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,MAAM,EAAE,YAAY,GAAG,YAAY,GAAG,UAAU,GAAG,WAAW,CAAC;IAC/D,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC/D,YAAY,EACV,qBAAqB,EACrB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,WAAW,EACX,cAAc,EACd,kBAAkB,EAClB,SAAS,EACT,sBAAsB,EACtB,sBAAsB,EACtB,gBAAgB,EAChB,wBAAwB,EACxB,oBAAoB,GACrB,MAAM,+BAA+B,CAAC;AAEvC,YAAY,EACV,qCAAqC,EACrC,aAAa,EACb,aAAa,GACd,MAAM,+CAA+C,CAAC;AAEvD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,cAAc;;;;;;EAuCvD;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,gBAAgB;;;;;cAuBhC,MAAM;EAE/B"}
|
|
@@ -333,6 +333,18 @@ namespace margelo::nitro::nitrolocationtracking {
|
|
|
333
333
|
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* title */, jni::alias_ref<jni::JString> /* body */)>("updateForegroundNotification");
|
|
334
334
|
method(_javaPart, jni::make_jstring(title), jni::make_jstring(body));
|
|
335
335
|
}
|
|
336
|
+
void JHybridNitroLocationTrackingSpec::startLiveActivity(const std::string& orderId, const std::string& customerName, const std::string& deliveryAddress, double orderCount, const std::string& status, const std::string& statusText, double estimatedMinutes, double distanceMeters) {
|
|
337
|
+
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* orderId */, jni::alias_ref<jni::JString> /* customerName */, jni::alias_ref<jni::JString> /* deliveryAddress */, double /* orderCount */, jni::alias_ref<jni::JString> /* status */, jni::alias_ref<jni::JString> /* statusText */, double /* estimatedMinutes */, double /* distanceMeters */)>("startLiveActivity");
|
|
338
|
+
method(_javaPart, jni::make_jstring(orderId), jni::make_jstring(customerName), jni::make_jstring(deliveryAddress), orderCount, jni::make_jstring(status), jni::make_jstring(statusText), estimatedMinutes, distanceMeters);
|
|
339
|
+
}
|
|
340
|
+
void JHybridNitroLocationTrackingSpec::updateLiveActivity(const std::string& status, const std::string& statusText, double estimatedMinutes, double distanceMeters) {
|
|
341
|
+
static const auto method = javaClassStatic()->getMethod<void(jni::alias_ref<jni::JString> /* status */, jni::alias_ref<jni::JString> /* statusText */, double /* estimatedMinutes */, double /* distanceMeters */)>("updateLiveActivity");
|
|
342
|
+
method(_javaPart, jni::make_jstring(status), jni::make_jstring(statusText), estimatedMinutes, distanceMeters);
|
|
343
|
+
}
|
|
344
|
+
void JHybridNitroLocationTrackingSpec::endLiveActivity() {
|
|
345
|
+
static const auto method = javaClassStatic()->getMethod<void()>("endLiveActivity");
|
|
346
|
+
method(_javaPart);
|
|
347
|
+
}
|
|
336
348
|
void JHybridNitroLocationTrackingSpec::destroy() {
|
|
337
349
|
static const auto method = javaClassStatic()->getMethod<void()>("destroy");
|
|
338
350
|
method(_javaPart);
|
|
@@ -96,6 +96,9 @@ namespace margelo::nitro::nitrolocationtracking {
|
|
|
96
96
|
double getDistanceToGeofence(const std::string& regionId) override;
|
|
97
97
|
void showLocalNotification(const std::string& title, const std::string& body) override;
|
|
98
98
|
void updateForegroundNotification(const std::string& title, const std::string& body) override;
|
|
99
|
+
void startLiveActivity(const std::string& orderId, const std::string& customerName, const std::string& deliveryAddress, double orderCount, const std::string& status, const std::string& statusText, double estimatedMinutes, double distanceMeters) override;
|
|
100
|
+
void updateLiveActivity(const std::string& status, const std::string& statusText, double estimatedMinutes, double distanceMeters) override;
|
|
101
|
+
void endLiveActivity() override;
|
|
99
102
|
void destroy() override;
|
|
100
103
|
|
|
101
104
|
private:
|
|
@@ -260,6 +260,18 @@ abstract class HybridNitroLocationTrackingSpec: HybridObject() {
|
|
|
260
260
|
@Keep
|
|
261
261
|
abstract fun updateForegroundNotification(title: String, body: String): Unit
|
|
262
262
|
|
|
263
|
+
@DoNotStrip
|
|
264
|
+
@Keep
|
|
265
|
+
abstract fun startLiveActivity(orderId: String, customerName: String, deliveryAddress: String, orderCount: Double, status: String, statusText: String, estimatedMinutes: Double, distanceMeters: Double): Unit
|
|
266
|
+
|
|
267
|
+
@DoNotStrip
|
|
268
|
+
@Keep
|
|
269
|
+
abstract fun updateLiveActivity(status: String, statusText: String, estimatedMinutes: Double, distanceMeters: Double): Unit
|
|
270
|
+
|
|
271
|
+
@DoNotStrip
|
|
272
|
+
@Keep
|
|
273
|
+
abstract fun endLiveActivity(): Unit
|
|
274
|
+
|
|
263
275
|
@DoNotStrip
|
|
264
276
|
@Keep
|
|
265
277
|
abstract fun destroy(): Unit
|
|
@@ -380,6 +380,24 @@ namespace margelo::nitro::nitrolocationtracking {
|
|
|
380
380
|
std::rethrow_exception(__result.error());
|
|
381
381
|
}
|
|
382
382
|
}
|
|
383
|
+
inline void startLiveActivity(const std::string& orderId, const std::string& customerName, const std::string& deliveryAddress, double orderCount, const std::string& status, const std::string& statusText, double estimatedMinutes, double distanceMeters) override {
|
|
384
|
+
auto __result = _swiftPart.startLiveActivity(orderId, customerName, deliveryAddress, std::forward<decltype(orderCount)>(orderCount), status, statusText, std::forward<decltype(estimatedMinutes)>(estimatedMinutes), std::forward<decltype(distanceMeters)>(distanceMeters));
|
|
385
|
+
if (__result.hasError()) [[unlikely]] {
|
|
386
|
+
std::rethrow_exception(__result.error());
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
inline void updateLiveActivity(const std::string& status, const std::string& statusText, double estimatedMinutes, double distanceMeters) override {
|
|
390
|
+
auto __result = _swiftPart.updateLiveActivity(status, statusText, std::forward<decltype(estimatedMinutes)>(estimatedMinutes), std::forward<decltype(distanceMeters)>(distanceMeters));
|
|
391
|
+
if (__result.hasError()) [[unlikely]] {
|
|
392
|
+
std::rethrow_exception(__result.error());
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
inline void endLiveActivity() override {
|
|
396
|
+
auto __result = _swiftPart.endLiveActivity();
|
|
397
|
+
if (__result.hasError()) [[unlikely]] {
|
|
398
|
+
std::rethrow_exception(__result.error());
|
|
399
|
+
}
|
|
400
|
+
}
|
|
383
401
|
inline void destroy() override {
|
|
384
402
|
auto __result = _swiftPart.destroy();
|
|
385
403
|
if (__result.hasError()) [[unlikely]] {
|
|
@@ -54,6 +54,9 @@ public protocol HybridNitroLocationTrackingSpec_protocol: HybridObject {
|
|
|
54
54
|
func getDistanceToGeofence(regionId: String) throws -> Double
|
|
55
55
|
func showLocalNotification(title: String, body: String) throws -> Void
|
|
56
56
|
func updateForegroundNotification(title: String, body: String) throws -> Void
|
|
57
|
+
func startLiveActivity(orderId: String, customerName: String, deliveryAddress: String, orderCount: Double, status: String, statusText: String, estimatedMinutes: Double, distanceMeters: Double) throws -> Void
|
|
58
|
+
func updateLiveActivity(status: String, statusText: String, estimatedMinutes: Double, distanceMeters: Double) throws -> Void
|
|
59
|
+
func endLiveActivity() throws -> Void
|
|
57
60
|
func destroy() throws -> Void
|
|
58
61
|
}
|
|
59
62
|
|
|
@@ -668,6 +668,39 @@ open class HybridNitroLocationTrackingSpec_cxx {
|
|
|
668
668
|
}
|
|
669
669
|
}
|
|
670
670
|
|
|
671
|
+
@inline(__always)
|
|
672
|
+
public final func startLiveActivity(orderId: std.string, customerName: std.string, deliveryAddress: std.string, orderCount: Double, status: std.string, statusText: std.string, estimatedMinutes: Double, distanceMeters: Double) -> bridge.Result_void_ {
|
|
673
|
+
do {
|
|
674
|
+
try self.__implementation.startLiveActivity(orderId: String(orderId), customerName: String(customerName), deliveryAddress: String(deliveryAddress), orderCount: orderCount, status: String(status), statusText: String(statusText), estimatedMinutes: estimatedMinutes, distanceMeters: distanceMeters)
|
|
675
|
+
return bridge.create_Result_void_()
|
|
676
|
+
} catch (let __error) {
|
|
677
|
+
let __exceptionPtr = __error.toCpp()
|
|
678
|
+
return bridge.create_Result_void_(__exceptionPtr)
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
@inline(__always)
|
|
683
|
+
public final func updateLiveActivity(status: std.string, statusText: std.string, estimatedMinutes: Double, distanceMeters: Double) -> bridge.Result_void_ {
|
|
684
|
+
do {
|
|
685
|
+
try self.__implementation.updateLiveActivity(status: String(status), statusText: String(statusText), estimatedMinutes: estimatedMinutes, distanceMeters: distanceMeters)
|
|
686
|
+
return bridge.create_Result_void_()
|
|
687
|
+
} catch (let __error) {
|
|
688
|
+
let __exceptionPtr = __error.toCpp()
|
|
689
|
+
return bridge.create_Result_void_(__exceptionPtr)
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
@inline(__always)
|
|
694
|
+
public final func endLiveActivity() -> bridge.Result_void_ {
|
|
695
|
+
do {
|
|
696
|
+
try self.__implementation.endLiveActivity()
|
|
697
|
+
return bridge.create_Result_void_()
|
|
698
|
+
} catch (let __error) {
|
|
699
|
+
let __exceptionPtr = __error.toCpp()
|
|
700
|
+
return bridge.create_Result_void_(__exceptionPtr)
|
|
701
|
+
}
|
|
702
|
+
}
|
|
703
|
+
|
|
671
704
|
@inline(__always)
|
|
672
705
|
public final func destroy() -> bridge.Result_void_ {
|
|
673
706
|
do {
|
|
@@ -55,6 +55,9 @@ namespace margelo::nitro::nitrolocationtracking {
|
|
|
55
55
|
prototype.registerHybridMethod("getDistanceToGeofence", &HybridNitroLocationTrackingSpec::getDistanceToGeofence);
|
|
56
56
|
prototype.registerHybridMethod("showLocalNotification", &HybridNitroLocationTrackingSpec::showLocalNotification);
|
|
57
57
|
prototype.registerHybridMethod("updateForegroundNotification", &HybridNitroLocationTrackingSpec::updateForegroundNotification);
|
|
58
|
+
prototype.registerHybridMethod("startLiveActivity", &HybridNitroLocationTrackingSpec::startLiveActivity);
|
|
59
|
+
prototype.registerHybridMethod("updateLiveActivity", &HybridNitroLocationTrackingSpec::updateLiveActivity);
|
|
60
|
+
prototype.registerHybridMethod("endLiveActivity", &HybridNitroLocationTrackingSpec::endLiveActivity);
|
|
58
61
|
prototype.registerHybridMethod("destroy", &HybridNitroLocationTrackingSpec::destroy);
|
|
59
62
|
});
|
|
60
63
|
}
|
|
@@ -123,6 +123,9 @@ namespace margelo::nitro::nitrolocationtracking {
|
|
|
123
123
|
virtual double getDistanceToGeofence(const std::string& regionId) = 0;
|
|
124
124
|
virtual void showLocalNotification(const std::string& title, const std::string& body) = 0;
|
|
125
125
|
virtual void updateForegroundNotification(const std::string& title, const std::string& body) = 0;
|
|
126
|
+
virtual void startLiveActivity(const std::string& orderId, const std::string& customerName, const std::string& deliveryAddress, double orderCount, const std::string& status, const std::string& statusText, double estimatedMinutes, double distanceMeters) = 0;
|
|
127
|
+
virtual void updateLiveActivity(const std::string& status, const std::string& statusText, double estimatedMinutes, double distanceMeters) = 0;
|
|
128
|
+
virtual void endLiveActivity() = 0;
|
|
126
129
|
virtual void destroy() = 0;
|
|
127
130
|
|
|
128
131
|
protected:
|
package/package.json
CHANGED
|
@@ -182,6 +182,25 @@ export interface NitroLocationTracking
|
|
|
182
182
|
showLocalNotification(title: string, body: string): void;
|
|
183
183
|
updateForegroundNotification(title: string, body: string): void;
|
|
184
184
|
|
|
185
|
+
// === Live Activity (iOS Dynamic Island / Lock Screen) ===
|
|
186
|
+
startLiveActivity(
|
|
187
|
+
orderId: string,
|
|
188
|
+
customerName: string,
|
|
189
|
+
deliveryAddress: string,
|
|
190
|
+
orderCount: number,
|
|
191
|
+
status: string,
|
|
192
|
+
statusText: string,
|
|
193
|
+
estimatedMinutes: number,
|
|
194
|
+
distanceMeters: number
|
|
195
|
+
): void;
|
|
196
|
+
updateLiveActivity(
|
|
197
|
+
status: string,
|
|
198
|
+
statusText: string,
|
|
199
|
+
estimatedMinutes: number,
|
|
200
|
+
distanceMeters: number
|
|
201
|
+
): void;
|
|
202
|
+
endLiveActivity(): void;
|
|
203
|
+
|
|
185
204
|
// === Lifecycle ===
|
|
186
205
|
destroy(): void;
|
|
187
206
|
}
|
package/src/index.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
2
|
+
import { Platform } from 'react-native';
|
|
2
3
|
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
4
|
import type {
|
|
4
5
|
NitroLocationTracking,
|
|
@@ -17,6 +18,21 @@ export const NitroLocationCalculations = NitroModules.createHybridObject<
|
|
|
17
18
|
>('NitroLocationComplexLogicsCalculation');
|
|
18
19
|
|
|
19
20
|
export default NitroLocationModule;
|
|
21
|
+
|
|
22
|
+
// Live Activities are an iOS-only feature (Android calls are safe no-ops).
|
|
23
|
+
// Use this guard before calling startLiveActivity / updateLiveActivity / endLiveActivity.
|
|
24
|
+
export function isLiveActivitySupported(): boolean {
|
|
25
|
+
return Platform.OS === 'ios';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Convenience type for the mutable state passed to startLiveActivity / updateLiveActivity.
|
|
29
|
+
export type LiveActivityState = {
|
|
30
|
+
status: 'picking_up' | 'on_the_way' | 'arriving' | 'delivered';
|
|
31
|
+
statusText: string;
|
|
32
|
+
estimatedMinutes: number;
|
|
33
|
+
distanceMeters: number;
|
|
34
|
+
};
|
|
35
|
+
|
|
20
36
|
export { requestLocationPermission } from './requestPermission';
|
|
21
37
|
export { LocationSmoother } from './LocationSmoother';
|
|
22
38
|
export { shortestRotation, calculateBearing } from './bearing';
|