mirror of
https://github.com/element-hq/element-android
synced 2024-11-28 13:38:49 +03:00
Propose to edit media before sending, when coming form another application
This commit is contained in:
parent
b7ec495d6b
commit
81de914360
20 changed files with 173 additions and 56 deletions
|
@ -51,16 +51,21 @@ interface SendService {
|
|||
/**
|
||||
* Method to send a media asynchronously.
|
||||
* @param attachment the media to send
|
||||
* @param compressBeforeSending set to true to compress media before sending them
|
||||
* @return a [Cancelable]
|
||||
*/
|
||||
fun sendMedia(attachment: ContentAttachmentData): Cancelable
|
||||
fun sendMedia(attachment: ContentAttachmentData,
|
||||
// TODO Change to a Compression Level Enum
|
||||
compressBeforeSending: Boolean): Cancelable
|
||||
|
||||
/**
|
||||
* Method to send a list of media asynchronously.
|
||||
* @param attachments the list of media to send
|
||||
* @return a [Cancelable]
|
||||
*/
|
||||
fun sendMedias(attachments: List<ContentAttachmentData>): Cancelable
|
||||
fun sendMedias(attachments: List<ContentAttachmentData>,
|
||||
// TODO Change to a Compression Level Enum
|
||||
compressBeforeSending: Boolean): Cancelable
|
||||
|
||||
/**
|
||||
* Send a poll to the room.
|
||||
|
|
|
@ -47,6 +47,7 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
|
|||
val event: Event,
|
||||
val attachment: ContentAttachmentData,
|
||||
val isRoomEncrypted: Boolean,
|
||||
val compressBeforeSending: Boolean,
|
||||
override val lastFailureMessage: String? = null
|
||||
) : SessionWorkerParams
|
||||
|
||||
|
@ -82,6 +83,8 @@ internal class UploadContentWorker(context: Context, params: WorkerParameters) :
|
|||
)
|
||||
}
|
||||
|
||||
// TODO Use compressBeforeSending
|
||||
|
||||
var uploadedThumbnailUrl: String? = null
|
||||
var uploadedThumbnailEncryptedFileInfo: EncryptedFileInfo? = null
|
||||
|
||||
|
|
|
@ -111,9 +111,9 @@ internal class DefaultSendService @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun sendMedias(attachments: List<ContentAttachmentData>): Cancelable {
|
||||
override fun sendMedias(attachments: List<ContentAttachmentData>, compressBeforeSending: Boolean): Cancelable {
|
||||
return attachments.mapTo(CancelableBag()) {
|
||||
sendMedia(it)
|
||||
sendMedia(it, compressBeforeSending)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -201,18 +201,18 @@ internal class DefaultSendService @AssistedInject constructor(
|
|||
}
|
||||
}
|
||||
|
||||
override fun sendMedia(attachment: ContentAttachmentData): Cancelable {
|
||||
override fun sendMedia(attachment: ContentAttachmentData, compressBeforeSending: Boolean): Cancelable {
|
||||
// Create an event with the media file path
|
||||
val event = localEchoEventFactory.createMediaEvent(roomId, attachment).also {
|
||||
createLocalEcho(it)
|
||||
}
|
||||
return internalSendMedia(event, attachment)
|
||||
return internalSendMedia(event, attachment, compressBeforeSending)
|
||||
}
|
||||
|
||||
private fun internalSendMedia(localEcho: Event, attachment: ContentAttachmentData): Cancelable {
|
||||
private fun internalSendMedia(localEcho: Event, attachment: ContentAttachmentData, compressBeforeSending: Boolean): Cancelable {
|
||||
val isRoomEncrypted = cryptoService.isRoomEncrypted(roomId)
|
||||
|
||||
val uploadWork = createUploadMediaWork(localEcho, attachment, isRoomEncrypted, startChain = true)
|
||||
val uploadWork = createUploadMediaWork(localEcho, attachment, isRoomEncrypted, compressBeforeSending, startChain = true)
|
||||
val sendWork = createSendEventWork(localEcho, false)
|
||||
|
||||
if (isRoomEncrypted) {
|
||||
|
@ -280,8 +280,9 @@ internal class DefaultSendService @AssistedInject constructor(
|
|||
private fun createUploadMediaWork(event: Event,
|
||||
attachment: ContentAttachmentData,
|
||||
isRoomEncrypted: Boolean,
|
||||
compressBeforeSending: Boolean,
|
||||
startChain: Boolean): OneTimeWorkRequest {
|
||||
val uploadMediaWorkerParams = UploadContentWorker.Params(sessionId, roomId, event, attachment, isRoomEncrypted)
|
||||
val uploadMediaWorkerParams = UploadContentWorker.Params(sessionId, roomId, event, attachment, isRoomEncrypted, compressBeforeSending)
|
||||
val uploadWorkData = WorkerParamsFactory.toData(uploadMediaWorkerParams)
|
||||
|
||||
return workManagerProvider.matrixOneTimeWorkRequestBuilder<UploadContentWorker>()
|
||||
|
|
|
@ -20,11 +20,16 @@ import android.content.Context
|
|||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.Fragment
|
||||
import com.kbeanie.multipicker.api.Picker.*
|
||||
import com.kbeanie.multipicker.api.Picker.PICK_AUDIO
|
||||
import com.kbeanie.multipicker.api.Picker.PICK_CONTACT
|
||||
import com.kbeanie.multipicker.api.Picker.PICK_FILE
|
||||
import com.kbeanie.multipicker.api.Picker.PICK_IMAGE_CAMERA
|
||||
import com.kbeanie.multipicker.api.Picker.PICK_IMAGE_DEVICE
|
||||
import com.kbeanie.multipicker.core.PickerManager
|
||||
import im.vector.matrix.android.BuildConfig
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.riotx.core.platform.Restorable
|
||||
import im.vector.riotx.features.attachments.AttachmentsHelper.Callback
|
||||
import timber.log.Timber
|
||||
|
||||
private const val CAPTURE_PATH_KEY = "CAPTURE_PATH_KEY"
|
||||
|
|
|
@ -16,7 +16,11 @@
|
|||
|
||||
package im.vector.riotx.features.attachments
|
||||
|
||||
import com.kbeanie.multipicker.api.entity.*
|
||||
import com.kbeanie.multipicker.api.entity.ChosenAudio
|
||||
import com.kbeanie.multipicker.api.entity.ChosenContact
|
||||
import com.kbeanie.multipicker.api.entity.ChosenFile
|
||||
import com.kbeanie.multipicker.api.entity.ChosenImage
|
||||
import com.kbeanie.multipicker.api.entity.ChosenVideo
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import timber.log.Timber
|
||||
|
||||
|
|
|
@ -21,7 +21,11 @@ import com.kbeanie.multipicker.api.callbacks.ContactPickerCallback
|
|||
import com.kbeanie.multipicker.api.callbacks.FilePickerCallback
|
||||
import com.kbeanie.multipicker.api.callbacks.ImagePickerCallback
|
||||
import com.kbeanie.multipicker.api.callbacks.VideoPickerCallback
|
||||
import com.kbeanie.multipicker.api.entity.*
|
||||
import com.kbeanie.multipicker.api.entity.ChosenAudio
|
||||
import com.kbeanie.multipicker.api.entity.ChosenContact
|
||||
import com.kbeanie.multipicker.api.entity.ChosenFile
|
||||
import com.kbeanie.multipicker.api.entity.ChosenImage
|
||||
import com.kbeanie.multipicker.api.entity.ChosenVideo
|
||||
|
||||
/**
|
||||
* This class delegates the PickerManager callbacks to an [AttachmentsHelper.Callback]
|
||||
|
|
|
@ -30,10 +30,11 @@ import im.vector.riotx.features.themes.ActivityOtherThemes
|
|||
class AttachmentsPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
|
||||
|
||||
companion object {
|
||||
const val REQUEST_CODE = 55
|
||||
|
||||
private const val EXTRA_FRAGMENT_ARGS = "EXTRA_FRAGMENT_ARGS"
|
||||
const val RESULT_NAME = "ATTACHMENTS_PREVIEW_RESULT"
|
||||
const val REQUEST_CODE = 55
|
||||
private const val ATTACHMENTS_PREVIEW_RESULT = "ATTACHMENTS_PREVIEW_RESULT"
|
||||
private const val KEEP_ORIGINAL_IMAGES_SIZE = "KEEP_ORIGINAL_IMAGES_SIZE"
|
||||
|
||||
fun newIntent(context: Context, args: AttachmentsPreviewArgs): Intent {
|
||||
return Intent(context, AttachmentsPreviewActivity::class.java).apply {
|
||||
|
@ -42,7 +43,11 @@ class AttachmentsPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
}
|
||||
|
||||
fun getOutput(intent: Intent): List<ContentAttachmentData> {
|
||||
return intent.getParcelableArrayListExtra(RESULT_NAME)
|
||||
return intent.getParcelableArrayListExtra(ATTACHMENTS_PREVIEW_RESULT)
|
||||
}
|
||||
|
||||
fun getKeepOriginalSize(intent: Intent): Boolean {
|
||||
return intent.getBooleanExtra(KEEP_ORIGINAL_IMAGES_SIZE, false)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -52,12 +57,20 @@ class AttachmentsPreviewActivity : VectorBaseActivity(), ToolbarConfigurable {
|
|||
|
||||
override fun initUiAndData() {
|
||||
if (isFirstCreation()) {
|
||||
val fragmentArgs: AttachmentsPreviewArgs = intent?.extras?.getParcelable(EXTRA_FRAGMENT_ARGS)
|
||||
?: return
|
||||
val fragmentArgs: AttachmentsPreviewArgs = intent?.extras?.getParcelable(EXTRA_FRAGMENT_ARGS) ?: return
|
||||
addFragment(R.id.simpleFragmentContainer, AttachmentsPreviewFragment::class.java, fragmentArgs)
|
||||
}
|
||||
}
|
||||
|
||||
fun setResultAndFinish(data: List<ContentAttachmentData>, keepOriginalImageSize: Boolean) {
|
||||
val resultIntent = Intent().apply {
|
||||
putParcelableArrayListExtra(ATTACHMENTS_PREVIEW_RESULT, ArrayList(data))
|
||||
putExtra(KEEP_ORIGINAL_IMAGES_SIZE, keepOriginalImageSize)
|
||||
}
|
||||
setResult(RESULT_OK, resultIntent)
|
||||
finish()
|
||||
}
|
||||
|
||||
override fun configure(toolbar: Toolbar) {
|
||||
configureToolbar(toolbar)
|
||||
}
|
||||
|
|
|
@ -54,7 +54,6 @@ import javax.inject.Inject
|
|||
|
||||
@Parcelize
|
||||
data class AttachmentsPreviewArgs(
|
||||
val roomId: String,
|
||||
val attachments: List<ContentAttachmentData>
|
||||
) : Parcelable
|
||||
|
||||
|
@ -133,11 +132,10 @@ class AttachmentsPreviewFragment @Inject constructor(
|
|||
}
|
||||
|
||||
private fun setResultAndFinish() = withState(viewModel) {
|
||||
val resultIntent = Intent().apply {
|
||||
putParcelableArrayListExtra(AttachmentsPreviewActivity.RESULT_NAME, ArrayList(it.attachments))
|
||||
}
|
||||
requireActivity().setResult(RESULT_OK, resultIntent)
|
||||
requireActivity().finish()
|
||||
(requireActivity() as? AttachmentsPreviewActivity)?.setResultAndFinish(
|
||||
it.attachments,
|
||||
attachmentPreviewerSendImageOriginalSize.isChecked
|
||||
)
|
||||
}
|
||||
|
||||
private fun applyInsets() {
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
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
|
||||
|
@ -25,7 +24,6 @@ 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<AttachmentsPreviewViewState, AttachmentsPreviewAction, AttachmentsPreviewViewEvents>(initialState) {
|
||||
|
|
|
@ -22,7 +22,8 @@ import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
|||
|
||||
data class AttachmentsPreviewViewState(
|
||||
val attachments: List<ContentAttachmentData>,
|
||||
val currentAttachmentIndex: Int = 0
|
||||
val currentAttachmentIndex: Int = 0,
|
||||
val sendImagesWithOriginalSize: Boolean = false
|
||||
) : MvRxState {
|
||||
|
||||
constructor(args: AttachmentsPreviewArgs) : this(attachments = args.attachments)
|
||||
|
|
|
@ -27,7 +27,7 @@ sealed class RoomDetailAction : VectorViewModelAction {
|
|||
data class UserIsTyping(val isTyping: Boolean) : RoomDetailAction()
|
||||
data class SaveDraft(val draft: String) : RoomDetailAction()
|
||||
data class SendMessage(val text: CharSequence, val autoMarkdown: Boolean) : RoomDetailAction()
|
||||
data class SendMedia(val attachments: List<ContentAttachmentData>) : RoomDetailAction()
|
||||
data class SendMedia(val attachments: List<ContentAttachmentData>, val compressBeforeSending: Boolean) : RoomDetailAction()
|
||||
data class TimelineEventTurnsVisible(val event: TimelineEvent) : RoomDetailAction()
|
||||
data class TimelineEventTurnsInvisible(val event: TimelineEvent) : RoomDetailAction()
|
||||
data class LoadMoreTimelineEvents(val direction: Timeline.Direction) : RoomDetailAction()
|
||||
|
|
|
@ -156,7 +156,6 @@ import io.reactivex.android.schedulers.AndroidSchedulers
|
|||
import io.reactivex.schedulers.Schedulers
|
||||
import kotlinx.android.parcel.Parcelize
|
||||
import kotlinx.android.synthetic.main.fragment_room_detail.*
|
||||
import kotlinx.android.synthetic.main.merge_composer_layout.*
|
||||
import kotlinx.android.synthetic.main.merge_composer_layout.view.*
|
||||
import kotlinx.android.synthetic.main.merge_overlay_waiting_view.*
|
||||
import org.commonmark.parser.Parser
|
||||
|
@ -306,7 +305,10 @@ class RoomDetailFragment @Inject constructor(
|
|||
is SharedData.Text -> {
|
||||
roomDetailViewModel.handle(RoomDetailAction.ExitSpecialMode(composerLayout.text.toString()))
|
||||
}
|
||||
is SharedData.Attachments -> roomDetailViewModel.handle(RoomDetailAction.SendMedia(sharedData.attachmentData))
|
||||
is SharedData.Attachments -> {
|
||||
// open share edition
|
||||
onContentAttachmentsReady(sharedData.attachmentData)
|
||||
}
|
||||
null -> Timber.v("No share data to process")
|
||||
}
|
||||
}
|
||||
|
@ -506,7 +508,8 @@ class RoomDetailFragment @Inject constructor(
|
|||
when (requestCode) {
|
||||
AttachmentsPreviewActivity.REQUEST_CODE -> {
|
||||
val sendData = AttachmentsPreviewActivity.getOutput(data)
|
||||
roomDetailViewModel.handle(RoomDetailAction.SendMedia(sendData))
|
||||
val keepOriginalSize = AttachmentsPreviewActivity.getKeepOriginalSize(data)
|
||||
roomDetailViewModel.handle(RoomDetailAction.SendMedia(sendData, keepOriginalSize))
|
||||
}
|
||||
REACTION_SELECT_REQUEST_CODE -> {
|
||||
val (eventId, reaction) = EmojiReactionPickerActivity.getOutput(data) ?: return
|
||||
|
@ -1351,11 +1354,11 @@ class RoomDetailFragment @Inject constructor(
|
|||
val previewable = attachments.filterPreviewables()
|
||||
val nonPreviewable = attachments.filterNonPreviewables()
|
||||
if (nonPreviewable.isNotEmpty()) {
|
||||
// Send the non previewable event right now (?)
|
||||
roomDetailViewModel.handle(RoomDetailAction.SendMedia(nonPreviewable))
|
||||
// Send the non previewable attachment right now (?)
|
||||
roomDetailViewModel.handle(RoomDetailAction.SendMedia(nonPreviewable, false))
|
||||
}
|
||||
if (previewable.isNotEmpty()) {
|
||||
val intent = AttachmentsPreviewActivity.newIntent(requireContext(), AttachmentsPreviewArgs(roomDetailArgs.roomId, previewable))
|
||||
val intent = AttachmentsPreviewActivity.newIntent(requireContext(), AttachmentsPreviewArgs(previewable))
|
||||
startActivityForResult(intent, AttachmentsPreviewActivity.REQUEST_CODE)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -579,10 +579,10 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro
|
|||
|
||||
if (maxUploadFileSize == HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN) {
|
||||
// Unknown limitation
|
||||
room.sendMedias(attachments)
|
||||
room.sendMedias(attachments, action.compressBeforeSending)
|
||||
} else {
|
||||
when (val tooBigFile = attachments.find { it.size > maxUploadFileSize }) {
|
||||
null -> room.sendMedias(attachments)
|
||||
null -> room.sendMedias(attachments, action.compressBeforeSending)
|
||||
else -> _viewEvents.post(RoomDetailViewEvents.FileTooBigError(
|
||||
tooBigFile.name ?: tooBigFile.path,
|
||||
tooBigFile.size,
|
||||
|
|
|
@ -19,9 +19,10 @@ package im.vector.riotx.features.share
|
|||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.riotx.core.platform.VectorViewModelAction
|
||||
|
||||
sealed class IncomingShareAction: VectorViewModelAction {
|
||||
sealed class IncomingShareAction : VectorViewModelAction {
|
||||
data class SelectRoom(val roomSummary: RoomSummary, val enableMultiSelect: Boolean) : IncomingShareAction()
|
||||
object ShareToSelectedRooms: IncomingShareAction()
|
||||
object ShareToSelectedRooms : IncomingShareAction()
|
||||
data class ShareMedia(val keepOriginalSize: Boolean) : IncomingShareAction()
|
||||
data class FilterWith(val filter: String) : IncomingShareAction()
|
||||
data class UpdateSharedData(val sharedData: SharedData): IncomingShareAction()
|
||||
data class UpdateSharedData(val sharedData: SharedData) : IncomingShareAction()
|
||||
}
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package im.vector.riotx.features.share
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.ClipDescription
|
||||
import android.content.Intent
|
||||
import android.os.Bundle
|
||||
|
@ -41,6 +42,8 @@ import im.vector.riotx.core.utils.PERMISSION_REQUEST_CODE_PICK_ATTACHMENT
|
|||
import im.vector.riotx.core.utils.allGranted
|
||||
import im.vector.riotx.core.utils.checkPermissions
|
||||
import im.vector.riotx.features.attachments.AttachmentsHelper
|
||||
import im.vector.riotx.features.attachments.preview.AttachmentsPreviewActivity
|
||||
import im.vector.riotx.features.attachments.preview.AttachmentsPreviewArgs
|
||||
import im.vector.riotx.features.login.LoginActivity
|
||||
import kotlinx.android.synthetic.main.fragment_incoming_share.*
|
||||
import javax.inject.Inject
|
||||
|
@ -98,11 +101,31 @@ class IncomingShareFragment @Inject constructor(
|
|||
}
|
||||
incomingShareViewModel.observeViewEvents {
|
||||
when (it) {
|
||||
is IncomingShareViewEvents.ShareToRoom -> handleShareToRoom(it)
|
||||
is IncomingShareViewEvents.ShareToRoom -> handleShareToRoom(it)
|
||||
is IncomingShareViewEvents.EditMediaBeforeSending -> handleEditMediaBeforeSending(it)
|
||||
}.exhaustive
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleEditMediaBeforeSending(event: IncomingShareViewEvents.EditMediaBeforeSending) {
|
||||
val intent = AttachmentsPreviewActivity.newIntent(requireContext(), AttachmentsPreviewArgs(event.contentAttachmentData))
|
||||
startActivityForResult(intent, AttachmentsPreviewActivity.REQUEST_CODE)
|
||||
}
|
||||
|
||||
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 -> {
|
||||
val sendData = AttachmentsPreviewActivity.getOutput(data)
|
||||
val keepOriginalSize = AttachmentsPreviewActivity.getKeepOriginalSize(data)
|
||||
incomingShareViewModel.handle(IncomingShareAction.UpdateSharedData(SharedData.Attachments(sendData)))
|
||||
incomingShareViewModel.handle(IncomingShareAction.ShareMedia(keepOriginalSize))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
|
||||
|
@ -189,7 +212,7 @@ class IncomingShareFragment @Inject constructor(
|
|||
}
|
||||
|
||||
override fun invalidate() = withState(incomingShareViewModel) {
|
||||
sendShareButton.isVisible = it.multiSelectionEnabled
|
||||
sendShareButton.isVisible = it.isInMultiSelectionMode
|
||||
incomingShareController.setData(it)
|
||||
}
|
||||
|
||||
|
|
|
@ -16,9 +16,11 @@
|
|||
|
||||
package im.vector.riotx.features.share
|
||||
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.api.session.room.model.RoomSummary
|
||||
import im.vector.riotx.core.platform.VectorViewEvents
|
||||
|
||||
sealed class IncomingShareViewEvents : VectorViewEvents {
|
||||
data class ShareToRoom(val roomSummary: RoomSummary, val sharedData: SharedData, val showAlert: Boolean) : IncomingShareViewEvents()
|
||||
data class EditMediaBeforeSending(val contentAttachmentData: List<ContentAttachmentData>) : IncomingShareViewEvents()
|
||||
}
|
||||
|
|
|
@ -24,12 +24,14 @@ import com.squareup.inject.assisted.Assisted
|
|||
import com.squareup.inject.assisted.AssistedInject
|
||||
import im.vector.matrix.android.api.query.QueryStringValue
|
||||
import im.vector.matrix.android.api.session.Session
|
||||
import im.vector.matrix.android.api.session.content.ContentAttachmentData
|
||||
import im.vector.matrix.android.api.session.room.model.Membership
|
||||
import im.vector.matrix.android.api.session.room.roomSummaryQueryParams
|
||||
import im.vector.matrix.rx.rx
|
||||
import im.vector.riotx.core.extensions.exhaustive
|
||||
import im.vector.riotx.core.platform.VectorViewModel
|
||||
import im.vector.riotx.features.home.room.list.BreadcrumbsRoomComparator
|
||||
import im.vector.riotx.features.attachments.filterNonPreviewables
|
||||
import im.vector.riotx.features.attachments.filterPreviewables
|
||||
import im.vector.riotx.features.home.room.list.ChronologicalRoomComparator
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
|
@ -92,6 +94,7 @@ class IncomingShareViewModel @AssistedInject constructor(@Assisted initialState:
|
|||
when (action) {
|
||||
is IncomingShareAction.SelectRoom -> handleSelectRoom(action)
|
||||
is IncomingShareAction.ShareToSelectedRooms -> handleShareToSelectedRooms()
|
||||
is IncomingShareAction.ShareMedia -> handleShareMediaToSelectedRooms(action)
|
||||
is IncomingShareAction.FilterWith -> handleFilter(action)
|
||||
is IncomingShareAction.UpdateSharedData -> handleUpdateSharedData(action)
|
||||
}.exhaustive
|
||||
|
@ -108,34 +111,70 @@ class IncomingShareViewModel @AssistedInject constructor(@Assisted initialState:
|
|||
private fun handleShareToSelectedRooms() = withState { state ->
|
||||
val sharedData = state.sharedData ?: return@withState
|
||||
if (state.selectedRoomIds.size == 1) {
|
||||
// In this case the edition of the media will be handled by the RoomDetailFragment
|
||||
val selectedRoomId = state.selectedRoomIds.first()
|
||||
val selectedRoom = state.roomSummaries()?.find { it.roomId == selectedRoomId } ?: return@withState
|
||||
_viewEvents.post(IncomingShareViewEvents.ShareToRoom(selectedRoom, sharedData, showAlert = false))
|
||||
} else {
|
||||
state.selectedRoomIds.forEach { roomId ->
|
||||
val room = session.getRoom(roomId)
|
||||
if (sharedData is SharedData.Text) {
|
||||
room?.sendTextMessage(sharedData.text)
|
||||
} else if (sharedData is SharedData.Attachments) {
|
||||
room?.sendMedias(sharedData.attachmentData)
|
||||
when (sharedData) {
|
||||
is SharedData.Text -> {
|
||||
state.selectedRoomIds.forEach { roomId ->
|
||||
val room = session.getRoom(roomId)
|
||||
room?.sendTextMessage(sharedData.text)
|
||||
}
|
||||
}
|
||||
is SharedData.Attachments -> {
|
||||
shareAttachments(sharedData.attachmentData, state.selectedRoomIds, proposeMediaEdition = true, compressMediaBeforeSending = false)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSelectRoom(action: IncomingShareAction.SelectRoom) = withState {
|
||||
if (it.multiSelectionEnabled) {
|
||||
val selectedRooms = it.selectedRoomIds
|
||||
private fun shareAttachments(attachmentData: List<ContentAttachmentData>,
|
||||
selectedRoomIds: Set<String>,
|
||||
proposeMediaEdition: Boolean,
|
||||
compressMediaBeforeSending: Boolean) {
|
||||
if (!proposeMediaEdition) {
|
||||
selectedRoomIds.forEach { roomId ->
|
||||
val room = session.getRoom(roomId)
|
||||
room?.sendMedias(attachmentData, compressMediaBeforeSending)
|
||||
}
|
||||
} else {
|
||||
val previewable = attachmentData.filterPreviewables()
|
||||
val nonPreviewable = attachmentData.filterNonPreviewables()
|
||||
if (nonPreviewable.isNotEmpty()) {
|
||||
// Send the non previewable attachment right now (?)
|
||||
selectedRoomIds.forEach { roomId ->
|
||||
val room = session.getRoom(roomId)
|
||||
room?.sendMedias(nonPreviewable, compressMediaBeforeSending)
|
||||
}
|
||||
}
|
||||
if (previewable.isNotEmpty()) {
|
||||
// In case of multiple share of media, edit them first
|
||||
_viewEvents.post(IncomingShareViewEvents.EditMediaBeforeSending(previewable))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleShareMediaToSelectedRooms(action: IncomingShareAction.ShareMedia) = withState { state ->
|
||||
(state.sharedData as? SharedData.Attachments)?.let {
|
||||
shareAttachments(it.attachmentData, state.selectedRoomIds, proposeMediaEdition = false, compressMediaBeforeSending = !action.keepOriginalSize)
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleSelectRoom(action: IncomingShareAction.SelectRoom) = withState { state ->
|
||||
if (state.isInMultiSelectionMode) {
|
||||
val selectedRooms = state.selectedRoomIds
|
||||
val newSelectedRooms = if (selectedRooms.contains(action.roomSummary.roomId)) {
|
||||
selectedRooms.minus(action.roomSummary.roomId)
|
||||
} else {
|
||||
selectedRooms.plus(action.roomSummary.roomId)
|
||||
}
|
||||
setState { copy(multiSelectionEnabled = newSelectedRooms.isNotEmpty(), selectedRoomIds = newSelectedRooms) }
|
||||
setState { copy(isInMultiSelectionMode = newSelectedRooms.isNotEmpty(), selectedRoomIds = newSelectedRooms) }
|
||||
} else if (action.enableMultiSelect) {
|
||||
setState { copy(multiSelectionEnabled = true, selectedRoomIds = setOf(action.roomSummary.roomId)) }
|
||||
setState { copy(isInMultiSelectionMode = true, selectedRoomIds = setOf(action.roomSummary.roomId)) }
|
||||
} else {
|
||||
val sharedData = it.sharedData ?: return@withState
|
||||
val sharedData = state.sharedData ?: return@withState
|
||||
_viewEvents.post(IncomingShareViewEvents.ShareToRoom(action.roomSummary, sharedData, showAlert = true))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,7 +26,7 @@ data class IncomingShareViewState(
|
|||
val roomSummaries: Async<List<RoomSummary>> = Uninitialized,
|
||||
val filteredRoomSummaries: Async<List<RoomSummary>> = Uninitialized,
|
||||
val selectedRoomIds: Set<String> = emptySet(),
|
||||
val multiSelectionEnabled: Boolean = false
|
||||
val isInMultiSelectionMode: Boolean = false
|
||||
) : MvRxState
|
||||
|
||||
|
||||
|
|
|
@ -39,11 +39,24 @@
|
|||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
app:layout_constraintBottom_toTopOf="@+id/attachmentPreviewerSendImageOriginalSize"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:itemCount="1"
|
||||
tools:listitem="@layout/item_attachment_miniature_preview" />
|
||||
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/attachmentPreviewerSendImageOriginalSize"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="8dp"
|
||||
android:textColor="@color/white"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
tools:itemCount="1"
|
||||
tools:listitem="@layout/item_attachment_miniature_preview" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/attachmentPreviewerMiniatureList"
|
||||
tools:text="@plurals/send_images_with_original_size" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
|
||||
|
|
|
@ -22,6 +22,10 @@
|
|||
<!-- BEGIN Strings added by Benoit -->
|
||||
<string name="message_action_item_redact">Remove…</string>
|
||||
<string name="share_confirm_room">Do you want to send this attachment to %1$s?</string>
|
||||
<plurals name="send_images_with_original_size">
|
||||
<item quantity="one">Send image with the original size</item>
|
||||
<item quantity="other">Send images with the original size</item>
|
||||
</plurals>
|
||||
<!-- END Strings added by Benoit -->
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue