Fix API breaks and an issue with the location changing not moving the camera

This commit is contained in:
Jorge Martín
2026-05-27 13:19:41 +02:00
parent 8fd5072ba5
commit e115d620ca
4 changed files with 33 additions and 20 deletions
@@ -13,6 +13,7 @@ import androidx.compose.ui.platform.LocalInspectionMode
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.features.location.impl.common.MapDefaults import io.element.android.features.location.impl.common.MapDefaults
import kotlinx.coroutines.flow.SharingStarted
import org.maplibre.compose.camera.CameraState import org.maplibre.compose.camera.CameraState
import org.maplibre.compose.location.DesiredAccuracy import org.maplibre.compose.location.DesiredAccuracy
import org.maplibre.compose.location.LocationPuck import org.maplibre.compose.location.LocationPuck
@@ -23,6 +24,9 @@ import org.maplibre.compose.location.UserLocationState
import org.maplibre.compose.location.rememberAndroidLocationProvider import org.maplibre.compose.location.rememberAndroidLocationProvider
import org.maplibre.compose.location.rememberNullLocationProvider import org.maplibre.compose.location.rememberNullLocationProvider
import org.maplibre.compose.location.rememberUserLocationState 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 import kotlin.time.Duration.Companion.seconds
@Composable @Composable
@@ -31,22 +35,28 @@ fun UserLocationPuck(
locationState: UserLocationState, locationState: UserLocationState,
trackUserLocation: Boolean, trackUserLocation: Boolean,
) { ) {
LocationTrackingEffect(
locationState = locationState,
enabled = trackUserLocation,
) {
val finalPosition = cameraState.position.copy(
target = currentLocation.position,
bearing = currentLocation.bearing ?: cameraState.position.bearing,
zoom = cameraState.position.zoom.coerceAtLeast(MapDefaults.DEFAULT_ZOOM)
)
cameraState.animateTo(finalPosition)
}
val location = locationState.location val location = locationState.location
if (location != null) { 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( LocationPuck(
idPrefix = "user-location", idPrefix = "user-location",
locationState = locationState, location = locationState.location,
cameraState = cameraState, cameraState = cameraState,
accuracyThreshold = Float.POSITIVE_INFINITY, accuracyThreshold = Float.POSITIVE_INFINITY,
showBearingAccuracy = false, showBearingAccuracy = false,
@@ -74,7 +84,8 @@ fun rememberUserLocationState(hasLocationPermission: Boolean): UserLocationState
rememberAndroidLocationProvider( rememberAndroidLocationProvider(
updateInterval = 5.seconds, updateInterval = 5.seconds,
desiredAccuracy = DesiredAccuracy.High, desiredAccuracy = DesiredAccuracy.High,
minDistanceMeters = 5f, minDistance = 5.meters,
sharingStarted = SharingStarted.Eagerly,
) )
} }
return rememberUserLocationState(locationProvider) return rememberUserLocationState(locationProvider)
@@ -36,6 +36,8 @@ import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onEach import kotlinx.coroutines.flow.onEach
import org.maplibre.compose.location.AndroidLocationProvider import org.maplibre.compose.location.AndroidLocationProvider
import org.maplibre.compose.location.DesiredAccuracy import org.maplibre.compose.location.DesiredAccuracy
import org.maplibre.spatialk.units.extensions.inMeters
import org.maplibre.spatialk.units.extensions.meters
import timber.log.Timber import timber.log.Timber
import kotlin.time.Duration.Companion.seconds import kotlin.time.Duration.Companion.seconds
import io.element.android.features.location.api.Location as ApiLocation import io.element.android.features.location.api.Location as ApiLocation
@@ -91,7 +93,7 @@ class LiveLocationSharingService : Service() {
val locationProvider = AndroidLocationProvider( val locationProvider = AndroidLocationProvider(
context = applicationContext, context = applicationContext,
updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds, updateInterval = UPDATE_INTERVAL_IN_SECOND.seconds,
minDistanceMeters = minDistanceMeters.toFloat(), minDistance = minDistanceMeters.meters,
desiredAccuracy = DesiredAccuracy.Balanced, desiredAccuracy = DesiredAccuracy.Balanced,
coroutineScope = coroutineScope coroutineScope = coroutineScope
) )
@@ -100,9 +102,9 @@ class LiveLocationSharingService : Service() {
.filterNotNull() .filterNotNull()
.map { location -> .map { location ->
ApiLocation( ApiLocation(
lat = location.position.latitude, lat = location.position.value.latitude,
lon = location.position.longitude, lon = location.position.value.longitude,
accuracy = location.accuracy.toFloat(), accuracy = location.position.accuracy?.inMeters?.toFloat() ?: 0f,
) )
} }
.onEach(coordinator::dispatch) .onEach(coordinator::dispatch)
@@ -94,8 +94,8 @@ class ShareLocationPresenter(
fun checkLocationConstraints() { fun checkLocationConstraints() {
// No need to check SendLiveLocationPermissions here // No need to check SendLiveLocationPermissions here
val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED) val locationConstraints = checkLocationConstraints(permissionsState, locationActions, SendLiveLocationPermissions.GRANTED)
dialogState = ShareLocationState.Dialog.Constraints(locationConstraints.toDialogState())
trackUserPosition = locationConstraints is LocationConstraintsCheck.Success trackUserPosition = locationConstraints is LocationConstraintsCheck.Success
dialogState = ShareLocationState.Dialog.Constraints(locationConstraints.toDialogState())
} }
suspend fun computeLiveLocationDialogState(): ShareLocationState.Dialog { suspend fun computeLiveLocationDialogState(): ShareLocationState.Dialog {
@@ -222,8 +222,8 @@ private fun BottomSheetContent(
state.eventSink( state.eventSink(
ShareLocationEvent.ShareStaticLocation( ShareLocationEvent.ShareStaticLocation(
location = Location( location = Location(
lat = userLocation.position.latitude, lat = userLocation.position.value.latitude,
lon = userLocation.position.longitude lon = userLocation.position.value.longitude
), ),
isPinned = false isPinned = false
) )