diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt index d74d2f36e1..9978c6e1f5 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationPresenter.kt @@ -37,6 +37,7 @@ import io.element.android.libraries.designsystem.components.PinVariant import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.room.location.AssetType +import kotlinx.collections.immutable.persistentListOf @AssistedInject class ShowLocationPresenter( @@ -95,7 +96,7 @@ class ShowLocationPresenter( } } - val markers = remember(mode) { + val markers = remember { when (mode) { is ShowLocationMode.Static -> { val pinVariant = if (mode.assetType == AssetType.PIN) { @@ -111,7 +112,7 @@ class ShowLocationPresenter( isLive = false, ) } - listOf( + persistentListOf( LocationMarkerData( id = mode.senderId.value, location = mode.location, @@ -119,16 +120,16 @@ class ShowLocationPresenter( ) ) } - ShowLocationMode.Live -> emptyList() + ShowLocationMode.Live -> persistentListOf() } } - val locationShares = remember(mode) { + val locationShares = remember { when (mode) { is ShowLocationMode.Static -> { val relativeTime = dateFormatter.format(timestamp = mode.timestamp, mode = DateFormatterMode.Full, useRelative = true) val formattedTimestamp = "Shared $relativeTime" - listOf( + persistentListOf( LocationShareItem( userId = mode.senderId, displayName = mode.senderName, @@ -145,13 +146,12 @@ class ShowLocationPresenter( ) ) } - ShowLocationMode.Live -> emptyList() + ShowLocationMode.Live -> persistentListOf() } } return ShowLocationState( dialogState = dialogState, - mode = mode, markers = markers, locationShares = locationShares, hasLocationPermission = permissionsState.isAnyGranted, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt index 85d79f1192..f6c2e6e18f 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationState.kt @@ -9,18 +9,17 @@ package io.element.android.features.location.impl.show import io.element.android.features.location.api.Location -import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.features.location.impl.common.ui.LocationMarkerData import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.location.AssetType +import kotlinx.collections.immutable.ImmutableList data class ShowLocationState( val dialogState: LocationConstraintsDialogState, - val mode: ShowLocationMode, - val markers: List, - val locationShares: List, + val markers: ImmutableList, + val locationShares: ImmutableList, val hasLocationPermission: Boolean, val isTrackMyLocation: Boolean, val appName: String, diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt index 9bbd818f1a..274ccfc8f2 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationStateProvider.kt @@ -10,7 +10,6 @@ package io.element.android.features.location.impl.show import androidx.compose.ui.tooling.preview.PreviewParameterProvider import io.element.android.features.location.api.Location -import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.ui.LocationConstraintsDialogState import io.element.android.features.location.impl.common.ui.LocationMarkerData import io.element.android.libraries.designsystem.components.PinVariant @@ -18,6 +17,7 @@ import io.element.android.libraries.designsystem.components.avatar.AvatarData import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.room.location.AssetType +import kotlinx.collections.immutable.toImmutableList private const val APP_NAME = "ApplicationName" @@ -45,62 +45,23 @@ class ShowLocationStateProvider : PreviewParameterProvider { ) } +private val defaultLocation = Location(1.23, 2.34, 4f) +private val defaultSenderId = UserId("@alice:matrix.org") +private const val defaultSenderName = "Alice" + fun aShowLocationState( constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None, - mode: ShowLocationMode = aStaticLocationMode(), - markers: List? = null, - locationSharers: List? = null, + markers: List = listOf(aLocationMarkerData()), + locationShares: List = listOf(aLocationShareItem()), hasLocationPermission: Boolean = false, isTrackMyLocation: Boolean = false, appName: String = APP_NAME, eventSink: (ShowLocationEvent) -> Unit = {}, ): ShowLocationState { - val effectiveMarkers = markers ?: when (mode) { - is ShowLocationMode.Static -> listOf( - LocationMarkerData( - id = mode.senderId.value, - location = mode.location, - variant = if (mode.assetType == AssetType.PIN) { - PinVariant.PinnedLocation - } else { - PinVariant.UserLocation( - avatarData = AvatarData( - id = mode.senderId.value, - name = mode.senderName, - url = mode.senderAvatarUrl, - size = AvatarSize.LocationPin, - ), - isLive = true, - ) - } - ) - ) - ShowLocationMode.Live -> emptyList() - } - val effectiveLocationSharers = locationSharers ?: when (mode) { - is ShowLocationMode.Static -> listOf( - LocationShareItem( - userId = mode.senderId, - displayName = mode.senderName, - avatarData = AvatarData( - id = mode.senderId.value, - name = mode.senderName, - url = mode.senderAvatarUrl, - size = AvatarSize.UserListItem, - ), - formattedTimestamp = "Shared 1 min ago", - isLive = false, - assetType = mode.assetType, - location = mode.location, - ) - ) - ShowLocationMode.Live -> emptyList() - } return ShowLocationState( dialogState = constraintsDialogState, - mode = mode, - markers = effectiveMarkers, - locationShares = effectiveLocationSharers, + markers = markers.toImmutableList(), + locationShares = locationShares.toImmutableList(), hasLocationPermission = hasLocationPermission, isTrackMyLocation = isTrackMyLocation, appName = appName, @@ -108,18 +69,43 @@ fun aShowLocationState( ) } -fun aStaticLocationMode( - location: Location = Location(1.23, 2.34, 4f), - senderName: String = "Alice", - senderId: UserId = UserId("@alice:matrix.org"), - senderAvatarUrl: String? = null, - timestamp: Long = System.currentTimeMillis(), - assetType: AssetType? = null, -) = ShowLocationMode.Static( +fun aLocationMarkerData( + id: String = defaultSenderId.value, + location: Location = defaultLocation, + variant: PinVariant = PinVariant.UserLocation( + avatarData = AvatarData( + id = defaultSenderId.value, + name = defaultSenderName, + url = null, + size = AvatarSize.LocationPin, + ), + isLive = false, + ), +) = LocationMarkerData( + id = id, location = location, - senderName = senderName, - senderId = senderId, - senderAvatarUrl = senderAvatarUrl, - timestamp = timestamp, + variant = variant, +) + +fun aLocationShareItem( + userId: UserId = defaultSenderId, + displayName: String = defaultSenderName, + avatarData: AvatarData = AvatarData( + id = defaultSenderId.value, + name = defaultSenderName, + url = null, + size = AvatarSize.UserListItem, + ), + formattedTimestamp: String = "Shared 1 min ago", + location: Location = defaultLocation, + isLive: Boolean = false, + assetType: AssetType? = null, +) = LocationShareItem( + userId = userId, + displayName = displayName, + avatarData = avatarData, + formattedTimestamp = formattedTimestamp, + location = location, + isLive = isLive, assetType = assetType, ) diff --git a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt index fdeb027b1e..d97cef81d0 100644 --- a/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt +++ b/features/location/impl/src/main/kotlin/io/element/android/features/location/impl/show/ShowLocationView.kt @@ -6,6 +6,8 @@ * Please see LICENSE files in the repository root for full details. */ +@file:Suppress("COMPOSE_APPLIER_CALL_MISMATCH") + package io.element.android.features.location.impl.show import androidx.compose.foundation.clickable @@ -19,6 +21,7 @@ import androidx.compose.material3.rememberBottomSheetScaffoldState import androidx.compose.material3.rememberStandardBottomSheetState import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier @@ -26,7 +29,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.tooling.preview.PreviewParameter import androidx.compose.ui.unit.dp import io.element.android.compound.theme.ElementTheme -import io.element.android.features.location.api.ShowLocationMode import io.element.android.features.location.impl.common.MapDefaults import io.element.android.features.location.impl.common.ui.LocationConstraintsDialog import io.element.android.features.location.impl.common.ui.LocationFloatingActionButton @@ -63,12 +65,16 @@ fun ShowLocationView( onDismiss = { state.eventSink(ShowLocationEvent.DismissDialog) }, ) - val initialPosition = when (val mode = state.mode) { - is ShowLocationMode.Static -> CameraPosition( - target = Position(latitude = mode.location.lat, longitude = mode.location.lon), - zoom = MapDefaults.DEFAULT_ZOOM - ) - ShowLocationMode.Live -> MapDefaults.defaultCameraPosition + val initialPosition = remember { + if (state.markers.isEmpty()) { + MapDefaults.defaultCameraPosition + } else { + val firstLocation = state.markers.first().location + CameraPosition( + target = Position(latitude = firstLocation.lat, longitude = firstLocation.lon), + zoom = MapDefaults.DEFAULT_ZOOM + ) + } } val cameraState = rememberCameraState(firstPosition = initialPosition) val userLocationState = rememberUserLocationState(state.hasLocationPermission)