Skip to content

Commit

Permalink
feat: use case to send Message Button Action [part-2] (#1896)
Browse files Browse the repository at this point in the history
* receive composite messages

* map composite to proto

* detekt

* detekt

* db migration

* db migration

* sqm

* map to composite entity

* detekt

* remove is pending state from the DB

* Update logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt

Co-authored-by: Vitor Hugo Schwaab <[email protected]>

* Update logic/src/commonMain/kotlin/com/wire/kalium/logic/data/message/MessageContent.kt

Co-authored-by: Vitor Hugo Schwaab <[email protected]>

* address PR comments

* detekt

* remove composite message preview mapping

* fix migration

* feat: use case to execute composite message action

* expose use case to message scope

* missing param

* rename use case

* docs

* map to proto

* merge issues

* address PR comments

* address PR comments

* detekt

* sent the message only to the message original sender

* detekt

* Update logic/src/commonTest/kotlin/com/wire/kalium/logic/data/message/MessageMetaDataRepositoryTest.kt

Co-authored-by: Alexandre Ferris <[email protected]>

* PR comments

---------

Co-authored-by: Vitor Hugo Schwaab <[email protected]>
Co-authored-by: Alexandre Ferris <[email protected]>
  • Loading branch information
3 people authored Jul 24, 2023
1 parent 787e880 commit 709e72e
Show file tree
Hide file tree
Showing 29 changed files with 861 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,6 @@ data class QualifiedClientID(
val clientId: ClientId,
val userId: UserId
)

typealias MessageId = String
typealias MessageButtonId = String
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.data.message

import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.id.toDao
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.wrapStorageRequest
import com.wire.kalium.persistence.dao.message.CompositeMessageDAO

interface CompositeMessageRepository {
suspend fun markSelected(
messageId: String,
conversationId: ConversationId,
buttonId: String
): Either<StorageFailure, Unit>

suspend fun resetSelection(
messageId: String,
conversationId: ConversationId
): Either<StorageFailure, Unit>
}

internal class CompositeMessageDatasource internal constructor(
private val compositeMessageDAO: CompositeMessageDAO
) : CompositeMessageRepository {
override suspend fun markSelected(
messageId: String,
conversationId: ConversationId,
buttonId: String
): Either<StorageFailure, Unit> = wrapStorageRequest {
compositeMessageDAO.markAsSelected(
messageId = messageId,
conversationId = conversationId.toDao(),
buttonId = buttonId
)
}

override suspend fun resetSelection(
messageId: String,
conversationId: ConversationId
): Either<StorageFailure, Unit> = wrapStorageRequest {
compositeMessageDAO.resetSelection(
messageId = messageId,
conversationId = conversationId.toDao()
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ package com.wire.kalium.logic.data.message
import com.wire.kalium.logger.obfuscateId
import com.wire.kalium.logic.data.conversation.ClientId
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.id.MessageButtonId
import com.wire.kalium.logic.data.id.MessageId
import com.wire.kalium.logic.data.message.mention.MessageMention
import com.wire.kalium.logic.data.message.receipt.ReceiptType
import com.wire.kalium.logic.data.user.UserAvailabilityStatus
Expand Down Expand Up @@ -185,12 +187,12 @@ sealed class MessageContent {
/**
* The ID of the original composite message.
*/
val referencedMessageId: String,
val referencedMessageId: MessageId,

/**
* ID of the button that was selected.
*/
val buttonId: String
val buttonId: MessageButtonId
) : Signaling()

/**
Expand All @@ -205,11 +207,11 @@ sealed class MessageContent {
/**
* ID fo the original composite message
*/
val referencedMessageId: String,
val referencedMessageId: MessageId,
/**
* ID of the selected button. Null if no button should be marked as selected.
*/
val buttonId: String?,
val buttonId: MessageButtonId?,
) : Signaling()

data class Unknown( // messages that aren't yet handled properly but stored in db in case
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.data.message

import com.wire.kalium.logic.StorageFailure
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.id.MessageId
import com.wire.kalium.logic.data.id.toDao
import com.wire.kalium.logic.data.id.toModel
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.functional.map
import com.wire.kalium.logic.wrapStorageRequest
import com.wire.kalium.persistence.dao.UserIDEntity
import com.wire.kalium.persistence.dao.message.MessageMetaDataDAO

interface MessageMetaDataRepository {
suspend fun originalSenderId(
conversationId: ConversationId,
messageId: MessageId
): Either<StorageFailure, UserId>
}

internal class MessageMetaDataDataSource internal constructor(
private val messageMetaDataDAO: MessageMetaDataDAO
) : MessageMetaDataRepository {
override suspend fun originalSenderId(conversationId: ConversationId, messageId: MessageId): Either<StorageFailure, UserId> =
wrapStorageRequest {
messageMetaDataDAO.originalSenderId(conversationId.toDao(), messageId)
}.map(UserIDEntity::toModel)
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import com.wire.kalium.protobuf.decodeFromByteArray
import com.wire.kalium.protobuf.encodeToByteArray
import com.wire.kalium.protobuf.messages.Asset
import com.wire.kalium.protobuf.messages.Button
import com.wire.kalium.protobuf.messages.ButtonAction
import com.wire.kalium.protobuf.messages.Calling
import com.wire.kalium.protobuf.messages.Cleared
import com.wire.kalium.protobuf.messages.ClientAction
Expand Down Expand Up @@ -123,12 +124,22 @@ class ProtoContentMapperImpl(
)

is MessageContent.Composite -> packComposite(readableContent, expectsReadConfirmation)
is MessageContent.ButtonAction -> packButtonAction(readableContent)

is MessageContent.ButtonActionConfirmation -> TODO()
is MessageContent.ButtonAction -> TODO()
}
}

private fun packButtonAction(
readableContent: MessageContent.ButtonAction
): GenericMessage.Content.ButtonAction =
GenericMessage.Content.ButtonAction(
ButtonAction(
buttonId = readableContent.buttonId,
referenceMessageId = readableContent.referencedMessageId
)
)

private fun packComposite(
readableContent: MessageContent.Composite,
expectsReadConfirmation: Boolean
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ import com.wire.kalium.logic.data.logout.LogoutRepository
import com.wire.kalium.logic.data.message.IsMessageSentInSelfConversationUseCase
import com.wire.kalium.logic.data.message.IsMessageSentInSelfConversationUseCaseImpl
import com.wire.kalium.logic.data.message.MessageDataSource
import com.wire.kalium.logic.data.message.MessageMetaDataDataSource
import com.wire.kalium.logic.data.message.MessageMetaDataRepository
import com.wire.kalium.logic.data.message.MessageRepository
import com.wire.kalium.logic.data.message.PersistMessageUseCase
import com.wire.kalium.logic.data.message.PersistMessageUseCaseImpl
Expand Down Expand Up @@ -555,6 +557,9 @@ class UserSessionScope internal constructor(
selfUserId = userId
)

private val messageMetaDataRepository: MessageMetaDataRepository
get() = MessageMetaDataDataSource(messageMetaDataDAO = userStorage.database.messageMetaDataDAO)

private val userRepository: UserRepository = UserDataSource(
userStorage.database.userDAO,
userStorage.database.metadataDAO,
Expand Down Expand Up @@ -1226,6 +1231,7 @@ class UserSessionScope internal constructor(
incrementalSyncRepository,
protoContentMapper,
observeSelfDeletingMessages,
messageMetaDataRepository,
this
)
val users: UserScope
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import com.wire.kalium.logic.data.connection.ConnectionRepository
import com.wire.kalium.logic.data.conversation.ConversationRepository
import com.wire.kalium.logic.data.conversation.MLSConversationRepository
import com.wire.kalium.logic.data.id.QualifiedID
import com.wire.kalium.logic.data.message.MessageMetaDataRepository
import com.wire.kalium.logic.data.message.MessageRepository
import com.wire.kalium.logic.data.message.PersistMessageUseCase
import com.wire.kalium.logic.data.message.PersistMessageUseCaseImpl
Expand All @@ -47,6 +48,7 @@ import com.wire.kalium.logic.feature.asset.UpdateAssetMessageDownloadStatusUseCa
import com.wire.kalium.logic.feature.asset.UpdateAssetMessageDownloadStatusUseCaseImpl
import com.wire.kalium.logic.feature.asset.UpdateAssetMessageUploadStatusUseCase
import com.wire.kalium.logic.feature.asset.UpdateAssetMessageUploadStatusUseCaseImpl
import com.wire.kalium.logic.feature.message.composite.SendButtonActionMessageUseCase
import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessageForSelfUserAsReceiverUseCaseImpl
import com.wire.kalium.logic.feature.message.ephemeral.DeleteEphemeralMessageForSelfUserAsSenderUseCaseImpl
import com.wire.kalium.logic.feature.message.ephemeral.EnqueueMessageSelfDeletionUseCase
Expand Down Expand Up @@ -86,6 +88,7 @@ class MessageScope internal constructor(
private val incrementalSyncRepository: IncrementalSyncRepository,
private val protoContentMapper: ProtoContentMapper,
private val observeSelfDeletingMessages: ObserveSelfDeletionTimerSettingsForConversationUseCase,
private val messageMetaDataRepository: MessageMetaDataRepository,
private val scope: CoroutineScope,
internal val dispatcher: KaliumDispatcher = KaliumDispatcherImpl
) {
Expand Down Expand Up @@ -298,6 +301,14 @@ class MessageScope internal constructor(
val resetSession: ResetSessionUseCase
get() = ResetSessionUseCaseImpl(proteusClientProvider, sessionResetSender, messageRepository)

val sendButtonActionMessage: SendButtonActionMessageUseCase
get() = SendButtonActionMessageUseCase(
syncManager = syncManager,
messageSender = messageSender,
selfUserId = selfUserId,
currentClientIdProvider = currentClientIdProvider,
messageMetaDataRepository = messageMetaDataRepository
)
private val deleteEphemeralMessageForSelfUserAsReceiver: DeleteEphemeralMessageForSelfUserAsReceiverUseCaseImpl
get() = DeleteEphemeralMessageForSelfUserAsReceiverUseCaseImpl(
messageRepository = messageRepository,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,10 @@ import com.wire.kalium.logic.data.conversation.Recipient
import com.wire.kalium.logic.data.user.UserId

sealed interface MessageTarget {
data class Users(val userId: List<UserId>) : MessageTarget
data class Users(val userId: List<UserId>) : MessageTarget {
constructor(vararg userId: UserId) : this(userId.toList())
}

class Client(val recipients: List<Recipient>) : MessageTarget
data class Conversation(val usersToIgnore: Set<UserId> = emptySet()) : MessageTarget
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Wire
* Copyright (C) 2023 Wire Swiss GmbH
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see http://www.gnu.org/licenses/.
*/
package com.wire.kalium.logic.feature.message.composite

import com.benasher44.uuid.uuid4
import com.wire.kalium.logic.CoreFailure
import com.wire.kalium.logic.data.id.ConversationId
import com.wire.kalium.logic.data.message.Message
import com.wire.kalium.logic.data.message.MessageContent
import com.wire.kalium.logic.data.message.MessageMetaDataRepository
import com.wire.kalium.logic.data.user.UserId
import com.wire.kalium.logic.feature.CurrentClientIdProvider
import com.wire.kalium.logic.feature.message.MessageSender
import com.wire.kalium.logic.feature.message.MessageTarget
import com.wire.kalium.logic.functional.flatMap
import com.wire.kalium.logic.functional.fold
import com.wire.kalium.logic.sync.SyncManager
import com.wire.kalium.util.DateTimeUtil

/**
* Use case for sending a button action message.
* @param conversationId The conversation id.
* @param messageId The id of the message that contains the button.
* @param buttonId The id of the button.
*
* the action message is sent only to the message original sender.
*/
class SendButtonActionMessageUseCase internal constructor(
private val messageSender: MessageSender,
private val messageMetaDataRepository: MessageMetaDataRepository,
private val syncManager: SyncManager,
private val currentClientIdProvider: CurrentClientIdProvider,
private val selfUserId: UserId
) {
suspend operator fun invoke(
conversationId: ConversationId,
messageId: String,
buttonId: String
): Result = syncManager.waitUntilLiveOrFailure().flatMap {
messageMetaDataRepository.originalSenderId(
conversationId,
messageId
).flatMap { originalSenderId ->
currentClientIdProvider().flatMap { currentClientId ->
val regularMessage = Message.Signaling(
id = uuid4().toString(),
content = MessageContent.ButtonAction(
referencedMessageId = messageId,
buttonId = buttonId
),
conversationId = conversationId,
date = DateTimeUtil.currentIsoDateTimeString(),
senderUserId = selfUserId,
senderClientId = currentClientId,
status = Message.Status.PENDING,
isSelfMessage = true,
expirationData = null
)
messageSender.sendMessage(regularMessage, messageTarget = MessageTarget.Users(originalSenderId))
}
}
}.fold(Result::Failure, { Result.Success })

sealed interface Result {
object Success : Result
data class Failure(
val error: CoreFailure
) : Result
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ import com.wire.kalium.logic.feature.SelfTeamIdProvider
import com.wire.kalium.logic.framework.TestConversation
import com.wire.kalium.logic.framework.TestUser
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangement
import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangementImpl
import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangement
import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangementImpl
import com.wire.kalium.logic.util.shouldFail
import com.wire.kalium.logic.util.shouldSucceed
import com.wire.kalium.network.api.base.authenticated.connection.ConnectionApi
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ import com.wire.kalium.logic.framework.TestUser
import com.wire.kalium.logic.functional.Either
import com.wire.kalium.logic.sync.receiver.conversation.MemberJoinEventHandler
import com.wire.kalium.logic.sync.receiver.conversation.MemberLeaveEventHandler
import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangement
import com.wire.kalium.logic.util.arrangment.dao.MemberDAOArrangementImpl
import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangement
import com.wire.kalium.logic.util.arrangement.dao.MemberDAOArrangementImpl
import com.wire.kalium.logic.util.shouldFail
import com.wire.kalium.logic.util.shouldSucceed
import com.wire.kalium.network.api.base.authenticated.conversation.AddServiceRequest
Expand Down
Loading

0 comments on commit 709e72e

Please sign in to comment.