Do not use deprecated Fragment.startActivityForResult anymore

This commit is contained in:
Benoit Marty 2020-10-07 16:02:01 +02:00
parent 05950ec1c8
commit ff0f42900d
38 changed files with 464 additions and 547 deletions

View File

@ -66,6 +66,7 @@ dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.2'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.fragment:fragment:1.3.0-beta01"
implementation "androidx.recyclerview:recyclerview:1.1.0"
implementation 'com.google.android.material:material:1.2.1'

View File

@ -36,6 +36,7 @@ android {
dependencies {
implementation project(":matrix-sdk-android")
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.fragment:fragment:1.3.0-beta01"
implementation 'io.reactivex.rxjava2:rxkotlin:2.3.0'
implementation 'io.reactivex.rxjava2:rxandroid:2.1.1'
// Paging

View File

@ -121,6 +121,7 @@ dependencies {
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$kotlin_coroutines_version"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.fragment:fragment:1.3.0-beta01"
implementation "androidx.core:core-ktx:1.3.2"
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycle_version"

View File

@ -41,9 +41,9 @@ android {
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation "androidx.fragment:fragment:1.3.0-beta01"
implementation 'androidx.exifinterface:exifinterface:1.3.0'
// Log

View File

@ -16,7 +16,6 @@
package im.vector.lib.multipicker
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.media.MediaMetadataRetriever
@ -30,15 +29,9 @@ class AudioPicker(override val requestCode: Int) : Picker<MultiPickerAudioType>(
/**
* Call this function from onActivityResult(int, int, Intent).
* Returns selected audio files or empty list if request code is wrong
* or result code is not Activity.RESULT_OK
* or user did not select any files.
* Returns selected audio files or empty list if user did not select any files.
*/
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerAudioType> {
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
return emptyList()
}
override fun getSelectedFiles(context: Context, data: Intent?): List<MultiPickerAudioType> {
val audioList = mutableListOf<MultiPickerAudioType>()
getSelectedUriList(data).forEach { selectedUri ->

View File

@ -21,8 +21,8 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.provider.MediaStore
import androidx.activity.result.ActivityResultLauncher
import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment
import im.vector.lib.multipicker.entity.MultiPickerImageType
import im.vector.lib.multipicker.utils.ImageUtils
import java.io.File
@ -51,15 +51,14 @@ class CameraPicker(val requestCode: Int) {
/**
* Start camera by using a Fragment
* @param fragment Fragment to handle onActivityResult().
* @return Uri of taken photo or null if the operation is cancelled.
*/
fun startWithExpectingFile(fragment: Fragment): Uri? {
val photoUri = createPhotoUri(fragment.requireContext())
fun startWithExpectingFile(context: Context, activityResultLauncher: ActivityResultLauncher<Intent>): Uri? {
val photoUri = createPhotoUri(context)
val intent = createIntent().apply {
putExtra(MediaStore.EXTRA_OUTPUT, photoUri)
}
fragment.startActivityForResult(intent, requestCode)
activityResultLauncher.launch(intent)
return photoUri
}
@ -69,8 +68,7 @@ class CameraPicker(val requestCode: Int) {
* or result code is not Activity.RESULT_OK
* or user cancelled the operation.
*/
fun getTakenPhoto(context: Context, requestCode: Int, resultCode: Int, photoUri: Uri): MultiPickerImageType? {
if (requestCode == this.requestCode && resultCode == Activity.RESULT_OK) {
fun getTakenPhoto(context: Context, photoUri: Uri): MultiPickerImageType? {
val projection = arrayOf(
MediaStore.Images.Media.DISPLAY_NAME,
MediaStore.Images.Media.SIZE
@ -104,7 +102,6 @@ class CameraPicker(val requestCode: Int) {
)
}
}
}
return null
}

View File

@ -16,7 +16,6 @@
package im.vector.lib.multipicker
import android.app.Activity
import android.content.ContentResolver
import android.content.Context
import android.content.Intent
@ -30,15 +29,9 @@ class ContactPicker(override val requestCode: Int) : Picker<MultiPickerContactTy
/**
* Call this function from onActivityResult(int, int, Intent).
* Returns selected contact or empty list if request code is wrong
* or result code is not Activity.RESULT_OK
* or user did not select any files.
* Returns selected contact or empty list if user did not select any contacts.
*/
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerContactType> {
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
return emptyList()
}
override fun getSelectedFiles(context: Context, data: Intent?): List<MultiPickerContactType> {
val contactList = mutableListOf<MultiPickerContactType>()
data?.data?.let { selectedUri ->

View File

@ -16,7 +16,6 @@
package im.vector.lib.multipicker
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.provider.OpenableColumns
@ -29,15 +28,9 @@ class FilePicker(override val requestCode: Int) : Picker<MultiPickerFileType>(re
/**
* Call this function from onActivityResult(int, int, Intent).
* Returns selected files or empty list if request code is wrong
* or result code is not Activity.RESULT_OK
* or user did not select any files.
* Returns selected files or empty list if user did not select any files.
*/
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerFileType> {
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
return emptyList()
}
override fun getSelectedFiles(context: Context, data: Intent?): List<MultiPickerFileType> {
val fileList = mutableListOf<MultiPickerFileType>()
getSelectedUriList(data).forEach { selectedUri ->

View File

@ -16,7 +16,6 @@
package im.vector.lib.multipicker
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.provider.MediaStore
@ -30,15 +29,9 @@ class ImagePicker(override val requestCode: Int) : Picker<MultiPickerImageType>(
/**
* Call this function from onActivityResult(int, int, Intent).
* Returns selected image files or empty list if request code is wrong
* or result code is not Activity.RESULT_OK
* or user did not select any files.
* Returns selected image files or empty list if user did not select any files.
*/
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerImageType> {
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
return emptyList()
}
override fun getSelectedFiles(context: Context, data: Intent?): List<MultiPickerImageType> {
val imageList = mutableListOf<MultiPickerImageType>()
getSelectedUriList(data).forEach { selectedUri ->

View File

@ -22,7 +22,7 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.content.pm.ResolveInfo
import android.net.Uri
import androidx.fragment.app.Fragment
import androidx.activity.result.ActivityResultLauncher
/**
* Abstract class to provide all types of Pickers
@ -33,11 +33,9 @@ abstract class Picker<T>(open val requestCode: Int) {
/**
* Call this function from onActivityResult(int, int, Intent).
* @return selected files or empty list if request code is wrong
* or result code is not Activity.RESULT_OK
* or user did not select any files.
* @return selected files or empty list if user did not select any files.
*/
abstract fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<T>
abstract fun getSelectedFiles(context: Context, data: Intent?): List<T>
/**
* Use this function to retrieve files which are shared from another application or internally
@ -61,7 +59,7 @@ abstract class Picker<T>(open val requestCode: Int) {
context.grantUriPermission(packageName, it, Intent.FLAG_GRANT_READ_URI_PERMISSION)
}
}
return getSelectedFiles(context, requestCode, Activity.RESULT_OK, data)
return getSelectedFiles(context, data)
}
/**
@ -84,10 +82,10 @@ abstract class Picker<T>(open val requestCode: Int) {
/**
* Start Storage Access Framework UI by using a Fragment.
* @param fragment Fragment to handle onActivityResult().
* @param activityResultLauncher to handle the result.
*/
fun startWith(fragment: Fragment) {
fragment.startActivityForResult(createIntent().apply { addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) }, requestCode)
fun startWith(activityResultLauncher: ActivityResultLauncher<Intent>) {
activityResultLauncher.launch(createIntent().apply { addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) })
}
protected fun getSelectedUriList(data: Intent?): List<Uri> {

View File

@ -16,7 +16,6 @@
package im.vector.lib.multipicker
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.media.MediaMetadataRetriever
@ -30,15 +29,9 @@ class VideoPicker(override val requestCode: Int) : Picker<MultiPickerVideoType>(
/**
* Call this function from onActivityResult(int, int, Intent).
* Returns selected video files or empty list if request code is wrong
* or result code is not Activity.RESULT_OK
* or user did not select any files.
* Returns selected video files or empty list if user did not select any files.
*/
override fun getSelectedFiles(context: Context, requestCode: Int, resultCode: Int, data: Intent?): List<MultiPickerVideoType> {
if (requestCode != this.requestCode && resultCode != Activity.RESULT_OK) {
return emptyList()
}
override fun getSelectedFiles(context: Context, data: Intent?): List<MultiPickerVideoType> {
val videoList = mutableListOf<MultiPickerVideoType>()
getSelectedUriList(data).forEach { selectedUri ->

View File

@ -17,7 +17,11 @@
package im.vector.app.core.extensions
import android.app.Activity
import android.content.Intent
import android.os.Parcelable
import androidx.activity.result.ActivityResult
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.fragment.app.Fragment
import im.vector.app.R
import im.vector.app.core.platform.VectorBaseFragment
@ -26,6 +30,10 @@ import java.text.SimpleDateFormat
import java.util.Date
import java.util.Locale
fun Fragment.registerStartForActivityResult(onResult: (ActivityResult) -> Unit): ActivityResultLauncher<Intent> {
return registerForActivityResult(ActivityResultContracts.StartActivityForResult(), onResult)
}
fun VectorBaseFragment.addFragment(
frameId: Int,
fragment: Fragment,
@ -160,15 +168,15 @@ fun Fragment.getAllChildFragments(): List<Fragment> {
// Define a missing constant
const val POP_BACK_STACK_EXCLUSIVE = 0
fun Fragment.queryExportKeys(userId: String, requestCode: Int) {
fun Fragment.queryExportKeys(userId: String, activityResultLauncher: ActivityResultLauncher<Intent>) {
val timestamp = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date())
selectTxtFileToWrite(
activity = requireActivity(),
fragment = this,
activityResultLauncher = activityResultLauncher,
defaultFileName = "element-megolm-export-$userId-$timestamp.txt",
chooserHint = getString(R.string.keys_backup_setup_step1_manual_export),
requestCode = requestCode
requestCode = 0
)
}
@ -177,7 +185,7 @@ fun Activity.queryExportKeys(userId: String, requestCode: Int) {
selectTxtFileToWrite(
activity = this,
fragment = null,
activityResultLauncher = null,
defaultFileName = "element-megolm-export-$userId-$timestamp.txt",
chooserHint = getString(R.string.keys_backup_setup_step1_manual_export),
requestCode = requestCode

View File

@ -31,6 +31,7 @@ import android.provider.Browser
import android.provider.MediaStore
import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.browser.customtabs.CustomTabsIntent
import androidx.browser.customtabs.CustomTabsSession
import androidx.core.content.ContextCompat
@ -130,7 +131,7 @@ fun openSoundRecorder(activity: Activity, requestCode: Int) {
* Open file selection activity
*/
fun openFileSelection(activity: Activity,
fragment: Fragment?,
activityResultLauncher: ActivityResultLauncher<Intent>?,
allowMultipleSelection: Boolean,
requestCode: Int) {
val fileIntent = Intent(Intent.ACTION_GET_CONTENT)
@ -140,8 +141,8 @@ fun openFileSelection(activity: Activity,
fileIntent.type = "*/*"
try {
fragment
?.startActivityForResult(fileIntent, requestCode)
activityResultLauncher
?.launch(fileIntent)
?: run {
activity.startActivityForResult(fileIntent, requestCode)
}
@ -440,7 +441,7 @@ fun openPlayStore(activity: Activity, appId: String = BuildConfig.APPLICATION_ID
*/
fun selectTxtFileToWrite(
activity: Activity,
fragment: Fragment?,
activityResultLauncher: ActivityResultLauncher<Intent>?,
defaultFileName: String,
chooserHint: String,
requestCode: Int
@ -452,8 +453,8 @@ fun selectTxtFileToWrite(
try {
val chooserIntent = Intent.createChooser(intent, chooserHint)
if (fragment != null) {
fragment.startActivityForResult(chooserIntent, requestCode)
if (activityResultLauncher != null) {
activityResultLauncher.launch(chooserIntent)
} else {
activity.startActivityForResult(chooserIntent, requestCode)
}

View File

@ -15,12 +15,11 @@
*/
package im.vector.app.features.attachments
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.activity.result.ActivityResultLauncher
import im.vector.app.core.platform.Restorable
import im.vector.lib.multipicker.MultiPicker
import org.matrix.android.sdk.BuildConfig
@ -48,6 +47,7 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
// Capture path allows to handle camera image picking. It must be restored if the activity gets killed.
private var captureUri: Uri? = null
// The pending type is set if we have to handle permission request. It must be restored if the activity gets killed.
var pendingType: AttachmentTypeSelectorView.Type? = null
@ -72,80 +72,79 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
/**
* Starts the process for handling file picking
*/
fun selectFile(fragment: Fragment) {
MultiPicker.get(MultiPicker.FILE).startWith(fragment)
fun selectFile(activityResultLauncher: ActivityResultLauncher<Intent>) {
MultiPicker.get(MultiPicker.FILE).startWith(activityResultLauncher)
}
/**
* Starts the process for handling image picking
*/
fun selectGallery(fragment: Fragment) {
MultiPicker.get(MultiPicker.IMAGE).startWith(fragment)
fun selectGallery(activityResultLauncher: ActivityResultLauncher<Intent>) {
MultiPicker.get(MultiPicker.IMAGE).startWith(activityResultLauncher)
}
/**
* Starts the process for handling audio picking
*/
fun selectAudio(fragment: Fragment) {
MultiPicker.get(MultiPicker.AUDIO).startWith(fragment)
fun selectAudio(activityResultLauncher: ActivityResultLauncher<Intent>) {
MultiPicker.get(MultiPicker.AUDIO).startWith(activityResultLauncher)
}
/**
* Starts the process for handling capture image picking
*/
fun openCamera(fragment: Fragment) {
captureUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(fragment)
fun openCamera(context: Context, activityResultLauncher: ActivityResultLauncher<Intent>) {
captureUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(context, activityResultLauncher)
}
/**
* Starts the process for handling contact picking
*/
fun selectContact(fragment: Fragment) {
MultiPicker.get(MultiPicker.CONTACT).startWith(fragment)
fun selectContact(activityResultLauncher: ActivityResultLauncher<Intent>) {
MultiPicker.get(MultiPicker.CONTACT).startWith(activityResultLauncher)
}
/**
* This methods aims to handle on activity result data.
*
* @return true if it can handle the data, false otherwise
* This methods aims to handle the result data.
*/
fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
MultiPicker.REQUEST_CODE_PICK_FILE -> {
fun onFileResult(data: Intent?) {
callback.onContentAttachmentsReady(
MultiPicker.get(MultiPicker.FILE)
.getSelectedFiles(context, requestCode, resultCode, data)
.getSelectedFiles(context, data)
.map { it.toContentAttachmentData() }
)
}
MultiPicker.REQUEST_CODE_PICK_AUDIO -> {
fun onAudioResult(data: Intent?) {
callback.onContentAttachmentsReady(
MultiPicker.get(MultiPicker.AUDIO)
.getSelectedFiles(context, requestCode, resultCode, data)
.getSelectedFiles(context, data)
.map { it.toContentAttachmentData() }
)
}
MultiPicker.REQUEST_CODE_PICK_CONTACT -> {
fun onContactResult(data: Intent?) {
MultiPicker.get(MultiPicker.CONTACT)
.getSelectedFiles(context, requestCode, resultCode, data)
.getSelectedFiles(context, data)
.firstOrNull()
?.toContactAttachment()
?.let {
callback.onContactAttachmentReady(it)
}
}
MultiPicker.REQUEST_CODE_PICK_IMAGE -> {
fun onImageResult(data: Intent?) {
callback.onContentAttachmentsReady(
MultiPicker.get(MultiPicker.IMAGE)
.getSelectedFiles(context, requestCode, resultCode, data)
.getSelectedFiles(context, data)
.map { it.toContentAttachmentData() }
)
}
MultiPicker.REQUEST_CODE_TAKE_PHOTO -> {
fun onPhotoResult() {
captureUri?.let { captureUri ->
MultiPicker.get(MultiPicker.CAMERA)
.getTakenPhoto(context, requestCode, resultCode, captureUri)
.getTakenPhoto(context, captureUri)
?.let {
callback.onContentAttachmentsReady(
listOf(it).map { it.toContentAttachmentData() }
@ -153,19 +152,14 @@ class AttachmentsHelper(val context: Context, val callback: Callback) : Restorab
}
}
}
MultiPicker.REQUEST_CODE_PICK_VIDEO -> {
fun onVideoResult(data: Intent?) {
callback.onContentAttachmentsReady(
MultiPicker.get(MultiPicker.VIDEO)
.getSelectedFiles(context, requestCode, resultCode, data)
.getSelectedFiles(context, data)
.map { it.toContentAttachmentData() }
)
}
else -> return false
}
return true
}
return false
}
/**
* This methods aims to handle share intent.

View File

@ -30,8 +30,6 @@ import org.matrix.android.sdk.api.session.content.ContentAttachmentData
class AttachmentsPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
companion object {
const val REQUEST_CODE = 55
private const val EXTRA_FRAGMENT_ARGS = "EXTRA_FRAGMENT_ARGS"
private const val ATTACHMENTS_PREVIEW_RESULT = "ATTACHMENTS_PREVIEW_RESULT"
private const val KEEP_ORIGINAL_IMAGES_SIZE = "KEEP_ORIGINAL_IMAGES_SIZE"

View File

@ -298,6 +298,7 @@ class VectorCallActivity : VectorBaseActivity(), CallControlsView.InteractionLis
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (requestCode == CAPTURE_PERMISSION_REQUEST_CODE && allGranted(grantResults)) {
start()
} else {

View File

@ -150,6 +150,7 @@ class VectorJitsiActivity : VectorBaseActivity(), JitsiMeetActivityInterface, Ji
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
JitsiMeetActivityDelegate.onRequestPermissionsResult(requestCode, permissions, grantResults)
}

View File

@ -111,6 +111,7 @@ class CreateDirectRoomActivity : SimpleFragmentActivity() {
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (allGranted(grantResults)) {
if (requestCode == PERMISSION_REQUEST_CODE_READ_CONTACTS) {
doOnPostResume { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) }

View File

@ -31,6 +31,7 @@ import butterknife.BindView
import butterknife.OnClick
import com.google.android.material.bottomsheet.BottomSheetDialog
import im.vector.app.R
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.LiveEvent
import im.vector.app.core.utils.copyToClipboard
@ -48,10 +49,6 @@ import javax.inject.Inject
class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment() {
companion object {
private const val SAVE_RECOVERY_KEY_REQUEST_CODE = 2754
}
override fun getLayoutResId() = R.layout.fragment_keys_backup_setup_step3
@BindView(R.id.keys_backup_setup_step3_button)
@ -138,10 +135,10 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment()
val timestamp = SimpleDateFormat("yyyy-MM-dd", Locale.getDefault()).format(Date())
selectTxtFileToWrite(
activity = requireActivity(),
fragment = this,
activityResultLauncher = saveRecoveryActivityResultLauncher,
defaultFileName = "recovery-key-$userId-$timestamp.txt",
chooserHint = getString(R.string.save_recovery_key_chooser_hint),
requestCode = SAVE_RECOVERY_KEY_REQUEST_CODE
requestCode = 0
)
dialog.dismiss()
}
@ -202,16 +199,12 @@ class KeysBackupSetupStep3Fragment @Inject constructor() : VectorBaseFragment()
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
SAVE_RECOVERY_KEY_REQUEST_CODE -> {
val uri = data?.data
if (resultCode == Activity.RESULT_OK && uri != null) {
private val saveRecoveryActivityResultLauncher = registerStartForActivityResult { activityRessult ->
val uri = activityRessult.data?.data ?: return@registerStartForActivityResult
if (activityRessult.resultCode == Activity.RESULT_OK) {
viewModel.recoveryKey.value?.let {
exportRecoveryKeyToFile(uri, it)
}
}
}
}
}
}

View File

@ -16,7 +16,6 @@
package im.vector.app.features.crypto.verification.choose
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.View
import com.airbnb.mvrx.fragmentViewModel
@ -25,6 +24,7 @@ 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
@ -91,17 +91,13 @@ class VerificationChooseMethodFragment @Inject constructor(
}
private fun doOpenQRCodeScanner() {
QrCodeScannerActivity.startForResult(this)
QrCodeScannerActivity.startForResult(requireActivity(), scanActivityResultLauncher)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
QrCodeScannerActivity.QR_CODE_SCANNER_REQUEST_CODE -> {
val scannedQrCode = QrCodeScannerActivity.getResultText(data)
val wasQrCode = QrCodeScannerActivity.getResultIsQrCode(data)
private val scanActivityResultLauncher = registerStartForActivityResult { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
val scannedQrCode = QrCodeScannerActivity.getResultText(activityResult.data)
val wasQrCode = QrCodeScannerActivity.getResultIsQrCode(activityResult.data)
if (wasQrCode && !scannedQrCode.isNullOrBlank()) {
onRemoteQrCodeScanned(scannedQrCode)
@ -110,8 +106,6 @@ class VerificationChooseMethodFragment @Inject constructor(
}
}
}
}
}
private fun onRemoteQrCodeScanned(remoteQrCode: String) = withState(sharedViewModel) { state ->
sharedViewModel.handle(VerificationAction.RemoteQrCodeScanned(

View File

@ -16,7 +16,6 @@
package im.vector.app.features.discovery
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.View
import androidx.appcompat.app.AlertDialog
@ -27,16 +26,17 @@ import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.observeEvent
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.ensureProtocol
import im.vector.app.features.discovery.change.SetIdentityServerFragment
import im.vector.app.features.settings.VectorSettingsActivity
import im.vector.app.features.terms.ReviewTermsActivity
import org.matrix.android.sdk.api.session.identity.SharedState
import org.matrix.android.sdk.api.session.identity.ThreePid
import org.matrix.android.sdk.api.session.terms.TermsService
import kotlinx.android.synthetic.main.fragment_generic_recycler.*
import timber.log.Timber
import javax.inject.Inject
class DiscoverySettingsFragment @Inject constructor(
@ -92,22 +92,19 @@ class DiscoverySettingsFragment @Inject constructor(
viewModel.handle(DiscoverySettingsAction.Refresh)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == ReviewTermsActivity.TERMS_REQUEST_CODE) {
if (Activity.RESULT_OK == resultCode) {
private val termsActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
viewModel.handle(DiscoverySettingsAction.RetrieveBinding)
} else {
// add some error?
}
}
super.onActivityResult(requestCode, resultCode, data)
}
override fun openIdentityServerTerms() = withState(viewModel) { state ->
if (state.termsNotSigned) {
navigator.openTerms(
this,
requireContext(),
termsActivityResultLauncher,
TermsService.ServiceType.IdentityService,
state.identityServer()?.ensureProtocol() ?: "",
null)

View File

@ -16,7 +16,6 @@
package im.vector.app.features.discovery.change
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.inputmethod.EditorInfo
@ -28,13 +27,13 @@ import com.airbnb.mvrx.withState
import com.jakewharton.rxbinding3.widget.textChanges
import im.vector.app.R
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.toReducedUrl
import im.vector.app.core.platform.VectorBaseActivity
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.resources.ColorProvider
import im.vector.app.core.utils.colorizeMatchingText
import im.vector.app.features.discovery.DiscoverySharedViewModel
import im.vector.app.features.terms.ReviewTermsActivity
import org.matrix.android.sdk.api.session.terms.TermsService
import kotlinx.android.synthetic.main.fragment_set_identity_server.*
import javax.inject.Inject
@ -121,7 +120,8 @@ class SetIdentityServerFragment @Inject constructor(
is SetIdentityServerViewEvents.TermsAccepted -> processIdentityServerChange()
is SetIdentityServerViewEvents.ShowTerms -> {
navigator.openTerms(
this,
requireContext(),
termsActivityResultLauncher,
TermsService.ServiceType.IdentityService,
it.identityServerUrl,
null)
@ -150,16 +150,13 @@ class SetIdentityServerFragment @Inject constructor(
(activity as? VectorBaseActivity)?.supportActionBar?.setTitle(R.string.identity_server)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (requestCode == ReviewTermsActivity.TERMS_REQUEST_CODE) {
if (Activity.RESULT_OK == resultCode) {
private val termsActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
processIdentityServerChange()
} else {
// add some error?
}
}
super.onActivityResult(requestCode, resultCode, data)
}
private fun processIdentityServerChange() {
viewModel.currentWantedUrl?.let {

View File

@ -17,7 +17,7 @@
package im.vector.app.features.home.room.detail
import android.annotation.SuppressLint
import android.app.Activity.RESULT_OK
import android.app.Activity
import android.content.DialogInterface
import android.content.Intent
import android.graphics.Typeface
@ -73,6 +73,7 @@ import im.vector.app.core.epoxy.LayoutManagerStateRestorer
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.extensions.showKeyboard
import im.vector.app.core.extensions.trackItemsVisibilityChange
@ -134,7 +135,6 @@ import im.vector.app.features.home.room.detail.timeline.item.MessageTextItem
import im.vector.app.features.home.room.detail.timeline.item.ReadReceiptData
import im.vector.app.features.home.room.detail.timeline.reactions.ViewReactionsBottomSheet
import im.vector.app.features.home.room.detail.widget.RoomWidgetsBottomSheet
import im.vector.app.features.home.room.detail.widget.WidgetRequestCodes
import im.vector.app.features.html.EventHtmlRenderer
import im.vector.app.features.html.PillImageSpan
import im.vector.app.features.invite.VectorInviteView
@ -202,8 +202,6 @@ data class RoomDetailArgs(
val sharedData: SharedData? = null
) : Parcelable
private const val REACTION_SELECT_REQUEST_CODE = 0
class RoomDetailFragment @Inject constructor(
private val session: Session,
private val avatarRenderer: AvatarRenderer,
@ -396,9 +394,14 @@ class RoomDetailFragment @Inject constructor(
}
}
private val integrationManagerActivityResultLauncher = registerStartForActivityResult {
// Noop
}
private fun openIntegrationManager(screen: String? = null) {
navigator.openIntegrationManager(
fragment = this,
context = requireContext(),
activityResultLauncher = integrationManagerActivityResultLauncher,
roomId = roomDetailArgs.roomId,
integId = null,
screen = screen
@ -435,7 +438,7 @@ class RoomDetailFragment @Inject constructor(
}
private fun openStickerPicker(event: RoomDetailViewEvents.OpenStickerPicker) {
navigator.openStickerPicker(this, roomDetailArgs.roomId, event.widget)
navigator.openStickerPicker(requireContext(), stickerActivityResultLauncher, roomDetailArgs.roomId, event.widget)
}
private fun startOpenFileIntent(action: RoomDetailViewEvents.OpenFile) {
@ -886,28 +889,64 @@ class RoomDetailFragment @Inject constructor(
roomDetailViewModel.handle(RoomDetailAction.SaveDraft(composerLayout.composerEditText.text.toString()))
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
val hasBeenHandled = attachmentsHelper.onActivityResult(requestCode, resultCode, data)
if (!hasBeenHandled && resultCode == RESULT_OK && data != null) {
when (requestCode) {
AttachmentsPreviewActivity.REQUEST_CODE -> {
private val attachmentFileActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
attachmentsHelper.onImageResult(it.data)
}
}
private val attachmentAudioActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
attachmentsHelper.onAudioResult(it.data)
}
}
private val attachmentContactActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
attachmentsHelper.onContactResult(it.data)
}
}
private val attachmentImageActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
attachmentsHelper.onImageResult(it.data)
}
}
private val attachmentPhotoActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
attachmentsHelper.onPhotoResult()
}
}
private val contentAttachmentActivityResultLauncher = registerStartForActivityResult { activityResult ->
val data = activityResult.data ?: return@registerStartForActivityResult
if (activityResult.resultCode == Activity.RESULT_OK) {
val sendData = AttachmentsPreviewActivity.getOutput(data)
val keepOriginalSize = AttachmentsPreviewActivity.getKeepOriginalSize(data)
roomDetailViewModel.handle(RoomDetailAction.SendMedia(sendData, !keepOriginalSize))
}
REACTION_SELECT_REQUEST_CODE -> {
val (eventId, reaction) = EmojiReactionPickerActivity.getOutput(data) ?: return
}
private val emojiActivityResultLauncher = registerStartForActivityResult { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
val eventId = EmojiReactionPickerActivity.getOutputEventId(activityResult.data)
val reaction = EmojiReactionPickerActivity.getOutputReaction(activityResult.data)
if (eventId != null && reaction != null) {
roomDetailViewModel.handle(RoomDetailAction.SendReaction(eventId, reaction))
}
WidgetRequestCodes.STICKER_PICKER_REQUEST_CODE -> {
val content = WidgetActivity.getOutput(data).toModel<MessageStickerContent>() ?: return
}
}
private val stickerActivityResultLauncher = registerStartForActivityResult { activityResult ->
val data = activityResult.data ?: return@registerStartForActivityResult
if (activityResult.resultCode == Activity.RESULT_OK) {
WidgetActivity.getOutput(data).toModel<MessageStickerContent>()
?.let { content ->
roomDetailViewModel.handle(RoomDetailAction.SendSticker(content))
}
}
}
// TODO why don't we call super here?
// super.onActivityResult(requestCode, resultCode, data)
}
// PRIVATE METHODS *****************************************************************************
@ -1600,7 +1639,7 @@ class RoomDetailFragment @Inject constructor(
openRoomMemberProfile(action.userId)
}
is EventSharedAction.AddReaction -> {
startActivityForResult(EmojiReactionPickerActivity.intent(requireContext(), action.eventId), REACTION_SELECT_REQUEST_CODE)
emojiActivityResultLauncher.launch(EmojiReactionPickerActivity.intent(requireContext(), action.eventId))
}
is EventSharedAction.ViewReactions -> {
ViewReactionsBottomSheet.newInstance(roomDetailArgs.roomId, action.messageInformationData)
@ -1827,11 +1866,11 @@ class RoomDetailFragment @Inject constructor(
private fun launchAttachmentProcess(type: AttachmentTypeSelectorView.Type) {
when (type) {
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera(this)
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(this)
AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(this)
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(this)
AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact(this)
AttachmentTypeSelectorView.Type.CAMERA -> attachmentsHelper.openCamera(requireContext(), attachmentPhotoActivityResultLauncher)
AttachmentTypeSelectorView.Type.FILE -> attachmentsHelper.selectFile(attachmentFileActivityResultLauncher)
AttachmentTypeSelectorView.Type.GALLERY -> attachmentsHelper.selectGallery(attachmentImageActivityResultLauncher)
AttachmentTypeSelectorView.Type.AUDIO -> attachmentsHelper.selectAudio(attachmentAudioActivityResultLauncher)
AttachmentTypeSelectorView.Type.CONTACT -> attachmentsHelper.selectContact(attachmentContactActivityResultLauncher)
AttachmentTypeSelectorView.Type.STICKER -> roomDetailViewModel.handle(RoomDetailAction.SelectStickerAttachment)
}.exhaustive
}
@ -1850,7 +1889,7 @@ class RoomDetailFragment @Inject constructor(
}
if (grouped.previewables.isNotEmpty()) {
val intent = AttachmentsPreviewActivity.newIntent(requireContext(), AttachmentsPreviewArgs(grouped.previewables))
startActivityForResult(intent, AttachmentsPreviewActivity.REQUEST_CODE)
contentAttachmentActivityResultLauncher.launch(intent)
}
}
}

View File

@ -1,22 +0,0 @@
/*
* Copyright (c) 2020 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.home.room.detail.widget
object WidgetRequestCodes {
const val STICKER_PICKER_REQUEST_CODE = 16000
const val INTEGRATION_MANAGER_REQUEST_CODE = 16001
}

View File

@ -112,6 +112,7 @@ class InviteUsersToRoomActivity : SimpleFragmentActivity() {
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (allGranted(grantResults)) {
if (requestCode == PERMISSION_REQUEST_CODE_READ_CONTACTS) {
doOnPostResume { addFragmentToBackstack(R.id.container, ContactsBookFragment::class.java) }

View File

@ -133,7 +133,7 @@ class BigImageViewerActivity : VectorBaseActivity() {
MultiPicker.REQUEST_CODE_TAKE_PHOTO -> {
avatarCameraUri?.let { uri ->
MultiPicker.get(MultiPicker.CAMERA)
.getTakenPhoto(this, requestCode, resultCode, uri)
.getTakenPhoto(this, uri)
?.let {
onRoomAvatarSelected(it)
}
@ -142,7 +142,7 @@ class BigImageViewerActivity : VectorBaseActivity() {
MultiPicker.REQUEST_CODE_PICK_IMAGE -> {
MultiPicker
.get(MultiPicker.IMAGE)
.getSelectedFiles(this, requestCode, resultCode, data)
.getSelectedFiles(this, data)
.firstOrNull()?.let {
onRoomAvatarSelected(it)
}
@ -154,6 +154,7 @@ class BigImageViewerActivity : VectorBaseActivity() {
}
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
if (allGranted(grantResults)) {
when (requestCode) {
PERMISSION_REQUEST_CODE_LAUNCH_CAMERA -> onAvatarTypeSelected(true)

View File

@ -21,11 +21,11 @@ import android.content.Context
import android.content.Intent
import android.view.View
import android.view.Window
import androidx.activity.result.ActivityResultLauncher
import androidx.core.app.ActivityOptionsCompat
import androidx.core.app.TaskStackBuilder
import androidx.core.util.Pair
import androidx.core.view.ViewCompat
import androidx.fragment.app.Fragment
import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.error.fatalError
@ -45,7 +45,6 @@ import im.vector.app.features.home.room.detail.RoomDetailActivity
import im.vector.app.features.home.room.detail.RoomDetailArgs
import im.vector.app.features.home.room.detail.search.SearchActivity
import im.vector.app.features.home.room.detail.search.SearchArgs
import im.vector.app.features.home.room.detail.widget.WidgetRequestCodes
import im.vector.app.features.home.room.filtered.FilteredRoomsActivity
import im.vector.app.features.invite.InviteUsersToRoomActivity
import im.vector.app.features.media.AttachmentData
@ -266,21 +265,32 @@ class DefaultNavigator @Inject constructor(
}
}
override fun openTerms(fragment: Fragment, serviceType: TermsService.ServiceType, baseUrl: String, token: String?, requestCode: Int) {
val intent = ReviewTermsActivity.intent(fragment.requireContext(), serviceType, baseUrl, token)
fragment.startActivityForResult(intent, requestCode)
override fun openTerms(context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
serviceType: TermsService.ServiceType,
baseUrl: String,
token: String?) {
val intent = ReviewTermsActivity.intent(context, serviceType, baseUrl, token)
activityResultLauncher.launch(intent)
}
override fun openStickerPicker(fragment: Fragment, roomId: String, widget: Widget, requestCode: Int) {
override fun openStickerPicker(context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
roomId: String,
widget: Widget) {
val widgetArgs = widgetArgsBuilder.buildStickerPickerArgs(roomId, widget)
val intent = WidgetActivity.newIntent(fragment.requireContext(), widgetArgs)
fragment.startActivityForResult(intent, WidgetRequestCodes.STICKER_PICKER_REQUEST_CODE)
val intent = WidgetActivity.newIntent(context, widgetArgs)
activityResultLauncher.launch(intent)
}
override fun openIntegrationManager(fragment: Fragment, roomId: String, integId: String?, screen: String?) {
override fun openIntegrationManager(context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
roomId: String,
integId: String?,
screen: String?) {
val widgetArgs = widgetArgsBuilder.buildIntegrationManagerArgs(roomId, integId, screen)
val intent = WidgetActivity.newIntent(fragment.requireContext(), widgetArgs)
fragment.startActivityForResult(intent, WidgetRequestCodes.INTEGRATION_MANAGER_REQUEST_CODE)
val intent = WidgetActivity.newIntent(context, widgetArgs)
activityResultLauncher.launch(intent)
}
override fun openRoomWidget(context: Context, roomId: String, widget: Widget, options: Map<String, Any>?) {
@ -293,9 +303,11 @@ class DefaultNavigator @Inject constructor(
}
}
override fun openPinCode(fragment: Fragment, pinMode: PinMode, requestCode: Int) {
val intent = PinActivity.newIntent(fragment.requireContext(), PinArgs(pinMode))
fragment.startActivityForResult(intent, requestCode)
override fun openPinCode(context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
pinMode: PinMode) {
val intent = PinActivity.newIntent(context, PinArgs(pinMode))
activityResultLauncher.launch(intent)
}
override fun openPinCode(activity: Activity, pinMode: PinMode, requestCode: Int) {

View File

@ -18,18 +18,17 @@ package im.vector.app.features.navigation
import android.app.Activity
import android.content.Context
import android.content.Intent
import android.view.View
import androidx.activity.result.ActivityResultLauncher
import androidx.core.util.Pair
import androidx.fragment.app.Fragment
import im.vector.app.features.crypto.recover.SetupMode
import im.vector.app.features.home.room.detail.widget.WidgetRequestCodes
import im.vector.app.features.media.AttachmentData
import im.vector.app.features.pin.PinActivity
import im.vector.app.features.pin.PinMode
import im.vector.app.features.roomdirectory.roompreview.RoomPreviewData
import im.vector.app.features.settings.VectorSettingsActivity
import im.vector.app.features.share.SharedData
import im.vector.app.features.terms.ReviewTermsActivity
import org.matrix.android.sdk.api.session.room.model.roomdirectory.PublicRoom
import org.matrix.android.sdk.api.session.room.model.thirdparty.RoomDirectoryData
import org.matrix.android.sdk.api.session.terms.TermsService
@ -84,22 +83,28 @@ interface Navigator {
fun openBigImageViewer(activity: Activity, sharedElement: View?, matrixItem: MatrixItem)
fun openPinCode(fragment: Fragment, pinMode: PinMode, requestCode: Int = PinActivity.PIN_REQUEST_CODE)
fun openPinCode(context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
pinMode: PinMode)
fun openPinCode(activity: Activity, pinMode: PinMode, requestCode: Int = PinActivity.PIN_REQUEST_CODE)
fun openTerms(fragment: Fragment,
fun openTerms(context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
serviceType: TermsService.ServiceType,
baseUrl: String,
token: String?,
requestCode: Int = ReviewTermsActivity.TERMS_REQUEST_CODE)
token: String?)
fun openStickerPicker(fragment: Fragment,
fun openStickerPicker(context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
roomId: String,
widget: Widget,
requestCode: Int = WidgetRequestCodes.STICKER_PICKER_REQUEST_CODE)
widget: Widget)
fun openIntegrationManager(fragment: Fragment, roomId: String, integId: String?, screen: String?)
fun openIntegrationManager(context: Context,
activityResultLauncher: ActivityResultLauncher<Intent>,
roomId: String,
integId: String?,
screen: String?)
fun openRoomWidget(context: Context, roomId: String, widget: Widget, options: Map<String, Any>? = null)

View File

@ -19,7 +19,7 @@ package im.vector.app.features.qrcode
import android.app.Activity
import android.content.Intent
import android.os.Bundle
import androidx.fragment.app.Fragment
import androidx.activity.result.ActivityResultLauncher
import com.google.zxing.BarcodeFormat
import com.google.zxing.Result
import com.google.zxing.ResultMetadataType
@ -82,8 +82,8 @@ class QrCodeScannerActivity : VectorBaseActivity() {
activity.startActivityForResult(Intent(activity, QrCodeScannerActivity::class.java), requestCode)
}
fun startForResult(fragment: Fragment, requestCode: Int = QR_CODE_SCANNER_REQUEST_CODE) {
fragment.startActivityForResult(Intent(fragment.requireActivity(), QrCodeScannerActivity::class.java), requestCode)
fun startForResult(activity: Activity, activityResultLauncher: ActivityResultLauncher<Intent>) {
activityResultLauncher.launch(Intent(activity, QrCodeScannerActivity::class.java))
}
fun getResultText(data: Intent?): String? {

View File

@ -212,10 +212,8 @@ class EmojiReactionPickerActivity : VectorBaseActivity(),
return intent
}
fun getOutput(data: Intent): Pair<String, String>? {
val eventId = data.getStringExtra(EXTRA_EVENT_ID) ?: return null
val reaction = data.getStringExtra(EXTRA_REACTION_RESULT) ?: return null
return eventId to reaction
}
fun getOutputEventId(data: Intent?): String? = data?.getStringExtra(EXTRA_EVENT_ID)
fun getOutputReaction(data: Intent?): String? = data?.getStringExtra(EXTRA_REACTION_RESULT)
}
}

View File

@ -42,6 +42,7 @@ import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.copyOnLongClick
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.core.intent.getFilenameFromUri
import im.vector.app.core.platform.VectorBaseFragment
@ -284,7 +285,7 @@ class RoomProfileFragment @Inject constructor(
.show()
}
private val takePhotoActivityResultLauncher = registerForPermissionsResult { allGranted ->
private val takePhotoPermissionActivityResultLauncher = registerForPermissionsResult { allGranted ->
if (allGranted) {
onAvatarTypeSelected(true)
}
@ -293,11 +294,11 @@ class RoomProfileFragment @Inject constructor(
private var avatarCameraUri: Uri? = null
private fun onAvatarTypeSelected(isCamera: Boolean) {
if (isCamera) {
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), takePhotoActivityResultLauncher)) {
avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(this)
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), takePhotoPermissionActivityResultLauncher)) {
avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(requireActivity(), takePhotoActivityResultLauncher)
}
} else {
MultiPicker.get(MultiPicker.IMAGE).single().startWith(this)
MultiPicker.get(MultiPicker.IMAGE).single().startWith(pickImageActivityResultLauncher)
}
}
@ -309,30 +310,37 @@ class RoomProfileFragment @Inject constructor(
.start(requireContext(), this)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
MultiPicker.REQUEST_CODE_TAKE_PHOTO -> {
private val takePhotoActivityResultLauncher = registerStartForActivityResult { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
avatarCameraUri?.let { uri ->
MultiPicker.get(MultiPicker.CAMERA)
.getTakenPhoto(requireContext(), requestCode, resultCode, uri)
.getTakenPhoto(requireContext(), uri)
?.let {
onRoomAvatarSelected(it)
}
}
}
MultiPicker.REQUEST_CODE_PICK_IMAGE -> {
}
private val pickImageActivityResultLauncher = registerStartForActivityResult { activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
MultiPicker
.get(MultiPicker.IMAGE)
.getSelectedFiles(requireContext(), requestCode, resultCode, data)
.getSelectedFiles(requireContext(), activityResult.data)
.firstOrNull()?.let {
onRoomAvatarSelected(it)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
UCrop.REQUEST_CROP -> data?.let { onAvatarCropped(UCrop.getOutput(it)) }
BigImageViewerActivity.REQUEST_CODE -> data?.let { onAvatarCropped(it.data) }
}
}
// TODO
super.onActivityResult(requestCode, resultCode, data)
}

View File

@ -41,6 +41,7 @@ import com.google.android.material.textfield.TextInputLayout
import com.yalantis.ucrop.UCrop
import im.vector.app.R
import im.vector.app.core.extensions.hideKeyboard
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.showPassword
import im.vector.app.core.intent.getFilenameFromUri
import im.vector.app.core.platform.SimpleTextWatcher
@ -278,81 +279,38 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
session.integrationManagerService().removeListener(integrationServiceListener)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_NEW_PHONE_NUMBER -> refreshPhoneNumbersList()
REQUEST_PHONEBOOK_COUNTRY -> onPhonebookCountryUpdate(data)
MultiPicker.REQUEST_CODE_TAKE_PHOTO -> {
private val attachmentPhotoActivityResultLauncher = registerStartForActivityResult {activityResult ->
if (activityResult.resultCode == Activity.RESULT_OK) {
avatarCameraUri?.let { uri ->
MultiPicker.get(MultiPicker.CAMERA)
.getTakenPhoto(requireContext(), requestCode, resultCode, uri)
.getTakenPhoto(requireContext(), uri)
?.let {
onAvatarSelected(it)
}
}
}
MultiPicker.REQUEST_CODE_PICK_IMAGE -> {
}
private val attachmentImageActivityResultLauncher = registerStartForActivityResult {activityResult ->
val data = activityResult.data ?: return@registerStartForActivityResult
if (activityResult.resultCode == Activity.RESULT_OK) {
MultiPicker
.get(MultiPicker.IMAGE)
.getSelectedFiles(requireContext(), requestCode, resultCode, data)
.getSelectedFiles(requireContext(), data)
.firstOrNull()?.let {
onAvatarSelected(it)
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
@Suppress("DEPRECATION")
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
// TODO Migrate this too
UCrop.REQUEST_CROP -> data?.let { onAvatarCropped(UCrop.getOutput(it)) }
/* TODO
VectorUtils.TAKE_IMAGE -> {
val thumbnailUri = VectorUtils.getThumbnailUriFromIntent(activity, data, session.mediaCache)
if (null != thumbnailUri) {
displayLoadingView()
val resource = ResourceUtils.openResource(activity, thumbnailUri, null)
if (null != resource) {
session.mediaCache.uploadContent(resource.mContentStream, null, resource.mMimeType, null, object : MXMediaUploadListener() {
override fun onUploadError(uploadId: String?, serverResponseCode: Int, serverErrorMessage: String?) {
activity?.runOnUiThread { onCommonDone(serverResponseCode.toString() + " : " + serverErrorMessage) }
}
override fun onUploadComplete(uploadId: String?, contentUri: String?) {
activity?.runOnUiThread {
session.myUser.updateAvatarUrl(contentUri, object : MatrixCallback<Unit> {
override fun onSuccess(info: Void?) {
onCommonDone(null)
refreshDisplay()
}
override fun onNetworkError(e: Exception) {
onCommonDone(e.localizedMessage)
}
override fun onMatrixError(e: MatrixError) {
if (MatrixError.M_CONSENT_NOT_GIVEN == e.errcode) {
activity?.runOnUiThread {
hideLoadingView()
(activity as VectorAppCompatActivity).consentNotGivenHelper.displayDialog(e)
}
} else {
onCommonDone(e.localizedMessage)
}
}
override fun onUnexpectedError(e: Exception) {
onCommonDone(e.localizedMessage)
}
})
}
}
})
}
}
}
*/
}
}
}
@ -400,10 +358,10 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
private fun onAvatarTypeSelected(isCamera: Boolean) {
if (isCamera) {
if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), takePhotoActivityResultLauncher)) {
avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(this)
avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(requireActivity(), attachmentPhotoActivityResultLauncher)
}
} else {
MultiPicker.get(MultiPicker.IMAGE).single().startWith(this)
MultiPicker.get(MultiPicker.IMAGE).single().startWith(attachmentImageActivityResultLauncher)
}
}
@ -461,29 +419,10 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
*/
}
private fun onPhonebookCountryUpdate(data: Intent?) {
/* TODO
if (data != null && data.hasExtra(CountryPickerActivity.EXTRA_OUT_COUNTRY_NAME)
&& data.hasExtra(CountryPickerActivity.EXTRA_OUT_COUNTRY_CODE)) {
val countryCode = data.getStringExtra(CountryPickerActivity.EXTRA_OUT_COUNTRY_CODE)
if (!TextUtils.equals(countryCode, PhoneNumberUtils.getCountryCode(activity))) {
PhoneNumberUtils.setCountryCode(activity, countryCode)
mContactPhonebookCountryPreference.summary = data.getStringExtra(CountryPickerActivity.EXTRA_OUT_COUNTRY_NAME)
}
}
*/
}
// ==============================================================================================================
// Phone number management
// ==============================================================================================================
/**
* Refresh phone number list
*/
private fun refreshPhoneNumbersList() {
}
/**
* Update the password.
*/
@ -643,9 +582,4 @@ class VectorSettingsGeneralFragment : VectorSettingsBaseFragment() {
})
}
}
companion object {
private const val REQUEST_NEW_PHONE_NUMBER = 456
private const val REQUEST_PHONEBOOK_COUNTRY = 789
}
}

View File

@ -16,14 +16,13 @@
package im.vector.app.features.settings
import android.content.Intent
import androidx.lifecycle.lifecycleScope
import androidx.preference.Preference
import androidx.preference.SwitchPreference
import im.vector.app.R
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.notifications.NotificationDrawerManager
import im.vector.app.features.pin.PinActivity
import im.vector.app.features.pin.PinCodeStore
import im.vector.app.features.pin.PinMode
import kotlinx.coroutines.launch
@ -67,17 +66,18 @@ class VectorSettingsPinFragment @Inject constructor(
refreshPinCodeStatus()
}
} else {
navigator.openPinCode(this@VectorSettingsPinFragment, PinMode.CREATE)
navigator.openPinCode(
requireContext(),
pinActivityResultLauncher,
PinMode.CREATE
)
}
true
}
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (requestCode == PinActivity.PIN_REQUEST_CODE) {
private val pinActivityResultLauncher = registerStartForActivityResult {
refreshPinCodeStatus()
}
}
}

View File

@ -39,6 +39,7 @@ import im.vector.app.R
import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.dialogs.ExportKeysDialog
import im.vector.app.core.extensions.queryExportKeys
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.extensions.showPassword
import im.vector.app.core.intent.ExternalIntentData
import im.vector.app.core.intent.analyseIntent
@ -55,7 +56,6 @@ import im.vector.app.features.crypto.keysbackup.settings.KeysBackupManageActivit
import im.vector.app.features.crypto.recover.BootstrapBottomSheet
import im.vector.app.features.crypto.recover.SetupMode
import im.vector.app.features.navigation.Navigator
import im.vector.app.features.pin.PinActivity
import im.vector.app.features.pin.PinCodeStore
import im.vector.app.features.pin.PinMode
import im.vector.app.features.raw.wellknown.getElementWellknown
@ -320,15 +320,10 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
}
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
when (requestCode) {
REQUEST_CODE_SAVE_MEGOLM_EXPORT -> {
val uri = data?.data
if (uri != null) {
activity?.let { activity ->
ExportKeysDialog().show(activity, object : ExportKeysDialog.ExportKeyDialogListener {
private val saveMegolmStartForActivityResult = registerStartForActivityResult {
val uri = it.data?.data ?: return@registerStartForActivityResult
if (it.resultCode == Activity.RESULT_OK)
ExportKeysDialog().show(requireActivity(), object : ExportKeysDialog.ExportKeyDialogListener {
override fun onPassphrase(passphrase: String) {
displayLoadingView()
@ -353,23 +348,28 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
}
})
}
}
}
PinActivity.PIN_REQUEST_CODE -> {
private val pinActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
doOpenPinCodePreferenceScreen()
}
REQUEST_E2E_FILE_REQUEST_CODE -> {
}
private val importKeysActivityResultLauncher = registerStartForActivityResult {
val data = it.data ?: return@registerStartForActivityResult
if (it.resultCode == Activity.RESULT_OK) {
importKeys(data)
}
}
}
}
private fun openPinCodePreferenceScreen() {
lifecycleScope.launchWhenResumed {
val hasPinCode = pinCodeStore.hasEncodedPin()
if (hasPinCode) {
navigator.openPinCode(this@VectorSettingsSecurityPrivacyFragment, PinMode.AUTH)
navigator.openPinCode(
requireContext(),
pinActivityResultLauncher,
PinMode.AUTH)
} else {
doOpenPinCodePreferenceScreen()
}
@ -391,7 +391,7 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
}
exportPref.onPreferenceClickListener = Preference.OnPreferenceClickListener {
queryExportKeys(activeSessionHolder.getSafeActiveSession()?.myUserId ?: "", REQUEST_CODE_SAVE_MEGOLM_EXPORT)
queryExportKeys(activeSessionHolder.getSafeActiveSession()?.myUserId ?: "", saveMegolmStartForActivityResult)
true
}
@ -406,7 +406,12 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
*/
@SuppressLint("NewApi")
private fun importKeys() {
activity?.let { openFileSelection(it, this, false, REQUEST_E2E_FILE_REQUEST_CODE) }
openFileSelection(
requireActivity(),
importKeysActivityResultLauncher,
false,
0
)
}
/**
@ -414,12 +419,7 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
*
* @param intent the intent result
*/
private fun importKeys(intent: Intent?) {
// sanity check
if (null == intent) {
return
}
private fun importKeys(intent: Intent) {
val sharedDataItems = analyseIntent(intent)
val thisActivity = activity
@ -605,9 +605,4 @@ class VectorSettingsSecurityPrivacyFragment @Inject constructor(
}
})
}
companion object {
private const val REQUEST_E2E_FILE_REQUEST_CODE = 123
private const val REQUEST_CODE_SAVE_MEGOLM_EXPORT = 124
}
}

View File

@ -33,6 +33,7 @@ import im.vector.app.core.di.ActiveSessionHolder
import im.vector.app.core.extensions.cleanup
import im.vector.app.core.extensions.configureWith
import im.vector.app.core.extensions.exhaustive
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.features.attachments.AttachmentsHelper
import im.vector.app.features.attachments.preview.AttachmentsPreviewActivity
@ -118,22 +119,18 @@ class IncomingShareFragment @Inject constructor(
private fun handleEditMediaBeforeSending(event: IncomingShareViewEvents.EditMediaBeforeSending) {
val intent = AttachmentsPreviewActivity.newIntent(requireContext(), AttachmentsPreviewArgs(event.contentAttachmentData))
startActivityForResult(intent, AttachmentsPreviewActivity.REQUEST_CODE)
attachmentPreviewActivityResultLauncher.launch(intent)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
val hasBeenHandled = attachmentsHelper.onActivityResult(requestCode, resultCode, data)
if (!hasBeenHandled && resultCode == Activity.RESULT_OK && data != null) {
when (requestCode) {
AttachmentsPreviewActivity.REQUEST_CODE -> {
private val attachmentPreviewActivityResultLauncher = registerStartForActivityResult {
val data = it.data ?: return@registerStartForActivityResult
if (it.resultCode == Activity.RESULT_OK) {
val sendData = AttachmentsPreviewActivity.getOutput(data)
val keepOriginalSize = AttachmentsPreviewActivity.getKeepOriginalSize(data)
viewModel.handle(IncomingShareAction.UpdateSharedData(SharedData.Attachments(sendData)))
viewModel.handle(IncomingShareAction.ShareMedia(keepOriginalSize))
}
}
}
}
private fun handleShareToRoom(event: IncomingShareViewEvents.ShareToRoom) {
if (event.showAlert) {

View File

@ -73,7 +73,6 @@ class ReviewTermsActivity : SimpleFragmentActivity() {
}
companion object {
const val TERMS_REQUEST_CODE = 15000
private const val EXTRA_INFO = "EXTRA_INFO"
fun intent(context: Context, serviceType: TermsService.ServiceType, baseUrl: String, token: String?): Intent {

View File

@ -37,11 +37,10 @@ import com.airbnb.mvrx.args
import com.airbnb.mvrx.withState
import org.matrix.android.sdk.api.session.terms.TermsService
import im.vector.app.R
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.OnBackPressed
import im.vector.app.core.platform.VectorBaseFragment
import im.vector.app.core.utils.openUrlInExternalBrowser
import im.vector.app.features.home.room.detail.widget.WidgetRequestCodes
import im.vector.app.features.terms.ReviewTermsActivity
import im.vector.app.features.webview.WebViewEventListener
import im.vector.app.features.widgets.webview.clearAfterWidget
import im.vector.app.features.widgets.webview.setupForWidget
@ -86,21 +85,20 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL
viewModel.handle(WidgetAction.LoadFormattedUrl)
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
when (requestCode) {
ReviewTermsActivity.TERMS_REQUEST_CODE -> {
private val termsActivityResultLauncher = registerStartForActivityResult {
Timber.v("On terms results")
if (resultCode == Activity.RESULT_OK) {
if (it.resultCode == Activity.RESULT_OK) {
viewModel.handle(WidgetAction.OnTermsReviewed)
} else {
vectorBaseActivity.finish()
}
}
WidgetRequestCodes.INTEGRATION_MANAGER_REQUEST_CODE -> {
private val integrationManagerActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
viewModel.handle(WidgetAction.LoadFormattedUrl)
}
}
}
override fun onDestroyView() {
super.onDestroyView()
@ -146,7 +144,12 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL
override fun onOptionsItemSelected(item: MenuItem): Boolean = withState(viewModel) { state ->
when (item.itemId) {
R.id.action_edit -> {
navigator.openIntegrationManager(this, state.roomId, state.widgetId, state.widgetKind.screenId)
navigator.openIntegrationManager(
requireContext(),
integrationManagerActivityResultLauncher,
state.roomId,
state.widgetId,
state.widgetKind.screenId)
return@withState true
}
R.id.action_delete -> {
@ -261,7 +264,8 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL
private fun displayTerms(displayTerms: WidgetViewEvents.DisplayTerms) {
navigator.openTerms(
fragment = this,
context = requireContext(),
activityResultLauncher = termsActivityResultLauncher,
serviceType = TermsService.ServiceType.IntegrationManager,
baseUrl = displayTerms.url,
token = displayTerms.token
@ -287,7 +291,8 @@ class WidgetFragment @Inject constructor() : VectorBaseFragment(), WebViewEventL
private fun displayIntegrationManager(event: WidgetViewEvents.DisplayIntegrationManager) {
navigator.openIntegrationManager(
fragment = this,
context = requireContext(),
activityResultLauncher = integrationManagerActivityResultLauncher,
roomId = fragmentArgs.roomId,
integId = event.integId,
screen = event.integType

View File

@ -18,7 +18,6 @@ package im.vector.app.features.workers.signout
import android.app.Activity
import android.app.Dialog
import android.content.Intent
import android.os.Bundle
import android.view.View
import android.view.ViewGroup
@ -39,6 +38,7 @@ import im.vector.app.R
import im.vector.app.core.di.ScreenComponent
import im.vector.app.core.dialogs.ExportKeysDialog
import im.vector.app.core.extensions.queryExportKeys
import im.vector.app.core.extensions.registerStartForActivityResult
import im.vector.app.core.platform.VectorBaseBottomSheetDialogFragment
import im.vector.app.features.crypto.keysbackup.setup.KeysBackupSetupActivity
import im.vector.app.features.crypto.recover.BootstrapBottomSheet
@ -77,9 +77,6 @@ class SignOutBottomSheetDialogFragment : VectorBaseBottomSheetDialogFragment(),
companion object {
fun newInstance() = SignOutBottomSheetDialogFragment()
private const val EXPORT_REQ = 0
private const val QUERY_EXPORT_KEYS = 1
}
init {
@ -130,12 +127,12 @@ class SignOutBottomSheetDialogFragment : VectorBaseBottomSheetDialogFragment(),
exportManuallyButton.action = {
withState(viewModel) { state ->
queryExportKeys(state.userId, QUERY_EXPORT_KEYS)
queryExportKeys(state.userId, manualExportKeysActivityResultLauncher)
}
}
setupMegolmBackupButton.action = {
startActivityForResult(KeysBackupSetupActivity.intent(requireContext(), true), EXPORT_REQ)
setupBackupActivityResultLauncher.launch(KeysBackupSetupActivity.intent(requireContext(), true))
}
viewModel.observeViewEvents {
@ -289,13 +286,10 @@ class SignOutBottomSheetDialogFragment : VectorBaseBottomSheetDialogFragment(),
return dialog
}
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK) {
if (requestCode == QUERY_EXPORT_KEYS) {
val uri = data?.data
if (resultCode == Activity.RESULT_OK && uri != null) {
private val manualExportKeysActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
val uri = it.data?.data
if (uri != null) {
activity?.let { activity ->
ExportKeysDialog().show(activity, object : ExportKeysDialog.ExportKeyDialogListener {
override fun onPassphrase(passphrase: String) {
@ -304,11 +298,14 @@ class SignOutBottomSheetDialogFragment : VectorBaseBottomSheetDialogFragment(),
})
}
}
} else if (requestCode == EXPORT_REQ) {
if (data?.getBooleanExtra(KeysBackupSetupActivity.MANUAL_EXPORT, false) == true) {
}
}
private val setupBackupActivityResultLauncher = registerStartForActivityResult {
if (it.resultCode == Activity.RESULT_OK) {
if (it.data?.getBooleanExtra(KeysBackupSetupActivity.MANUAL_EXPORT, false) == true) {
viewModel.handle(SignoutCheckViewModel.Actions.KeySuccessfullyManuallyExported)
}
}
}
}
}