Fix some misunderstanding about the permissions request - step 2

This commit is contained in:
Benoit Marty 2021-07-13 00:10:09 +02:00
parent 80657251a5
commit 067349f602
13 changed files with 87 additions and 24 deletions

View file

@ -26,6 +26,8 @@ import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.utils.PERMISSIONS_ALL
import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.onPermissionDeniedDialog
import im.vector.app.core.utils.onPermissionDeniedSnackbar
import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.databinding.ActivityDebugPermissionBinding
import timber.log.Timber
@ -34,6 +36,8 @@ class DebugPermissionActivity : VectorBaseActivity<ActivityDebugPermissionBindin
override fun getBinding() = ActivityDebugPermissionBinding.inflate(layoutInflater)
override fun getCoordinatorLayout() = views.coordinatorLayout
private var lastPermissions = emptyList<String>()
override fun initUiAndData() {
@ -67,12 +71,19 @@ class DebugPermissionActivity : VectorBaseActivity<ActivityDebugPermissionBindin
}
}
private var dialogOrSnackbar = false
private val launcher = registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) {
Toast.makeText(this, "All granted", Toast.LENGTH_SHORT).show()
} else {
if (deniedPermanently) {
Toast.makeText(this, "Denied forever", Toast.LENGTH_SHORT).show()
dialogOrSnackbar = !dialogOrSnackbar
if (dialogOrSnackbar) {
onPermissionDeniedDialog(R.string.denied_permission_camera)
} else {
onPermissionDeniedSnackbar(R.string.denied_permission_camera)
}
} else {
Toast.makeText(this, "Denied", Toast.LENGTH_SHORT).show()
}

View file

@ -29,6 +29,7 @@ import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.onPermissionDeniedDialog
import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.features.media.createUCropWithDefaultSettings
import im.vector.lib.multipicker.MultiPicker
@ -55,9 +56,11 @@ class GalleryOrCameraDialogHelper(
private val listener = fragment as? Listener ?: error("Fragment must implement GalleryOrCameraDialogHelper.Listener")
private val takePhotoPermissionActivityResultLauncher = fragment.registerForPermissionsResult { allGranted ->
private val takePhotoPermissionActivityResultLauncher = fragment.registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) {
doOpenCamera()
} else if (deniedPermanently) {
activity.onPermissionDeniedDialog(R.string.denied_permission_camera)
}
}

View file

@ -26,6 +26,7 @@ import androidx.annotation.StringRes
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseActivity
@ -78,9 +79,22 @@ fun ComponentActivity.registerForPermissionsResult(lambda: (allGranted: Boolean,
}
}
fun Fragment.registerForPermissionsResult(allGranted: (Boolean) -> Unit): ActivityResultLauncher<Array<String>> {
fun Fragment.registerForPermissionsResult(lambda: (allGranted: Boolean, deniedPermanently: Boolean) -> Unit): ActivityResultLauncher<Array<String>> {
return registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { result ->
allGranted.invoke(result.keys.all { result[it] == true })
if (result.keys.all { result[it] == true }) {
lambda(true, /* not used */ false)
} else {
if (permissionDialogDisplayed) {
// A permission dialog has been displayed, so even if the user has checked the do not ask again button, we do
// not tell the user to open the app settings
lambda(false, false)
} else {
// No dialog has been displayed, so tell the user to go to the system setting
lambda(false, true)
}
}
// Reset
permissionDialogDisplayed = false
}
}
@ -163,3 +177,14 @@ fun VectorBaseActivity<*>.onPermissionDeniedSnackbar(@StringRes rationaleMessage
openAppSettingsPage(this)
}
}
fun FragmentActivity.onPermissionDeniedDialog(@StringRes rationaleMessage: Int) {
MaterialAlertDialogBuilder(this)
.setTitle(R.string.missing_permissions_title)
.setMessage(rationaleMessage)
.setPositiveButton(R.string.open_settings) { _, _ ->
openAppSettingsPage(this)
}
.setNegativeButton(R.string.cancel, null)
.show()
}

View file

@ -27,6 +27,7 @@ import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.onPermissionDeniedDialog
import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.databinding.FragmentQrCodeScannerBinding
import im.vector.app.features.userdirectory.PendingSelection
@ -44,9 +45,11 @@ class CreateDirectRoomByQrCodeFragment @Inject constructor() : VectorBaseFragmen
return FragmentQrCodeScannerBinding.inflate(inflater, container, false)
}
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted ->
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) {
startCamera()
} else if (deniedPermanently) {
activity?.onPermissionDeniedDialog(R.string.denied_permission_camera)
}
}

