mirror of
https://github.com/Novaloop-AG/element-x-android.git
synced 2026-11-02 12:07:28 +00:00
Use simple custom LocationTrackingEffect waiting for a fix from maplibre
This commit is contained in:
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2026 Element Creations Ltd.
|
||||
*
|
||||
* SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-Element-Commercial.
|
||||
* Please see LICENSE files in the repository root for full details.
|
||||
*/
|
||||
|
||||
package io.element.android.features.location.impl.common.ui
|
||||
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.rememberUpdatedState
|
||||
import androidx.compose.runtime.snapshotFlow
|
||||
import kotlinx.coroutines.flow.distinctUntilChanged
|
||||
import org.maplibre.compose.location.Location
|
||||
import org.maplibre.compose.location.UserLocationState
|
||||
import kotlin.math.abs
|
||||
|
||||
/**
|
||||
* Drop-in replacement for the library's LocationTrackingEffect.
|
||||
* TODO remove once https://github.com/maplibre/maplibre-compose/issues/808 is fixed
|
||||
*/
|
||||
@Composable
|
||||
internal fun SimpleLocationTrackingEffect(
|
||||
locationState: UserLocationState,
|
||||
enabled: Boolean = true,
|
||||
precision: Double = 0.00001,
|
||||
onLocationChange: suspend (Location?) -> Unit,
|
||||
) {
|
||||
val latestOnLocationChange by rememberUpdatedState(onLocationChange)
|
||||
|
||||
LaunchedEffect(locationState, enabled) {
|
||||
if (!enabled) return@LaunchedEffect
|
||||
val locationStateFlow = snapshotFlow { locationState.location }
|
||||
locationStateFlow
|
||||
.distinctUntilChanged { oldLocation, newLocation ->
|
||||
if (oldLocation != null && newLocation != null) {
|
||||
when {
|
||||
abs(oldLocation.position.value.latitude - newLocation.position.value.latitude) >= precision -> false
|
||||
abs(oldLocation.position.value.longitude - newLocation.position.value.longitude) >= precision -> false
|
||||
else -> true
|
||||
}
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
.collect { location ->
|
||||
latestOnLocationChange(location)
|
||||
}
|
||||
}
|
||||
}
|
||||
+14
-23
@@ -13,19 +13,15 @@ import androidx.compose.ui.platform.LocalInspectionMode
|
||||
import androidx.compose.ui.unit.dp
|
||||
import io.element.android.compound.theme.ElementTheme
|
||||
import io.element.android.features.location.impl.common.MapDefaults
|
||||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import org.maplibre.compose.camera.CameraState
|
||||
import org.maplibre.compose.location.DesiredAccuracy
|
||||
import org.maplibre.compose.location.LocationPuck
|
||||
import org.maplibre.compose.location.LocationPuckColors
|
||||
import org.maplibre.compose.location.LocationPuckSizes
|
||||
import org.maplibre.compose.location.LocationTrackingEffect
|
||||
import org.maplibre.compose.location.UserLocationState
|
||||
import org.maplibre.compose.location.rememberAndroidLocationProvider
|
||||
import org.maplibre.compose.location.rememberNullLocationProvider
|
||||
import org.maplibre.compose.location.rememberUserLocationState
|
||||
import org.maplibre.spatialk.units.Bearing
|
||||
import org.maplibre.spatialk.units.extensions.inDegrees
|
||||
import org.maplibre.spatialk.units.extensions.meters
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
@@ -35,28 +31,24 @@ fun UserLocationPuck(
|
||||
locationState: UserLocationState,
|
||||
trackUserLocation: Boolean,
|
||||
) {
|
||||
SimpleLocationTrackingEffect(
|
||||
locationState = locationState,
|
||||
enabled = trackUserLocation,
|
||||
) { currentLocation ->
|
||||
val target = currentLocation?.position?.value ?: cameraState.position.target
|
||||
val newPosition = cameraState.position.copy(
|
||||
target = target,
|
||||
// Force pointing to NORTH
|
||||
bearing = 0.0,
|
||||
zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM)
|
||||
)
|
||||
cameraState.animateTo(newPosition)
|
||||
}
|
||||
val location = locationState.location
|
||||
if (location != null) {
|
||||
// Moved inside this block so it correctly tracks the updated locationState value
|
||||
LocationTrackingEffect(
|
||||
locationState = locationState,
|
||||
enabled = trackUserLocation,
|
||||
) {
|
||||
val newTarget = currentLocation.location?.position?.value
|
||||
val newBearing = currentLocation.orientation?.orientation?.value?.clockwiseRotationTo(Bearing.North)?.inDegrees
|
||||
if (newTarget != null || newBearing != null) {
|
||||
val finalPosition = cameraState.position.copy(
|
||||
target = newTarget ?: cameraState.position.target,
|
||||
bearing = newBearing ?: cameraState.position.bearing,
|
||||
zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM)
|
||||
)
|
||||
cameraState.animateTo(finalPosition)
|
||||
}
|
||||
}
|
||||
|
||||
LocationPuck(
|
||||
idPrefix = "user-location",
|
||||
location = locationState.location,
|
||||
location = location,
|
||||
cameraState = cameraState,
|
||||
accuracyThreshold = Float.POSITIVE_INFINITY,
|
||||
showBearingAccuracy = false,
|
||||
@@ -85,7 +77,6 @@ fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState
|
||||
updateInterval = 5.seconds,
|
||||
desiredAccuracy = DesiredAccuracy.High,
|
||||
minDistance = 5.meters,
|
||||
sharingStarted = SharingStarted.Eagerly,
|
||||
)
|
||||
}
|
||||
return rememberUserLocationState(locationProvider)
|
||||
|
||||
+3
-1
@@ -153,7 +153,9 @@ fun ShowLocationView(
|
||||
val position = CameraPosition(
|
||||
padding = sheetPaddings,
|
||||
target = Position(locationShare.location.lon, locationShare.location.lat),
|
||||
zoom = MapDefaults.DEFAULT_ZOOM
|
||||
// Force pointing to NORTH
|
||||
bearing = 0.0,
|
||||
zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM),
|
||||
)
|
||||
coroutineScope.launch {
|
||||
cameraState.animateTo(finalPosition = position)
|
||||
|
||||
Reference in New Issue
Block a user