Implement user list bottom sheet.

This commit is contained in:
Onuray Sahin 2022-05-27 15:34:42 +03:00
parent 8247b1dd7a
commit daa0734e5b
2 changed files with 27 additions and 11 deletions

View File

@ -17,7 +17,9 @@
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
@ -35,8 +37,9 @@ import com.mapbox.mapboxsdk.plugins.annotation.SymbolOptions
import com.mapbox.mapboxsdk.style.layers.Property import com.mapbox.mapboxsdk.style.layers.Property
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.extensions.configureWith
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.databinding.FragmentSimpleContainerBinding import im.vector.app.databinding.FragmentLocationLiveMapViewBinding
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
@ -50,7 +53,8 @@ import javax.inject.Inject
*/ */
class LocationLiveMapViewFragment @Inject constructor( class LocationLiveMapViewFragment @Inject constructor(
private var urlMapProvider: UrlMapProvider, private var urlMapProvider: UrlMapProvider,
) : VectorBaseFragment<FragmentSimpleContainerBinding>() { private var bottomSheetController: LiveLocationBottomSheetController,
) : VectorBaseFragment<FragmentLocationLiveMapViewBinding>() {
private val viewModel: LocationLiveMapViewModel by fragmentViewModel() private val viewModel: LocationLiveMapViewModel by fragmentViewModel()
@ -60,8 +64,13 @@ class LocationLiveMapViewFragment @Inject constructor(
private val pendingLiveLocations = mutableListOf<UserLiveLocationViewState>() private val pendingLiveLocations = mutableListOf<UserLiveLocationViewState>()
private var isMapFirstUpdate = true private var isMapFirstUpdate = true
override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentSimpleContainerBinding { override fun getBinding(inflater: LayoutInflater, container: ViewGroup?): FragmentLocationLiveMapViewBinding {
return FragmentSimpleContainerBinding.inflate(layoutInflater, container, false) return FragmentLocationLiveMapViewBinding.inflate(layoutInflater, container, false)
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
views.bottomSheetRecyclerView.configureWith(bottomSheetController, hasFixedSize = false, disableItemAnimation = true)
} }
override fun onResume() { override fun onResume() {
@ -95,6 +104,11 @@ class LocationLiveMapViewFragment @Inject constructor(
override fun invalidate() = withState(viewModel) { viewState -> override fun invalidate() = withState(viewModel) { viewState ->
updateMap(viewState.userLocations) updateMap(viewState.userLocations)
updateUserListBottomSheet(viewState.userLocations)
}
private fun updateUserListBottomSheet(userLocations: List<UserLiveLocationViewState>) {
bottomSheetController.setData(userLocations)
} }
private fun updateMap(userLiveLocations: List<UserLiveLocationViewState>) { private fun updateMap(userLiveLocations: List<UserLiveLocationViewState>) {
@ -114,7 +128,7 @@ class LocationLiveMapViewFragment @Inject constructor(
} }
private fun createOrUpdateSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) = withState(viewModel) { state -> private fun createOrUpdateSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) = withState(viewModel) { state ->
val symbolId = state.mapSymbolIds[userLocation.userId] val symbolId = state.mapSymbolIds[userLocation.matrixItem.id]
if (symbolId == null || symbolManager.annotations.get(symbolId) == null) { if (symbolId == null || symbolManager.annotations.get(symbolId) == null) {
createSymbol(userLocation, symbolManager) createSymbol(userLocation, symbolManager)
@ -124,10 +138,10 @@ class LocationLiveMapViewFragment @Inject constructor(
} }
private fun createSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) { private fun createSymbol(userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) {
addUserPinToMapStyle(userLocation.userId, userLocation.pinDrawable) addUserPinToMapStyle(userLocation.matrixItem.id, userLocation.pinDrawable)
val symbolOptions = buildSymbolOptions(userLocation) val symbolOptions = buildSymbolOptions(userLocation)
val symbol = symbolManager.create(symbolOptions) val symbol = symbolManager.create(symbolOptions)
viewModel.handle(LocationLiveMapAction.AddMapSymbol(userLocation.userId, symbol.id)) viewModel.handle(LocationLiveMapAction.AddMapSymbol(userLocation.matrixItem.id, symbol.id))
} }
private fun updateSymbol(symbolId: Long, userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) { private fun updateSymbol(symbolId: Long, userLocation: UserLiveLocationViewState, symbolManager: SymbolManager) {
@ -140,7 +154,7 @@ class LocationLiveMapViewFragment @Inject constructor(
} }
private fun removeOutdatedSymbols(userLiveLocations: List<UserLiveLocationViewState>, symbolManager: SymbolManager) = withState(viewModel) { state -> private fun removeOutdatedSymbols(userLiveLocations: List<UserLiveLocationViewState>, symbolManager: SymbolManager) = withState(viewModel) { state ->
val userIdsToRemove = state.mapSymbolIds.keys.subtract(userLiveLocations.map { it.userId }.toSet()) val userIdsToRemove = state.mapSymbolIds.keys.subtract(userLiveLocations.map { it.matrixItem.id }.toSet())
userIdsToRemove.forEach { userId -> userIdsToRemove.forEach { userId ->
removeUserPinFromMapStyle(userId) removeUserPinFromMapStyle(userId)
viewModel.handle(LocationLiveMapAction.RemoveMapSymbol(userId)) viewModel.handle(LocationLiveMapAction.RemoveMapSymbol(userId))
@ -185,7 +199,7 @@ class LocationLiveMapViewFragment @Inject constructor(
private fun buildSymbolOptions(userLiveLocation: UserLiveLocationViewState) = private fun buildSymbolOptions(userLiveLocation: UserLiveLocationViewState) =
SymbolOptions() SymbolOptions()
.withLatLng(LatLng(userLiveLocation.locationData.latitude, userLiveLocation.locationData.longitude)) .withLatLng(LatLng(userLiveLocation.locationData.latitude, userLiveLocation.locationData.longitude))
.withIconImage(userLiveLocation.userId) .withIconImage(userLiveLocation.matrixItem.id)
.withIconAnchor(Property.ICON_ANCHOR_BOTTOM) .withIconAnchor(Property.ICON_ANCHOR_BOTTOM)
companion object { companion object {

View File

@ -19,6 +19,7 @@ package im.vector.app.features.location.live.map
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import com.airbnb.mvrx.MavericksState import com.airbnb.mvrx.MavericksState
import im.vector.app.features.location.LocationData import im.vector.app.features.location.LocationData
import org.matrix.android.sdk.api.util.MatrixItem
data class LocationLiveMapViewState( data class LocationLiveMapViewState(
val roomId: String, val roomId: String,
@ -34,8 +35,9 @@ data class LocationLiveMapViewState(
} }
data class UserLiveLocationViewState( data class UserLiveLocationViewState(
val userId: String, val matrixItem: MatrixItem,
val pinDrawable: Drawable, val pinDrawable: Drawable,
val locationData: LocationData, val locationData: LocationData,
val endOfLiveTimestampMillis: Long? val endOfLiveTimestampMillis: Long?,
val locationTimestampMillis: Long?
) )