diff --git a/build.gradle b/build.gradle index 9d87774f3c..14522b33fd 100644 --- a/build.gradle +++ b/build.gradle @@ -12,7 +12,7 @@ buildscript { } } dependencies { - classpath 'com.android.tools.build:gradle:3.5.0' + classpath 'com.android.tools.build:gradle:3.5.1' classpath 'com.google.gms:google-services:4.3.2' classpath "com.airbnb.okreplay:gradle-plugin:1.5.0" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" diff --git a/vector/build.gradle b/vector/build.gradle index e6e5667b94..70be341557 100644 --- a/vector/build.gradle +++ b/vector/build.gradle @@ -320,6 +320,7 @@ dependencies { // File picker implementation 'com.github.jaiselrahman:FilePicker:1.2.2' + implementation 'com.kbeanie:multipicker:1.6@aar' // DI implementation "com.google.dagger:dagger:$daggerVersion" diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/Attachment.kt b/vector/src/main/java/im/vector/riotx/features/attachments/Attachment.kt deleted file mode 100644 index 37640ad179..0000000000 --- a/vector/src/main/java/im/vector/riotx/features/attachments/Attachment.kt +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2019 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.riotx.core.resources.MIME_TYPE_ALL_CONTENT - -data class Attachment(val path: String, - val mimeType: String, - val name: String? = "", - val width: Long? = 0, - val height: Long? = 0, - val size: Long = 0, - val duration: Long? = 0, - val date: Long = 0) { - - val type: Int - get() { - if (mimeType == null) { - return TYPE_FILE - } - return when { - mimeType.startsWith("image/") -> TYPE_IMAGE - mimeType.startsWith("video/") -> TYPE_VIDEO - mimeType.startsWith("audio/") - -> TYPE_AUDIO - else -> TYPE_FILE - } - } - - companion object { - val TYPE_FILE = 0 - val TYPE_IMAGE = 1 - val TYPE_AUDIO = 2 - val TYPE_VIDEO = 3 - } -} \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsHelper.kt b/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsHelper.kt index 042ec7da79..444835cf9e 100644 --- a/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsHelper.kt +++ b/vector/src/main/java/im/vector/riotx/features/attachments/AttachmentsHelper.kt @@ -15,138 +15,174 @@ */ package im.vector.riotx.features.attachments -import android.content.ActivityNotFoundException -import android.content.Context +import android.app.Activity import android.content.Intent -import android.net.Uri -import android.os.Environment -import android.provider.MediaStore -import android.provider.OpenableColumns -import androidx.core.content.FileProvider +import android.os.Bundle import androidx.fragment.app.Fragment -import im.vector.riotx.BuildConfig -import im.vector.riotx.core.resources.MIME_TYPE_ALL_CONTENT -import timber.log.Timber -import java.io.File -import java.io.IOException -import java.text.SimpleDateFormat -import java.util.* +import com.kbeanie.multipicker.api.CameraImagePicker +import com.kbeanie.multipicker.api.FilePicker +import com.kbeanie.multipicker.api.ImagePicker +import com.kbeanie.multipicker.api.Picker.* +import com.kbeanie.multipicker.api.callbacks.FilePickerCallback +import com.kbeanie.multipicker.api.callbacks.ImagePickerCallback +import com.kbeanie.multipicker.api.entity.ChosenFile +import com.kbeanie.multipicker.api.entity.ChosenImage +import com.kbeanie.multipicker.api.entity.ChosenVideo +import com.kbeanie.multipicker.core.PickerManager +import im.vector.matrix.android.api.session.content.ContentAttachmentData +import im.vector.riotx.core.platform.Restorable +private const val CAPTURE_PATH_KEY = "CAPTURE_PATH_KEY" -class AttachmentsHelper(private val context: Context) { +class AttachmentsHelper(private val fragment: Fragment, private val callback: Callback) : Restorable { - private var capturePath: String? = null - - fun selectFile(fragment: Fragment, requestCode: Int) { - selectMediaType(fragment, "*/*", null, requestCode) + interface Callback { + fun onAttachmentsReady(attachments: List) + fun onAttachmentsProcessFailed() } - fun selectGallery(fragment: Fragment, requestCode: Int) { - selectMediaType(fragment, "image/*", arrayOf("image/*", "video/*"), requestCode) - } + private val attachmentsPickerCallback = AttachmentsPickerCallback(callback) - fun openCamera(fragment: Fragment, requestCode: Int) { - dispatchTakePictureIntent(fragment, requestCode) - } - - - fun handleOpenCameraResult(): List { - val attachment = getAttachmentFromContentResolver(Uri.parse(capturePath)) - return if (attachment == null) { - emptyList() - } else { - listOf(attachment) + private val imagePicker by lazy { + ImagePicker(fragment).also { + it.setImagePickerCallback(attachmentsPickerCallback) + it.allowMultiple() } } - fun handleSelectResult(data: Intent?): List { - val clipData = data?.clipData - if (clipData != null) { - return (0 until clipData.itemCount).map { - clipData.getItemAt(it) - }.mapNotNull { - getAttachmentFromContentResolver(it.uri) + private val cameraImagePicker by lazy { + CameraImagePicker(fragment).also { + it.setImagePickerCallback(attachmentsPickerCallback) + } + } + + private val filePicker by lazy { + FilePicker(fragment).also { + it.allowMultiple() + it.setFilePickerCallback(attachmentsPickerCallback) + } + } + + override fun onSaveInstanceState(outState: Bundle) { + capturePath?.also { + outState.putString(CAPTURE_PATH_KEY, it) + } + } + + override fun onRestoreInstanceState(savedInstanceState: Bundle?) { + capturePath = savedInstanceState?.getString(CAPTURE_PATH_KEY) + } + + var capturePath: String? = null + private set + + fun selectFile() { + filePicker.pickFile() + } + + fun selectGallery() { + imagePicker.pickImage() + } + + fun openCamera() { + capturePath = cameraImagePicker.pickImage() + } + + fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?): Boolean { + if (resultCode == Activity.RESULT_OK) { + val pickerManager = getPickerManager(requestCode) + if (pickerManager != null) { + pickerManager.submit(data) + return true } - } else { - val uri = data?.data ?: return emptyList() - val attachment = getAttachmentFromContentResolver(uri) - return if (attachment == null) { - emptyList() + } + return false + } + + private fun getPickerManager(requestCode: Int): PickerManager? { + return when (requestCode) { + PICK_IMAGE_DEVICE -> imagePicker + PICK_IMAGE_CAMERA -> cameraImagePicker + PICK_FILE -> filePicker + else -> null + } + } + + private inner class AttachmentsPickerCallback(private val callback: Callback) : ImagePickerCallback, FilePickerCallback { + + override fun onFilesChosen(files: MutableList?) { + if (files.isNullOrEmpty()) { + callback.onAttachmentsProcessFailed() } else { - listOf(attachment) + val attachments = files.map { + it.toContentAttachmentData() + } + callback.onAttachmentsReady(attachments) } } - } - private fun selectMediaType(fragment: Fragment, type: String, extraMimeType: Array?, requestCode: Int) { - val intent = Intent() - intent.type = type - intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true) - if (extraMimeType != null) { - intent.putExtra(Intent.EXTRA_MIME_TYPES, extraMimeType) - } - intent.action = Intent.ACTION_OPEN_DOCUMENT - try { - fragment.startActivityForResult(intent, requestCode) - return - } catch (exception: ActivityNotFoundException) { - Timber.e(exception) - } - intent.action = Intent.ACTION_GET_CONTENT - try { - fragment.startActivityForResult(intent, requestCode) - } catch (exception: ActivityNotFoundException) { - Timber.e(exception) - } - } - - private fun getAttachmentFromContentResolver(uri: Uri): Attachment? { - return context.contentResolver.query(uri, null, null, null, null)?.use { - if (it.moveToFirst()) { - val fileName = it.getString(it.getColumnIndex(OpenableColumns.DISPLAY_NAME)) - val fileSize = it.getLong(it.getColumnIndex(OpenableColumns.SIZE)) - val mimeType = context.contentResolver.getType(uri) ?: MIME_TYPE_ALL_CONTENT - Attachment(uri.toString(), mimeType, fileName, fileSize) + override fun onImagesChosen(images: MutableList?) { + if (images.isNullOrEmpty()) { + callback.onAttachmentsProcessFailed() } else { - null + val attachments = images.map { + it.toContentAttachmentData() + } + callback.onAttachmentsReady(attachments) } } + + override fun onError(error: String?) { + callback.onAttachmentsProcessFailed() + } } - @Throws(IOException::class) - private fun createImageFile(context: Context): File { - val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss").format(Date()) - val imageFileName = "JPEG_" + timeStamp + "_" - val storageDir = context.getExternalFilesDir(Environment.DIRECTORY_PICTURES) - val image = File.createTempFile( - imageFileName, /* prefix */ - ".jpg", /* suffix */ - storageDir /* directory */ + private fun ChosenFile.toContentAttachmentData(): ContentAttachmentData { + return ContentAttachmentData( + path = originalPath, + mimeType = mimeType, + type = mapType(), + size = size, + date = createdAt.time, + name = displayName ) - // Save a file: path for use with ACTION_VIEW intents - capturePath = image.absolutePath - return image } - private fun dispatchTakePictureIntent(fragment: Fragment, requestCode: Int) { - val takePictureIntent = Intent(MediaStore.ACTION_IMAGE_CAPTURE) - // Ensure that there's a camera activity to handle the intent - if (takePictureIntent.resolveActivity(fragment.requireActivity().packageManager) != null) { - // Create the File where the photo should go - var photoFile: File? = null - try { - photoFile = createImageFile(fragment.requireContext()) - } catch (ex: IOException) { - Timber.e(ex, "Couldn't create image file") - } - // Continue only if the File was successfully created - if (photoFile != null) { - val photoURI = FileProvider.getUriForFile(fragment.requireContext(), BuildConfig.APPLICATION_ID + ".fileProvider", photoFile) - takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT, photoURI) - fragment.startActivityForResult(takePictureIntent, requestCode) - } + private fun ChosenFile.mapType(): ContentAttachmentData.Type { + return when { + mimeType.startsWith("image/") -> ContentAttachmentData.Type.IMAGE + mimeType.startsWith("video/") -> ContentAttachmentData.Type.VIDEO + mimeType.startsWith("audio/") -> ContentAttachmentData.Type.AUDIO + else -> ContentAttachmentData.Type.FILE } } + private fun ChosenImage.toContentAttachmentData(): ContentAttachmentData { + return ContentAttachmentData( + path = originalPath, + mimeType = mimeType, + type = mapType(), + name = displayName, + size = size, + height = height.toLong(), + width = width.toLong(), + date = createdAt.time + ) + } + + private fun ChosenVideo.toContentAttachmentData(): ContentAttachmentData { + return ContentAttachmentData( + path = originalPath, + mimeType = mimeType, + type = ContentAttachmentData.Type.VIDEO, + size = size, + date = createdAt.time, + height = height.toLong(), + width = width.toLong(), + duration = duration, + name = displayName + ) + } + } \ No newline at end of file diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailActions.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailActions.kt index da11e0fbc3..630511ed20 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailActions.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailActions.kt @@ -16,17 +16,17 @@ package im.vector.riotx.features.home.room.detail +import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.model.message.MessageFileContent import im.vector.matrix.android.api.session.room.timeline.Timeline import im.vector.matrix.android.api.session.room.timeline.TimelineEvent -import im.vector.riotx.features.attachments.Attachment sealed class RoomDetailActions { data class SaveDraft(val draft: String) : RoomDetailActions() data class SendMessage(val text: String, val autoMarkdown: Boolean) : RoomDetailActions() - data class SendMedia(val attachments: List) : RoomDetailActions() + data class SendMedia(val attachments: List) : RoomDetailActions() data class TimelineEventTurnsVisible(val event: TimelineEvent) : RoomDetailActions() data class TimelineEventTurnsInvisible(val event: TimelineEvent) : RoomDetailActions() data class LoadMoreTimelineEvents(val direction: Timeline.Direction) : RoomDetailActions() 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 f543868656..99a2531de6 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 @@ -49,13 +49,12 @@ import com.airbnb.mvrx.* import com.github.piasy.biv.BigImageViewer import com.github.piasy.biv.loader.ImageLoader import com.google.android.material.snackbar.Snackbar -import com.jaiselrahman.filepicker.activity.FilePickerActivity -import com.jaiselrahman.filepicker.model.MediaFile import com.otaliastudios.autocomplete.Autocomplete import com.otaliastudios.autocomplete.AutocompleteCallback import com.otaliastudios.autocomplete.CharPolicy import im.vector.matrix.android.api.permalinks.PermalinkFactory import im.vector.matrix.android.api.session.Session +import im.vector.matrix.android.api.session.content.ContentAttachmentData import im.vector.matrix.android.api.session.events.model.Event import im.vector.matrix.android.api.session.room.model.Membership import im.vector.matrix.android.api.session.room.model.message.* @@ -125,10 +124,7 @@ data class RoomDetailArgs( ) : Parcelable -private const val REQUEST_CODE_SELECT_FILE = 1 -private const val REQUEST_CODE_SELECT_GALLERY = 2 -private const val REQUEST_CODE_OPEN_CAMERA = 3 -private const val REACTION_SELECT_REQUEST_CODE = 4 +private const val REACTION_SELECT_REQUEST_CODE = 0 class RoomDetailFragment : VectorBaseFragment(), @@ -136,7 +132,8 @@ class RoomDetailFragment : AutocompleteUserPresenter.Callback, VectorInviteView.Callback, JumpToReadMarkerView.Callback, - AttachmentTypeSelectorView.Callback { + AttachmentTypeSelectorView.Callback, + AttachmentsHelper.Callback { companion object { @@ -198,7 +195,15 @@ class RoomDetailFragment : private lateinit var actionViewModel: ActionsHandler private lateinit var layoutManager: LinearLayoutManager - private lateinit var attachmentsHelper: AttachmentsHelper + + private lateinit var _attachmentsHelper: AttachmentsHelper + private val attachmentsHelper: AttachmentsHelper + get() { + if (::_attachmentsHelper.isInitialized.not()) { + _attachmentsHelper = AttachmentsHelper(this, this).register() + } + return _attachmentsHelper + } @BindView(R.id.composerLayout) lateinit var composerLayout: TextComposerView @@ -213,7 +218,6 @@ class RoomDetailFragment : override fun onActivityCreated(savedInstanceState: Bundle?) { super.onActivityCreated(savedInstanceState) actionViewModel = ViewModelProviders.of(requireActivity()).get(ActionsHandler::class.java) - attachmentsHelper = AttachmentsHelper((requireActivity())) setupToolbar(roomToolbar) setupRecyclerView() setupComposer() @@ -302,9 +306,9 @@ class RoomDetailFragment : AlertDialog.Builder(requireActivity()) .setTitle(R.string.dialog_title_error) .setMessage(getString(R.string.error_file_too_big, - error.filename, - TextUtils.formatFileSize(requireContext(), error.fileSizeInBytes), - TextUtils.formatFileSize(requireContext(), error.homeServerLimitInBytes) + error.filename, + TextUtils.formatFileSize(requireContext(), error.fileSizeInBytes), + TextUtils.formatFileSize(requireContext(), error.homeServerLimitInBytes) )) .setPositiveButton(R.string.ok, null) .show() @@ -381,11 +385,11 @@ class RoomDetailFragment : if (messageContent is MessageTextContent && messageContent.format == MessageType.FORMAT_MATRIX_HTML) { val parser = Parser.builder().build() val document = parser.parse(messageContent.formattedBody - ?: messageContent.body) + ?: messageContent.body) formattedBody = eventHtmlRenderer.render(document) } composerLayout.composerRelatedMessageContent.text = formattedBody - ?: nonFormattedBody + ?: nonFormattedBody updateComposerText(defaultContent) @@ -394,11 +398,11 @@ class RoomDetailFragment : avatarRenderer.render(event.senderAvatar, event.root.senderId - ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar) + ?: "", event.senderName, composerLayout.composerRelatedMessageAvatar) avatarRenderer.render(event.senderAvatar, - event.root.senderId ?: "", - event.senderName, - composerLayout.composerRelatedMessageAvatar) + event.root.senderId ?: "", + event.senderName, + composerLayout.composerRelatedMessageAvatar) composerLayout.expand { //need to do it here also when not using quick reply focusComposerAndShowKeyboard() @@ -430,31 +434,22 @@ class RoomDetailFragment : } override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { - if (resultCode == RESULT_OK) { - if (requestCode == REQUEST_CODE_OPEN_CAMERA) { - val attachments = attachmentsHelper.handleOpenCameraResult() - roomDetailViewModel.process(RoomDetailActions.SendMedia(attachments)) - } else if (data != null) { - when (requestCode) { - REQUEST_CODE_SELECT_FILE, - REQUEST_CODE_SELECT_GALLERY -> { - val attachments = attachmentsHelper.handleSelectResult(data) - roomDetailViewModel.process(RoomDetailActions.SendMedia(attachments)) - } - REACTION_SELECT_REQUEST_CODE -> { - val eventId = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_EVENT_ID) - ?: return - val reaction = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_REACTION_RESULT) - ?: return - //TODO check if already reacted with that? - roomDetailViewModel.process(RoomDetailActions.SendReaction(reaction, eventId)) - } + val hasBeenHandled = attachmentsHelper.onActivityResult(requestCode, resultCode, data) + if (!hasBeenHandled && resultCode == RESULT_OK && data != null) { + when (requestCode) { + REACTION_SELECT_REQUEST_CODE -> { + val eventId = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_EVENT_ID) + ?: return + val reaction = data.getStringExtra(EmojiReactionPickerActivity.EXTRA_REACTION_RESULT) + ?: return + //TODO check if already reacted with that? + roomDetailViewModel.process(RoomDetailActions.SendReaction(reaction, eventId)) } } } } - // PRIVATE METHODS ***************************************************************************** +// PRIVATE METHODS ***************************************************************************** private fun setupRecyclerView() { @@ -1086,7 +1081,7 @@ class RoomDetailFragment : } -// VectorInviteView.Callback + // VectorInviteView.Callback override fun onAcceptInvite() { notificationDrawerManager.clearMemberShipNotificationForRoom(roomDetailArgs.roomId) @@ -1098,7 +1093,7 @@ class RoomDetailFragment : roomDetailViewModel.process(RoomDetailActions.RejectInvite) } -// JumpToReadMarkerView.Callback + // JumpToReadMarkerView.Callback override fun onJumpToReadMarkerClicked(readMarkerId: String) { roomDetailViewModel.process(RoomDetailActions.NavigateToEvent(readMarkerId, false)) @@ -1108,14 +1103,25 @@ class RoomDetailFragment : roomDetailViewModel.process(RoomDetailActions.MarkAllAsRead) } -// AttachmentTypeSelectorView.Callback ********************************************************* + // AttachmentTypeSelectorView.Callback override fun onTypeSelected(type: Int) { when (type) { - AttachmentTypeSelectorView.TYPE_CAMERA -> attachmentsHelper.openCamera(this, REQUEST_CODE_OPEN_CAMERA) - AttachmentTypeSelectorView.TYPE_FILE -> attachmentsHelper.selectFile(this, REQUEST_CODE_SELECT_FILE) - AttachmentTypeSelectorView.TYPE_GALLERY -> attachmentsHelper.selectGallery(this, REQUEST_CODE_SELECT_GALLERY) + AttachmentTypeSelectorView.TYPE_CAMERA -> attachmentsHelper.openCamera() + AttachmentTypeSelectorView.TYPE_FILE -> attachmentsHelper.selectFile() + AttachmentTypeSelectorView.TYPE_GALLERY -> attachmentsHelper.selectGallery() AttachmentTypeSelectorView.TYPE_STICKER -> vectorBaseActivity.notImplemented("Adding stickers") } } + + // AttachmentsHelper.Callback + + override fun onAttachmentsReady(attachments: List) { + Timber.v("onAttachmentsReady") + roomDetailViewModel.process(RoomDetailActions.SendMedia(attachments)) + } + + override fun onAttachmentsProcessFailed() { + Timber.v("onAttachmentsProcessFailed") + } } diff --git a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt index e86238bd8b..f0c17cad4f 100644 --- a/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt +++ b/vector/src/main/java/im/vector/riotx/features/home/room/detail/RoomDetailViewModel.kt @@ -178,23 +178,23 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro copy( // Create a sendMode from a draft and retrieve the TimelineEvent sendMode = when (draft) { - is UserDraft.REGULAR -> SendMode.REGULAR(draft.text) - is UserDraft.QUOTE -> { - room.getTimeLineEvent(draft.linkedEventId)?.let { timelineEvent -> - SendMode.QUOTE(timelineEvent, draft.text) - } - } - is UserDraft.REPLY -> { - room.getTimeLineEvent(draft.linkedEventId)?.let { timelineEvent -> - SendMode.REPLY(timelineEvent, draft.text) - } - } - is UserDraft.EDIT -> { - room.getTimeLineEvent(draft.linkedEventId)?.let { timelineEvent -> - SendMode.EDIT(timelineEvent, draft.text) - } - } - } ?: SendMode.REGULAR("") + is UserDraft.REGULAR -> SendMode.REGULAR(draft.text) + is UserDraft.QUOTE -> { + room.getTimeLineEvent(draft.linkedEventId)?.let { timelineEvent -> + SendMode.QUOTE(timelineEvent, draft.text) + } + } + is UserDraft.REPLY -> { + room.getTimeLineEvent(draft.linkedEventId)?.let { timelineEvent -> + SendMode.REPLY(timelineEvent, draft.text) + } + } + is UserDraft.EDIT -> { + room.getTimeLineEvent(draft.linkedEventId)?.let { timelineEvent -> + SendMode.EDIT(timelineEvent, draft.text) + } + } + } ?: SendMode.REGULAR("") ) } } @@ -203,7 +203,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro private fun handleTombstoneEvent(action: RoomDetailActions.HandleTombstoneEvent) { val tombstoneContent = action.event.getClearContent().toModel() - ?: return + ?: return val roomId = tombstoneContent.replacementRoom ?: "" val isRoomJoined = session.getRoom(roomId)?.roomSummary()?.membership == Membership.JOIN @@ -337,7 +337,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro is SendMode.EDIT -> { //is original event a reply? val inReplyTo = state.sendMode.timelineEvent.root.getClearContent().toModel()?.relatesTo?.inReplyTo?.eventId - ?: state.sendMode.timelineEvent.root.content.toModel()?.relatesTo?.inReplyTo?.eventId + ?: state.sendMode.timelineEvent.root.content.toModel()?.relatesTo?.inReplyTo?.eventId if (inReplyTo != null) { //TODO check if same content? room.getTimeLineEvent(inReplyTo)?.let { @@ -346,13 +346,13 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro } else { val messageContent: MessageContent? = state.sendMode.timelineEvent.annotations?.editSummary?.aggregatedContent.toModel() - ?: state.sendMode.timelineEvent.root.getClearContent().toModel() + ?: state.sendMode.timelineEvent.root.getClearContent().toModel() val existingBody = messageContent?.body ?: "" if (existingBody != action.text) { room.editTextMessage(state.sendMode.timelineEvent.root.eventId ?: "", - messageContent?.type ?: MessageType.MSGTYPE_TEXT, - action.text, - action.autoMarkdown) + messageContent?.type ?: MessageType.MSGTYPE_TEXT, + action.text, + action.autoMarkdown) } else { Timber.w("Same message content, do not send edition") } @@ -363,7 +363,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro is SendMode.QUOTE -> { val messageContent: MessageContent? = state.sendMode.timelineEvent.annotations?.editSummary?.aggregatedContent.toModel() - ?: state.sendMode.timelineEvent.root.getClearContent().toModel() + ?: state.sendMode.timelineEvent.root.getClearContent().toModel() val textMsg = messageContent?.body val finalText = legacyRiotQuoteText(textMsg, action.text) @@ -466,24 +466,8 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro } private fun handleSendMedia(action: RoomDetailActions.SendMedia) { - val attachments = action.attachments.map { - val nameWithExtension = getFilenameFromUri(null, Uri.parse(it.path)) - - ContentAttachmentData( - size = it.size, - duration = it.duration, - date = it.date, - height = it.height, - width = it.width, - name = nameWithExtension ?: it.name, - path = it.path, - mimeType = it.mimeType, - type = ContentAttachmentData.Type.values()[it.type] - ) - } - + val attachments = action.attachments val homeServerCapabilities = session.getHomeServerCapabilities() - val maxUploadFileSize = homeServerCapabilities.maxUploadFileSize if (maxUploadFileSize == HomeServerCapabilities.MAX_UPLOAD_FILE_SIZE_UNKNOWN) { @@ -493,7 +477,7 @@ class RoomDetailViewModel @AssistedInject constructor(@Assisted initialState: Ro when (val tooBigFile = attachments.find { it.size > maxUploadFileSize }) { null -> room.sendMedias(attachments) else -> _fileTooBigEvent.postValue(LiveEvent(FileTooBigError(tooBigFile.name - ?: tooBigFile.path, tooBigFile.size, maxUploadFileSize))) + ?: tooBigFile.path, tooBigFile.size, maxUploadFileSize))) } } }