Fix permission handling + share my code by text
This commit is contained in:
parent
ae6de8fdf1
commit
baef9f5aa7
@ -587,6 +587,16 @@ abstract class VectorBaseActivity : AppCompatActivity(), HasScreenInjector {
|
||||
}
|
||||
}
|
||||
|
||||
fun showSnackbar(message: String, @StringRes withActionTitle: Int?, action: (() -> Unit)?) {
|
||||
coordinatorLayout?.let {
|
||||
Snackbar.make(it, message, Snackbar.LENGTH_LONG).apply {
|
||||
withActionTitle?.let {
|
||||
setAction(withActionTitle, { action?.invoke() })
|
||||
}
|
||||
}.show()
|
||||
}
|
||||
}
|
||||
|
||||
/* ==========================================================================================
|
||||
* User Consent
|
||||
* ========================================================================================== */
|
||||
|
@ -19,8 +19,11 @@ package im.vector.app.core.utils
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.pm.PackageManager
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.provider.Settings
|
||||
import android.widget.Toast
|
||||
import androidx.activity.result.ActivityResultLauncher
|
||||
import androidx.activity.result.contract.ActivityResultContracts
|
||||
@ -30,6 +33,8 @@ import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.fragment.app.Fragment
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import org.matrix.android.sdk.api.extensions.tryOrNull
|
||||
import timber.log.Timber
|
||||
|
||||
// Android M permission request code management
|
||||
@ -284,6 +289,19 @@ private fun checkPermissions(permissionsToBeGrantedBitMap: Int,
|
||||
return isPermissionGranted
|
||||
}
|
||||
|
||||
fun VectorBaseActivity.onPermissionDeniedSnackbar(@StringRes rationaleMessage: Int) {
|
||||
showSnackbar(getString(rationaleMessage), R.string.settings) {
|
||||
tryOrNull {
|
||||
startActivity(
|
||||
Intent().apply {
|
||||
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
|
||||
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||
data = Uri.fromParts("package", this@onPermissionDeniedSnackbar.packageName, null)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method used in [.checkPermissions] to populate the list of the
|
||||
* permissions to be granted (permissionsListToBeGrantedOut) and the list of the permissions already denied (permissionAlreadyDeniedListOut).
|
||||
|
@ -22,7 +22,6 @@ import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.app.AlertDialog
|
||||
import com.airbnb.mvrx.Async
|
||||
import com.airbnb.mvrx.Fail
|
||||
@ -43,6 +42,7 @@ import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_LAUNCH_CAMERA
|
||||
import im.vector.app.core.utils.PERMISSION_REQUEST_CODE_READ_CONTACTS
|
||||
import im.vector.app.core.utils.allGranted
|
||||
import im.vector.app.core.utils.checkPermissions
|
||||
import im.vector.app.core.utils.onPermissionDeniedSnackbar
|
||||
import im.vector.app.features.contactsbook.ContactsBookFragment
|
||||
import im.vector.app.features.contactsbook.ContactsBookViewModel
|
||||
import im.vector.app.features.userdirectory.UserListFragment
|
||||
@ -132,9 +132,10 @@ class CreateDirectRoomActivity : SimpleFragmentActivity(), UserListViewModel.Fac
|
||||
addFragment(R.id.container, CreateDirectRoomByQrCodeFragment::class.java)
|
||||
}
|
||||
} else {
|
||||
Toast.makeText(baseContext, R.string.missing_permissions_error, Toast.LENGTH_SHORT).show()
|
||||
if (requestCode == PERMISSION_REQUEST_CODE_LAUNCH_CAMERA) {
|
||||
finish()
|
||||
onPermissionDeniedSnackbar(R.string.permissions_denied_qr_code)
|
||||
} else if (requestCode == PERMISSION_REQUEST_CODE_READ_CONTACTS) {
|
||||
onPermissionDeniedSnackbar(R.string.permissions_denied_add_contact)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -16,10 +16,13 @@
|
||||
|
||||
package im.vector.app.features.usercode
|
||||
|
||||
import android.Manifest
|
||||
import android.app.Activity
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.Bundle
|
||||
import android.view.View
|
||||
import android.widget.Toast
|
||||
import androidx.core.content.ContextCompat
|
||||
import com.airbnb.mvrx.activityViewModel
|
||||
import com.google.zxing.Result
|
||||
import com.google.zxing.ResultMetadataType
|
||||
@ -60,6 +63,9 @@ class ScanUserCodeFragment @Inject constructor()
|
||||
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
startCamera()
|
||||
} else {
|
||||
// For now just go back
|
||||
sharedViewModel.handle(UserCodeActions.SwitchMode(UserCodeState.Mode.SHOW))
|
||||
}
|
||||
}
|
||||
|
||||
@ -90,12 +96,18 @@ class ScanUserCodeFragment @Inject constructor()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onStart() {
|
||||
super.onStart()
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), openCameraActivityResultLauncher)) {
|
||||
startCamera()
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
// Register ourselves as a handler for scan results.
|
||||
userCodeScannerView.setResultHandler(this)
|
||||
// Start camera on resume
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), openCameraActivityResultLauncher)) {
|
||||
if (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(requireContext(), Manifest.permission.CAMERA)) {
|
||||
startCamera()
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,10 @@ import com.airbnb.mvrx.withState
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.extensions.setTextOrHide
|
||||
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.registerForPermissionsResult
|
||||
import im.vector.app.core.utils.startSharePlainTextIntent
|
||||
import im.vector.app.features.home.AvatarRenderer
|
||||
import kotlinx.android.synthetic.main.fragment_user_code_show.*
|
||||
import javax.inject.Inject
|
||||
@ -35,13 +39,38 @@ class ShowUserCodeFragment @Inject constructor(
|
||||
|
||||
val sharedViewModel: UserCodeSharedViewModel by activityViewModel()
|
||||
|
||||
private val openCameraActivityResultLauncher = registerForPermissionsResult { allGranted ->
|
||||
if (allGranted) {
|
||||
doOpenQRCodeScanner()
|
||||
} else {
|
||||
sharedViewModel.handle(UserCodeActions.CameraPermissionNotGranted)
|
||||
}
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
showUserCodeClose.debouncedClicks {
|
||||
sharedViewModel.handle(UserCodeActions.DismissAction)
|
||||
}
|
||||
showUserCodeScanButton.debouncedClicks {
|
||||
doOpenQRCodeScanner()
|
||||
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), openCameraActivityResultLauncher)) {
|
||||
doOpenQRCodeScanner()
|
||||
}
|
||||
}
|
||||
shareByText.debouncedClicks {
|
||||
sharedViewModel.handle(UserCodeActions.ShareByText)
|
||||
}
|
||||
|
||||
sharedViewModel.observeViewEvents {
|
||||
if (it is UserCodeShareViewEvents.SharePlainText) {
|
||||
startSharePlainTextIntent(
|
||||
fragment = this,
|
||||
activityResultLauncher = null,
|
||||
chooserTitle = it.title,
|
||||
text = it.text,
|
||||
extraTitle = it.richPlainText
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -24,4 +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()
|
||||
object ShareByText : UserCodeActions()
|
||||
}
|
||||
|
@ -32,6 +32,7 @@ import im.vector.app.core.di.ScreenComponent
|
||||
import im.vector.app.core.extensions.commitTransaction
|
||||
import im.vector.app.core.extensions.exhaustive
|
||||
import im.vector.app.core.platform.VectorBaseActivity
|
||||
import im.vector.app.core.utils.onPermissionDeniedSnackbar
|
||||
import im.vector.app.features.matrixto.MatrixToBottomSheet
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.activity_simple.*
|
||||
@ -78,13 +79,15 @@ class UserCodeActivity
|
||||
|
||||
sharedViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is UserCodeShareViewEvents.InviteFriend -> TODO()
|
||||
UserCodeShareViewEvents.Dismiss -> ActivityCompat.finishAfterTransition(this)
|
||||
UserCodeShareViewEvents.ShowWaitingScreen -> simpleActivityWaitingView.isVisible = true
|
||||
UserCodeShareViewEvents.HideWaitingScreen -> simpleActivityWaitingView.isVisible = false
|
||||
is UserCodeShareViewEvents.ToastMessage -> Toast.makeText(this, it.message, Toast.LENGTH_LONG).show()
|
||||
is UserCodeShareViewEvents.NavigateToRoom -> navigator.openRoom(this, it.roomId)
|
||||
}.exhaustive
|
||||
UserCodeShareViewEvents.Dismiss -> ActivityCompat.finishAfterTransition(this)
|
||||
UserCodeShareViewEvents.ShowWaitingScreen -> simpleActivityWaitingView.isVisible = true
|
||||
UserCodeShareViewEvents.HideWaitingScreen -> 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)
|
||||
else -> {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,11 @@ package im.vector.app.features.usercode
|
||||
import im.vector.app.core.platform.VectorViewEvents
|
||||
|
||||
sealed class UserCodeShareViewEvents : VectorViewEvents {
|
||||
data class InviteFriend(val permalink: String) : UserCodeShareViewEvents()
|
||||
object Dismiss : UserCodeShareViewEvents()
|
||||
object ShowWaitingScreen : UserCodeShareViewEvents()
|
||||
object HideWaitingScreen : UserCodeShareViewEvents()
|
||||
data class ToastMessage(val message: String) : UserCodeShareViewEvents()
|
||||
data class NavigateToRoom(val roomId: String) : UserCodeShareViewEvents()
|
||||
object CameraPermissionNotGranted : UserCodeShareViewEvents()
|
||||
data class SharePlainText(val text: String, val title: String, val richPlainText: String) : UserCodeShareViewEvents()
|
||||
}
|
||||
|
@ -71,12 +71,6 @@ class UserCodeSharedViewModel @AssistedInject constructor(
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleInviteFriend() {
|
||||
session.permalinkService().createPermalink(initialState.userId)?.let { permalink ->
|
||||
_viewEvents.post(UserCodeShareViewEvents.InviteFriend(permalink))
|
||||
}
|
||||
}
|
||||
|
||||
@AssistedInject.Factory
|
||||
interface Factory {
|
||||
fun create(initialState: UserCodeState, args: UserCodeActivity.Args): UserCodeSharedViewModel
|
||||
@ -84,10 +78,23 @@ class UserCodeSharedViewModel @AssistedInject constructor(
|
||||
|
||||
override fun handle(action: UserCodeActions) {
|
||||
when (action) {
|
||||
UserCodeActions.DismissAction -> _viewEvents.post(UserCodeShareViewEvents.Dismiss)
|
||||
is UserCodeActions.SwitchMode -> setState { copy(mode = action.mode) }
|
||||
is UserCodeActions.DecodedQRCode -> handleQrCodeDecoded(action)
|
||||
is UserCodeActions.StartChattingWithUser -> handleStartChatting(action)
|
||||
UserCodeActions.DismissAction -> _viewEvents.post(UserCodeShareViewEvents.Dismiss)
|
||||
is UserCodeActions.SwitchMode -> setState { copy(mode = action.mode) }
|
||||
is UserCodeActions.DecodedQRCode -> handleQrCodeDecoded(action)
|
||||
is UserCodeActions.StartChattingWithUser -> handleStartChatting(action)
|
||||
UserCodeActions.CameraPermissionNotGranted -> _viewEvents.post(UserCodeShareViewEvents.CameraPermissionNotGranted)
|
||||
UserCodeActions.ShareByText -> handleShareByText()
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleShareByText() {
|
||||
session.permalinkService().createPermalink(session.myUserId)?.let { permalink ->
|
||||
val text = stringProvider.getString(R.string.invite_friends_text, permalink)
|
||||
_viewEvents.post(UserCodeShareViewEvents.SharePlainText(
|
||||
text,
|
||||
stringProvider.getString(R.string.invite_friends),
|
||||
stringProvider.getString(R.string.invite_friends_rich_title)
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,26 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/vector_coordinator_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/VectorToolbarStyle"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
||||
<androidx.appcompat.widget.Toolbar
|
||||
android:id="@+id/toolbar"
|
||||
style="@style/VectorToolbarStyle"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:elevation="4dp"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<include layout="@layout/merge_overlay_waiting_view"/>
|
||||
<androidx.fragment.app.FragmentContainerView
|
||||
android:id="@+id/container"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/toolbar" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<include layout="@layout/merge_overlay_waiting_view" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@ -49,6 +49,19 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/showUserCodeClose"
|
||||
app:layout_constraintEnd_toStartOf="@id/shareByText"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/shareByText"
|
||||
android:layout_width="@dimen/layout_touch_size"
|
||||
android:layout_height="@dimen/layout_touch_size"
|
||||
android:scaleType="center"
|
||||
android:src="@drawable/ic_share"
|
||||
app:tint="@color/riotx_accent"
|
||||
android:layout_marginEnd="@dimen/layout_horizontal_margin"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
@ -425,6 +425,8 @@
|
||||
<string name="permissions_msg_contacts_warning_other_androids">Element can check your address book to find other Matrix users based on their email and phone numbers.\n\nDo you agree to share your address book for this purpose?</string>
|
||||
|
||||
<string name="permissions_action_not_performed_missing_permissions">Sorry. Action not performed, due to missing permissions</string>
|
||||
<string name="permissions_denied_qr_code">To scan a QR code, allow Camera permission to take a picture</string>
|
||||
<string name="permissions_denied_add_contact">To check your address book, allow Contact permission.</string>
|
||||
|
||||
<!-- medias slider string -->
|
||||
<string name="media_slider_saved">Saved</string>
|
||||
|
@ -5,7 +5,9 @@
|
||||
<item name="android:background">@color/notification_accent_color</item>
|
||||
</style>
|
||||
|
||||
<style name="VectorSnackBarButton" parent="@style/Widget.MaterialComponents.Button" />
|
||||
<style name="VectorSnackBarButton" parent="@style/Widget.MaterialComponents.Button">
|
||||
<item name="android:textColor">@color/white</item>
|
||||
</style>
|
||||
|
||||
<style name="VectorSnackBarText" parent="@style/Widget.MaterialComponents.Snackbar.TextView">
|
||||
<item name="android:textColor">@color/white</item>
|
||||
|
Loading…
x
Reference in New Issue
Block a user