View file

@ -23,12 +23,14 @@ import android.view.ViewGroup
import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.parentFragmentViewModel
import com.airbnb.mvrx.withState
import im.vector.app.R
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
import im.vector.app.core.utils.checkPermissions
import im.vector.app.core.utils.onPermissionDeniedDialog
import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.databinding.BottomSheetVerificationChildFragmentBinding
import im.vector.app.features.crypto.verification.VerificationAction
@ -79,9 +81,11 @@ class VerificationChooseMethodFragment @Inject constructor(
state.pendingRequest.invoke()?.transactionId ?: ""))
}
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted ->
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) {
doOpenQRCodeScanner()
} else if (deniedPermanently) {
activity?.onPermissionDeniedDialog(R.string.denied_permission_camera)
}
}

View file

@ -101,6 +101,7 @@ import im.vector.app.core.utils.copyToClipboard
import im.vector.app.core.utils.createJSonViewerStyleProvider
import im.vector.app.core.utils.createUIHandler
import im.vector.app.core.utils.isValidUrl
import im.vector.app.core.utils.onPermissionDeniedDialog
import im.vector.app.core.utils.openUrlInExternalBrowser
import im.vector.app.core.utils.registerForPermissionsResult
import im.vector.app.core.utils.saveMedia
@ -1062,14 +1063,16 @@ class RoomDetailFragment @Inject constructor(
}
}
private val startCallActivityResultLauncher = registerForPermissionsResult { allGranted ->
private val startCallActivityResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) {
(roomDetailViewModel.pendingAction as? RoomDetailAction.StartCall)?.let {
roomDetailViewModel.pendingAction = null
roomDetailViewModel.handle(it)
}
} else {
context?.toast(R.string.permissions_action_not_performed_missing_permissions)
if (deniedPermanently) {
activity?.onPermissionDeniedDialog(R.string.denied_permission_generic)
}
cleanUpAfterPermissionNotGranted()
}
}
@ -1738,13 +1741,16 @@ class RoomDetailFragment @Inject constructor(
}
}
private val saveActionActivityResultLauncher = registerForPermissionsResult { allGranted ->
private val saveActionActivityResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) {
sharedActionViewModel.pendingAction?.let {
handleActions(it)
sharedActionViewModel.pendingAction = null
}
} else {
if (deniedPermanently) {
activity?.onPermissionDeniedDialog(R.string.denied_permission_generic)
}
cleanUpAfterPermissionNotGranted()
}
}
@ -1977,7 +1983,7 @@ class RoomDetailFragment @Inject constructor(
// AttachmentTypeSelectorView.Callback
private val typeSelectedActivityResultLauncher = registerForPermissionsResult { allGranted ->
private val typeSelectedActivityResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) {
val pendingType = attachmentsHelper.pendingType
if (pendingType != null) {
@ -1985,6 +1991,9 @@ class RoomDetailFragment @Inject constructor(
launchAttachmentProcess(pendingType)
}
} else {
if (deniedPermanently) {
activity?.onPermissionDeniedDialog(R.string.denied_permission_generic)
}
cleanUpAfterPermissionNotGranted()
}
}

View file

@ -65,7 +65,7 @@ class ScanUserCodeFragment @Inject constructor()
}
}
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted ->
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted, _ ->
if (allGranted) {
startCamera()
} else {

View file

@ -43,11 +43,11 @@ class ShowUserCodeFragment @Inject constructor(
val sharedViewModel: UserCodeSharedViewModel by activityViewModel()
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted ->
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted, deniedPermanently ->
if (allGranted) {
doOpenQRCodeScanner()
} else {
sharedViewModel.handle(UserCodeActions.CameraPermissionNotGranted)
sharedViewModel.handle(UserCodeActions.CameraPermissionNotGranted(deniedPermanently))
}
}

View file

@ -24,6 +24,6 @@ sealed class UserCodeActions : VectorViewModelAction {
data class SwitchMode(val mode: UserCodeState.Mode) : UserCodeActions()
data class DecodedQRCode(val code: String) : UserCodeActions()
data class StartChattingWithUser(val matrixItem: MatrixItem) : UserCodeActions()
object CameraPermissionNotGranted : UserCodeActions()
data class CameraPermissionNotGranted(val deniedPermanently: Boolean) : UserCodeActions()
object ShareByText : UserCodeActions()
}

View file

@ -86,7 +86,11 @@ class UserCodeActivity : VectorBaseActivity<ActivitySimpleBinding>(),
UserCodeShareViewEvents.HideWaitingScreen -> views.simpleActivityWaitingView.isVisible = false
is UserCodeShareViewEvents.ToastMessage -> Toast.makeText(this, it.message, Toast.LENGTH_LONG).show()
is UserCodeShareViewEvents.NavigateToRoom -> navigator.openRoom(this, it.roomId)
UserCodeShareViewEvents.CameraPermissionNotGranted -> onPermissionDeniedSnackbar(R.string.permissions_denied_qr_code)
is UserCodeShareViewEvents.CameraPermissionNotGranted -> {
if (it.deniedPermanently) {
onPermissionDeniedSnackbar(R.string.permissions_denied_qr_code)
}
}
else -> {
}
}

