Merge pull request #2152 from vector-im/feature/various_fixes

Redcude requested permission to access file on the phone
This commit is contained in:
Benoit Marty 2020-09-23 16:57:20 +02:00 committed by GitHub
commit 34d2c3d391
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 28 additions and 60 deletions

View File

@ -7,6 +7,7 @@ Features ✨:
Improvements 🙌: Improvements 🙌:
- Add "show password" in import Megolm keys dialog - Add "show password" in import Megolm keys dialog
- Visually disable call buttons in menu and prohibit calling when permissions are insufficient (#2112) - Visually disable call buttons in menu and prohibit calling when permissions are insufficient (#2112)
- Better management of requested permissions (#2048)
- Add a setting to show timestamp for all messages (#2123) - Add a setting to show timestamp for all messages (#2123)
- Use cache for user color - Use cache for user color
- Allow using an outdated homeserver, at user's risk (#1972) - Allow using an outdated homeserver, at user's risk (#1972)

View File

@ -30,8 +30,6 @@ import androidx.fragment.app.Fragment
import im.vector.app.R import im.vector.app.R
import timber.log.Timber import timber.log.Timber
private const val LOG_TAG = "PermissionUtils"
// Android M permission request code management // Android M permission request code management
private const val PERMISSIONS_GRANTED = true private const val PERMISSIONS_GRANTED = true
private const val PERMISSIONS_DENIED = !PERMISSIONS_GRANTED private const val PERMISSIONS_DENIED = !PERMISSIONS_GRANTED
@ -42,16 +40,18 @@ const val PERMISSION_CAMERA = 0x1
private const val PERMISSION_WRITE_EXTERNAL_STORAGE = 0x1 shl 1 private const val PERMISSION_WRITE_EXTERNAL_STORAGE = 0x1 shl 1
private const val PERMISSION_RECORD_AUDIO = 0x1 shl 2 private const val PERMISSION_RECORD_AUDIO = 0x1 shl 2
private const val PERMISSION_READ_CONTACTS = 0x1 shl 3 private const val PERMISSION_READ_CONTACTS = 0x1 shl 3
private const val PERMISSION_READ_EXTERNAL_STORAGE = 0x1 shl 4
// Permissions sets // Permissions sets
const val PERMISSIONS_FOR_AUDIO_IP_CALL = PERMISSION_RECORD_AUDIO const val PERMISSIONS_FOR_AUDIO_IP_CALL = PERMISSION_RECORD_AUDIO
const val PERMISSIONS_FOR_VIDEO_IP_CALL = PERMISSION_CAMERA or PERMISSION_RECORD_AUDIO const val PERMISSIONS_FOR_VIDEO_IP_CALL = PERMISSION_CAMERA or PERMISSION_RECORD_AUDIO
const val PERMISSIONS_FOR_TAKING_PHOTO = PERMISSION_CAMERA or PERMISSION_WRITE_EXTERNAL_STORAGE const val PERMISSIONS_FOR_TAKING_PHOTO = PERMISSION_CAMERA
const val PERMISSIONS_FOR_MEMBERS_SEARCH = PERMISSION_READ_CONTACTS const val PERMISSIONS_FOR_MEMBERS_SEARCH = PERMISSION_READ_CONTACTS
const val PERMISSIONS_FOR_MEMBER_DETAILS = PERMISSION_READ_CONTACTS const val PERMISSIONS_FOR_MEMBER_DETAILS = PERMISSION_READ_CONTACTS
const val PERMISSIONS_FOR_ROOM_AVATAR = PERMISSION_CAMERA const val PERMISSIONS_FOR_ROOM_AVATAR = PERMISSION_CAMERA
const val PERMISSIONS_FOR_VIDEO_RECORDING = PERMISSION_CAMERA or PERMISSION_RECORD_AUDIO const val PERMISSIONS_FOR_VIDEO_RECORDING = PERMISSION_CAMERA or PERMISSION_RECORD_AUDIO
const val PERMISSIONS_FOR_WRITING_FILES = PERMISSION_WRITE_EXTERNAL_STORAGE const val PERMISSIONS_FOR_WRITING_FILES = PERMISSION_WRITE_EXTERNAL_STORAGE
const val PERMISSIONS_FOR_READING_FILES = PERMISSION_READ_EXTERNAL_STORAGE
const val PERMISSIONS_FOR_PICKING_CONTACT = PERMISSION_READ_CONTACTS const val PERMISSIONS_FOR_PICKING_CONTACT = PERMISSION_READ_CONTACTS
const val PERMISSIONS_EMPTY = PERMISSION_BYPASSED const val PERMISSIONS_EMPTY = PERMISSION_BYPASSED
@ -67,7 +67,6 @@ const val PERMISSION_REQUEST_CODE_CHANGE_AVATAR = 574
const val PERMISSION_REQUEST_CODE_DOWNLOAD_FILE = 575 const val PERMISSION_REQUEST_CODE_DOWNLOAD_FILE = 575
const val PERMISSION_REQUEST_CODE_PICK_ATTACHMENT = 576 const val PERMISSION_REQUEST_CODE_PICK_ATTACHMENT = 576
const val PERMISSION_REQUEST_CODE_INCOMING_URI = 577 const val PERMISSION_REQUEST_CODE_INCOMING_URI = 577
const val PERMISSION_REQUEST_CODE_PREVIEW_FRAGMENT = 578
const val PERMISSION_REQUEST_CODE_READ_CONTACTS = 579 const val PERMISSION_REQUEST_CODE_READ_CONTACTS = 579
/** /**
@ -79,6 +78,7 @@ fun logPermissionStatuses(context: Context) {
Manifest.permission.CAMERA, Manifest.permission.CAMERA,
Manifest.permission.RECORD_AUDIO, Manifest.permission.RECORD_AUDIO,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.READ_CONTACTS) Manifest.permission.READ_CONTACTS)
Timber.v("## logPermissionStatuses() : log the permissions status used by the app") Timber.v("## logPermissionStatuses() : log the permissions status used by the app")
@ -145,7 +145,7 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
fragment: Fragment?, fragment: Fragment?,
requestCode: Int, requestCode: Int,
@StringRes rationaleMessage: Int @StringRes rationaleMessage: Int
): Boolean { ): Boolean {
var isPermissionGranted = false var isPermissionGranted = false
// sanity check // sanity check
@ -161,7 +161,8 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
&& PERMISSIONS_FOR_MEMBER_DETAILS != permissionsToBeGrantedBitMap && PERMISSIONS_FOR_MEMBER_DETAILS != permissionsToBeGrantedBitMap
&& PERMISSIONS_FOR_ROOM_AVATAR != permissionsToBeGrantedBitMap && PERMISSIONS_FOR_ROOM_AVATAR != permissionsToBeGrantedBitMap
&& PERMISSIONS_FOR_VIDEO_RECORDING != permissionsToBeGrantedBitMap && PERMISSIONS_FOR_VIDEO_RECORDING != permissionsToBeGrantedBitMap
&& PERMISSIONS_FOR_WRITING_FILES != permissionsToBeGrantedBitMap) { && PERMISSIONS_FOR_WRITING_FILES != permissionsToBeGrantedBitMap
&& PERMISSIONS_FOR_READING_FILES != permissionsToBeGrantedBitMap) {
Timber.w("## checkPermissions(): permissions to be granted are not supported") Timber.w("## checkPermissions(): permissions to be granted are not supported")
isPermissionGranted = false isPermissionGranted = false
} else { } else {
@ -188,6 +189,12 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permissionType) updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permissionType)
} }
if (PERMISSION_READ_EXTERNAL_STORAGE == permissionsToBeGrantedBitMap and PERMISSION_READ_EXTERNAL_STORAGE) {
val permissionType = Manifest.permission.READ_EXTERNAL_STORAGE
isRequestPermissionRequired = isRequestPermissionRequired or
updatePermissionsToBeGranted(activity, permissionListAlreadyDenied, permissionsListToBeGranted, permissionType)
}
// the contact book access is requested for any android platforms // the contact book access is requested for any android platforms
// for android M, we use the system preferences // for android M, we use the system preferences
// for android < M, we use a dedicated settings // for android < M, we use a dedicated settings

View File

@ -42,7 +42,6 @@ import im.vector.app.core.extensions.getMeasurements
import im.vector.app.core.utils.PERMISSIONS_EMPTY import im.vector.app.core.utils.PERMISSIONS_EMPTY
import im.vector.app.core.utils.PERMISSIONS_FOR_PICKING_CONTACT import im.vector.app.core.utils.PERMISSIONS_FOR_PICKING_CONTACT
import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO
import im.vector.app.core.utils.PERMISSIONS_FOR_WRITING_FILES
import im.vector.app.features.attachments.AttachmentTypeSelectorView.Callback import im.vector.app.features.attachments.AttachmentTypeSelectorView.Callback
import kotlin.math.max import kotlin.math.max
@ -215,10 +214,10 @@ class AttachmentTypeSelectorView(context: Context,
*/ */
enum class Type(val permissionsBit: Int) { enum class Type(val permissionsBit: Int) {
CAMERA(PERMISSIONS_FOR_TAKING_PHOTO), CAMERA(PERMISSIONS_FOR_TAKING_PHOTO),
GALLERY(PERMISSIONS_FOR_WRITING_FILES), GALLERY(PERMISSIONS_EMPTY),
FILE(PERMISSIONS_FOR_WRITING_FILES), FILE(PERMISSIONS_EMPTY),
STICKER(PERMISSIONS_EMPTY), STICKER(PERMISSIONS_EMPTY),
AUDIO(PERMISSIONS_FOR_WRITING_FILES), AUDIO(PERMISSIONS_EMPTY),
CONTACT(PERMISSIONS_FOR_PICKING_CONTACT) CONTACT(PERMISSIONS_FOR_PICKING_CONTACT)
} }
} }

View File

@ -42,17 +42,13 @@ import im.vector.app.core.extensions.cleanup
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.resources.ColorProvider import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.utils.OnSnapPositionChangeListener import im.vector.app.core.utils.OnSnapPositionChangeListener
import im.vector.app.core.utils.PERMISSIONS_FOR_WRITING_FILES
import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_PREVIEW_FRAGMENT
import im.vector.app.core.utils.SnapOnScrollListener import im.vector.app.core.utils.SnapOnScrollListener
import im.vector.app.core.utils.allGranted
import im.vector.app.core.utils.attachSnapHelperWithListener import im.vector.app.core.utils.attachSnapHelperWithListener
import im.vector.app.core.utils.checkPermissions
import im.vector.app.features.media.createUCropWithDefaultSettings import im.vector.app.features.media.createUCropWithDefaultSettings
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
import kotlinx.android.synthetic.main.fragment_attachments_preview.* import kotlinx.android.synthetic.main.fragment_attachments_preview.*
import org.matrix.android.sdk.api.extensions.orFalse
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import timber.log.Timber import timber.log.Timber
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
@ -102,7 +98,7 @@ class AttachmentsPreviewFragment @Inject constructor(
handleRemoveAction() handleRemoveAction()
true true
} }
R.id.attachmentsPreviewEditAction -> { R.id.attachmentsPreviewEditAction -> {
handleEditAction() handleEditAction()
true true
} }
@ -183,22 +179,7 @@ class AttachmentsPreviewFragment @Inject constructor(
viewModel.handle(AttachmentsPreviewAction.RemoveCurrentAttachment) viewModel.handle(AttachmentsPreviewAction.RemoveCurrentAttachment)
} }
private fun handleEditAction() { private fun handleEditAction() = withState(viewModel) {
// check permissions
if (checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_PREVIEW_FRAGMENT)) {
doHandleEditAction()
}
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSION_REQUEST_CODE_PREVIEW_FRAGMENT && allGranted(grantResults)) {
doHandleEditAction()
}
}
private fun doHandleEditAction() = withState(viewModel) {
val currentAttachment = it.attachments.getOrNull(it.currentAttachmentIndex) ?: return@withState val currentAttachment = it.attachments.getOrNull(it.currentAttachmentIndex) ?: return@withState
val destinationFile = File(requireContext().cacheDir, "${currentAttachment.name}_edited_image_${System.currentTimeMillis()}") val destinationFile = File(requireContext().cacheDir, "${currentAttachment.name}_edited_image_${System.currentTimeMillis()}")
val uri = currentAttachment.queryUri val uri = currentAttachment.queryUri

View File

@ -28,23 +28,19 @@ import androidx.appcompat.widget.SearchView
import androidx.core.view.isVisible import androidx.core.view.isVisible
import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.fragmentViewModel
import com.airbnb.mvrx.withState import com.airbnb.mvrx.withState
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.exhaustive import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.platform.VectorBaseFragment import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.PERMISSIONS_FOR_WRITING_FILES
import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_PICK_ATTACHMENT
import im.vector.app.core.utils.allGranted
import im.vector.app.core.utils.checkPermissions
import im.vector.app.features.attachments.AttachmentsHelper import im.vector.app.features.attachments.AttachmentsHelper
import im.vector.app.features.attachments.preview.AttachmentsPreviewActivity import im.vector.app.features.attachments.preview.AttachmentsPreviewActivity
import im.vector.app.features.attachments.preview.AttachmentsPreviewArgs import im.vector.app.features.attachments.preview.AttachmentsPreviewArgs
import im.vector.app.features.login.LoginActivity import im.vector.app.features.login.LoginActivity
import kotlinx.android.synthetic.main.fragment_incoming_share.* import kotlinx.android.synthetic.main.fragment_incoming_share.*
import org.matrix.android.sdk.api.session.content.ContentAttachmentData
import org.matrix.android.sdk.api.session.room.model.RoomSummary
import javax.inject.Inject import javax.inject.Inject
/** /**
@ -76,7 +72,7 @@ class IncomingShareFragment @Inject constructor(
val intent = vectorBaseActivity.intent val intent = vectorBaseActivity.intent
val isShareManaged = when (intent?.action) { val isShareManaged = when (intent?.action) {
Intent.ACTION_SEND -> { Intent.ACTION_SEND -> {
var isShareManaged = attachmentsHelper.handleShareIntent(requireContext(), intent) var isShareManaged = attachmentsHelper.handleShareIntent(requireContext(), intent)
if (!isShareManaged) { if (!isShareManaged) {
isShareManaged = handleTextShare(intent) isShareManaged = handleTextShare(intent)
@ -106,7 +102,7 @@ class IncomingShareFragment @Inject constructor(
} }
viewModel.observeViewEvents { viewModel.observeViewEvents {
when (it) { when (it) {
is IncomingShareViewEvents.ShareToRoom -> handleShareToRoom(it) is IncomingShareViewEvents.ShareToRoom -> handleShareToRoom(it)
is IncomingShareViewEvents.EditMediaBeforeSending -> handleEditMediaBeforeSending(it) is IncomingShareViewEvents.EditMediaBeforeSending -> handleEditMediaBeforeSending(it)
is IncomingShareViewEvents.MultipleRoomsShareDone -> handleMultipleRoomsShareDone(it) is IncomingShareViewEvents.MultipleRoomsShareDone -> handleMultipleRoomsShareDone(it)
}.exhaustive }.exhaustive
@ -139,22 +135,6 @@ class IncomingShareFragment @Inject constructor(
} }
} }
override fun onResume() {
super.onResume()
// We need the read file permission
checkPermissions(PERMISSIONS_FOR_WRITING_FILES, this, PERMISSION_REQUEST_CODE_PICK_ATTACHMENT)
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == PERMISSION_REQUEST_CODE_PICK_ATTACHMENT && !allGranted(grantResults)) {
// Permission is mandatory
cannotManageShare(R.string.missing_permissions_error)
}
}
private fun handleShareToRoom(event: IncomingShareViewEvents.ShareToRoom) { private fun handleShareToRoom(event: IncomingShareViewEvents.ShareToRoom) {
if (event.showAlert) { if (event.showAlert) {
showConfirmationDialog(event.roomSummary, event.sharedData) showConfirmationDialog(event.roomSummary, event.sharedData)

View File

@ -47,7 +47,7 @@
<TextView <TextView
android:id="@+id/riot_desktop_web" android:id="@+id/app_desktop_web"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
@ -59,7 +59,7 @@
app:layout_constraintTop_toBottomOf="@id/monitorIcon" /> app:layout_constraintTop_toBottomOf="@id/monitorIcon" />
<TextView <TextView
android:id="@+id/riot_ios_android" android:id="@+id/app_ios_android"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
@ -75,7 +75,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:barrierDirection="bottom" app:barrierDirection="bottom"
app:constraint_referenced_ids="riot_ios_android,riot_desktop_web" /> app:constraint_referenced_ids="app_ios_android,app_desktop_web" />
<TextView <TextView