mirror of
https://github.com/element-hq/element-android
synced 2024-11-23 01:45:36 +03:00
Render user location pin on the live location sharing map preview
This commit is contained in:
parent
f676a65544
commit
b5af6f5a0f
8 changed files with 202 additions and 62 deletions
|
@ -33,6 +33,7 @@ class CountUpTimer(
|
|||
|
||||
private val lastTime: AtomicLong = AtomicLong(clock.epochMillis())
|
||||
private val elapsedTime: AtomicLong = AtomicLong(0)
|
||||
|
||||
// To ensure that the regular tick value is an exact multiple of `intervalInMs`
|
||||
private val specialRound = SpecialRound(intervalInMs)
|
||||
|
||||
|
|
|
@ -23,4 +23,5 @@ sealed class LiveLocationMapAction : VectorViewModelAction {
|
|||
data class RemoveMapSymbol(val key: String) : LiveLocationMapAction()
|
||||
object StopSharing : LiveLocationMapAction()
|
||||
object ShowMapLoadingError : LiveLocationMapAction()
|
||||
object ZoomToUserLocation : LiveLocationMapAction()
|
||||
}
|
||||
|
|
|
@ -17,7 +17,10 @@
|
|||
package im.vector.app.features.location.live.map
|
||||
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
import im.vector.app.features.location.LocationData
|
||||
|
||||
sealed interface LiveLocationMapViewEvents : VectorViewEvents {
|
||||
data class Error(val error: Throwable) : LiveLocationMapViewEvents
|
||||
data class LiveLocationError(val error: Throwable) : LiveLocationMapViewEvents
|
||||
data class ZoomToUserLocation(val userLocation: LocationData) : LiveLocationMapViewEvents
|
||||
object UserLocationNotAvailableError : LiveLocationMapViewEvents
|
||||
}
|
||||
|
|
|
@ -48,11 +48,17 @@ import im.vector.app.core.extensions.addChildFragment
|
|||
import im.vector.app.core.extensions.cleanup
|
||||
import im.vector.app.core.extensions.configureWith
|
||||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.core.resources.DrawableProvider
|
||||
import im.vector.app.core.utils.DimensionConverter
|
||||
import im.vector.app.core.utils.PERMISSIONS_FOR_FOREGROUND_LOCATION_SHARING
|
||||
import im.vector.app.core.utils.checkPermissions
|
||||
import im.vector.app.core.utils.onPermissionDeniedDialog
|
||||
import im.vector.app.core.utils.openLocation
|
||||
import im.vector.app.core.utils.registerForPermissionsResult
|
||||
import im.vector.app.databinding.FragmentLiveLocationMapViewBinding
|
||||
import im.vector.app.features.location.LocationData
|
||||
import im.vector.app.features.location.UrlMapProvider
|
||||
import im.vector.app.features.location.showUserLocationNotAvailableErrorDialog
|
||||
import im.vector.app.features.location.zoomToBounds
|
||||
import im.vector.app.features.location.zoomToLocation
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -60,6 +66,8 @@ import timber.log.Timber
|
|||
import java.lang.ref.WeakReference
|
||||
import javax.inject.Inject
|
||||
|
||||
private const val USER_LOCATION_PIN_ID = "user-location-pin-id"
|
||||
|
||||
/**
|
||||
* Screen showing a map with all the current users sharing their live location in a room.
|
||||
*/
|
||||
|
@ -70,6 +78,7 @@ class LiveLocationMapViewFragment :
|
|||
@Inject lateinit var urlMapProvider: UrlMapProvider
|
||||
@Inject lateinit var bottomSheetController: LiveLocationBottomSheetController
|
||||
@Inject lateinit var dimensionConverter: DimensionConverter
|
||||
@Inject lateinit var drawableProvider: DrawableProvider
|
||||
|
||||
private val viewModel: LiveLocationMapViewModel by fragmentViewModel()
|
||||
|
||||
|
@ -77,7 +86,7 @@ class LiveLocationMapViewFragment :
|
|||
private var mapView: MapView? = null
|
||||
private var symbolManager: SymbolManager? = null
|
||||
private var mapStyle: Style? = null
|
||||
private val pendingLiveLocations = mutableListOf<UserLiveLocationViewState>()
|
||||
private val userLocationDrawable by lazy { drawableProvider.getDrawable(R.drawable.ic_location_user) }
|
||||
private var isMapFirstUpdate = true
|
||||
private var onSymbolClickListener: OnSymbolClickListener? = null
|
||||
private var mapLoadingErrorListener: MapView.OnDidFailLoadingMapListener? = null
|
||||
|
@ -90,6 +99,7 @@ class LiveLocationMapViewFragment :
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
observeViewEvents()
|
||||
setupMap()
|
||||
initLocateButton()
|
||||
|
||||
views.liveLocationBottomSheetRecyclerView.configureWith(bottomSheetController, hasFixedSize = false, disableItemAnimation = true)
|
||||
|
||||
|
@ -107,11 +117,23 @@ class LiveLocationMapViewFragment :
|
|||
private fun observeViewEvents() {
|
||||
viewModel.observeViewEvents { viewEvent ->
|
||||
when (viewEvent) {
|
||||
is LiveLocationMapViewEvents.Error -> displayErrorDialog(viewEvent.error)
|
||||
is LiveLocationMapViewEvents.LiveLocationError -> displayErrorDialog(viewEvent.error)
|
||||
is LiveLocationMapViewEvents.ZoomToUserLocation -> handleZoomToUserLocationEvent(viewEvent)
|
||||
LiveLocationMapViewEvents.UserLocationNotAvailableError -> handleUserLocationNotAvailableError()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleZoomToUserLocationEvent(event: LiveLocationMapViewEvents.ZoomToUserLocation) {
|
||||
mapboxMap?.get().zoomToLocation(event.userLocation)
|
||||
}
|
||||
|
||||
private fun handleUserLocationNotAvailableError() {
|
||||
showUserLocationNotAvailableErrorDialog {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
onSymbolClickListener?.let { symbolManager?.removeClickListener(it) }
|
||||
symbolManager?.onDestroy()
|
||||
|
@ -141,14 +163,33 @@ class LiveLocationMapViewFragment :
|
|||
true
|
||||
}.also { addClickListener(it) }
|
||||
}
|
||||
pendingLiveLocations
|
||||
.takeUnless { it.isEmpty() }
|
||||
?.let { updateMap(it) }
|
||||
// force refresh of the map using the last viewState
|
||||
invalidate()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initLocateButton() {
|
||||
views.liveLocationMapLocateButton.setOnClickListener {
|
||||
if (checkPermissions(PERMISSIONS_FOR_FOREGROUND_LOCATION_SHARING, requireActivity(), foregroundLocationResultLauncher)) {
|
||||
zoomToUserLocation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun zoomToUserLocation() {
|
||||
viewModel.handle(LiveLocationMapAction.ZoomToUserLocation)
|
||||
}
|
||||
|
||||
private val foregroundLocationResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->
|
||||
if (allGranted) {
|
||||
zoomToUserLocation()
|
||||
} else if (deniedPermanently) {
|
||||
activity?.onPermissionDeniedDialog(R.string.denied_permission_generic)
|
||||
}
|
||||
}
|
||||
|
||||
private fun listenMapLoadingError(mapView: MapView) {
|
||||
mapLoadingErrorListener = MapView.OnDidFailLoadingMapListener {
|
||||
viewModel.handle(LiveLocationMapAction.ShowMapLoadingError)
|
||||
|
@ -191,10 +232,15 @@ class LiveLocationMapViewFragment :
|
|||
views.mapPreviewLoadingError.isVisible = true
|
||||
} else {
|
||||
views.mapPreviewLoadingError.isGone = true
|
||||
updateMap(viewState.userLocations)
|
||||
updateMap(userLiveLocations = viewState.userLocations, userLocation = viewState.lastKnownUserLocation)
|
||||
}
|
||||
if (viewState.isLoadingUserLocation) {
|
||||
showLoadingDialog()
|
||||
} else {
|
||||
dismissLoadingDialog()
|
||||
}
|
||||
updateUserListBottomSheet(viewState.userLocations)
|
||||
updateLocateButton(showLocateButton = viewState.showLocateButton)
|
||||
updateLocateButton(showLocateButton = viewState.showLocateUserButton)
|
||||
}
|
||||
|
||||
private fun updateUserListBottomSheet(userLocations: List<UserLiveLocationViewState>) {
|
||||
|
@ -253,7 +299,10 @@ class LiveLocationMapViewFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun updateMap(userLiveLocations: List<UserLiveLocationViewState>) {
|
||||
private fun updateMap(
|
||||
userLiveLocations: List<UserLiveLocationViewState>,
|
||||
userLocation: LocationData?,
|
||||
) {
|
||||
symbolManager?.let { sManager ->
|
||||
val latLngBoundsBuilder = LatLngBounds.Builder()
|
||||
userLiveLocations.forEach { userLocation ->
|
||||
|
@ -266,28 +315,60 @@ class LiveLocationMapViewFragment :
|
|||
|
||||
removeOutdatedSymbols(userLiveLocations, sManager)
|
||||
updateMapZoomWhenNeeded(userLiveLocations, latLngBoundsBuilder)
|
||||
} ?: postponeUpdateOfMap(userLiveLocations)
|
||||
}
|
||||
|
||||
private fun createOrUpdateSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) = withState(viewModel) { state ->
|
||||
val symbolId = state.mapSymbolIds[userLocation.matrixItem.id]
|
||||
|
||||
if (symbolId == null || symbolManager.annotations.get(symbolId) == null) {
|
||||
createSymbol(userLocation, symbolManager)
|
||||
} else {
|
||||
updateSymbol(symbolId, userLocation, symbolManager)
|
||||
if (userLocation == null) {
|
||||
removeUserSymbol(sManager)
|
||||
} else {
|
||||
createOrUpdateUserSymbol(userLocation, sManager)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) {
|
||||
addUserPinToMapStyle(userLocation.matrixItem.id, userLocation.pinDrawable)
|
||||
val symbolOptions = buildSymbolOptions(userLocation)
|
||||
val symbol = symbolManager.create(symbolOptions)
|
||||
viewModel.handle(LiveLocationMapAction.AddMapSymbol(userLocation.matrixItem.id, symbol.id))
|
||||
private fun createOrUpdateSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) {
|
||||
val pinId = userLocation.matrixItem.id
|
||||
val pinDrawable = userLocation.pinDrawable
|
||||
createOrUpdateSymbol(pinId, pinDrawable, userLocation.locationData, symbolManager)
|
||||
}
|
||||
|
||||
private fun updateSymbol(symbolId: Long, userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) {
|
||||
val newLocation = LatLng(userLocation.locationData.latitude, userLocation.locationData.longitude)
|
||||
private fun createOrUpdateUserSymbol(locationData: LocationData, symbolManager: SymbolManager) {
|
||||
userLocationDrawable?.let { pinDrawable -> createOrUpdateSymbol(USER_LOCATION_PIN_ID, pinDrawable, locationData, symbolManager) }
|
||||
}
|
||||
|
||||
private fun removeUserSymbol(symbolManager: SymbolManager) = withState(viewModel) { state ->
|
||||
val pinId = USER_LOCATION_PIN_ID
|
||||
state.mapSymbolIds[pinId]?.let { symbolId ->
|
||||
removeSymbol(pinId, symbolId, symbolManager)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createOrUpdateSymbol(
|
||||
pinId: String,
|
||||
pinDrawable: Drawable,
|
||||
locationData: LocationData,
|
||||
symbolManager: SymbolManager
|
||||
) = withState(viewModel) { state ->
|
||||
val symbolId = state.mapSymbolIds[pinId]
|
||||
|
||||
if (symbolId == null || symbolManager.annotations.get(symbolId) == null) {
|
||||
createSymbol(pinId, pinDrawable, locationData, symbolManager)
|
||||
} else {
|
||||
updateSymbol(symbolId, locationData, symbolManager)
|
||||
}
|
||||
}
|
||||
|
||||
private fun createSymbol(
|
||||
pinId: String,
|
||||
pinDrawable: Drawable,
|
||||
locationData: LocationData,
|
||||
symbolManager: SymbolManager
|
||||
) {
|
||||
addPinToMapStyle(pinId, pinDrawable)
|
||||
val symbolOptions = buildSymbolOptions(locationData, pinId)
|
||||
val symbol = symbolManager.create(symbolOptions)
|
||||
viewModel.handle(LiveLocationMapAction.AddMapSymbol(pinId, symbol.id))
|
||||
}
|
||||
|
||||
private fun updateSymbol(symbolId: Long, locationData: LocationData, symbolManager: SymbolManager) {
|
||||
val newLocation = LatLng(locationData.latitude, locationData.longitude)
|
||||
val symbol = symbolManager.annotations.get(symbolId)
|
||||
symbol?.let {
|
||||
it.latLng = newLocation
|
||||
|
@ -296,17 +377,11 @@ class LiveLocationMapViewFragment :
|
|||
}
|
||||
|
||||
private fun removeOutdatedSymbols(userLiveLocations: List<UserLiveLocationViewState>, symbolManager: SymbolManager) = withState(viewModel) { state ->
|
||||
val userIdsToRemove = state.mapSymbolIds.keys.subtract(userLiveLocations.map { it.matrixItem.id }.toSet())
|
||||
userIdsToRemove.forEach { userId ->
|
||||
removeUserPinFromMapStyle(userId)
|
||||
viewModel.handle(LiveLocationMapAction.RemoveMapSymbol(userId))
|
||||
|
||||
state.mapSymbolIds[userId]?.let { symbolId ->
|
||||
Timber.d("trying to delete symbol with id: $symbolId")
|
||||
symbolManager.annotations.get(symbolId)?.let {
|
||||
symbolManager.delete(it)
|
||||
}
|
||||
}
|
||||
val pinIdsToKeep = userLiveLocations.map { it.matrixItem.id } + USER_LOCATION_PIN_ID
|
||||
val pinIdsToRemove = state.mapSymbolIds.keys.subtract(pinIdsToKeep.toSet())
|
||||
pinIdsToRemove.forEach { pinId ->
|
||||
val symbolId = state.mapSymbolIds[pinId]
|
||||
removeSymbol(pinId, symbolId, symbolManager)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -321,27 +396,35 @@ class LiveLocationMapViewFragment :
|
|||
}
|
||||
}
|
||||
|
||||
private fun postponeUpdateOfMap(userLiveLocations: List<UserLiveLocationViewState>) {
|
||||
pendingLiveLocations.clear()
|
||||
pendingLiveLocations.addAll(userLiveLocations)
|
||||
}
|
||||
|
||||
private fun addUserPinToMapStyle(userId: String, userPinDrawable: Drawable) {
|
||||
private fun addPinToMapStyle(pinId: String, pinDrawable: Drawable) {
|
||||
mapStyle?.let { style ->
|
||||
if (style.getImage(userId) == null) {
|
||||
style.addImage(userId, userPinDrawable.toBitmap())
|
||||
if (style.getImage(pinId) == null) {
|
||||
style.addImage(pinId, pinDrawable.toBitmap())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun removeUserPinFromMapStyle(userId: String) {
|
||||
mapStyle?.removeImage(userId)
|
||||
private fun removeSymbol(pinId: String, symbolId: Long?, symbolManager: SymbolManager) {
|
||||
removeUserPinFromMapStyle(pinId)
|
||||
|
||||
symbolId?.let { id ->
|
||||
Timber.d("trying to delete symbol with id: $id")
|
||||
symbolManager.annotations.get(id)?.let {
|
||||
symbolManager.delete(it)
|
||||
}
|
||||
}
|
||||
|
||||
viewModel.handle(LiveLocationMapAction.RemoveMapSymbol(pinId))
|
||||
}
|
||||
|
||||
private fun buildSymbolOptions(userLiveLocation: UserLiveLocationViewState) =
|
||||
private fun removeUserPinFromMapStyle(pinId: String) {
|
||||
mapStyle?.removeImage(pinId)
|
||||
}
|
||||
|
||||
private fun buildSymbolOptions(locationData: LocationData, pinId: String) =
|
||||
SymbolOptions()
|
||||
.withLatLng(LatLng(userLiveLocation.locationData.latitude, userLiveLocation.locationData.longitude))
|
||||
.withIconImage(userLiveLocation.matrixItem.id)
|
||||
.withLatLng(LatLng(locationData.latitude, locationData.longitude))
|
||||
.withIconImage(pinId)
|
||||
.withIconAnchor(Property.ICON_ANCHOR_BOTTOM)
|
||||
|
||||
private fun handleBottomSheetUserSelected(userId: String) = withState(viewModel) { state ->
|
||||
|
|
|
@ -23,8 +23,11 @@ import dagger.assisted.AssistedInject
|
|||
import im.vector.app.core.di.MavericksAssistedViewModelFactory
|
||||
import im.vector.app.core.di.hiltMavericksViewModelFactory
|
||||
import im.vector.app.core.platform.VectorViewModel
|
||||
import im.vector.app.features.location.LocationData
|
||||
import im.vector.app.features.location.LocationTracker
|
||||
import im.vector.app.features.location.live.StopLiveLocationShareUseCase
|
||||
import im.vector.app.features.location.live.tracking.LocationSharingServiceConnection
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.flow.launchIn
|
||||
import kotlinx.coroutines.flow.onEach
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -37,7 +40,11 @@ class LiveLocationMapViewModel @AssistedInject constructor(
|
|||
getListOfUserLiveLocationUseCase: GetListOfUserLiveLocationUseCase,
|
||||
private val locationSharingServiceConnection: LocationSharingServiceConnection,
|
||||
private val stopLiveLocationShareUseCase: StopLiveLocationShareUseCase,
|
||||
) : VectorViewModel<LiveLocationMapViewState, LiveLocationMapAction, LiveLocationMapViewEvents>(initialState), LocationSharingServiceConnection.Callback {
|
||||
private val locationTracker: LocationTracker,
|
||||
) :
|
||||
VectorViewModel<LiveLocationMapViewState, LiveLocationMapAction, LiveLocationMapViewEvents>(initialState),
|
||||
LocationSharingServiceConnection.Callback,
|
||||
LocationTracker.Callback {
|
||||
|
||||
@AssistedFactory
|
||||
interface Factory : MavericksAssistedViewModelFactory<LiveLocationMapViewModel, LiveLocationMapViewState> {
|
||||
|
@ -48,12 +55,37 @@ class LiveLocationMapViewModel @AssistedInject constructor(
|
|||
|
||||
init {
|
||||
getListOfUserLiveLocationUseCase.execute(initialState.roomId)
|
||||
.onEach { setState { copy(userLocations = it, showLocateButton = it.none { it.matrixItem.id == session.myUserId }) } }
|
||||
.onEach { setState { copy(userLocations = it, showLocateUserButton = it.none { it.matrixItem.id == session.myUserId }) } }
|
||||
.launchIn(viewModelScope)
|
||||
locationSharingServiceConnection.bind(this)
|
||||
initLocationTracking()
|
||||
}
|
||||
|
||||
private fun initLocationTracking() {
|
||||
locationTracker.addCallback(this)
|
||||
locationTracker.locations
|
||||
.onEach(::onLocationUpdate)
|
||||
.launchIn(viewModelScope)
|
||||
}
|
||||
|
||||
private fun onLocationUpdate(locationData: LocationData) = withState { state ->
|
||||
val zoomToUserLocation = state.isLoadingUserLocation
|
||||
val showLocateButton = state.showLocateUserButton
|
||||
|
||||
setState {
|
||||
copy(
|
||||
lastKnownUserLocation = if (showLocateButton) locationData else null,
|
||||
isLoadingUserLocation = false,
|
||||
)
|
||||
}
|
||||
|
||||
if (zoomToUserLocation) {
|
||||
_viewEvents.post(LiveLocationMapViewEvents.ZoomToUserLocation(locationData))
|
||||
}
|
||||
}
|
||||
|
||||
override fun onCleared() {
|
||||
locationTracker.removeCallback(this)
|
||||
locationSharingServiceConnection.unbind(this)
|
||||
super.onCleared()
|
||||
}
|
||||
|
@ -64,6 +96,7 @@ class LiveLocationMapViewModel @AssistedInject constructor(
|
|||
is LiveLocationMapAction.RemoveMapSymbol -> handleRemoveMapSymbol(action)
|
||||
LiveLocationMapAction.StopSharing -> handleStopSharing()
|
||||
LiveLocationMapAction.ShowMapLoadingError -> handleShowMapLoadingError()
|
||||
LiveLocationMapAction.ZoomToUserLocation -> handleZoomToUserLocation()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -85,7 +118,7 @@ class LiveLocationMapViewModel @AssistedInject constructor(
|
|||
viewModelScope.launch {
|
||||
val result = stopLiveLocationShareUseCase.execute(initialState.roomId)
|
||||
if (result is UpdateLiveLocationShareResult.Failure) {
|
||||
_viewEvents.post(LiveLocationMapViewEvents.Error(result.error))
|
||||
_viewEvents.post(LiveLocationMapViewEvents.LiveLocationError(result.error))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +127,19 @@ class LiveLocationMapViewModel @AssistedInject constructor(
|
|||
setState { copy(loadingMapHasFailed = true) }
|
||||
}
|
||||
|
||||
// TODO add unit tests
|
||||
private fun handleZoomToUserLocation() = withState { state ->
|
||||
if (!state.isLoadingUserLocation) {
|
||||
setState {
|
||||
copy(isLoadingUserLocation = true)
|
||||
}
|
||||
viewModelScope.launch(Dispatchers.Main) {
|
||||
locationTracker.start()
|
||||
locationTracker.requestLastKnownLocation()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onLocationServiceRunning(roomIds: Set<String>) {
|
||||
// NOOP
|
||||
}
|
||||
|
@ -103,6 +149,10 @@ class LiveLocationMapViewModel @AssistedInject constructor(
|
|||
}
|
||||
|
||||
override fun onLocationServiceError(error: Throwable) {
|
||||
_viewEvents.post(LiveLocationMapViewEvents.Error(error))
|
||||
_viewEvents.post(LiveLocationMapViewEvents.LiveLocationError(error))
|
||||
}
|
||||
|
||||
override fun onNoLocationProviderAvailable() {
|
||||
_viewEvents.post(LiveLocationMapViewEvents.UserLocationNotAvailableError)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -29,7 +29,9 @@ data class LiveLocationMapViewState(
|
|||
*/
|
||||
val mapSymbolIds: Map<String, Long> = emptyMap(),
|
||||
val loadingMapHasFailed: Boolean = false,
|
||||
val showLocateButton: Boolean = false,
|
||||
val showLocateUserButton: Boolean = false,
|
||||
val isLoadingUserLocation: Boolean = false,
|
||||
val lastKnownUserLocation: LocationData? = null,
|
||||
) : MavericksState {
|
||||
constructor(liveLocationMapViewArgs: LiveLocationMapViewArgs) : this(
|
||||
roomId = liveLocationMapViewArgs.roomId
|
||||
|
|
|
@ -94,12 +94,8 @@ class LocationPreviewViewModel @AssistedInject constructor(
|
|||
_viewEvents.post(LocationPreviewViewEvents.UserLocationNotAvailableError)
|
||||
}
|
||||
|
||||
private fun onLocationUpdate(locationData: LocationData) {
|
||||
withState { state ->
|
||||
if (state.isLoadingUserLocation) {
|
||||
_viewEvents.post(LocationPreviewViewEvents.ZoomToUserLocation(locationData))
|
||||
}
|
||||
}
|
||||
private fun onLocationUpdate(locationData: LocationData) = withState { state ->
|
||||
val zoomToUserLocation = state.isLoadingUserLocation
|
||||
|
||||
setState {
|
||||
copy(
|
||||
|
@ -107,5 +103,9 @@ class LocationPreviewViewModel @AssistedInject constructor(
|
|||
isLoadingUserLocation = false,
|
||||
)
|
||||
}
|
||||
|
||||
if (zoomToUserLocation) {
|
||||
_viewEvents.post(LocationPreviewViewEvents.ZoomToUserLocation(locationData))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,7 @@ data class LocationPreviewViewState(
|
|||
val lastKnownUserLocation: LocationData? = null,
|
||||
) : MavericksState {
|
||||
|
||||
constructor(args: LocationSharingArgs): this(
|
||||
constructor(args: LocationSharingArgs) : this(
|
||||
pinLocationData = args.initialLocationData,
|
||||
pinUserId = args.locationOwnerId,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue