Check user power level before sharing live location.

This commit is contained in:
Onuray Sahin 2022-07-18 18:46:03 +03:00
parent b0237a4e22
commit e2cd75284f
6 changed files with 61 additions and 9 deletions

View file

@ -23,5 +23,6 @@ sealed class LocationSharingAction : VectorViewModelAction {
data class PinnedLocationSharing(val locationData: LocationData?) : LocationSharingAction()
data class LocationTargetChange(val locationData: LocationData) : LocationSharingAction()
object ZoomToUserLocation : LocationSharingAction()
object LiveLocationSharingRequested : LocationSharingAction()
data class StartLiveLocationSharing(val durationMillis: Long) : LocationSharingAction()
}

View file

@ -104,6 +104,9 @@ class LocationSharingFragment @Inject constructor(
LocationSharingViewEvents.LocationNotAvailableError -> handleLocationNotAvailableError()
is LocationSharingViewEvents.ZoomToUserLocation -> handleZoomToUserLocationEvent(it)
is LocationSharingViewEvents.StartLiveLocationService -> handleStartLiveLocationService(it)
LocationSharingViewEvents.ChooseLiveLocationDuration -> handleChooseLiveLocationDuration()
LocationSharingViewEvents.ShowLabsFlagPromotion -> handleShowLabsFlagPromotion()
LocationSharingViewEvents.LiveLocationSharingNotEnoughPermission -> handleLiveLocationSharingNotEnoughPermission()
}
}
}
@ -168,6 +171,16 @@ class LocationSharingFragment @Inject constructor(
.show()
}
private fun handleLiveLocationSharingNotEnoughPermission() {
MaterialAlertDialogBuilder(requireActivity())
.setTitle(R.string.live_location_not_enough_permission_dialog_title)
.setMessage(R.string.live_location_not_enough_permission_dialog_description)
.setPositiveButton(R.string.ok) { dialogInterface, _ ->
dialogInterface.dismiss()
}
.show()
}
private fun initLocateButton() {
views.mapView.locateButton.setOnClickListener {
viewModel.handle(LocationSharingAction.ZoomToUserLocation)
@ -201,7 +214,7 @@ class LocationSharingFragment @Inject constructor(
viewModel.handle(LocationSharingAction.CurrentUserLocationSharing)
}
views.shareLocationOptionsPicker.optionUserLive.debouncedClicks {
tryStartLiveLocationSharing()
viewModel.handle(LocationSharingAction.LiveLocationSharingRequested)
}
}
@ -212,13 +225,13 @@ class LocationSharingFragment @Inject constructor(
}
}
private fun tryStartLiveLocationSharing() {
if (vectorPreferences.labsEnableLiveLocation()) {
startLiveLocationSharing()
} else {
LiveLocationLabsFlagPromotionBottomSheet.newInstance()
.show(requireActivity().supportFragmentManager, "DISPLAY_LIVE_LOCATION_LABS_FLAG_PROMOTION")
}
private fun handleChooseLiveLocationDuration() {
startLiveLocationSharing()
}
private fun handleShowLabsFlagPromotion() {
LiveLocationLabsFlagPromotionBottomSheet.newInstance()
.show(requireActivity().supportFragmentManager, "DISPLAY_LIVE_LOCATION_LABS_FLAG_PROMOTION")
}
private val foregroundLocationResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->

View file

@ -23,4 +23,7 @@ sealed class LocationSharingViewEvents : VectorViewEvents {
object LocationNotAvailableError : LocationSharingViewEvents()
data class ZoomToUserLocation(val userLocation: LocationData) : LocationSharingViewEvents()
data class StartLiveLocationService(val sessionId: String, val roomId: String, val durationMillis: Long) : LocationSharingViewEvents()
object ChooseLiveLocationDuration : LocationSharingViewEvents()
object ShowLabsFlagPromotion : LocationSharingViewEvents()
object LiveLocationSharingNotEnoughPermission : LocationSharingViewEvents()
}

View file

@ -26,6 +26,8 @@ import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import im.vector.app.features.home.room.detail.timeline.helper.LocationPinProvider
import im.vector.app.features.location.domain.usecase.CompareLocationsUseCase
import im.vector.app.features.powerlevel.PowerLevelsFlowFactory
import im.vector.app.features.settings.VectorPreferences
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.lastOrNull
@ -36,8 +38,10 @@ import kotlinx.coroutines.flow.sample
import kotlinx.coroutines.launch
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.getRoom
import org.matrix.android.sdk.api.session.getUser
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
import org.matrix.android.sdk.api.util.toMatrixItem
import timber.log.Timber
@ -52,6 +56,7 @@ class LocationSharingViewModel @AssistedInject constructor(
private val locationPinProvider: LocationPinProvider,
private val session: Session,
private val compareLocationsUseCase: CompareLocationsUseCase,
private val vectorPreferences: VectorPreferences,
) : VectorViewModel<LocationSharingViewState, LocationSharingAction, LocationSharingViewEvents>(initialState), LocationTracker.Callback {
private val room = session.getRoom(initialState.roomId)!!
@ -70,6 +75,22 @@ class LocationSharingViewModel @AssistedInject constructor(
setUserItem()
updatePin()
compareTargetAndUserLocation()
checkPowerLevelsForLiveLocationSharing()
}
private fun checkPowerLevelsForLiveLocationSharing() {
PowerLevelsFlowFactory(room).createFlow()
.distinctUntilChanged()
.onEach {
val powerLevelsHelper = PowerLevelsHelper(it)
val canShareLiveLocation = EventType.STATE_ROOM_BEACON_INFO
.map { beaconInfoType ->
powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, beaconInfoType)
}
.all { isUserAllowed -> isUserAllowed }
setState { copy(canShareLiveLocation = canShareLiveLocation) }
}.launchIn(viewModelScope)
}
private fun initLocationTracking() {
@ -130,10 +151,21 @@ class LocationSharingViewModel @AssistedInject constructor(
is LocationSharingAction.PinnedLocationSharing -> handlePinnedLocationSharingAction(action)
is LocationSharingAction.LocationTargetChange -> handleLocationTargetChangeAction(action)
LocationSharingAction.ZoomToUserLocation -> handleZoomToUserLocationAction()
LocationSharingAction.LiveLocationSharingRequested -> handleLiveLocationSharingRequestedAction()
is LocationSharingAction.StartLiveLocationSharing -> handleStartLiveLocationSharingAction(action.durationMillis)
}
}
private fun handleLiveLocationSharingRequestedAction() = withState { state ->
if (!state.canShareLiveLocation) {
_viewEvents.post(LocationSharingViewEvents.LiveLocationSharingNotEnoughPermission)
} else if (vectorPreferences.labsEnableLiveLocation()) {
_viewEvents.post(LocationSharingViewEvents.ChooseLiveLocationDuration)
} else {
_viewEvents.post(LocationSharingViewEvents.ShowLabsFlagPromotion)
}
}
private fun handleCurrentUserLocationSharingAction() = withState { state ->
shareLocation(state.lastKnownUserLocation, isUserLocation = true)
}

View file

@ -34,7 +34,8 @@ data class LocationSharingViewState(
val userItem: MatrixItem.UserItem? = null,
val areTargetAndUserLocationEqual: Boolean? = null,
val lastKnownUserLocation: LocationData? = null,
val locationTargetDrawable: Drawable? = null
val locationTargetDrawable: Drawable? = null,
val canShareLiveLocation: Boolean = false,
) : MavericksState {
constructor(locationSharingArgs: LocationSharingArgs) : this(

View file

@ -3054,6 +3054,8 @@
<!-- TODO remove key -->
<string name="live_location_bottom_sheet_stop_sharing" tools:ignore="UnusedResources">Stop sharing</string>
<string name="live_location_bottom_sheet_last_updated_at">Updated %1$s ago</string>
<string name="live_location_not_enough_permission_dialog_title">You dont have permission to share locations</string>
<string name="live_location_not_enough_permission_dialog_description">You need to have the right permissions in order to share locations in this room.</string>
<string name="message_bubbles">Show Message bubbles</string>