From 7af9fe6da2d7de4d9029ca0f5e15c3c7ea6a0d06 Mon Sep 17 00:00:00 2001 From: Danil Nikolaev Date: Mon, 11 Oct 2021 12:08:28 +0300 Subject: [PATCH] editing messages --- .../kotlin/com/meloda/fast/api/VKConstants.kt | 13 ++ .../kotlin/com/meloda/fast/api/VkUtils.kt | 24 ++++ .../com/meloda/fast/api/model/VkMessage.kt | 45 ++----- .../api/model/attachments/VkAttachment.kt | 6 +- .../fast/api/model/attachments/VkAudio.kt | 13 +- .../fast/api/model/attachments/VkFile.kt | 13 +- .../fast/api/model/attachments/VkPhoto.kt | 9 ++ .../fast/api/model/attachments/VkVideo.kt | 13 +- .../api/model/base/attachments/BaseVkAudio.kt | 6 +- .../api/model/base/attachments/BaseVkFile.kt | 6 +- .../api/model/base/attachments/BaseVkVideo.kt | 6 +- .../com/meloda/fast/api/network/VkUrls.kt | 1 + .../network/messages/MessagesDataSource.kt | 3 + .../fast/api/network/messages/MessagesRepo.kt | 4 + .../api/network/messages/MessagesRequest.kt | 34 ++++++ .../messages/MessagesHistoryAdapter.kt | 9 ++ .../messages/MessagesHistoryFragment.kt | 111 ++++++++++++------ .../messages/MessagesHistoryViewModel.kt | 29 +++++ .../screens/messages/MessagesPreparator.kt | 2 +- .../res/drawable/ic_trash_can_outline_24.xml | 10 ++ 20 files changed, 270 insertions(+), 87 deletions(-) create mode 100644 app/src/main/res/drawable/ic_trash_can_outline_24.xml diff --git a/app/src/main/kotlin/com/meloda/fast/api/VKConstants.kt b/app/src/main/kotlin/com/meloda/fast/api/VKConstants.kt index ebfbd0bd..90d32bf9 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/VKConstants.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/VKConstants.kt @@ -1,5 +1,7 @@ package com.meloda.fast.api +import com.meloda.fast.api.model.attachments.* + object VKConstants { const val GROUP_FIELDS = "description,members_count,counters,status,verified" @@ -35,4 +37,15 @@ object VKConstants { const val PASSWORD = "password" } } + + val restrictedToEditAttachments = listOf( + VkCall::class.java, + VkCurator::class.java, + VkEvent::class.java, + VkGift::class.java, + VkGraffiti::class.java, + VkGroupCall::class.java, + VkStory::class.java, + VkVoiceMessage::class.java + ) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/meloda/fast/api/VkUtils.kt b/app/src/main/kotlin/com/meloda/fast/api/VkUtils.kt index e82af0b9..d446c464 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/VkUtils.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/VkUtils.kt @@ -17,6 +17,30 @@ import com.meloda.fast.api.model.base.attachments.BaseVkAttachmentItem object VkUtils { + fun attachmentToString( + attachmentClass: Class, + id: Int, + ownerId: Int, + withAccessKey: Boolean, + accessKey: String? + ): String { + val type = when (attachmentClass) { + VkAudio::class.java -> "audio" + VkFile::class.java -> "doc" + VkVideo::class.java -> "video" + VkPhoto::class.java -> "photo" + else -> throw IllegalArgumentException("unknown attachment class: $attachmentClass") + } + + val result = StringBuilder(type).append(ownerId).append('_').append(id) + if (withAccessKey && !accessKey.isNullOrBlank()) { + result.append('_') + result.append(accessKey) + } + return result.toString() + } + + fun getMessageUser(message: VkMessage, profiles: Map): VkUser? { return (if (!message.isUser()) null else profiles[message.fromId]).also { message.user.value = it } diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/VkMessage.kt b/app/src/main/kotlin/com/meloda/fast/api/model/VkMessage.kt index 424c43e1..83f8d229 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/VkMessage.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/VkMessage.kt @@ -5,6 +5,7 @@ import androidx.room.Entity import androidx.room.Ignore import androidx.room.PrimaryKey import com.meloda.fast.api.UserConfig +import com.meloda.fast.api.VKConstants import com.meloda.fast.api.model.attachments.VkAttachment import com.meloda.fast.base.adapter.SelectableItem import com.meloda.fast.util.TimeUtils @@ -15,8 +16,8 @@ import kotlinx.parcelize.Parcelize @Parcelize data class VkMessage( @PrimaryKey(autoGenerate = false) - val id: Int, - val text: String? = null, + var id: Int, + var text: String? = null, val isOut: Boolean, val peerId: Int, val fromId: Int, @@ -28,7 +29,7 @@ data class VkMessage( val actionConversationMessageId: Int? = null, val actionMessage: String? = null, val geoType: String? = null, - val important: Boolean = false, + var important: Boolean = false, var forwards: List? = null, var attachments: List? = null, @@ -62,43 +63,11 @@ data class VkMessage( fun canEdit() = fromId == UserConfig.userId && + (attachments == null || !VKConstants.restrictedToEditAttachments.contains( + attachments!![0].javaClass + )) && (System.currentTimeMillis() / 1000 - date.toLong() < TimeUtils.ONE_DAY_IN_SECONDS) - fun copyMessage( - id: Int = this.id, - text: String? = this.text, - isOut: Boolean = this.isOut, - peerId: Int = this.peerId, - fromId: Int = this.fromId, - date: Int = this.date, - randomId: Int = this.randomId, - action: String? = this.action, - actionMemberId: Int? = this.actionMemberId, - actionText: String? = this.actionText, - actionConversationMessageId: Int? = this.actionConversationMessageId, - actionMessage: String? = this.actionMessage, - geoType: String? = this.geoType, - important: Boolean = this.important - ) = VkMessage( - id = id, - text = text, - isOut = isOut, - peerId = peerId, - fromId = fromId, - date = date, - randomId = randomId, - action = action, - actionMemberId = actionMemberId, - actionText = actionText, - actionConversationMessageId = actionConversationMessageId, - actionMessage = actionMessage, - geoType = geoType, - important = important - ).also { - it.attachments = attachments - it.forwards = forwards - } - enum class Action(val value: String) { CHAT_CREATE("chat_create"), CHAT_PHOTO_UPDATE("chat_photo_update"), diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkAttachment.kt b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkAttachment.kt index 26d3bc1a..2662b547 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkAttachment.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkAttachment.kt @@ -4,4 +4,8 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize @Parcelize -open class VkAttachment : Parcelable \ No newline at end of file +open class VkAttachment : Parcelable { + + open fun asString(withAccessKey: Boolean = true) = "" + +} \ No newline at end of file diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkAudio.kt b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkAudio.kt index cdf4e450..f2283066 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkAudio.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkAudio.kt @@ -1,17 +1,28 @@ package com.meloda.fast.api.model.attachments +import com.meloda.fast.api.VkUtils import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @Parcelize data class VkAudio( val id: Int, + val ownerId: Int, val title: String, val artist: String, val url: String, - val duration: Int + val duration: Int, + val accessKey: String? ) : VkAttachment() { @IgnoredOnParcel val className: String = this::class.java.name + + override fun asString(withAccessKey: Boolean) = VkUtils.attachmentToString( + attachmentClass = this::class.java, + id = id, + ownerId = ownerId, + withAccessKey = withAccessKey, + accessKey = accessKey + ) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkFile.kt b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkFile.kt index e1e91542..19e7f7b1 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkFile.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkFile.kt @@ -1,17 +1,28 @@ package com.meloda.fast.api.model.attachments +import com.meloda.fast.api.VkUtils import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @Parcelize data class VkFile( val id: Int, + val ownerId: Int, val title: String, val ext: String, val size: Int, - val url: String + val url: String, + val accessKey: String? ) : VkAttachment() { @IgnoredOnParcel val className: String = this::class.java.name + + override fun asString(withAccessKey: Boolean) = VkUtils.attachmentToString( + attachmentClass = this::class.java, + id = id, + ownerId = ownerId, + withAccessKey = withAccessKey, + accessKey = accessKey + ) } \ No newline at end of file diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkPhoto.kt b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkPhoto.kt index 5e008c84..8a661d4b 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkPhoto.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkPhoto.kt @@ -1,6 +1,7 @@ package com.meloda.fast.api.model.attachments import androidx.room.Ignore +import com.meloda.fast.api.VkUtils import com.meloda.fast.api.model.base.attachments.BaseVkPhoto import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @@ -39,6 +40,14 @@ data class VkPhoto( @IgnoredOnParcel val className: String = this::class.java.name + override fun asString(withAccessKey: Boolean) = VkUtils.attachmentToString( + attachmentClass = this::class.java, + id = id, + ownerId = ownerId, + withAccessKey = withAccessKey, + accessKey = accessKey + ) + fun getMaxSize(): BaseVkPhoto.Size? { return getSizeOrSmaller(sizesChars.peek()) } diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkVideo.kt b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkVideo.kt index 33424408..b817897c 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkVideo.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/attachments/VkVideo.kt @@ -1,5 +1,6 @@ package com.meloda.fast.api.model.attachments +import com.meloda.fast.api.VkUtils import com.meloda.fast.api.model.base.attachments.BaseVkVideo import kotlinx.parcelize.IgnoredOnParcel import kotlinx.parcelize.Parcelize @@ -7,8 +8,10 @@ import kotlinx.parcelize.Parcelize @Parcelize data class VkVideo( val id: Int, + val ownerId: Int, val images: List, - val firstFrames: List? + val firstFrames: List?, + val accessKey: String? ) : VkAttachment() { @IgnoredOnParcel @@ -18,4 +21,12 @@ data class VkVideo( return images.find { it.width == width } } + override fun asString(withAccessKey: Boolean) = VkUtils.attachmentToString( + attachmentClass = this::class.java, + id = id, + ownerId = ownerId, + withAccessKey = withAccessKey, + accessKey = accessKey + ) + } \ No newline at end of file diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkAudio.kt b/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkAudio.kt index a497bd44..09de47b9 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkAudio.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkAudio.kt @@ -13,7 +13,7 @@ data class BaseVkAudio( val url: String, val date: Int, val owner_id: Int, - val access_key: String, + val access_key: String?, val is_explicit: Boolean, val is_focus_track: Boolean, val is_licensed: Boolean, @@ -27,10 +27,12 @@ data class BaseVkAudio( fun asVkAudio() = VkAudio( id = id, + ownerId = owner_id, title = title, artist = artist, url = url, - duration = duration + duration = duration, + accessKey = access_key ) @Parcelize diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkFile.kt b/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkFile.kt index 07b2a967..8c09507f 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkFile.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkFile.kt @@ -16,16 +16,18 @@ data class BaseVkFile( val url: String, val preview: Preview?, val ic_licensed: Int, - val access_key: String, + val access_key: String?, val web_preview_url: String? ) : BaseVkAttachment() { fun asVkFile() = VkFile( id = id, + ownerId = owner_id, title = title, ext = ext, url = url, - size = size + size = size, + accessKey = access_key ) @Parcelize diff --git a/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkVideo.kt b/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkVideo.kt index c659c095..258e7a97 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkVideo.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/model/base/attachments/BaseVkVideo.kt @@ -26,7 +26,7 @@ data class BaseVkVideo( val can_add_to_faves: Int, val can_add: Int, val can_attach_link: Int, - val access_key: String, + val access_key: String?, val owner_id: Int, val ov_id: String, val is_favorite: Boolean, @@ -40,8 +40,10 @@ data class BaseVkVideo( fun asVkVideo() = VkVideo( id = id, + ownerId = owner_id, images = image, - firstFrames = first_frame + firstFrames = first_frame, + accessKey = access_key ) @Parcelize diff --git a/app/src/main/kotlin/com/meloda/fast/api/network/VkUrls.kt b/app/src/main/kotlin/com/meloda/fast/api/network/VkUrls.kt index 60f8e3dd..dcbcb39c 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/network/VkUrls.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/network/VkUrls.kt @@ -31,6 +31,7 @@ object VkUrls { const val Pin = "$API/messages.pin" const val Unpin = "$API/messages.unpin" const val Delete = "$API/messages.delete" + const val Edit = "$API/messages.edit" } diff --git a/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesDataSource.kt b/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesDataSource.kt index 479a9392..1fee173b 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesDataSource.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesDataSource.kt @@ -30,6 +30,9 @@ class MessagesDataSource @Inject constructor( suspend fun delete(params: MessagesDeleteRequest) = repo.delete(params.map) + suspend fun edit(params: MessagesEditRequest) = + repo.edit(params.map) + suspend fun store(messages: List) = dao.insert(messages) suspend fun getCached(peerId: Int) = dao.getByPeerId(peerId) diff --git a/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesRepo.kt b/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesRepo.kt index 4732ed19..729414c9 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesRepo.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesRepo.kt @@ -39,4 +39,8 @@ interface MessagesRepo { @POST(VkUrls.Messages.Delete) suspend fun delete(@FieldMap params: Map): Answer> + @FormUrlEncoded + @POST(VkUrls.Messages.Edit) + suspend fun edit(@FieldMap params: Map): Answer> + } \ No newline at end of file diff --git a/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesRequest.kt b/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesRequest.kt index a0e46a17..a96918cd 100644 --- a/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesRequest.kt +++ b/app/src/main/kotlin/com/meloda/fast/api/network/messages/MessagesRequest.kt @@ -2,6 +2,7 @@ package com.meloda.fast.api.network.messages import android.os.Parcelable import com.meloda.fast.api.ApiExtensions.intString +import com.meloda.fast.api.model.attachments.VkAttachment import kotlinx.parcelize.Parcelize @Parcelize @@ -130,5 +131,38 @@ data class MessagesDeleteRequest( this["conversation_message_ids"] = it.joinToString { id -> id.toString() } } } +} + +@Parcelize +data class MessagesEditRequest( + val peerId: Int, + val messageId: Int, + val message: String? = null, + val lat: Float? = null, + val lon: Float? = null, + val attachments: List? = null, + val notParseLinks: Boolean = false, + val keepSnippets: Boolean = true, + val keepForwardedMessages: Boolean = true +) : Parcelable { + + val map + get() = mutableMapOf( + "peer_id" to peerId.toString(), + "message_id" to messageId.toString(), + "dont_parse_links" to notParseLinks.intString, + "keep_snippets" to keepSnippets.intString, + "keep_forward_messages" to keepForwardedMessages.intString + ).apply { + message?.let { this["message"] = it } + lat?.let { this["lat"] = it.toString() } + lon?.let { this["lon"] = it.toString() } + attachments?.let { + val attachments = + if (it.isEmpty()) "" + else it.joinToString(separator = ",") { attachment -> attachment.asString() } + this["attachment"] = attachments + } + } } \ No newline at end of file diff --git a/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryAdapter.kt b/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryAdapter.kt index 426b8a24..038b4a25 100644 --- a/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryAdapter.kt +++ b/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryAdapter.kt @@ -267,6 +267,15 @@ class MessagesHistoryAdapter constructor( return positions } + fun searchMessageIndex(messageId: Int): Int? { + for (i in values.indices) { + val message = values[i] + if (message.id == messageId) return i + } + + return null + } + companion object { private const val SERVICE = 1 private const val HEADER = 0 diff --git a/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryFragment.kt b/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryFragment.kt index be48f2df..b4242f11 100644 --- a/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryFragment.kt +++ b/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryFragment.kt @@ -51,7 +51,7 @@ class MessagesHistoryFragment : private val action = MutableLiveData() private enum class Action { - RECORD, SEND, EDIT + RECORD, SEND, EDIT, DELETE } private val user: VkUser? by lazy { @@ -167,12 +167,11 @@ class MessagesHistoryFragment : }) binding.message.doAfterTextChanged { - val canSend = - it.toString().isNotBlank() + val canSend = it.toString().isNotBlank() - val newValue = + val newValue: Action = when { - attachmentController.isEditing -> Action.EDIT + attachmentController.isEditing -> if (it.isNullOrBlank()) Action.DELETE else Action.EDIT canSend -> Action.SEND else -> Action.RECORD } @@ -203,11 +202,16 @@ class MessagesHistoryFragment : Action.EDIT -> { binding.action.setImageResource(R.drawable.ic_round_done_24) } + Action.DELETE -> { + binding.action.setImageResource(R.drawable.ic_trash_can_outline_24) + } else -> return@observe } } attachmentController.isPanelVisible.observe(viewLifecycleOwner) { + if (it) binding.message.setSelection(binding.message.text.toString().length) + val layoutParams = binding.refreshLayout.layoutParams as CoordinatorLayout.LayoutParams layoutParams.bottomMargin = if (it) (binding.attachmentPanel.height / 1.5).roundToInt() else 0 @@ -280,39 +284,58 @@ class MessagesHistoryFragment : } private fun performAction() { - if (action.value == Action.RECORD) { - return - } else if (action.value == Action.SEND) { - val messageText = binding.message.text.toString().trim() - if (messageText.isBlank()) return + when (action.value) { + Action.RECORD -> { + } + Action.SEND -> { + val messageText = binding.message.text.toString().trim() + if (messageText.isBlank()) return - val date = System.currentTimeMillis() + val date = System.currentTimeMillis() - var message = VkMessage( - id = -1, - text = messageText, - isOut = true, - peerId = conversation.id, - fromId = UserConfig.userId, - date = (date / 1000).toInt(), - randomId = 0, - replyMessage = attachmentController.message.value - ) + val message = VkMessage( + id = -1, + text = messageText, + isOut = true, + peerId = conversation.id, + fromId = UserConfig.userId, + date = (date / 1000).toInt(), + randomId = 0, + replyMessage = attachmentController.message.value + ) - adapter.add(message) - adapter.notifyItemInserted(adapter.actualSize - 1) - binding.recyclerView.smoothScrollToPosition(adapter.lastPosition) - binding.message.clear() + adapter.add(message) + adapter.notifyItemInserted(adapter.actualSize - 1) + binding.recyclerView.smoothScrollToPosition(adapter.lastPosition) + binding.message.clear() - val replyMessage = attachmentController.message.value - attachmentController.message.value = null + val replyMessage = attachmentController.message.value + attachmentController.message.value = null - viewModel.sendMessage( - peerId = conversation.id, - message = messageText, - randomId = 0, - replyTo = replyMessage?.id - ) { message = message.copyMessage(id = it) } + viewModel.sendMessage( + peerId = conversation.id, + message = messageText, + randomId = 0, + replyTo = replyMessage?.id + ) { message.id = it } + } + Action.EDIT -> { + val message = attachmentController.message.value ?: return + val messageText = binding.message.text.toString().trim() + + attachmentController.message.value = null + + viewModel.editMessage( + originalMessage = message, + peerId = conversation.id, + messageId = message.id, + message = messageText, + attachments = message.attachments + ) + } + Action.DELETE -> attachmentController.message.value?.let { + showDeleteMessageDialog(it) + } } } @@ -328,6 +351,7 @@ class MessagesHistoryFragment : is MessagesPin -> conversation.pinnedMessage = event.message is MessagesUnpin -> conversation.pinnedMessage = null is MessagesDelete -> deleteMessages(event) + is MessagesEdit -> editMessage(event) } } @@ -377,14 +401,13 @@ class MessagesHistoryFragment : for (i in adapter.values.indices) { val message = adapter.values[i] + message.important = event.important if (event.messagesIds.contains(message.id)) { if (!changed) changed = true positions.add(i) - adapter.values[i] = message.copyMessage( - important = event.important - ) + adapter.values[i] = message } } @@ -532,17 +555,22 @@ class MessagesHistoryFragment : else R.string.message_mark_as_spam ) - binding.check.isEnabled = !message.isOut || message.canEdit() + binding.check.isEnabled = + (conversation.id != UserConfig.userId) && (!message.isOut || message.canEdit()) + + if (conversation.id == UserConfig.userId) binding.check.isChecked = true MaterialAlertDialogBuilder(requireContext()) .setTitle(R.string.confirm_delete_message) .setView(binding.root) .setPositiveButton(R.string.action_delete) { _, _ -> + attachmentController.message.value = null + viewModel.deleteMessage( peerId = conversation.id, messagesIds = listOf(message.id), isSpam = if (message.isOut) null else binding.check.isChecked, - deleteForAll = if (!message.isOut || !message.canEdit()) null else binding.check.isChecked + deleteForAll = if (!binding.check.isEnabled) null else binding.check.isChecked ) } .setNegativeButton(android.R.string.cancel, null) @@ -555,6 +583,13 @@ class MessagesHistoryFragment : } } + private fun editMessage(event: MessagesEdit) { + adapter.searchMessageIndex(event.message.id)?.let { index -> + adapter.values[index] = event.message + adapter.notifyItemChanged(index) + } + } + private inner class AttachmentPanelController { val isPanelVisible = MutableLiveData(false) val message = MutableLiveData() diff --git a/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryViewModel.kt b/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryViewModel.kt index 6f76f407..a4c07e50 100644 --- a/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryViewModel.kt +++ b/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesHistoryViewModel.kt @@ -6,6 +6,7 @@ import com.meloda.fast.api.model.VkConversation import com.meloda.fast.api.model.VkGroup import com.meloda.fast.api.model.VkMessage import com.meloda.fast.api.model.VkUser +import com.meloda.fast.api.model.attachments.VkAttachment import com.meloda.fast.api.network.messages.* import com.meloda.fast.base.viewmodel.BaseViewModel import com.meloda.fast.base.viewmodel.VkEvent @@ -173,6 +174,31 @@ class MessagesHistoryViewModel @Inject constructor( ) }, onAnswer = { sendEvent(MessagesDelete(messagesIds = messagesIds ?: listOf())) }) } + + fun editMessage( + originalMessage: VkMessage, + peerId: Int, + messageId: Int, + message: String? = null, + attachments: List? = null + ) = viewModelScope.launch { + makeJob( + { + messages.edit( + MessagesEditRequest( + peerId = peerId, + messageId = messageId, + message = message, + attachments = attachments + ) + ) + }, + onAnswer = { + originalMessage.text = message + sendEvent(MessagesEdit(originalMessage)) + } + ) + } } data class MessagesLoaded( @@ -198,3 +224,6 @@ data class MessagesDelete( val messagesIds: List ) : VkEvent() +data class MessagesEdit( + val message: VkMessage +) : VkEvent() \ No newline at end of file diff --git a/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesPreparator.kt b/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesPreparator.kt index 89af81ac..b5bfc38e 100644 --- a/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesPreparator.kt +++ b/app/src/main/kotlin/com/meloda/fast/screens/messages/MessagesPreparator.kt @@ -213,7 +213,7 @@ class MessagesPreparator constructor( } else { text.isVisible = true bubble.isVisible = true - text.text = VkUtils.prepareMessageText(message.text) + text.text = VkUtils.prepareMessageText(message.text ?: "") } } } diff --git a/app/src/main/res/drawable/ic_trash_can_outline_24.xml b/app/src/main/res/drawable/ic_trash_can_outline_24.xml new file mode 100644 index 00000000..05862a21 --- /dev/null +++ b/app/src/main/res/drawable/ic_trash_can_outline_24.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file