diff --git a/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt b/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt new file mode 100644 index 0000000000..769ec45dac --- /dev/null +++ b/vector/src/main/java/im/vector/app/core/dialogs/GalleryOrCameraDialogHelper.kt @@ -0,0 +1,103 @@ +/* + * 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.core.dialogs + +import android.app.Activity +import android.net.Uri +import androidx.appcompat.app.AlertDialog +import androidx.fragment.app.Fragment +import im.vector.app.R +import im.vector.app.core.extensions.registerStartForActivityResult +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.lib.multipicker.MultiPicker +import im.vector.lib.multipicker.entity.MultiPickerImageType + +class GalleryOrCameraDialogHelper( + private val fragment: Fragment +) { + interface Listener { + fun onImageReady(image: MultiPickerImageType) + } + + private val activity by lazy { fragment.requireActivity() } + + private val listener: Listener = fragment as? Listener ?: error("Fragment must implements GalleryOrCameraDialogHelper.Listener") + + private val takePhotoPermissionActivityResultLauncher = fragment.registerForPermissionsResult { allGranted -> + if (allGranted) { + doOpenCamera() + } + } + + private val takePhotoActivityResultLauncher = fragment.registerStartForActivityResult { activityResult -> + if (activityResult.resultCode == Activity.RESULT_OK) { + avatarCameraUri?.let { uri -> + MultiPicker.get(MultiPicker.CAMERA) + .getTakenPhoto(fragment.requireContext(), uri) + ?.let { + listener.onImageReady(it) + } + } + } + } + + private val pickImageActivityResultLauncher = fragment.registerStartForActivityResult { activityResult -> + if (activityResult.resultCode == Activity.RESULT_OK) { + MultiPicker + .get(MultiPicker.IMAGE) + .getSelectedFiles(fragment.requireContext(), activityResult.data) + .firstOrNull()?.let { + listener.onImageReady(it) + } + } + } + + private enum class Type { + Gallery, + Camera + } + + fun show() { + AlertDialog.Builder(fragment.requireContext()) + .setItems(arrayOf( + fragment.getString(R.string.attachment_type_camera), + fragment.getString(R.string.attachment_type_gallery) + )) { dialog, which -> + dialog.cancel() + onAvatarTypeSelected(if (which == 0) Type.Camera else Type.Gallery) + } + .show() + } + + private fun onAvatarTypeSelected(type: Type) { + when (type) { + Type.Gallery -> + MultiPicker.get(MultiPicker.IMAGE).single().startWith(pickImageActivityResultLauncher) + Type.Camera -> + if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, activity, takePhotoPermissionActivityResultLauncher)) { + avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(fragment.requireContext(), takePhotoActivityResultLauncher) + } + } + } + + private var avatarCameraUri: Uri? = null + private fun doOpenCamera() { + avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(activity, takePhotoActivityResultLauncher) + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt index c2f25c08d3..814efcee82 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/RoomProfileFragment.kt @@ -38,6 +38,7 @@ import com.yalantis.ucrop.UCrop import im.vector.app.R import im.vector.app.core.animations.AppBarStateChangeListener import im.vector.app.core.animations.MatrixItemAppBarStateChangeListener +import im.vector.app.core.dialogs.GalleryOrCameraDialogHelper import im.vector.app.core.extensions.cleanup import im.vector.app.core.extensions.configureWith import im.vector.app.core.extensions.copyOnLongClick @@ -46,10 +47,7 @@ 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 -import im.vector.app.core.utils.PERMISSIONS_FOR_TAKING_PHOTO -import im.vector.app.core.utils.checkPermissions import im.vector.app.core.utils.copyToClipboard -import im.vector.app.core.utils.registerForPermissionsResult import im.vector.app.core.utils.startSharePlainTextIntent import im.vector.app.features.crypto.util.toImageRes import im.vector.app.features.home.AvatarRenderer @@ -59,7 +57,6 @@ import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedA import im.vector.app.features.home.room.list.actions.RoomListQuickActionsSharedActionViewModel import im.vector.app.features.media.BigImageViewerActivity import im.vector.app.features.media.createUCropWithDefaultSettings -import im.vector.lib.multipicker.MultiPicker import im.vector.lib.multipicker.entity.MultiPickerImageType import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_matrix_profile.* @@ -80,7 +77,9 @@ class RoomProfileFragment @Inject constructor( private val roomProfileController: RoomProfileController, private val avatarRenderer: AvatarRenderer, val roomProfileViewModelFactory: RoomProfileViewModel.Factory -) : VectorBaseFragment(), RoomProfileController.Callback { +) : VectorBaseFragment(), + RoomProfileController.Callback, + GalleryOrCameraDialogHelper.Listener { private val roomProfileArgs: RoomProfileArgs by args() private lateinit var roomListQuickActionsSharedActionViewModel: RoomListQuickActionsSharedActionViewModel @@ -93,6 +92,8 @@ class RoomProfileFragment @Inject constructor( override fun getMenuRes() = R.menu.vector_room_profile + private val galleryOrCameraDialogHelper = GalleryOrCameraDialogHelper(this) + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) roomListQuickActionsSharedActionViewModel = activityViewModelProvider.get(RoomListQuickActionsSharedActionViewModel::class.java) @@ -272,40 +273,12 @@ class RoomProfileFragment @Inject constructor( val options = ActivityOptionsCompat.makeSceneTransitionAnimation(requireActivity(), view, ViewCompat.getTransitionName(view) ?: "") bigImageStartForActivityResult.launch(intent, options) } else if (it.canChangeAvatar) { - showAvatarSelector() + galleryOrCameraDialogHelper.show() } } - private fun showAvatarSelector() { - AlertDialog.Builder(requireContext()) - .setItems(arrayOf( - getString(R.string.attachment_type_camera), - getString(R.string.attachment_type_gallery) - )) { dialog, which -> - dialog.cancel() - onAvatarTypeSelected(isCamera = (which == 0)) - } - .show() - } - private val takePhotoPermissionActivityResultLauncher = registerForPermissionsResult { allGranted -> - if (allGranted) { - onAvatarTypeSelected(true) - } - } - - private var avatarCameraUri: Uri? = null - private fun onAvatarTypeSelected(isCamera: Boolean) { - if (isCamera) { - if (checkPermissions(PERMISSIONS_FOR_TAKING_PHOTO, requireActivity(), takePhotoPermissionActivityResultLauncher)) { - avatarCameraUri = MultiPicker.get(MultiPicker.CAMERA).startWithExpectingFile(requireActivity(), takePhotoActivityResultLauncher) - } - } else { - MultiPicker.get(MultiPicker.IMAGE).single().startWith(pickImageActivityResultLauncher) - } - } - - private fun onRoomAvatarSelected(image: MultiPickerImageType) { + override fun onImageReady(image: MultiPickerImageType) { val destinationFile = File(requireContext().cacheDir, "${image.displayName}_edited_image_${System.currentTimeMillis()}") val uri = image.contentUri createUCropWithDefaultSettings(requireContext(), uri, destinationFile.toUri(), image.displayName) @@ -313,29 +286,6 @@ class RoomProfileFragment @Inject constructor( .start(requireContext(), this) } - private val takePhotoActivityResultLauncher = registerStartForActivityResult { activityResult -> - if (activityResult.resultCode == Activity.RESULT_OK) { - avatarCameraUri?.let { uri -> - MultiPicker.get(MultiPicker.CAMERA) - .getTakenPhoto(requireContext(), uri) - ?.let { - onRoomAvatarSelected(it) - } - } - } - } - - private val pickImageActivityResultLauncher = registerStartForActivityResult { activityResult -> - if (activityResult.resultCode == Activity.RESULT_OK) { - MultiPicker - .get(MultiPicker.IMAGE) - .getSelectedFiles(requireContext(), activityResult.data) - .firstOrNull()?.let { - onRoomAvatarSelected(it) - } - } - } - private val bigImageStartForActivityResult = registerStartForActivityResult { activityResult -> if (activityResult.resultCode == Activity.RESULT_OK) { activityResult.data?.let { onAvatarCropped(it.data) }