expo-location 18.0.8-canary-20250306-d9d3e02 → 18.0.8
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/CHANGELOG.md +13 -6
- package/android/build.gradle +11 -7
- package/android/libs/io.nlopez.smartlocation-3.3.3-jetified.aar +0 -0
- package/android/src/main/java/expo/modules/location/LocationHelpers.kt +41 -12
- package/android/src/main/java/expo/modules/location/LocationModule.kt +28 -63
- package/expo-module.config.json +16 -3
- package/ios/LocationModule.swift +1 -5
- package/ios/Requesters/EXBackgroundLocationPermissionRequester.m +1 -1
- package/ios/Requesters/EXForegroundPermissionRequester.m +1 -1
- package/package.json +4 -4
- package/android/proguard-rules.pro +0 -3
- package/android/src/main/java/expo/modules/location/LocationParams.kt +0 -14
package/CHANGELOG.md
CHANGED
|
@@ -8,35 +8,42 @@
|
|
|
8
8
|
|
|
9
9
|
### 🐛 Bug fixes
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
### 💡 Others
|
|
12
|
+
|
|
13
|
+
## 18.0.8 — 2025-03-14
|
|
13
14
|
|
|
14
15
|
### 💡 Others
|
|
15
16
|
|
|
17
|
+
- On iOS, added setting the scope value as per our documentation. ([#35452](https://github.com/expo/expo/pull/35452) by [@chrfalch](https://github.com/chrfalch))
|
|
18
|
+
|
|
19
|
+
## 18.0.7 — 2025-02-19
|
|
20
|
+
|
|
16
21
|
- On Android, remove dependency on `smart-location-lib`. ([#33609](https://github.com/expo/expo/pull/33609) by [@alanjhughes](https://github.com/alanjhughes))
|
|
17
22
|
- [Android] Started using expo modules gradle plugin. ([#34176](https://github.com/expo/expo/pull/34176) by [@lukmccall](https://github.com/lukmccall))
|
|
18
23
|
|
|
19
24
|
## 18.0.7 - 2025-02-19
|
|
20
25
|
|
|
26
|
+
- ([iOS][location] Add scope to foreground and background iOS permissions as pr. documentation (#35452))
|
|
27
|
+
|
|
21
28
|
### 🐛 Bug fixes
|
|
22
29
|
|
|
23
30
|
- [iOS] Added error handler to the streaming location/heading methods since these can fail while streaming ([#35004](https://github.com/expo/expo/pull/35004) by [@chrfalch](https://github.com/chrfalch))
|
|
24
31
|
|
|
25
|
-
## 18.0.6
|
|
32
|
+
## 18.0.6 — 2025-02-10
|
|
26
33
|
|
|
27
34
|
### 🐛 Bug fixes
|
|
28
35
|
|
|
29
36
|
- [Android] Use less specific exception in catch block of `resolveUserSettingsForRequest`. ([#34784](https://github.com/expo/expo/pull/34784) by [@alanjhughes](https://github.com/alanjhughes))
|
|
30
37
|
|
|
31
|
-
## 18.0.5
|
|
38
|
+
## 18.0.5 — 2025-01-10
|
|
32
39
|
|
|
33
40
|
_This version does not introduce any user-facing changes._
|
|
34
41
|
|
|
35
|
-
## 18.0.4
|
|
42
|
+
## 18.0.4 — 2024-12-10
|
|
36
43
|
|
|
37
44
|
_This version does not introduce any user-facing changes._
|
|
38
45
|
|
|
39
|
-
## 18.0.3
|
|
46
|
+
## 18.0.3 — 2024-11-29
|
|
40
47
|
|
|
41
48
|
_This version does not introduce any user-facing changes._
|
|
42
49
|
|
package/android/build.gradle
CHANGED
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
|
|
2
|
-
id 'com.android.library'
|
|
3
|
-
id 'expo-module-gradle-plugin'
|
|
4
|
-
}
|
|
1
|
+
apply plugin: 'com.android.library'
|
|
5
2
|
|
|
6
3
|
group = 'host.exp.exponent'
|
|
7
|
-
version = '18.0.
|
|
4
|
+
version = '18.0.8'
|
|
5
|
+
|
|
6
|
+
def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
|
|
7
|
+
apply from: expoModulesCorePlugin
|
|
8
|
+
applyKotlinExpoModulesCorePlugin()
|
|
9
|
+
useCoreDependencies()
|
|
10
|
+
useDefaultAndroidSdkVersions()
|
|
11
|
+
useExpoPublishing()
|
|
8
12
|
|
|
9
13
|
android {
|
|
10
14
|
namespace "expo.modules.location"
|
|
11
15
|
defaultConfig {
|
|
12
16
|
versionCode 29
|
|
13
|
-
versionName "18.0.
|
|
14
|
-
consumerProguardFiles("proguard-rules.pro")
|
|
17
|
+
versionName "18.0.8"
|
|
15
18
|
}
|
|
16
19
|
}
|
|
17
20
|
|
|
18
21
|
dependencies {
|
|
19
22
|
api 'com.google.android.gms:play-services-location:21.0.1'
|
|
23
|
+
implementation project(":${project.name}\$io.nlopez.smartlocation-jetified-aar")
|
|
20
24
|
}
|
|
Binary file
|
|
@@ -16,6 +16,8 @@ import expo.modules.location.records.LocationLastKnownOptions
|
|
|
16
16
|
import expo.modules.location.records.LocationOptions
|
|
17
17
|
import expo.modules.location.records.LocationResponse
|
|
18
18
|
import expo.modules.location.records.PermissionRequestResponse
|
|
19
|
+
import io.nlopez.smartlocation.location.config.LocationAccuracy
|
|
20
|
+
import io.nlopez.smartlocation.location.config.LocationParams
|
|
19
21
|
import kotlin.coroutines.resume
|
|
20
22
|
import kotlin.coroutines.resumeWithException
|
|
21
23
|
import kotlin.coroutines.suspendCoroutine
|
|
@@ -108,16 +110,16 @@ class LocationHelpers {
|
|
|
108
110
|
|
|
109
111
|
private fun mapOptionsToLocationParams(options: LocationOptions): LocationParams {
|
|
110
112
|
val accuracy = options.accuracy
|
|
111
|
-
val
|
|
113
|
+
val locationParamsBuilder = buildLocationParamsForAccuracy(accuracy)
|
|
112
114
|
|
|
113
115
|
options.timeInterval?.let {
|
|
114
|
-
|
|
116
|
+
locationParamsBuilder.setInterval(it)
|
|
115
117
|
}
|
|
116
118
|
options.distanceInterval?.let {
|
|
117
|
-
|
|
119
|
+
locationParamsBuilder.setDistance(it.toFloat())
|
|
118
120
|
}
|
|
119
121
|
|
|
120
|
-
return
|
|
122
|
+
return locationParamsBuilder.build()
|
|
121
123
|
}
|
|
122
124
|
|
|
123
125
|
private fun mapAccuracyToPriority(accuracy: Int): Int {
|
|
@@ -129,15 +131,42 @@ class LocationHelpers {
|
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
133
|
|
|
132
|
-
private fun buildLocationParamsForAccuracy(accuracy: Int): LocationParams {
|
|
134
|
+
private fun buildLocationParamsForAccuracy(accuracy: Int): LocationParams.Builder {
|
|
133
135
|
return when (accuracy) {
|
|
134
|
-
LocationModule.ACCURACY_LOWEST -> LocationParams(
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
LocationModule.
|
|
140
|
-
|
|
136
|
+
LocationModule.ACCURACY_LOWEST -> LocationParams.Builder()
|
|
137
|
+
.setAccuracy(LocationAccuracy.LOWEST)
|
|
138
|
+
.setDistance(3000f)
|
|
139
|
+
.setInterval(10000)
|
|
140
|
+
|
|
141
|
+
LocationModule.ACCURACY_LOW -> LocationParams.Builder()
|
|
142
|
+
.setAccuracy(LocationAccuracy.LOW)
|
|
143
|
+
.setDistance(1000f)
|
|
144
|
+
.setInterval(5000)
|
|
145
|
+
|
|
146
|
+
LocationModule.ACCURACY_BALANCED -> LocationParams.Builder()
|
|
147
|
+
.setAccuracy(LocationAccuracy.MEDIUM)
|
|
148
|
+
.setDistance(100f)
|
|
149
|
+
.setInterval(3000)
|
|
150
|
+
|
|
151
|
+
LocationModule.ACCURACY_HIGH -> LocationParams.Builder()
|
|
152
|
+
.setAccuracy(LocationAccuracy.HIGH)
|
|
153
|
+
.setDistance(50f)
|
|
154
|
+
.setInterval(2000)
|
|
155
|
+
|
|
156
|
+
LocationModule.ACCURACY_HIGHEST -> LocationParams.Builder()
|
|
157
|
+
.setAccuracy(LocationAccuracy.HIGH)
|
|
158
|
+
.setDistance(25f)
|
|
159
|
+
.setInterval(1000)
|
|
160
|
+
|
|
161
|
+
LocationModule.ACCURACY_BEST_FOR_NAVIGATION -> LocationParams.Builder()
|
|
162
|
+
.setAccuracy(LocationAccuracy.HIGH)
|
|
163
|
+
.setDistance(0f)
|
|
164
|
+
.setInterval(500)
|
|
165
|
+
|
|
166
|
+
else -> LocationParams.Builder()
|
|
167
|
+
.setAccuracy(LocationAccuracy.MEDIUM)
|
|
168
|
+
.setDistance(100f)
|
|
169
|
+
.setInterval(3000)
|
|
141
170
|
}
|
|
142
171
|
}
|
|
143
172
|
|
|
@@ -12,14 +12,11 @@ import android.hardware.SensorEventListener
|
|
|
12
12
|
import android.hardware.SensorManager
|
|
13
13
|
import android.location.Geocoder
|
|
14
14
|
import android.location.Location
|
|
15
|
-
import android.location.LocationManager
|
|
16
15
|
import android.os.Build
|
|
17
16
|
import android.os.Bundle
|
|
18
17
|
import android.os.Looper
|
|
19
18
|
import android.util.Log
|
|
20
19
|
import androidx.annotation.ChecksSdkIntAtLeast
|
|
21
|
-
import androidx.core.app.ActivityCompat
|
|
22
|
-
import androidx.core.location.LocationManagerCompat
|
|
23
20
|
import androidx.core.os.bundleOf
|
|
24
21
|
import com.google.android.gms.common.api.ApiException
|
|
25
22
|
import com.google.android.gms.common.api.CommonStatusCodes
|
|
@@ -55,6 +52,9 @@ import expo.modules.location.records.ReverseGeocodeLocation
|
|
|
55
52
|
import expo.modules.location.records.ReverseGeocodeResponse
|
|
56
53
|
import expo.modules.location.taskConsumers.GeofencingTaskConsumer
|
|
57
54
|
import expo.modules.location.taskConsumers.LocationTaskConsumer
|
|
55
|
+
import io.nlopez.smartlocation.SmartLocation
|
|
56
|
+
import io.nlopez.smartlocation.geocoding.utils.LocationAddress
|
|
57
|
+
import io.nlopez.smartlocation.location.config.LocationParams
|
|
58
58
|
import java.util.Locale
|
|
59
59
|
import kotlin.coroutines.resume
|
|
60
60
|
import kotlin.coroutines.resumeWithException
|
|
@@ -158,12 +158,21 @@ class LocationModule : Module(), LifecycleEventListener, SensorEventListener, Ac
|
|
|
158
158
|
}
|
|
159
159
|
|
|
160
160
|
AsyncFunction<LocationProviderStatus>("getProviderStatusAsync") {
|
|
161
|
-
|
|
161
|
+
val state = SmartLocation.with(mContext).location().state()
|
|
162
|
+
|
|
163
|
+
return@AsyncFunction LocationProviderStatus().apply {
|
|
164
|
+
backgroundModeEnabled = state.locationServicesEnabled()
|
|
165
|
+
gpsAvailable = state.isGpsAvailable
|
|
166
|
+
networkAvailable = state.isNetworkAvailable
|
|
167
|
+
locationServicesEnabled = state.locationServicesEnabled()
|
|
168
|
+
passiveAvailable = state.isPassiveAvailable
|
|
169
|
+
}
|
|
162
170
|
}
|
|
163
171
|
|
|
164
172
|
AsyncFunction("watchDeviceHeading") { watchId: Int ->
|
|
165
173
|
mHeadingId = watchId
|
|
166
|
-
|
|
174
|
+
startHeadingUpdate()
|
|
175
|
+
return@AsyncFunction
|
|
167
176
|
}
|
|
168
177
|
|
|
169
178
|
AsyncFunction("watchPositionImplAsync") { watchId: Int, options: LocationOptions, promise: Promise ->
|
|
@@ -206,6 +215,7 @@ class LocationModule : Module(), LifecycleEventListener, SensorEventListener, Ac
|
|
|
206
215
|
} else {
|
|
207
216
|
removeLocationUpdatesForRequest(watchId)
|
|
208
217
|
}
|
|
218
|
+
return@AsyncFunction
|
|
209
219
|
}
|
|
210
220
|
|
|
211
221
|
AsyncFunction("geocodeAsync") Coroutine { address: String ->
|
|
@@ -332,23 +342,6 @@ class LocationModule : Module(), LifecycleEventListener, SensorEventListener, Ac
|
|
|
332
342
|
} ?: throw NoPermissionsModuleException()
|
|
333
343
|
}
|
|
334
344
|
|
|
335
|
-
private fun getProviderStatus(): LocationProviderStatus {
|
|
336
|
-
val manager = mContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
|
|
337
|
-
|
|
338
|
-
val isGpsAvailable = manager.isProviderEnabled(LocationManager.GPS_PROVIDER)
|
|
339
|
-
val isNetworkAvailable = manager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)
|
|
340
|
-
val isLocationServicesEnabled = LocationManagerCompat.isLocationEnabled(manager)
|
|
341
|
-
val isPassiveAvailable = manager.isProviderEnabled(LocationManager.PASSIVE_PROVIDER)
|
|
342
|
-
|
|
343
|
-
return LocationProviderStatus().apply {
|
|
344
|
-
backgroundModeEnabled = isLocationServicesEnabled
|
|
345
|
-
gpsAvailable = isGpsAvailable
|
|
346
|
-
networkAvailable = isNetworkAvailable
|
|
347
|
-
locationServicesEnabled = isLocationServicesEnabled
|
|
348
|
-
passiveAvailable = isPassiveAvailable
|
|
349
|
-
}
|
|
350
|
-
}
|
|
351
|
-
|
|
352
345
|
private suspend fun requestBackgroundPermissionsAsync(): PermissionRequestResponse {
|
|
353
346
|
if (!isBackgroundPermissionInManifest()) {
|
|
354
347
|
throw NoPermissionInManifestException("ACCESS_BACKGROUND_LOCATION")
|
|
@@ -508,54 +501,27 @@ class LocationModule : Module(), LifecycleEventListener, SensorEventListener, Ac
|
|
|
508
501
|
}
|
|
509
502
|
|
|
510
503
|
private fun startHeadingUpdate() {
|
|
511
|
-
val
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
) {
|
|
515
|
-
return
|
|
516
|
-
}
|
|
517
|
-
val lastLocation =
|
|
518
|
-
locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER)
|
|
519
|
-
?: locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)
|
|
520
|
-
|
|
521
|
-
if (lastLocation != null) {
|
|
504
|
+
val locationControl = SmartLocation.with(mContext).location().oneFix().config(LocationParams.BEST_EFFORT)
|
|
505
|
+
val currLoc = locationControl.lastLocation
|
|
506
|
+
if (currLoc != null) {
|
|
522
507
|
mGeofield = GeomagneticField(
|
|
523
|
-
|
|
524
|
-
lastLocation.longitude.toFloat(),
|
|
525
|
-
lastLocation.altitude.toFloat(),
|
|
508
|
+
currLoc.latitude.toFloat(), currLoc.longitude.toFloat(), currLoc.altitude.toFloat(),
|
|
526
509
|
System.currentTimeMillis()
|
|
527
510
|
)
|
|
528
511
|
} else {
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
val locationCallback = object : LocationCallback() {
|
|
536
|
-
override fun onLocationResult(locationResult: LocationResult) {
|
|
537
|
-
locationResult.lastLocation?.let {
|
|
538
|
-
mGeofield = GeomagneticField(
|
|
539
|
-
it.latitude.toFloat(),
|
|
540
|
-
it.longitude.toFloat(),
|
|
541
|
-
it.altitude.toFloat(),
|
|
542
|
-
System.currentTimeMillis()
|
|
543
|
-
)
|
|
544
|
-
}
|
|
545
|
-
}
|
|
512
|
+
locationControl.start { location: Location ->
|
|
513
|
+
mGeofield = GeomagneticField(
|
|
514
|
+
location.latitude.toFloat(), location.longitude.toFloat(), location.altitude.toFloat(),
|
|
515
|
+
System.currentTimeMillis()
|
|
516
|
+
)
|
|
546
517
|
}
|
|
547
|
-
mLocationProvider.requestLocationUpdates(locationRequest, locationCallback, Looper.getMainLooper())
|
|
548
518
|
}
|
|
549
519
|
mSensorManager.registerListener(
|
|
550
520
|
this,
|
|
551
521
|
mSensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD),
|
|
552
522
|
SensorManager.SENSOR_DELAY_NORMAL
|
|
553
523
|
)
|
|
554
|
-
mSensorManager.registerListener(
|
|
555
|
-
this,
|
|
556
|
-
mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER),
|
|
557
|
-
SensorManager.SENSOR_DELAY_NORMAL
|
|
558
|
-
)
|
|
524
|
+
mSensorManager.registerListener(this, mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL)
|
|
559
525
|
}
|
|
560
526
|
|
|
561
527
|
private fun sendUpdate() {
|
|
@@ -633,6 +599,7 @@ class LocationModule : Module(), LifecycleEventListener, SensorEventListener, Ac
|
|
|
633
599
|
private fun stopWatching() {
|
|
634
600
|
// if permissions not granted it won't work anyway, but this can be invoked when permission dialog appears
|
|
635
601
|
if (Geocoder.isPresent() && !isMissingForegroundPermissions()) {
|
|
602
|
+
SmartLocation.with(mContext).geocoding().stop()
|
|
636
603
|
mGeocoderPaused = true
|
|
637
604
|
}
|
|
638
605
|
for (requestId in mLocationCallbacks.keys) {
|
|
@@ -699,10 +666,8 @@ class LocationModule : Module(), LifecycleEventListener, SensorEventListener, Ac
|
|
|
699
666
|
locations?.let { location ->
|
|
700
667
|
location.let {
|
|
701
668
|
val results = it.mapNotNull { address ->
|
|
702
|
-
val
|
|
703
|
-
|
|
704
|
-
newLocation.longitude = address.longitude
|
|
705
|
-
GeocodeResponse.from(newLocation)
|
|
669
|
+
val locationAddress = LocationAddress(address)
|
|
670
|
+
GeocodeResponse.from(locationAddress.location)
|
|
706
671
|
}
|
|
707
672
|
continuation.resume(results)
|
|
708
673
|
}
|
package/expo-module.config.json
CHANGED
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
{
|
|
2
|
-
"platforms": [
|
|
2
|
+
"platforms": [
|
|
3
|
+
"apple",
|
|
4
|
+
"android"
|
|
5
|
+
],
|
|
3
6
|
"apple": {
|
|
4
|
-
"modules": [
|
|
7
|
+
"modules": [
|
|
8
|
+
"LocationModule"
|
|
9
|
+
]
|
|
5
10
|
},
|
|
6
11
|
"android": {
|
|
7
|
-
"modules": [
|
|
12
|
+
"modules": [
|
|
13
|
+
"expo.modules.location.LocationModule"
|
|
14
|
+
],
|
|
15
|
+
"gradleAarProjects": [
|
|
16
|
+
{
|
|
17
|
+
"name": "io.nlopez.smartlocation-jetified-aar",
|
|
18
|
+
"aarFilePath": "android/libs/io.nlopez.smartlocation-3.3.3-jetified.aar"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
8
21
|
}
|
|
9
22
|
}
|
package/ios/LocationModule.swift
CHANGED
|
@@ -163,13 +163,9 @@ public final class LocationModule: Module {
|
|
|
163
163
|
// Background location
|
|
164
164
|
|
|
165
165
|
AsyncFunction("startLocationUpdatesAsync") { (taskName: String, options: [String: Any]) in
|
|
166
|
-
// There are two ways of starting this service.
|
|
167
|
-
// 1. As a background location service, this requires the background location permission.
|
|
168
|
-
// 2. As a user-initiated foreground service, this does NOT require the background location permission.
|
|
169
|
-
// Unfortunately, we cannot distinguish between those cases.
|
|
170
|
-
// So we only check foreground permission which needs to be granted in both cases.
|
|
171
166
|
try ensureLocationServicesEnabled()
|
|
172
167
|
try ensureForegroundLocationPermissions(appContext)
|
|
168
|
+
try ensureBackgroundLocationPermissions(appContext)
|
|
173
169
|
|
|
174
170
|
guard CLLocationManager.significantLocationChangeMonitoringAvailable() else {
|
|
175
171
|
throw Exceptions.LocationUpdatesUnavailable()
|
|
@@ -93,7 +93,7 @@ static SEL alwaysAuthorizationSelector;
|
|
|
93
93
|
}
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
return @{ @"status": @(status) };
|
|
96
|
+
return @{ @"status": @(status), @"scope": @(systemStatus == kCLAuthorizationStatusAuthorizedWhenInUse ? "whenInUse" : systemStatus == kCLAuthorizationStatusAuthorizedAlways ? "always" : "none") };
|
|
97
97
|
}
|
|
98
98
|
|
|
99
99
|
@end
|
|
@@ -54,7 +54,7 @@ static SEL whenInUseAuthorizationSelector;
|
|
|
54
54
|
}
|
|
55
55
|
}
|
|
56
56
|
|
|
57
|
-
return @{ @"status": @(status) };
|
|
57
|
+
return @{ @"status": @(status), @"scope": @(systemStatus == kCLAuthorizationStatusAuthorizedWhenInUse ? "whenInUse" : systemStatus == kCLAuthorizationStatusAuthorizedAlways ? "always" : "none") };
|
|
58
58
|
}
|
|
59
59
|
|
|
60
60
|
@end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-location",
|
|
3
|
-
"version": "18.0.8
|
|
3
|
+
"version": "18.0.8",
|
|
4
4
|
"description": "Allows reading geolocation information from the device. Your app can poll for the current location or subscribe to location update events.",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"types": "build/index.d.ts",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"preset": "expo-module-scripts"
|
|
40
40
|
},
|
|
41
41
|
"devDependencies": {
|
|
42
|
-
"expo-module-scripts": "4.0.
|
|
42
|
+
"expo-module-scripts": "^4.0.4"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"expo": "
|
|
45
|
+
"expo": "*"
|
|
46
46
|
},
|
|
47
|
-
"gitHead": "
|
|
47
|
+
"gitHead": "ee33df50fbe6bf9bb5d772e7f341f85a27cf9993"
|
|
48
48
|
}
|