Fix stability

This commit is contained in:
ganfra 2026-03-13 15:48:56 +01:00
parent 249d45ce04
commit 83832a38f9
4 changed files with 69 additions and 78 deletions

View file

@ -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.AvatarData
import io.element.android.libraries.designsystem.components.avatar.AvatarSize import io.element.android.libraries.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.room.location.AssetType
import kotlinx.collections.immutable.persistentListOf
@AssistedInject @AssistedInject
class ShowLocationPresenter( class ShowLocationPresenter(
@ -95,7 +96,7 @@ class ShowLocationPresenter(
} }
} }
val markers = remember(mode) { val markers = remember {
when (mode) { when (mode) {
is ShowLocationMode.Static -> { is ShowLocationMode.Static -> {
val pinVariant = if (mode.assetType == AssetType.PIN) { val pinVariant = if (mode.assetType == AssetType.PIN) {
@ -111,7 +112,7 @@ class ShowLocationPresenter(
isLive = false, isLive = false,
) )
} }
listOf( persistentListOf(
LocationMarkerData( LocationMarkerData(
id = mode.senderId.value, id = mode.senderId.value,
location = mode.location, location = mode.location,
@ -119,16 +120,16 @@ class ShowLocationPresenter(
) )
) )
} }
ShowLocationMode.Live -> emptyList() ShowLocationMode.Live -> persistentListOf()
} }
} }
val locationShares = remember(mode) { val locationShares = remember {
when (mode) { when (mode) {
is ShowLocationMode.Static -> { is ShowLocationMode.Static -> {
val relativeTime = dateFormatter.format(timestamp = mode.timestamp, mode = DateFormatterMode.Full, useRelative = true) val relativeTime = dateFormatter.format(timestamp = mode.timestamp, mode = DateFormatterMode.Full, useRelative = true)
val formattedTimestamp = "Shared $relativeTime" val formattedTimestamp = "Shared $relativeTime"
listOf( persistentListOf(
LocationShareItem( LocationShareItem(
userId = mode.senderId, userId = mode.senderId,
displayName = mode.senderName, displayName = mode.senderName,
@ -145,13 +146,12 @@ class ShowLocationPresenter(
) )
) )
} }
ShowLocationMode.Live -> emptyList() ShowLocationMode.Live -> persistentListOf()
} }
} }
return ShowLocationState( return ShowLocationState(
dialogState = dialogState, dialogState = dialogState,
mode = mode,
markers = markers, markers = markers,
locationShares = locationShares, locationShares = locationShares,
hasLocationPermission = permissionsState.isAnyGranted, hasLocationPermission = permissionsState.isAnyGranted,

View file

@ -9,18 +9,17 @@
package io.element.android.features.location.impl.show package io.element.android.features.location.impl.show
import io.element.android.features.location.api.Location 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.LocationConstraintsDialogState
import io.element.android.features.location.impl.common.ui.LocationMarkerData import io.element.android.features.location.impl.common.ui.LocationMarkerData
import io.element.android.libraries.designsystem.components.avatar.AvatarData 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.core.UserId
import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.room.location.AssetType
import kotlinx.collections.immutable.ImmutableList
data class ShowLocationState( data class ShowLocationState(
val dialogState: LocationConstraintsDialogState, val dialogState: LocationConstraintsDialogState,
val mode: ShowLocationMode, val markers: ImmutableList<LocationMarkerData>,
val markers: List<LocationMarkerData>, val locationShares: ImmutableList<LocationShareItem>,
val locationShares: List<LocationShareItem>,
val hasLocationPermission: Boolean, val hasLocationPermission: Boolean,
val isTrackMyLocation: Boolean, val isTrackMyLocation: Boolean,
val appName: String, val appName: String,

View file

@ -10,7 +10,6 @@ package io.element.android.features.location.impl.show
import androidx.compose.ui.tooling.preview.PreviewParameterProvider import androidx.compose.ui.tooling.preview.PreviewParameterProvider
import io.element.android.features.location.api.Location 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.LocationConstraintsDialogState
import io.element.android.features.location.impl.common.ui.LocationMarkerData import io.element.android.features.location.impl.common.ui.LocationMarkerData
import io.element.android.libraries.designsystem.components.PinVariant 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.designsystem.components.avatar.AvatarSize
import io.element.android.libraries.matrix.api.core.UserId import io.element.android.libraries.matrix.api.core.UserId
import io.element.android.libraries.matrix.api.room.location.AssetType import io.element.android.libraries.matrix.api.room.location.AssetType
import kotlinx.collections.immutable.toImmutableList
private const val APP_NAME = "ApplicationName" private const val APP_NAME = "ApplicationName"
@ -45,62 +45,23 @@ class ShowLocationStateProvider : PreviewParameterProvider<ShowLocationState> {
) )
} }
private val defaultLocation = Location(1.23, 2.34, 4f)
private val defaultSenderId = UserId("@alice:matrix.org")
private const val defaultSenderName = "Alice"
fun aShowLocationState( fun aShowLocationState(
constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None, constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None,
mode: ShowLocationMode = aStaticLocationMode(), markers: List<LocationMarkerData> = listOf(aLocationMarkerData()),
markers: List<LocationMarkerData>? = null, locationShares: List<LocationShareItem> = listOf(aLocationShareItem()),
locationSharers: List<LocationShareItem>? = null,
hasLocationPermission: Boolean = false, hasLocationPermission: Boolean = false,
isTrackMyLocation: Boolean = false, isTrackMyLocation: Boolean = false,
appName: String = APP_NAME, appName: String = APP_NAME,
eventSink: (ShowLocationEvent) -> Unit = {}, eventSink: (ShowLocationEvent) -> Unit = {},
): ShowLocationState { ): 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( return ShowLocationState(
dialogState = constraintsDialogState, dialogState = constraintsDialogState,
mode = mode, markers = markers.toImmutableList(),
markers = effectiveMarkers, locationShares = locationShares.toImmutableList(),
locationShares = effectiveLocationSharers,
hasLocationPermission = hasLocationPermission, hasLocationPermission = hasLocationPermission,
isTrackMyLocation = isTrackMyLocation, isTrackMyLocation = isTrackMyLocation,
appName = appName, appName = appName,
@ -108,18 +69,43 @@ fun aShowLocationState(
) )
} }
fun aStaticLocationMode( fun aLocationMarkerData(
location: Location = Location(1.23, 2.34, 4f), id: String = defaultSenderId.value,
senderName: String = "Alice", location: Location = defaultLocation,
senderId: UserId = UserId("@alice:matrix.org"), variant: PinVariant = PinVariant.UserLocation(
senderAvatarUrl: String? = null, avatarData = AvatarData(
timestamp: Long = System.currentTimeMillis(), id = defaultSenderId.value,
assetType: AssetType? = null, name = defaultSenderName,
) = ShowLocationMode.Static( url = null,
size = AvatarSize.LocationPin,
),
isLive = false,
),
) = LocationMarkerData(
id = id,
location = location, location = location,
senderName = senderName, variant = variant,
senderId = senderId, )
senderAvatarUrl = senderAvatarUrl,
timestamp = timestamp, 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, assetType = assetType,
) )

View file

@ -6,6 +6,8 @@
* Please see LICENSE files in the repository root for full details. * 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 package io.element.android.features.location.impl.show
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
@ -19,6 +21,7 @@ import androidx.compose.material3.rememberBottomSheetScaffoldState
import androidx.compose.material3.rememberStandardBottomSheetState import androidx.compose.material3.rememberStandardBottomSheetState
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier 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.tooling.preview.PreviewParameter
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.api.ShowLocationMode
import io.element.android.features.location.impl.common.MapDefaults 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.LocationConstraintsDialog
import io.element.android.features.location.impl.common.ui.LocationFloatingActionButton import io.element.android.features.location.impl.common.ui.LocationFloatingActionButton
@ -63,12 +65,16 @@ fun ShowLocationView(
onDismiss = { state.eventSink(ShowLocationEvent.DismissDialog) }, onDismiss = { state.eventSink(ShowLocationEvent.DismissDialog) },
) )
val initialPosition = when (val mode = state.mode) { val initialPosition = remember {
is ShowLocationMode.Static -> CameraPosition( if (state.markers.isEmpty()) {
target = Position(latitude = mode.location.lat, longitude = mode.location.lon), MapDefaults.defaultCameraPosition
zoom = MapDefaults.DEFAULT_ZOOM } else {
) val firstLocation = state.markers.first().location
ShowLocationMode.Live -> MapDefaults.defaultCameraPosition CameraPosition(
target = Position(latitude = firstLocation.lat, longitude = firstLocation.lon),
zoom = MapDefaults.DEFAULT_ZOOM
)
}
} }
val cameraState = rememberCameraState(firstPosition = initialPosition) val cameraState = rememberCameraState(firstPosition = initialPosition)
val userLocationState = rememberUserLocationState(state.hasLocationPermission) val userLocationState = rememberUserLocationState(state.hasLocationPermission)