Add focused location tracking when opening the map
This commit is contained in:
parent
5f3226107a
commit
f6eeea2134
6 changed files with 28 additions and 16 deletions
|
|
@ -24,5 +24,7 @@ sealed interface ShowLocationMode : Parcelable {
|
||||||
) : ShowLocationMode
|
) : ShowLocationMode
|
||||||
|
|
||||||
@Parcelize
|
@Parcelize
|
||||||
data object Live : ShowLocationMode
|
data class Live(
|
||||||
|
val senderId: UserId
|
||||||
|
) : ShowLocationMode
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,8 @@ class ShowLocationPresenter(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ShowLocationMode.Live -> {
|
is ShowLocationMode.Live -> {
|
||||||
val liveShares by produceState(persistentListOf()) {
|
produceState(persistentListOf()) {
|
||||||
val liveLocationSharesFlow = joinedRoom.subscribeToLiveLocationShares()
|
val liveLocationSharesFlow = joinedRoom.subscribeToLiveLocationShares()
|
||||||
val membersStateFlow = joinedRoom.membersStateFlow.mapState { it.joinedRoomMembers() }
|
val membersStateFlow = joinedRoom.membersStateFlow.mapState { it.joinedRoomMembers() }
|
||||||
combine(liveLocationSharesFlow, membersStateFlow) { liveShares, members ->
|
combine(liveLocationSharesFlow, membersStateFlow) { liveShares, members ->
|
||||||
|
|
@ -158,14 +158,19 @@ class ShowLocationPresenter(
|
||||||
)
|
)
|
||||||
}.toPersistentList()
|
}.toPersistentList()
|
||||||
}.collect { value = it }
|
}.collect { value = it }
|
||||||
}
|
}.value
|
||||||
liveShares
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val focusedLocation = when (mode) {
|
||||||
|
is ShowLocationMode.Static -> locationShares.firstOrNull()
|
||||||
|
is ShowLocationMode.Live -> locationShares.firstOrNull { it.userId == mode.senderId }
|
||||||
|
}
|
||||||
|
|
||||||
return ShowLocationState(
|
return ShowLocationState(
|
||||||
dialogState = dialogState,
|
dialogState = dialogState,
|
||||||
locationShares = locationShares,
|
locationShares = locationShares,
|
||||||
|
focusedLocation = focusedLocation,
|
||||||
hasLocationPermission = permissionsState.isAnyGranted,
|
hasLocationPermission = permissionsState.isAnyGranted,
|
||||||
isTrackMyLocation = isTrackMyLocation,
|
isTrackMyLocation = isTrackMyLocation,
|
||||||
isLive = mode is ShowLocationMode.Live,
|
isLive = mode is ShowLocationMode.Live,
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@
|
||||||
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.PinVariant
|
import io.element.android.libraries.designsystem.components.PinVariant
|
||||||
|
|
@ -22,6 +21,7 @@ data class ShowLocationState(
|
||||||
val isLive: Boolean,
|
val isLive: Boolean,
|
||||||
val dialogState: LocationConstraintsDialogState,
|
val dialogState: LocationConstraintsDialogState,
|
||||||
val locationShares: ImmutableList<LocationShareItem>,
|
val locationShares: ImmutableList<LocationShareItem>,
|
||||||
|
val focusedLocation: LocationShareItem?,
|
||||||
val hasLocationPermission: Boolean,
|
val hasLocationPermission: Boolean,
|
||||||
val isTrackMyLocation: Boolean,
|
val isTrackMyLocation: Boolean,
|
||||||
val appName: String,
|
val appName: String,
|
||||||
|
|
|
||||||
|
|
@ -50,6 +50,7 @@ fun aShowLocationState(
|
||||||
isLive: Boolean = false,
|
isLive: Boolean = false,
|
||||||
constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None,
|
constraintsDialogState: LocationConstraintsDialogState = LocationConstraintsDialogState.None,
|
||||||
locationShares: List<LocationShareItem> = listOf(aLocationShareItem(isLive = isLive)),
|
locationShares: List<LocationShareItem> = listOf(aLocationShareItem(isLive = isLive)),
|
||||||
|
focusedLocation: LocationShareItem? = locationShares.firstOrNull(),
|
||||||
hasLocationPermission: Boolean = false,
|
hasLocationPermission: Boolean = false,
|
||||||
isTrackMyLocation: Boolean = false,
|
isTrackMyLocation: Boolean = false,
|
||||||
appName: String = APP_NAME,
|
appName: String = APP_NAME,
|
||||||
|
|
@ -58,6 +59,7 @@ fun aShowLocationState(
|
||||||
return ShowLocationState(
|
return ShowLocationState(
|
||||||
dialogState = constraintsDialogState,
|
dialogState = constraintsDialogState,
|
||||||
locationShares = locationShares.toImmutableList(),
|
locationShares = locationShares.toImmutableList(),
|
||||||
|
focusedLocation = focusedLocation,
|
||||||
hasLocationPermission = hasLocationPermission,
|
hasLocationPermission = hasLocationPermission,
|
||||||
isTrackMyLocation = isTrackMyLocation,
|
isTrackMyLocation = isTrackMyLocation,
|
||||||
appName = appName,
|
appName = appName,
|
||||||
|
|
|
||||||
|
|
@ -22,8 +22,11 @@ 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.getValue
|
||||||
|
import androidx.compose.runtime.mutableStateOf
|
||||||
import androidx.compose.runtime.remember
|
import androidx.compose.runtime.remember
|
||||||
import androidx.compose.runtime.rememberCoroutineScope
|
import androidx.compose.runtime.rememberCoroutineScope
|
||||||
|
import androidx.compose.runtime.setValue
|
||||||
import androidx.compose.ui.Alignment
|
import androidx.compose.ui.Alignment
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.res.stringResource
|
import androidx.compose.ui.res.stringResource
|
||||||
|
|
@ -67,25 +70,25 @@ fun ShowLocationView(
|
||||||
onDismiss = { state.eventSink(ShowLocationEvent.DismissDialog) },
|
onDismiss = { state.eventSink(ShowLocationEvent.DismissDialog) },
|
||||||
)
|
)
|
||||||
|
|
||||||
val initialPosition = remember {
|
val cameraState = rememberCameraState(firstPosition = MapDefaults.defaultCameraPosition)
|
||||||
if (state.locationShares.isEmpty()) {
|
var hasAnimatedToFocusedLocation by remember { mutableStateOf(false) }
|
||||||
MapDefaults.defaultCameraPosition
|
LaunchedEffect(state.focusedLocation) {
|
||||||
} else {
|
if (state.focusedLocation != null && !hasAnimatedToFocusedLocation) {
|
||||||
val firstLocation = state.locationShares.first().location
|
hasAnimatedToFocusedLocation = true
|
||||||
CameraPosition(
|
val position = CameraPosition(
|
||||||
target = Position(latitude = firstLocation.lat, longitude = firstLocation.lon),
|
target = Position(latitude = state.focusedLocation.location.lat, longitude = state.focusedLocation.location.lon),
|
||||||
zoom = MapDefaults.DEFAULT_ZOOM
|
zoom = MapDefaults.DEFAULT_ZOOM
|
||||||
)
|
)
|
||||||
|
cameraState.position = position
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
val cameraState = rememberCameraState(firstPosition = initialPosition)
|
|
||||||
val userLocationState = rememberUserLocationState(state.hasLocationPermission)
|
|
||||||
LaunchedEffect(cameraState.isCameraMoving) {
|
LaunchedEffect(cameraState.isCameraMoving) {
|
||||||
if (cameraState.moveReason == CameraMoveReason.GESTURE) {
|
if (cameraState.moveReason == CameraMoveReason.GESTURE) {
|
||||||
state.eventSink(ShowLocationEvent.TrackMyLocation(false))
|
state.eventSink(ShowLocationEvent.TrackMyLocation(false))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val userLocationState = rememberUserLocationState(state.hasLocationPermission)
|
||||||
val scaffoldState = rememberBottomSheetScaffoldState(
|
val scaffoldState = rememberBottomSheetScaffoldState(
|
||||||
bottomSheetState = rememberStandardBottomSheetState(
|
bottomSheetState = rememberStandardBottomSheetState(
|
||||||
initialValue =
|
initialValue =
|
||||||
|
|
|
||||||
|
|
@ -571,7 +571,7 @@ class MessagesFlowNode(
|
||||||
}
|
}
|
||||||
is TimelineItemLocationContent -> {
|
is TimelineItemLocationContent -> {
|
||||||
val mode = when(event.content.mode){
|
val mode = when(event.content.mode){
|
||||||
is TimelineItemLocationContent.Mode.Live -> ShowLocationMode.Live
|
is TimelineItemLocationContent.Mode.Live -> ShowLocationMode.Live(event.senderId)
|
||||||
is TimelineItemLocationContent.Mode.Static -> ShowLocationMode.Static(
|
is TimelineItemLocationContent.Mode.Static -> ShowLocationMode.Static(
|
||||||
location = event.content.mode.location,
|
location = event.content.mode.location,
|
||||||
senderName = event.safeSenderName,
|
senderName = event.safeSenderName,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue