From e2cd75284fc6a2e1a3946fec8b35ab4a8588e320 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 18 Jul 2022 18:46:03 +0300 Subject: [PATCH 1/3] 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 From 5fb10ab28760f1a330c93fc33241156181dda8e4 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Mon, 18 Jul 2022 18:52:37 +0300 Subject: [PATCH 2/3] Changelog added. --- changelog.d/6587.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 changelog.d/6587.bugfix diff --git a/changelog.d/6587.bugfix b/changelog.d/6587.bugfix new file mode 100644 index 0000000000..0273689cfd --- /dev/null +++ b/changelog.d/6587.bugfix @@ -0,0 +1 @@ +Check user power level before sharing live location From 493dc57a292e0ed708727d2bc1f7e2f9a2fbece6 Mon Sep 17 00:00:00 2001 From: Onuray Sahin Date: Tue, 19 Jul 2022 13:41:00 +0300 Subject: [PATCH 3/3] Code review fixes. --- .../features/location/LocationSharingFragment.kt | 4 +--- .../features/location/LocationSharingViewModel.kt | 13 ++++++------- vector/src/main/res/values/strings.xml | 4 ++-- 3 files changed, 9 insertions(+), 12 deletions(-) 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 d131ff3f74..17e53e63d1 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 @@ -175,9 +175,7 @@ class LocationSharingFragment @Inject constructor( 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() - } + .setPositiveButton(R.string.ok, null) .show() } 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 8e166ee350..8056b72d57 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 @@ -75,22 +75,21 @@ class LocationSharingViewModel @AssistedInject constructor( setUserItem() updatePin() compareTargetAndUserLocation() - checkPowerLevelsForLiveLocationSharing() + observePowerLevelsForLiveLocationSharing() } - private fun checkPowerLevelsForLiveLocationSharing() { + private fun observePowerLevelsForLiveLocationSharing() { PowerLevelsFlowFactory(room).createFlow() .distinctUntilChanged() - .onEach { + .setOnEach { val powerLevelsHelper = PowerLevelsHelper(it) val canShareLiveLocation = EventType.STATE_ROOM_BEACON_INFO - .map { beaconInfoType -> + .all { beaconInfoType -> powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, beaconInfoType) } - .all { isUserAllowed -> isUserAllowed } - setState { copy(canShareLiveLocation = canShareLiveLocation) } - }.launchIn(viewModelScope) + copy(canShareLiveLocation = canShareLiveLocation) + } } private fun initLocationTracking() { diff --git a/vector/src/main/res/values/strings.xml b/vector/src/main/res/values/strings.xml index bd5860c1ab..69ea15ea9b 100644 --- a/vector/src/main/res/values/strings.xml +++ b/vector/src/main/res/values/strings.xml @@ -3054,8 +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. + You don’t have permission to share live location + You need to have the right permissions in order to share live location in this room. Show Message bubbles