From b7a7aa2f153ed9d48844d560562cd7b76ff9ec9a Mon Sep 17 00:00:00 2001 From: Ganard Date: Thu, 6 Feb 2020 18:42:18 +0100 Subject: [PATCH] Attachment: continue working on preview screen --- .../session/content/ContentAttachmentData.kt | 1 + vector/src/main/AndroidManifest.xml | 5 +- .../riotx/core/utils/SnapHelperUtils.kt | 76 +++++++++++ .../features/attachments/AttachmentsMapper.kt | 12 +- .../attachments/ContentAttachmentData.kt | 32 +++++ .../preview/AttachmentPreviewControllers.kt | 10 +- .../preview/AttachmentsPreviewAction.kt | 8 +- .../preview/AttachmentsPreviewActivity.kt | 16 ++- .../preview/AttachmentsPreviewFragment.kt | 129 ++++++++++++++++-- .../preview/AttachmentsPreviewViewModel.kt | 35 ++++- .../preview/AttachmentsPreviewViewState.kt | 3 +- .../home/room/detail/RoomDetailFragment.kt | 19 ++- .../features/themes/ActivityOtherThemes.kt | 6 + .../layout/fragment_attachments_preview.xml | 42 ++++-- .../res/menu/vector_attachments_preview.xml | 19 +++ .../src/main/res/values-v21/theme_common.xml | 16 +++ vector/src/main/res/values/theme_common.xml | 2 + 17 files changed, 385 insertions(+), 46 deletions(-) create mode 100644 vector/src/main/java/im/vector/riotx/core/utils/SnapHelperUtils.kt create mode 100644 vector/src/main/java/im/vector/riotx/features/attachments/ContentAttachmentData.kt create mode 100755 vector/src/main/res/menu/vector_attachments_preview.xml create mode 100644 vector/src/main/res/values-v21/theme_common.xml diff --git a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/content/ContentAttachmentData.kt b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/content/ContentAttachmentData.kt index 0d8ef2c52b..48dff4e56d 100644 --- a/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/content/ContentAttachmentData.kt +++ b/matrix-sdk-android/src/main/java/im/vector/matrix/android/api/session/content/ContentAttachmentData.kt @@ -29,6 +29,7 @@ data class ContentAttachmentData( val width: Long? = 0, val exifOrientation: Int = ExifInterface.ORIENTATION_UNDEFINED, val name: String? = null, + val queryUri: String, val path: String, val mimeType: String?, val type: Type diff --git a/vector/src/main/AndroidManifest.xml b/vector/src/main/AndroidManifest.xml index d1873b650e..9d7495ef23 100644 --- a/vector/src/main/AndroidManifest.xml +++ b/vector/src/main/AndroidManifest.xml @@ -143,7 +143,10 @@ - + + diff --git a/vector/src/main/java/im/vector/riotx/core/utils/SnapHelperUtils.kt b/vector/src/main/java/im/vector/riotx/core/utils/SnapHelperUtils.kt new file mode 100644 index 0000000000..70831730b4 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/core/utils/SnapHelperUtils.kt @@ -0,0 +1,76 @@ +/* + * 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.riotx.core.utils + +import androidx.recyclerview.widget.RecyclerView +import androidx.recyclerview.widget.SnapHelper + +interface OnSnapPositionChangeListener { + + fun onSnapPositionChange(position: Int) +} + +fun RecyclerView.attachSnapHelperWithListener( + snapHelper: SnapHelper, + behavior: SnapOnScrollListener.Behavior = SnapOnScrollListener.Behavior.NOTIFY_ON_SCROLL_STATE_IDLE, + onSnapPositionChangeListener: OnSnapPositionChangeListener) { + snapHelper.attachToRecyclerView(this) + val snapOnScrollListener = SnapOnScrollListener(snapHelper, behavior, onSnapPositionChangeListener) + addOnScrollListener(snapOnScrollListener) +} + +fun SnapHelper.getSnapPosition(recyclerView: RecyclerView): Int { + val layoutManager = recyclerView.layoutManager ?: return RecyclerView.NO_POSITION + val snapView = findSnapView(layoutManager) ?: return RecyclerView.NO_POSITION + return layoutManager.getPosition(snapView) +} + +class SnapOnScrollListener( + private val snapHelper: SnapHelper, + var behavior: Behavior = Behavior.NOTIFY_ON_SCROLL, + var onSnapPositionChangeListener: OnSnapPositionChangeListener? = null +) : RecyclerView.OnScrollListener() { + + enum class Behavior { + NOTIFY_ON_SCROLL, + NOTIFY_ON_SCROLL_STATE_IDLE + } + + private var snapPosition = RecyclerView.NO_POSITION + + override fun onScrolled(recyclerView: RecyclerView, dx: Int, dy: Int) { + if (behavior == Behavior.NOTIFY_ON_SCROLL) { + maybeNotifySnapPositionChange(recyclerView) + } + } + + override fun onScrollStateChanged(recyclerView: RecyclerView, newState: Int) { + if (behavior == Behavior.NOTIFY_ON_SCROLL_STATE_IDLE + && newState == RecyclerView.SCROLL_STATE_IDLE) { + maybeNotifySnapPositionChange(recyclerView) + } + } + + private fun maybeNotifySnapPositionChange(recyclerView: RecyclerView) { + val snapPosition = snapHelper.getSnapPosition(recyclerView) + val snapPositionChanged = this.snapPosition != snapPosition + if (snapPositionChanged) { + onSnapPositionChangeListener?.onSnapPositionChange(snapPosition) + this.snapPosition = snapPosition + } + } +} diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsMapper.kt b/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsMapper.kt index 4b51c548a7..c0009a7e49 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsMapper.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsMapper.kt @@ -37,7 +37,8 @@ fun ChosenFile.toContentAttachmentData(): ContentAttachmentData { type = mapType(), size = size, date = createdAt?.time ?: System.currentTimeMillis(), - name = displayName + name = displayName, + queryUri = queryUri ) } @@ -50,7 +51,8 @@ fun ChosenAudio.toContentAttachmentData(): ContentAttachmentData { size = size, date = createdAt?.time ?: System.currentTimeMillis(), name = displayName, - duration = duration + duration = duration, + queryUri = queryUri ) } @@ -74,7 +76,8 @@ fun ChosenImage.toContentAttachmentData(): ContentAttachmentData { height = height.toLong(), width = width.toLong(), exifOrientation = orientation, - date = createdAt?.time ?: System.currentTimeMillis() + date = createdAt?.time ?: System.currentTimeMillis(), + queryUri = queryUri ) } @@ -89,6 +92,7 @@ fun ChosenVideo.toContentAttachmentData(): ContentAttachmentData { height = height.toLong(), width = width.toLong(), duration = duration, - name = displayName + name = displayName, + queryUri = queryUri ) } diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/ContentAttachmentData.kt b/vector/src/main/java/im/vector/riotx/features/attachments/ContentAttachmentData.kt new file mode 100644 index 0000000000..ecd979f900 --- /dev/null +++ b/vector/src/main/java/im/vector/riotx/features/attachments/ContentAttachmentData.kt @@ -0,0 +1,32 @@ +/* + * 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.riotx.features.attachments + +import im.vector.matrix.android.api.session.content.ContentAttachmentData + +fun ContentAttachmentData.isPreviewable(): Boolean { + return type == ContentAttachmentData.Type.IMAGE || type == ContentAttachmentData.Type.VIDEO +} + +fun List.filterPreviewables(): List { + return filter { it.isPreviewable() } +} + +fun List.filterNonPreviewables(): List { + return filter { it.isPreviewable().not() } +} + diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentPreviewControllers.kt b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentPreviewControllers.kt index 9cef33d402..966bfe26cd 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentPreviewControllers.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentPreviewControllers.kt @@ -35,18 +35,18 @@ class AttachmentBigPreviewController @Inject constructor() : TypedEpoxyControlle class AttachmentMiniaturePreviewController @Inject constructor() : TypedEpoxyController() { interface Callback { - fun onAttachmentClicked(contentAttachmentData: ContentAttachmentData) + fun onAttachmentClicked(position: Int, contentAttachmentData: ContentAttachmentData) } var callback: Callback? = null override fun buildModels(data: AttachmentsPreviewViewState) { - data.attachments.forEach { + data.attachments.forEachIndexed { index, contentAttachmentData -> attachmentMiniaturePreviewItem { - id(it.path) - attachment(it) + id(contentAttachmentData.path) + attachment(contentAttachmentData) clickListener { _ -> - callback?.onAttachmentClicked(it) + callback?.onAttachmentClicked(index, contentAttachmentData) } } } diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewAction.kt b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewAction.kt index 61fb41a774..a016b71fab 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewAction.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewAction.kt @@ -19,4 +19,10 @@ package im.vector.riotx.features.attachments.preview import im.vector.riotx.core.platform.VectorViewModelAction -sealed class AttachmentsPreviewAction : VectorViewModelAction +sealed class AttachmentsPreviewAction : VectorViewModelAction { + object RemoveCurrentAttachment : AttachmentsPreviewAction() + data class SetCurrentAttachment(val index: Int): AttachmentsPreviewAction() + data class UpdatePathOfCurrentAttachment(val newPath: String): AttachmentsPreviewAction() + + +} diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewActivity.kt b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewActivity.kt index d8d19cd550..70dc0734ed 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewActivity.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewActivity.kt @@ -19,19 +19,20 @@ package im.vector.riotx.features.attachments.preview import android.content.Context import android.content.Intent -import android.os.Bundle -import android.view.WindowManager import androidx.appcompat.widget.Toolbar +import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.riotx.R import im.vector.riotx.core.extensions.addFragment import im.vector.riotx.core.platform.ToolbarConfigurable import im.vector.riotx.core.platform.VectorBaseActivity +import im.vector.riotx.features.themes.ActivityOtherThemes class AttachmentsPreviewActivity : VectorBaseActivity(), ToolbarConfigurable { companion object { private const val EXTRA_FRAGMENT_ARGS = "EXTRA_FRAGMENT_ARGS" + const val RESULT_NAME = "ATTACHMENTS_PREVIEW_RESULT" const val REQUEST_CODE = 55 fun newIntent(context: Context, args: AttachmentsPreviewArgs): Intent { @@ -39,15 +40,16 @@ class AttachmentsPreviewActivity : VectorBaseActivity(), ToolbarConfigurable { putExtra(EXTRA_FRAGMENT_ARGS, args) } } + + fun getOutput(intent: Intent): List { + return intent.getParcelableArrayListExtra(RESULT_NAME) + } } + override fun getOtherThemes() = ActivityOtherThemes.AttachmentsPreview + override fun getLayoutRes() = R.layout.activity_simple - override fun onCreate(savedInstanceState: Bundle?) { - window.setFlags(WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS, WindowManager.LayoutParams.FLAG_LAYOUT_NO_LIMITS) - super.onCreate(savedInstanceState) - } - override fun initUiAndData() { if (isFirstCreation()) { val fragmentArgs: AttachmentsPreviewArgs = intent?.extras?.getParcelable(EXTRA_FRAGMENT_ARGS) diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewFragment.kt b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewFragment.kt index 99280c3830..e13e7c6b60 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewFragment.kt @@ -17,24 +17,41 @@ package im.vector.riotx.features.attachments.preview +import android.app.Activity.RESULT_CANCELED +import android.app.Activity.RESULT_OK +import android.content.Intent import android.os.Bundle import android.os.Parcelable +import android.view.MenuItem import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.core.net.toUri +import androidx.core.view.ViewCompat +import androidx.core.view.updateLayoutParams +import androidx.core.view.updatePadding import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.PagerSnapHelper import com.airbnb.mvrx.args import com.airbnb.mvrx.fragmentViewModel import com.airbnb.mvrx.withState +import com.yalantis.ucrop.UCrop import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.riotx.R import im.vector.riotx.core.extensions.cleanup import im.vector.riotx.core.platform.VectorBaseFragment +import im.vector.riotx.core.utils.OnSnapPositionChangeListener +import im.vector.riotx.core.utils.SnapOnScrollListener +import im.vector.riotx.core.utils.attachSnapHelperWithListener import kotlinx.android.parcel.Parcelize import kotlinx.android.synthetic.main.fragment_attachments_preview.* +import timber.log.Timber +import java.io.File import javax.inject.Inject @Parcelize data class AttachmentsPreviewArgs( + val roomId: String, val attachments: List ) : Parcelable @@ -51,13 +68,107 @@ class AttachmentsPreviewFragment @Inject constructor( override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) + applyInsets() setupRecyclerViews() setupToolbar(attachmentPreviewerToolbar) + attachmentPreviewerSendButton.setOnClickListener { + setResultAndFinish() + } } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + if (resultCode == RESULT_OK) { + if (requestCode == UCrop.REQUEST_CROP && data != null) { + Timber.v("Crop success") + handleCropResult(data) + } + } + if (resultCode == UCrop.RESULT_ERROR) { + Timber.v("Crop error") + } + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.attachmentsPreviewRemoveAction -> { + handleRemoveAction() + true + } + R.id.attachmentsPreviewEditAction -> { + handleEditAction() + true + } + else -> { + super.onOptionsItemSelected(item) + } + } + } + + override fun getMenuRes() = R.menu.vector_attachments_preview + override fun onDestroyView() { super.onDestroyView() attachmentPreviewerMiniatureList.cleanup() + attachmentPreviewerBigList.cleanup() + } + + override fun invalidate() = withState(viewModel) { state -> + if (state.attachments.isEmpty()) { + requireActivity().setResult(RESULT_CANCELED) + requireActivity().finish() + } else { + attachmentMiniaturePreviewController.setData(state) + attachmentBigPreviewController.setData(state) + attachmentPreviewerBigList.scrollToPosition(state.currentAttachmentIndex) + attachmentPreviewerMiniatureList.scrollToPosition(state.currentAttachmentIndex) + } + } + + override fun onAttachmentClicked(position: Int, contentAttachmentData: ContentAttachmentData) { + viewModel.handle(AttachmentsPreviewAction.SetCurrentAttachment(position)) + } + + private fun setResultAndFinish() = withState(viewModel) { + val resultIntent = Intent().apply { + putParcelableArrayListExtra(AttachmentsPreviewActivity.RESULT_NAME, ArrayList(it.attachments)) + } + requireActivity().setResult(RESULT_OK, resultIntent) + requireActivity().finish() + } + + private fun applyInsets() { + view?.systemUiVisibility = View.SYSTEM_UI_FLAG_LAYOUT_STABLE or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION + ViewCompat.setOnApplyWindowInsetsListener(attachmentPreviewerBottomContainer) { v, insets -> + v.updatePadding(bottom = insets.systemWindowInsetBottom) + insets + } + ViewCompat.setOnApplyWindowInsetsListener(attachmentPreviewerToolbar) { v, insets -> + v.updateLayoutParams { + topMargin = insets.systemWindowInsetTop + } + insets + } + } + + private fun handleCropResult(result: Intent) { + val resultPath = UCrop.getOutput(result)?.path + if (resultPath != null) { + viewModel.handle(AttachmentsPreviewAction.UpdatePathOfCurrentAttachment(resultPath)) + } else { + Toast.makeText(requireContext(), "Cannot retrieve cropped value", Toast.LENGTH_SHORT).show() + } + } + + private fun handleRemoveAction() { + viewModel.handle(AttachmentsPreviewAction.RemoveCurrentAttachment) + } + + private fun handleEditAction() = withState(viewModel) { + val currentAttachment = it.attachments.getOrNull(it.currentAttachmentIndex) ?: return@withState + val destinationFile = File(requireContext().cacheDir, "${currentAttachment.name}_edited_image_${System.currentTimeMillis()}") + UCrop.of(currentAttachment.queryUri.toUri(), destinationFile.toUri()) + .withOptions(UCrop.Options()) + .start(requireContext(), this) } private fun setupRecyclerViews() { @@ -67,20 +178,12 @@ class AttachmentsPreviewFragment @Inject constructor( attachmentMiniaturePreviewController.callback = this attachmentPreviewerBigList.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false) - val snapHelper = PagerSnapHelper() - snapHelper.attachToRecyclerView(attachmentPreviewerBigList) + attachmentPreviewerBigList.attachSnapHelperWithListener(PagerSnapHelper(), SnapOnScrollListener.Behavior.NOTIFY_ON_SCROLL_STATE_IDLE, object : OnSnapPositionChangeListener { + override fun onSnapPositionChange(position: Int) { + viewModel.handle(AttachmentsPreviewAction.SetCurrentAttachment(position)) + } + }) attachmentPreviewerBigList.setHasFixedSize(true) attachmentPreviewerBigList.adapter = attachmentBigPreviewController.adapter - } - - override fun invalidate() = withState(viewModel) { state -> - attachmentMiniaturePreviewController.setData(state) - attachmentBigPreviewController.setData(state) - } - - override fun onAttachmentClicked(contentAttachmentData: ContentAttachmentData) { - - } - } diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewViewModel.kt b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewViewModel.kt index 28a0aaebd6..b3be853eea 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewViewModel.kt @@ -17,12 +17,15 @@ package im.vector.riotx.features.attachments.preview +import androidx.lifecycle.viewModelScope import com.airbnb.mvrx.FragmentViewModelContext import com.airbnb.mvrx.MvRxViewModelFactory import com.airbnb.mvrx.ViewModelContext import com.squareup.inject.assisted.Assisted import com.squareup.inject.assisted.AssistedInject +import im.vector.riotx.core.extensions.exhaustive import im.vector.riotx.core.platform.VectorViewModel +import kotlinx.coroutines.launch class AttachmentsPreviewViewModel @AssistedInject constructor(@Assisted initialState: AttachmentsPreviewViewState) : VectorViewModel(initialState) { @@ -42,6 +45,36 @@ class AttachmentsPreviewViewModel @AssistedInject constructor(@Assisted initialS } override fun handle(action: AttachmentsPreviewAction) { - //TODO + when (action) { + is AttachmentsPreviewAction.SetCurrentAttachment -> handleSetCurrentAttachment(action) + is AttachmentsPreviewAction.UpdatePathOfCurrentAttachment -> handleUpdatePathOfCurrentAttachment(action) + AttachmentsPreviewAction.RemoveCurrentAttachment -> handleRemoveCurrentAttachment() + }.exhaustive + } + + private fun handleRemoveCurrentAttachment() = withState { + val currentAttachment = it.attachments.getOrNull(it.currentAttachmentIndex) ?: return@withState + val attachments = it.attachments.minusElement(currentAttachment) + val newAttachmentIndex = it.currentAttachmentIndex.coerceAtMost(attachments.size - 1) + setState { + copy(attachments = attachments, currentAttachmentIndex = newAttachmentIndex) + } + } + + private fun handleUpdatePathOfCurrentAttachment(action: AttachmentsPreviewAction.UpdatePathOfCurrentAttachment) = withState { + val attachments = it.attachments.mapIndexed { index, contentAttachmentData -> + if (index == it.currentAttachmentIndex) { + contentAttachmentData.copy(path = action.newPath) + } else { + contentAttachmentData + } + } + setState { + copy(attachments = attachments) + } + } + + private fun handleSetCurrentAttachment(action: AttachmentsPreviewAction.SetCurrentAttachment) = setState { + copy(currentAttachmentIndex = action.index) } } diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewViewState.kt b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewViewState.kt index f92abb97ea..feb1a32210 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewViewState.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/preview/AttachmentsPreviewViewState.kt @@ -21,7 +21,8 @@ import com.airbnb.mvrx.MvRxState import im.vector.matrix.android.api.session.content.ContentAttachmentData data class AttachmentsPreviewViewState( - val attachments: List + val attachments: List, + val currentAttachmentIndex: Int = 0 ) : MvRxState { constructor(args: AttachmentsPreviewArgs) : this(attachments = args.attachments) diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt index 1caada8ce6..f63f82ca26 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailFragment.kt @@ -116,6 +116,8 @@ import im.vector.riotx.core.utils.toast import im.vector.riotx.features.attachments.AttachmentTypeSelectorView import im.vector.riotx.features.attachments.AttachmentsHelper import im.vector.riotx.features.attachments.ContactAttachment +import im.vector.riotx.features.attachments.filterNonPreviewables +import im.vector.riotx.features.attachments.filterPreviewables import im.vector.riotx.features.attachments.preview.AttachmentsPreviewActivity import im.vector.riotx.features.attachments.preview.AttachmentsPreviewArgs import im.vector.riotx.features.command.Command @@ -502,7 +504,11 @@ class RoomDetailFragment @Inject constructor( val hasBeenHandled = attachmentsHelper.onActivityResult(requestCode, resultCode, data) if (!hasBeenHandled && resultCode == RESULT_OK && data != null) { when (requestCode) { - REACTION_SELECT_REQUEST_CODE -> { + AttachmentsPreviewActivity.REQUEST_CODE -> { + val sendData = AttachmentsPreviewActivity.getOutput(data) + roomDetailViewModel.handle(RoomDetailAction.SendMedia(sendData)) + } + REACTION_SELECT_REQUEST_CODE -> { val (eventId, reaction) = EmojiReactionPickerActivity.getOutput(data) ?: return roomDetailViewModel.handle(RoomDetailAction.SendReaction(eventId, reaction)) } @@ -1342,8 +1348,15 @@ class RoomDetailFragment @Inject constructor( // AttachmentsHelper.Callback override fun onContentAttachmentsReady(attachments: List) { - val intent = AttachmentsPreviewActivity.newIntent(requireContext(), AttachmentsPreviewArgs(attachments)) - startActivityForResult(intent, AttachmentsPreviewActivity.REQUEST_CODE) + val previewable = attachments.filterPreviewables() + val nonPreviewable = attachments.filterNonPreviewables() + if (nonPreviewable.isNotEmpty()) { + roomDetailViewModel.handle(RoomDetailAction.SendMedia(nonPreviewable)) + } + if (previewable.isNotEmpty()) { + val intent = AttachmentsPreviewActivity.newIntent(requireContext(), AttachmentsPreviewArgs(roomDetailArgs.roomId, previewable)) + startActivityForResult(intent, AttachmentsPreviewActivity.REQUEST_CODE) + } } override fun onAttachmentsProcessFailed() { diff --git a/vector/src/main/java/im/vector/riotx/features/themes/ActivityOtherThemes.kt b/vector/src/main/java/im/vector/riotx/features/themes/ActivityOtherThemes.kt index 411069e9ca..b37c1a4818 100644 --- a/vector/src/main/java/im/vector/riotx/features/themes/ActivityOtherThemes.kt +++ b/vector/src/main/java/im/vector/riotx/features/themes/ActivityOtherThemes.kt @@ -32,4 +32,10 @@ sealed class ActivityOtherThemes(@StyleRes val dark: Int, R.style.AppTheme_Black, R.style.AppTheme_Status ) + + object AttachmentsPreview : ActivityOtherThemes( + R.style.AppTheme_AttachmentsPreview, + R.style.AppTheme_AttachmentsPreview, + R.style.AppTheme_AttachmentsPreview + ) } diff --git a/vector/src/main/res/layout/fragment_attachments_preview.xml b/vector/src/main/res/layout/fragment_attachments_preview.xml index 5acc8835b0..bcb5d682c4 100644 --- a/vector/src/main/res/layout/fragment_attachments_preview.xml +++ b/vector/src/main/res/layout/fragment_attachments_preview.xml @@ -1,37 +1,59 @@ + android:layout_height="match_parent"> + app:layout_constraintTop_toTopOf="parent" + tools:listitem="@layout/item_attachment_big_preview" /> - + app:layout_constraintStart_toStartOf="parent"> + + + + + + diff --git a/vector/src/main/res/menu/vector_attachments_preview.xml b/vector/src/main/res/menu/vector_attachments_preview.xml new file mode 100755 index 0000000000..4adf9dcff9 --- /dev/null +++ b/vector/src/main/res/menu/vector_attachments_preview.xml @@ -0,0 +1,19 @@ + + + + + + + + diff --git a/vector/src/main/res/values-v21/theme_common.xml b/vector/src/main/res/values-v21/theme_common.xml new file mode 100644 index 0000000000..155c73acdc --- /dev/null +++ b/vector/src/main/res/values-v21/theme_common.xml @@ -0,0 +1,16 @@ + + + + + + + + + \ No newline at end of file diff --git a/vector/src/main/res/values/theme_common.xml b/vector/src/main/res/values/theme_common.xml index 159b2ecb55..151d97c097 100644 --- a/vector/src/main/res/values/theme_common.xml +++ b/vector/src/main/res/values/theme_common.xml @@ -8,4 +8,6 @@ @color/primary_color_dark +