From e2cd75284fc6a2e1a3946fec8b35ab4a8588e320 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 18 Jul 2022 18:46:03 +0300 Subject: [PATCH] Check user power level before sharing live location. --- .../location/LocationSharingAction.kt | 1 + .../location/LocationSharingFragment.kt | 29 ++++++++++++----- .../location/LocationSharingViewEvents.kt | 3 ++ .../location/LocationSharingViewModel.kt | 32 +++++++++++++++++++ .../location/LocationSharingViewState.kt | 3 +- vector/src/main/res/values/strings.xml | 2 ++ 6 files changed, 61 insertions(+), 9 deletions(-) diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt index d86d97e6b0..264b1f0e0b 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingAction.kt @@ -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() } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt index be5f0aed6f..d131ff3f74 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingFragment.kt @@ -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 -> diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt index 1116003e41..c9e411c8d7 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewEvents.kt @@ -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() } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt index b9a2dc830c..8e166ee350 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewModel.kt @@ -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(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) } diff --git a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt index 64f324bc1b..d5226eacfb 100644 --- a/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt +++ b/vector/src/main/java/im/vector/app/features/location/LocationSharingViewState.kt @@ -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( diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index ae5834c250..bd5860c1ab 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -3054,6 +3054,8 @@ Stop sharing Updated %1$s ago + You don’t have permission to share locations + You need to have the right permissions in order to share locations in this room. Show Message bubbles