View file

@ -24,6 +24,6 @@ sealed class UserCodeShareViewEvents : VectorViewEvents {
object HideWaitingScreen : UserCodeShareViewEvents()
data class ToastMessage(val message: String) : UserCodeShareViewEvents()
data class NavigateToRoom(val roomId: String) : UserCodeShareViewEvents()
object CameraPermissionNotGranted : UserCodeShareViewEvents()
data class CameraPermissionNotGranted(val deniedPermanently: Boolean) : UserCodeShareViewEvents()
data class SharePlainText(val text: String, val title: String, val richPlainText: String) : UserCodeShareViewEvents()
}

View file

@ -76,7 +76,7 @@ class UserCodeSharedViewModel @AssistedInject constructor(
is UserCodeActions.SwitchMode -> setState { copy(mode = action.mode) }
is UserCodeActions.DecodedQRCode -> handleQrCodeDecoded(action)
is UserCodeActions.StartChattingWithUser -> handleStartChatting(action)
UserCodeActions.CameraPermissionNotGranted -> _viewEvents.post(UserCodeShareViewEvents.CameraPermissionNotGranted)
is UserCodeActions.CameraPermissionNotGranted -> _viewEvents.post(UserCodeShareViewEvents.CameraPermissionNotGranted(action.deniedPermanently))
UserCodeActions.ShareByText -> handleShareByText()
}
}

View file

@ -386,12 +386,16 @@
<string name="reset">Reset</string>
<string name="start_chatting">Start Chatting</string>
<!-- Permissions denied forever -->
<string name="denied_permission_generic">Some permissions are missing to perform this action, please grant the permissions from the system settings.</string>
<string name="denied_permission_camera">To perform this action, please grant the Camera permission from the system settings.</string>
<!-- First param will be replace by the value of ongoing_conference_call_voice, and second one by the value of ongoing_conference_call_video -->
<string name="ongoing_conference_call">Ongoing conference call.\nJoin as %1$s or %2$s</string>
<string name="ongoing_conference_call_voice">Voice</string>
<string name="ongoing_conference_call_video">Video</string>
<string name="cannot_start_call">Cannot start the call, please try later</string>
<string name="missing_permissions_title">Missing permissions</string>
<string name="missing_permissions_warning">"Due to missing permissions, some features may be missing…</string>
<string name="missing_permissions_error">"Due to missing permissions, this action is not possible.</string>
<string name="missing_permissions_to_start_conf_call">You need permission to invite to start a conference in this room</string>