Code review fixes.
This commit is contained in:
parent
eda0aa97d0
commit
03a8289a13
@ -64,6 +64,7 @@ import im.vector.app.features.home.room.list.RoomListFragment
|
|||||||
import im.vector.app.features.home.room.threads.list.views.ThreadListFragment
|
import im.vector.app.features.home.room.threads.list.views.ThreadListFragment
|
||||||
import im.vector.app.features.location.LocationPreviewFragment
|
import im.vector.app.features.location.LocationPreviewFragment
|
||||||
import im.vector.app.features.location.LocationSharingFragment
|
import im.vector.app.features.location.LocationSharingFragment
|
||||||
|
import im.vector.app.features.location.live.map.LocationLiveMapViewFragment
|
||||||
import im.vector.app.features.login.LoginCaptchaFragment
|
import im.vector.app.features.login.LoginCaptchaFragment
|
||||||
import im.vector.app.features.login.LoginFragment
|
import im.vector.app.features.login.LoginFragment
|
||||||
import im.vector.app.features.login.LoginGenericTextInputFormFragment
|
import im.vector.app.features.login.LoginGenericTextInputFormFragment
|
||||||
@ -1005,4 +1006,9 @@ interface FragmentModule {
|
|||||||
@IntoMap
|
@IntoMap
|
||||||
@FragmentKey(LocationPreviewFragment::class)
|
@FragmentKey(LocationPreviewFragment::class)
|
||||||
fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment
|
fun bindLocationPreviewFragment(fragment: LocationPreviewFragment): Fragment
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@FragmentKey(LocationLiveMapViewFragment::class)
|
||||||
|
fun bindLocationLiveMapViewFragment(fragment: LocationLiveMapViewFragment): Fragment
|
||||||
}
|
}
|
||||||
|
@ -18,4 +18,7 @@ package im.vector.app.features.location.live.map
|
|||||||
|
|
||||||
import im.vector.app.core.platform.VectorViewModelAction
|
import im.vector.app.core.platform.VectorViewModelAction
|
||||||
|
|
||||||
sealed interface LocationLiveMapAction : VectorViewModelAction
|
sealed class LocationLiveMapAction : VectorViewModelAction {
|
||||||
|
data class AddMapSymbol(val key: String, val value: Long) : LocationLiveMapAction()
|
||||||
|
data class RemoveMapSymbol(val key: String) : LocationLiveMapAction()
|
||||||
|
}
|
||||||
|
@ -17,13 +17,10 @@
|
|||||||
package im.vector.app.features.location.live.map
|
package im.vector.app.features.location.live.map
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.os.Bundle
|
|
||||||
import android.view.LayoutInflater
|
import android.view.LayoutInflater
|
||||||
import android.view.View
|
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import androidx.core.graphics.drawable.toBitmap
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import com.airbnb.mvrx.args
|
|
||||||
import com.airbnb.mvrx.fragmentViewModel
|
import com.airbnb.mvrx.fragmentViewModel
|
||||||
import com.airbnb.mvrx.withState
|
import com.airbnb.mvrx.withState
|
||||||
import com.mapbox.mapboxsdk.geometry.LatLng
|
import com.mapbox.mapboxsdk.geometry.LatLng
|
||||||
@ -36,7 +33,6 @@ import com.mapbox.mapboxsdk.maps.SupportMapFragment
|
|||||||
import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager
|
import com.mapbox.mapboxsdk.plugins.annotation.SymbolManager
|
||||||
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
|
import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
|
||||||
import com.mapbox.mapboxsdk.style.layers.Property
|
import com.mapbox.mapboxsdk.style.layers.Property
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
|
||||||
import im.vector.app.R
|
import im.vector.app.R
|
||||||
import im.vector.app.core.extensions.addChildFragment
|
import im.vector.app.core.extensions.addChildFragment
|
||||||
import im.vector.app.core.platform.VectorBaseFragment
|
import im.vector.app.core.platform.VectorBaseFragment
|
||||||
@ -44,6 +40,7 @@ import im.vector.app.databinding.FragmentSimpleContainerBinding
|
|||||||
import im.vector.app.features.location.UrlMapProvider
|
import im.vector.app.features.location.UrlMapProvider
|
||||||
import im.vector.app.features.location.zoomToBounds
|
import im.vector.app.features.location.zoomToBounds
|
||||||
import im.vector.app.features.location.zoomToLocation
|
import im.vector.app.features.location.zoomToLocation
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import timber.log.Timber
|
import timber.log.Timber
|
||||||
import java.lang.ref.WeakReference
|
import java.lang.ref.WeakReference
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -51,13 +48,9 @@ import javax.inject.Inject
|
|||||||
/**
|
/**
|
||||||
* Screen showing a map with all the current users sharing their live location in a room.
|
* Screen showing a map with all the current users sharing their live location in a room.
|
||||||
*/
|
*/
|
||||||
@AndroidEntryPoint
|
class LocationLiveMapViewFragment @Inject constructor(
|
||||||
class LocationLiveMapViewFragment : VectorBaseFragment<FragmentSimpleContainerBinding>() {
|
private var urlMapProvider: UrlMapProvider,
|
||||||
|
) : VectorBaseFragment<FragmentSimpleContainerBinding>() {
|
||||||
@Inject
|
|
||||||
lateinit var urlMapProvider: UrlMapProvider
|
|
||||||
|
|
||||||
private val args: LocationLiveMapViewArgs by args()
|
|
||||||
|
|
||||||
private val viewModel: LocationLiveMapViewModel by fragmentViewModel()
|
private val viewModel: LocationLiveMapViewModel by fragmentViewModel()
|
||||||
|
|
||||||
@ -71,16 +64,15 @@ class LocationLiveMapViewFragment : VectorBaseFragment<FragmentSimpleContainerBi
|
|||||||
return FragmentSimpleContainerBinding.inflate(layoutInflater, container, false)
|
return FragmentSimpleContainerBinding.inflate(layoutInflater, container, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
override fun onResume() {
|
||||||
super.onViewCreated(view, savedInstanceState)
|
super.onResume()
|
||||||
setupMap()
|
setupMap()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupMap() {
|
private fun setupMap() {
|
||||||
val mapFragment = getOrCreateSupportMapFragment()
|
val mapFragment = getOrCreateSupportMapFragment()
|
||||||
|
|
||||||
mapFragment.getMapAsync { mapboxMap ->
|
mapFragment.getMapAsync { mapboxMap ->
|
||||||
lifecycleScope.launchWhenCreated {
|
lifecycleScope.launch {
|
||||||
mapboxMap.setStyle(urlMapProvider.getMapUrl()) { style ->
|
mapboxMap.setStyle(urlMapProvider.getMapUrl()) { style ->
|
||||||
mapStyle = style
|
mapStyle = style
|
||||||
this@LocationLiveMapViewFragment.mapboxMap = WeakReference(mapboxMap)
|
this@LocationLiveMapViewFragment.mapboxMap = WeakReference(mapboxMap)
|
||||||
@ -108,10 +100,8 @@ class LocationLiveMapViewFragment : VectorBaseFragment<FragmentSimpleContainerBi
|
|||||||
private fun updateMap(userLiveLocations: List<UserLiveLocationViewState>) {
|
private fun updateMap(userLiveLocations: List<UserLiveLocationViewState>) {
|
||||||
symbolManager?.let { sManager ->
|
symbolManager?.let { sManager ->
|
||||||
val latLngBoundsBuilder = LatLngBounds.Builder()
|
val latLngBoundsBuilder = LatLngBounds.Builder()
|
||||||
|
|
||||||
userLiveLocations.forEach { userLocation ->
|
userLiveLocations.forEach { userLocation ->
|
||||||
createOrUpdateSymbol(userLocation, sManager)
|
createOrUpdateSymbol(userLocation, sManager)
|
||||||
|
|
||||||
if (isMapFirstUpdate) {
|
if (isMapFirstUpdate) {
|
||||||
val latLng = LatLng(userLocation.locationData.latitude, userLocation.locationData.longitude)
|
val latLng = LatLng(userLocation.locationData.latitude, userLocation.locationData.longitude)
|
||||||
latLngBoundsBuilder.include(latLng)
|
latLngBoundsBuilder.include(latLng)
|
||||||
@ -123,10 +113,10 @@ class LocationLiveMapViewFragment : VectorBaseFragment<FragmentSimpleContainerBi
|
|||||||
} ?: postponeUpdateOfMap(userLiveLocations)
|
} ?: postponeUpdateOfMap(userLiveLocations)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createOrUpdateSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) {
|
private fun createOrUpdateSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) = withState(viewModel) { state ->
|
||||||
val symbolId = viewModel.mapSymbolIds[userLocation.userId]
|
val symbolId = state.mapSymbolIds[userLocation.userId]
|
||||||
|
|
||||||
if (symbolId == null) {
|
if (symbolId == null || symbolManager.annotations.get(symbolId) == null) {
|
||||||
createSymbol(userLocation, symbolManager)
|
createSymbol(userLocation, symbolManager)
|
||||||
} else {
|
} else {
|
||||||
updateSymbol(symbolId, userLocation, symbolManager)
|
updateSymbol(symbolId, userLocation, symbolManager)
|
||||||
@ -137,7 +127,7 @@ class LocationLiveMapViewFragment : VectorBaseFragment<FragmentSimpleContainerBi
|
|||||||
addUserPinToMapStyle(userLocation.userId, userLocation.pinDrawable)
|
addUserPinToMapStyle(userLocation.userId, userLocation.pinDrawable)
|
||||||
val symbolOptions = buildSymbolOptions(userLocation)
|
val symbolOptions = buildSymbolOptions(userLocation)
|
||||||
val symbol = symbolManager.create(symbolOptions)
|
val symbol = symbolManager.create(symbolOptions)
|
||||||
viewModel.mapSymbolIds[userLocation.userId] = symbol.id
|
viewModel.handle(LocationLiveMapAction.AddMapSymbol(userLocation.userId, symbol.id))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun updateSymbol(symbolId: Long, userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) {
|
private fun updateSymbol(symbolId: Long, userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) {
|
||||||
@ -149,21 +139,20 @@ class LocationLiveMapViewFragment : VectorBaseFragment<FragmentSimpleContainerBi
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun removeOutdatedSymbols(userLiveLocations: List<UserLiveLocationViewState>, symbolManager: SymbolManager) {
|
private fun removeOutdatedSymbols(userLiveLocations: List<UserLiveLocationViewState>, symbolManager: SymbolManager) = withState(viewModel) { state ->
|
||||||
val userIdsToRemove = viewModel.mapSymbolIds.keys.subtract(userLiveLocations.map { it.userId }.toSet())
|
val userIdsToRemove = state.mapSymbolIds.keys.subtract(userLiveLocations.map { it.userId }.toSet())
|
||||||
userIdsToRemove
|
userIdsToRemove.forEach { userId ->
|
||||||
.mapNotNull { userId ->
|
|
||||||
removeUserPinFromMapStyle(userId)
|
removeUserPinFromMapStyle(userId)
|
||||||
viewModel.mapSymbolIds[userId]
|
viewModel.handle(LocationLiveMapAction.RemoveMapSymbol(userId))
|
||||||
viewModel.mapSymbolIds.remove(userId)
|
|
||||||
}
|
state.mapSymbolIds[userId]?.let { symbolId ->
|
||||||
.forEach { symbolId ->
|
|
||||||
Timber.d("trying to delete symbol with id: $symbolId")
|
Timber.d("trying to delete symbol with id: $symbolId")
|
||||||
symbolManager.annotations.get(symbolId)?.let {
|
symbolManager.annotations.get(symbolId)?.let {
|
||||||
symbolManager.delete(it)
|
symbolManager.delete(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun updateMapZoomWhenNeeded(userLiveLocations: List<UserLiveLocationViewState>, latLngBoundsBuilder: LatLngBounds.Builder) {
|
private fun updateMapZoomWhenNeeded(userLiveLocations: List<UserLiveLocationViewState>, latLngBoundsBuilder: LatLngBounds.Builder) {
|
||||||
if (userLiveLocations.isNotEmpty() && isMapFirstUpdate) {
|
if (userLiveLocations.isNotEmpty() && isMapFirstUpdate) {
|
||||||
|
@ -38,11 +38,6 @@ class LocationLiveMapViewModel @AssistedInject constructor(
|
|||||||
|
|
||||||
companion object : MavericksViewModelFactory<LocationLiveMapViewModel, LocationLiveMapViewState> by hiltMavericksViewModelFactory()
|
companion object : MavericksViewModelFactory<LocationLiveMapViewModel, LocationLiveMapViewState> by hiltMavericksViewModelFactory()
|
||||||
|
|
||||||
/**
|
|
||||||
* Map to keep track of symbol ids associated to each user Id.
|
|
||||||
*/
|
|
||||||
val mapSymbolIds = mutableMapOf<String, Long>()
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
getListOfUserLiveLocationUseCase.execute(initialState.roomId)
|
getListOfUserLiveLocationUseCase.execute(initialState.roomId)
|
||||||
.onEach { setState { copy(userLocations = it) } }
|
.onEach { setState { copy(userLocations = it) } }
|
||||||
@ -50,6 +45,23 @@ class LocationLiveMapViewModel @AssistedInject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun handle(action: LocationLiveMapAction) {
|
override fun handle(action: LocationLiveMapAction) {
|
||||||
// do nothing, no action for now
|
when (action) {
|
||||||
|
is LocationLiveMapAction.AddMapSymbol -> handleAddMapSymbol(action)
|
||||||
|
is LocationLiveMapAction.RemoveMapSymbol -> handleRemoveMapSymbol(action)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleAddMapSymbol(action: LocationLiveMapAction.AddMapSymbol) = withState { state ->
|
||||||
|
val newMapSymbolIds = state.mapSymbolIds.toMutableMap().apply { set(action.key, action.value) }
|
||||||
|
setState {
|
||||||
|
copy(mapSymbolIds = newMapSymbolIds)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun handleRemoveMapSymbol(action: LocationLiveMapAction.RemoveMapSymbol) = withState { state ->
|
||||||
|
val newMapSymbolIds = state.mapSymbolIds.toMutableMap().apply { remove(action.key) }
|
||||||
|
setState {
|
||||||
|
copy(mapSymbolIds = newMapSymbolIds)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,11 @@ import im.vector.app.features.location.LocationData
|
|||||||
|
|
||||||
data class LocationLiveMapViewState(
|
data class LocationLiveMapViewState(
|
||||||
val roomId: String,
|
val roomId: String,
|
||||||
val userLocations: List<UserLiveLocationViewState> = emptyList()
|
val userLocations: List<UserLiveLocationViewState> = emptyList(),
|
||||||
|
/**
|
||||||
|
* Map to keep track of symbol ids associated to each user Id.
|
||||||
|
*/
|
||||||
|
val mapSymbolIds: Map<String, Long> = emptyMap()
|
||||||
) : MavericksState {
|
) : MavericksState {
|
||||||
constructor(locationLiveMapViewArgs: LocationLiveMapViewArgs) : this(
|
constructor(locationLiveMapViewArgs: LocationLiveMapViewArgs) : this(
|
||||||
roomId = locationLiveMapViewArgs.roomId
|
roomId = locationLiveMapViewArgs.roomId
|
||||||
|
Loading…
Reference in New Issue
Block a user