forked from melod1n/fast-messenger
refactor: extract message interactions
This commit is contained in:
+246
@@ -0,0 +1,246 @@
|
||||
package dev.meloda.fast.messageshistory
|
||||
|
||||
import android.os.Bundle
|
||||
import dev.meloda.fast.common.extensions.getParcelableCompat
|
||||
import dev.meloda.fast.common.extensions.setValue
|
||||
import dev.meloda.fast.messageshistory.model.MessageDialog
|
||||
import dev.meloda.fast.messageshistory.model.MessageOption
|
||||
import dev.meloda.fast.messageshistory.model.MessagesHistoryScreenState
|
||||
import dev.meloda.fast.model.api.domain.VkMessage
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
|
||||
internal class MessagesHistoryInteractionHandler(
|
||||
private val screenState: MutableStateFlow<MessagesHistoryScreenState>,
|
||||
private val messages: MutableStateFlow<List<VkMessage>>,
|
||||
private val dialog: MutableStateFlow<MessageDialog?>,
|
||||
private val selectedMessages: MutableStateFlow<List<VkMessage>>,
|
||||
private val messageActions: MessagesHistoryMessageActions,
|
||||
private val messageTransportActions: MessagesHistoryMessageTransportActions,
|
||||
private val syncUiMessages: () -> Unit
|
||||
) {
|
||||
fun onDialogConfirmed(dialog: MessageDialog, bundle: Bundle) {
|
||||
onDialogDismissed(dialog)
|
||||
|
||||
when (dialog) {
|
||||
is MessageDialog.MessageOptions -> Unit
|
||||
|
||||
is MessageDialog.MessageDelete -> {
|
||||
val deleteForEveryone = bundle.getBoolean("everyone")
|
||||
|
||||
if (dialog.message.id <= 0) {
|
||||
val newMessages = messages.value.toMutableList()
|
||||
newMessages.remove(dialog.message)
|
||||
messages.setValue { newMessages }
|
||||
syncUiMessages()
|
||||
return
|
||||
}
|
||||
|
||||
messageTransportActions.deleteMessage(
|
||||
messageIds = listOf(dialog.message.id),
|
||||
deleteForAll = deleteForEveryone
|
||||
)
|
||||
}
|
||||
|
||||
is MessageDialog.MessagesDelete -> {
|
||||
val deleteForEveryone = bundle.getBoolean("everyone")
|
||||
|
||||
val failedMessages = dialog.messages.filter { it.id <= 0 }
|
||||
val messageIdsToDelete =
|
||||
dialog.messages
|
||||
.filter { it.id > 0 }
|
||||
.map(VkMessage::id)
|
||||
|
||||
messageTransportActions.deleteMessage(
|
||||
messageIds = messageIdsToDelete,
|
||||
deleteForAll = deleteForEveryone,
|
||||
onSuccess = {
|
||||
val newMessages = messages.value.toMutableList()
|
||||
newMessages.removeAll(failedMessages)
|
||||
messages.setValue { newMessages }
|
||||
selectedMessages.setValue { emptyList() }
|
||||
syncUiMessages()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is MessageDialog.MessagePin -> {
|
||||
messageTransportActions.pinMessage(dialog.messageId)
|
||||
}
|
||||
|
||||
is MessageDialog.MessageUnpin -> {
|
||||
messageTransportActions.unpinMessage(dialog.messageId)
|
||||
}
|
||||
|
||||
is MessageDialog.MessageMarkImportance -> {
|
||||
messageTransportActions.markAsImportant(
|
||||
messageIds = listOf(dialog.message.id),
|
||||
important = dialog.isImportant
|
||||
)
|
||||
}
|
||||
|
||||
is MessageDialog.MessageSpam -> {
|
||||
if (dialog.isSpam) {
|
||||
messageTransportActions.deleteMessage(
|
||||
messageIds = listOf(dialog.message.id),
|
||||
spam = true
|
||||
)
|
||||
} else {
|
||||
// TODO: 29-Mar-25, Danil Nikolaev: report as not spam
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onDialogDismissed(dialog: MessageDialog) {
|
||||
this.dialog.setValue { null }
|
||||
}
|
||||
|
||||
fun onDialogItemPicked(dialog: MessageDialog, bundle: Bundle) {
|
||||
when (dialog) {
|
||||
is MessageDialog.MessageOptions -> {
|
||||
val cmId = bundle.getLong("cmId")
|
||||
|
||||
when (val option = bundle.getParcelableCompat("option", MessageOption::class)) {
|
||||
null -> Unit
|
||||
|
||||
MessageOption.Retry -> {
|
||||
// TODO: 28-Mar-25, Danil Nikolaev: retry sending
|
||||
}
|
||||
|
||||
MessageOption.Reply -> messageActions.replyToMessage(cmId)
|
||||
|
||||
MessageOption.ForwardHere -> {
|
||||
|
||||
}
|
||||
|
||||
MessageOption.Forward -> {
|
||||
|
||||
}
|
||||
|
||||
MessageOption.Pin -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessagePin(dialog.message.id)
|
||||
}
|
||||
}
|
||||
|
||||
MessageOption.Unpin -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessageUnpin(dialog.message.id)
|
||||
}
|
||||
}
|
||||
|
||||
MessageOption.Read -> {
|
||||
messageTransportActions.readMessage(dialog.message)
|
||||
}
|
||||
|
||||
MessageOption.Copy -> {
|
||||
messageTransportActions.copyMessage(dialog.message)
|
||||
}
|
||||
|
||||
MessageOption.MarkAsImportant,
|
||||
MessageOption.UnmarkAsImportant -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessageMarkImportance(
|
||||
message = dialog.message,
|
||||
isImportant = option is MessageOption.MarkAsImportant
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
MessageOption.MarkAsSpam,
|
||||
MessageOption.UnmarkAsSpam -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessageSpam(
|
||||
message = dialog.message,
|
||||
isSpam = option is MessageOption.MarkAsSpam
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
MessageOption.Edit -> {
|
||||
messageActions.editMessage(cmId)
|
||||
syncUiMessages()
|
||||
}
|
||||
|
||||
MessageOption.Delete -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessageDelete(dialog.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is MessageDialog.MessageDelete -> Unit
|
||||
is MessageDialog.MessageUnpin -> Unit
|
||||
is MessageDialog.MessageMarkImportance -> Unit
|
||||
is MessageDialog.MessageSpam -> Unit
|
||||
is MessageDialog.MessagePin -> Unit
|
||||
is MessageDialog.MessagesDelete -> Unit
|
||||
}
|
||||
}
|
||||
|
||||
fun onCloseButtonClicked() {
|
||||
if (selectedMessages.value.isNotEmpty()) {
|
||||
selectedMessages.setValue { emptyList() }
|
||||
}
|
||||
|
||||
if (screenState.value.editCmId != null) {
|
||||
messageActions.stopEditMessage()
|
||||
}
|
||||
|
||||
syncUiMessages()
|
||||
}
|
||||
|
||||
fun onMessageClicked(messageId: Long) {
|
||||
val currentMessage = messages.value.firstOrNull { it.id == messageId } ?: return
|
||||
|
||||
if (selectedMessages.value.isNotEmpty()) {
|
||||
val isSelected = selectedMessages.value.contains(currentMessage)
|
||||
|
||||
selectedMessages.setValue { old ->
|
||||
old.toMutableList().also {
|
||||
if (isSelected) {
|
||||
it.remove(currentMessage)
|
||||
} else {
|
||||
it.add(currentMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
syncUiMessages()
|
||||
} else {
|
||||
dialog.setValue {
|
||||
MessageDialog.MessageOptions(currentMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun onMessageLongClicked(messageId: Long) {
|
||||
val currentMessage = messages.value.firstOrNull { it.id == messageId } ?: return
|
||||
|
||||
val isSelected = selectedMessages.value.contains(currentMessage)
|
||||
if (isSelected) return
|
||||
|
||||
selectedMessages.setValue { old ->
|
||||
old.toMutableList().also {
|
||||
it.add(currentMessage)
|
||||
}
|
||||
}
|
||||
syncUiMessages()
|
||||
}
|
||||
|
||||
fun onEditSelectedMessageClicked() {
|
||||
val cmId = selectedMessages.value.firstOrNull()?.cmId ?: return
|
||||
|
||||
selectedMessages.setValue { emptyList() }
|
||||
|
||||
messageActions.editMessage(cmId)
|
||||
|
||||
syncUiMessages()
|
||||
}
|
||||
|
||||
fun onDeleteSelectedMessagesClicked() {
|
||||
dialog.setValue {
|
||||
MessageDialog.MessagesDelete(selectedMessages.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
+26
-221
@@ -8,7 +8,6 @@ import androidx.lifecycle.SavedStateHandle
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.conena.nanokt.collections.indexOfFirstOrNull
|
||||
import dev.meloda.fast.common.extensions.getParcelableCompat
|
||||
import dev.meloda.fast.common.extensions.listenValue
|
||||
import dev.meloda.fast.common.extensions.setValue
|
||||
import dev.meloda.fast.common.provider.ResourceProvider
|
||||
@@ -21,7 +20,6 @@ import dev.meloda.fast.domain.MessagesUseCase
|
||||
import dev.meloda.fast.messageshistory.model.ActionMode
|
||||
import dev.meloda.fast.messageshistory.model.MessageDialog
|
||||
import dev.meloda.fast.messageshistory.model.MessageNavigation
|
||||
import dev.meloda.fast.messageshistory.model.MessageOption
|
||||
import dev.meloda.fast.messageshistory.model.MessagesHistoryScreenState
|
||||
import dev.meloda.fast.messageshistory.navigation.MessagesHistory
|
||||
import dev.meloda.fast.model.BaseError
|
||||
@@ -116,6 +114,16 @@ class MessagesHistoryViewModelImpl(
|
||||
onPinnedMessageChanged = pinnedMessageHandler::update
|
||||
)
|
||||
|
||||
private val interactionHandler = MessagesHistoryInteractionHandler(
|
||||
screenState = screenState,
|
||||
messages = messages,
|
||||
dialog = dialog,
|
||||
selectedMessages = selectedMessages,
|
||||
messageActions = messageActions,
|
||||
messageTransportActions = messageTransportActions,
|
||||
syncUiMessages = ::syncUiMessages
|
||||
)
|
||||
|
||||
init {
|
||||
val arguments = MessagesHistory.from(savedStateHandle).arguments
|
||||
|
||||
@@ -150,183 +158,21 @@ class MessagesHistoryViewModelImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogConfirmed(dialog: MessageDialog, bundle: Bundle) {
|
||||
onDialogDismissed(dialog)
|
||||
override fun onDialogConfirmed(dialog: MessageDialog, bundle: Bundle) =
|
||||
interactionHandler.onDialogConfirmed(dialog, bundle)
|
||||
|
||||
when (dialog) {
|
||||
is MessageDialog.MessageOptions -> Unit
|
||||
override fun onDialogDismissed(dialog: MessageDialog) =
|
||||
interactionHandler.onDialogDismissed(dialog)
|
||||
|
||||
is MessageDialog.MessageDelete -> {
|
||||
val deleteForEveryone = bundle.getBoolean("everyone")
|
||||
|
||||
if (dialog.message.id <= 0) {
|
||||
val newMessages = messages.value.toMutableList()
|
||||
newMessages.remove(dialog.message)
|
||||
messages.setValue { newMessages }
|
||||
syncUiMessages()
|
||||
return
|
||||
}
|
||||
|
||||
messageTransportActions.deleteMessage(
|
||||
messageIds = listOf(dialog.message.id),
|
||||
deleteForAll = deleteForEveryone
|
||||
)
|
||||
}
|
||||
|
||||
is MessageDialog.MessagesDelete -> {
|
||||
val deleteForEveryone = bundle.getBoolean("everyone")
|
||||
|
||||
val failedMessages = dialog.messages.filter { it.id <= 0 }
|
||||
val messageIdsToDelete =
|
||||
dialog.messages
|
||||
.filter { it.id > 0 }
|
||||
.map(VkMessage::id)
|
||||
|
||||
messageTransportActions.deleteMessage(
|
||||
messageIds = messageIdsToDelete,
|
||||
deleteForAll = deleteForEveryone,
|
||||
onSuccess = {
|
||||
val newMessages = messages.value.toMutableList()
|
||||
newMessages.removeAll(failedMessages)
|
||||
messages.setValue { newMessages }
|
||||
selectedMessages.setValue { emptyList() }
|
||||
syncUiMessages()
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
is MessageDialog.MessagePin -> {
|
||||
messageTransportActions.pinMessage(dialog.messageId)
|
||||
}
|
||||
|
||||
is MessageDialog.MessageUnpin -> {
|
||||
messageTransportActions.unpinMessage(dialog.messageId)
|
||||
}
|
||||
|
||||
is MessageDialog.MessageMarkImportance -> {
|
||||
messageTransportActions.markAsImportant(
|
||||
messageIds = listOf(dialog.message.id),
|
||||
important = dialog.isImportant
|
||||
)
|
||||
}
|
||||
|
||||
is MessageDialog.MessageSpam -> {
|
||||
if (dialog.isSpam) {
|
||||
messageTransportActions.deleteMessage(
|
||||
messageIds = listOf(dialog.message.id),
|
||||
spam = true
|
||||
)
|
||||
} else {
|
||||
// TODO: 29-Mar-25, Danil Nikolaev: report as not spam
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onDialogDismissed(dialog: MessageDialog) {
|
||||
this.dialog.setValue { null }
|
||||
}
|
||||
|
||||
override fun onDialogItemPicked(dialog: MessageDialog, bundle: Bundle) {
|
||||
when (dialog) {
|
||||
is MessageDialog.MessageOptions -> {
|
||||
// val messageId = bundle.getLong("messageId")
|
||||
val cmId = bundle.getLong("cmId")
|
||||
|
||||
when (val option = bundle.getParcelableCompat("option", MessageOption::class)) {
|
||||
null -> Unit
|
||||
|
||||
MessageOption.Retry -> {
|
||||
// TODO: 28-Mar-25, Danil Nikolaev: retry sending
|
||||
}
|
||||
|
||||
MessageOption.Reply -> messageActions.replyToMessage(cmId)
|
||||
|
||||
MessageOption.ForwardHere -> {
|
||||
|
||||
}
|
||||
|
||||
MessageOption.Forward -> {
|
||||
|
||||
}
|
||||
|
||||
MessageOption.Pin -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessagePin(dialog.message.id)
|
||||
}
|
||||
}
|
||||
|
||||
MessageOption.Unpin -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessageUnpin(dialog.message.id)
|
||||
}
|
||||
}
|
||||
|
||||
MessageOption.Read -> {
|
||||
messageTransportActions.readMessage(dialog.message)
|
||||
}
|
||||
|
||||
MessageOption.Copy -> {
|
||||
messageTransportActions.copyMessage(dialog.message)
|
||||
}
|
||||
|
||||
MessageOption.MarkAsImportant,
|
||||
MessageOption.UnmarkAsImportant -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessageMarkImportance(
|
||||
message = dialog.message,
|
||||
isImportant = option is MessageOption.MarkAsImportant
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
MessageOption.MarkAsSpam,
|
||||
MessageOption.UnmarkAsSpam -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessageSpam(
|
||||
message = dialog.message,
|
||||
isSpam = option is MessageOption.MarkAsSpam
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
MessageOption.Edit -> {
|
||||
messageActions.editMessage(cmId)
|
||||
syncUiMessages()
|
||||
}
|
||||
|
||||
MessageOption.Delete -> {
|
||||
this.dialog.setValue {
|
||||
MessageDialog.MessageDelete(dialog.message)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
is MessageDialog.MessageDelete -> Unit
|
||||
is MessageDialog.MessageUnpin -> Unit
|
||||
is MessageDialog.MessageMarkImportance -> Unit
|
||||
is MessageDialog.MessageSpam -> Unit
|
||||
is MessageDialog.MessagePin -> Unit
|
||||
is MessageDialog.MessagesDelete -> Unit
|
||||
}
|
||||
}
|
||||
override fun onDialogItemPicked(dialog: MessageDialog, bundle: Bundle) =
|
||||
interactionHandler.onDialogItemPicked(dialog, bundle)
|
||||
|
||||
override fun onScrolledToIndex() {
|
||||
isNeedToScrollToIndex.setValue { null }
|
||||
}
|
||||
|
||||
override fun onCloseButtonClicked() {
|
||||
if (selectedMessages.value.isNotEmpty()) {
|
||||
selectedMessages.setValue { emptyList() }
|
||||
}
|
||||
|
||||
if (screenState.value.editCmId != null) {
|
||||
messageActions.stopEditMessage()
|
||||
}
|
||||
|
||||
syncUiMessages()
|
||||
}
|
||||
override fun onCloseButtonClicked() =
|
||||
interactionHandler.onCloseButtonClicked()
|
||||
|
||||
override fun onRefresh() {
|
||||
loaders.loadMessagesHistory(offset = 0)
|
||||
@@ -391,42 +237,11 @@ class MessagesHistoryViewModelImpl(
|
||||
loaders.loadMessagesHistory(currentOffset.value)
|
||||
}
|
||||
|
||||
override fun onMessageClicked(messageId: Long) {
|
||||
val currentMessage = messages.value.firstOrNull { it.id == messageId } ?: return
|
||||
override fun onMessageClicked(messageId: Long) =
|
||||
interactionHandler.onMessageClicked(messageId)
|
||||
|
||||
if (selectedMessages.value.isNotEmpty()) {
|
||||
val isSelected = selectedMessages.value.contains(currentMessage)
|
||||
|
||||
selectedMessages.setValue { old ->
|
||||
old.toMutableList().also {
|
||||
if (isSelected) {
|
||||
it.remove(currentMessage)
|
||||
} else {
|
||||
it.add(currentMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
syncUiMessages()
|
||||
} else {
|
||||
dialog.setValue {
|
||||
MessageDialog.MessageOptions(currentMessage)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onMessageLongClicked(messageId: Long) {
|
||||
val currentMessage = messages.value.firstOrNull { it.id == messageId } ?: return
|
||||
|
||||
val isSelected = selectedMessages.value.contains(currentMessage)
|
||||
if (isSelected) return
|
||||
|
||||
selectedMessages.setValue { old ->
|
||||
old.toMutableList().also {
|
||||
it.add(currentMessage)
|
||||
}
|
||||
}
|
||||
syncUiMessages()
|
||||
}
|
||||
override fun onMessageLongClicked(messageId: Long) =
|
||||
interactionHandler.onMessageLongClicked(messageId)
|
||||
|
||||
override fun onPinnedMessageClicked(messageId: Long) {
|
||||
val uiMessages = uiMessages.value
|
||||
@@ -448,21 +263,11 @@ class MessagesHistoryViewModelImpl(
|
||||
}
|
||||
}
|
||||
|
||||
override fun onEditSelectedMessageClicked() {
|
||||
val cmId = selectedMessages.value.firstOrNull()?.cmId ?: return
|
||||
override fun onEditSelectedMessageClicked() =
|
||||
interactionHandler.onEditSelectedMessageClicked()
|
||||
|
||||
selectedMessages.setValue { emptyList() }
|
||||
|
||||
messageActions.editMessage(cmId)
|
||||
|
||||
syncUiMessages()
|
||||
}
|
||||
|
||||
override fun onDeleteSelectedMessagesClicked() {
|
||||
dialog.setValue {
|
||||
MessageDialog.MessagesDelete(selectedMessages.value)
|
||||
}
|
||||
}
|
||||
override fun onDeleteSelectedMessagesClicked() =
|
||||
interactionHandler.onDeleteSelectedMessagesClicked()
|
||||
|
||||
override fun onBoldClicked() {
|
||||
messageActions.onBoldClicked()
|
||||
|
||||
Reference in New Issue
Block a user