Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Check user power level before sharing live location (PSG-620) #6587

Merged
merged 4 commits into from
Jul 20, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/6587.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Check user power level before sharing live location
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
}
}
Expand Down Expand Up @@ -168,6 +171,14 @@ 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, null)
.show()
}

private fun initLocateButton() {
views.mapView.locateButton.setOnClickListener {
viewModel.handle(LocationSharingAction.ZoomToUserLocation)
Expand Down Expand Up @@ -201,7 +212,7 @@ class LocationSharingFragment @Inject constructor(
viewModel.handle(LocationSharingAction.CurrentUserLocationSharing)
}
views.shareLocationOptionsPicker.optionUserLive.debouncedClicks {
tryStartLiveLocationSharing()
viewModel.handle(LocationSharingAction.LiveLocationSharingRequested)
}
}

Expand All @@ -212,13 +223,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 ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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()
}
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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)!!
Expand All @@ -70,6 +75,21 @@ class LocationSharingViewModel @AssistedInject constructor(
setUserItem()
updatePin()
compareTargetAndUserLocation()
observePowerLevelsForLiveLocationSharing()
}

private fun observePowerLevelsForLiveLocationSharing() {
PowerLevelsFlowFactory(room).createFlow()
.distinctUntilChanged()
.setOnEach {
val powerLevelsHelper = PowerLevelsHelper(it)
val canShareLiveLocation = EventType.STATE_ROOM_BEACON_INFO
.all { beaconInfoType ->
powerLevelsHelper.isUserAllowedToSend(session.myUserId, true, beaconInfoType)
}

copy(canShareLiveLocation = canShareLiveLocation)
}
}

private fun initLocationTracking() {
Expand Down Expand Up @@ -130,10 +150,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)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
2 changes: 2 additions & 0 deletions vector/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3116,6 +3116,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 don’t have permission to share live location</string>
<string name="live_location_not_enough_permission_dialog_description">You need to have the right permissions in order to share live location in this room.</string>
<string name="live_location_share_location_item_share">Share location</string>

<string name="message_bubbles">Show Message bubbles</string>
Expand Down