Fix stability
This commit is contained in:
parent
249d45ce04
commit
83832a38f9
4 changed files with 69 additions and 78 deletions
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue