Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ import io.getstream.chat.android.client.events.ChannelUpdatedEvent
import io.getstream.chat.android.client.events.ChannelUserBannedEvent
import io.getstream.chat.android.client.events.ChannelVisibleEvent
import io.getstream.chat.android.client.events.ConnectedEvent
import io.getstream.chat.android.client.events.DraftMessageDeletedEvent
import io.getstream.chat.android.client.events.DraftMessageUpdatedEvent
import io.getstream.chat.android.client.events.MarkAllReadEvent
import io.getstream.chat.android.client.events.MemberAddedEvent
import io.getstream.chat.android.client.events.MemberRemovedEvent
Expand Down Expand Up @@ -61,6 +63,7 @@ import io.getstream.chat.android.client.parser2.adapters.internal.StreamDateForm
import io.getstream.chat.android.client.query.QueryChannelsSpec
import io.getstream.chat.android.models.Answer
import io.getstream.chat.android.models.Channel
import io.getstream.chat.android.models.DraftMessage
import io.getstream.chat.android.models.EventType
import io.getstream.chat.android.models.FilterObject
import io.getstream.chat.android.models.Member
Expand All @@ -79,6 +82,7 @@ import io.getstream.chat.android.randomBoolean
import io.getstream.chat.android.randomCID
import io.getstream.chat.android.randomChannel
import io.getstream.chat.android.randomDate
import io.getstream.chat.android.randomDraftMessage
import io.getstream.chat.android.randomInt
import io.getstream.chat.android.randomMember
import io.getstream.chat.android.randomMessage
Expand Down Expand Up @@ -806,6 +810,26 @@ public fun randomPollDeletedEvent(
)
}

public fun randomDraftMessageUpdatedEvent(
createdAt: Date = randomDate(),
draftMessage: DraftMessage = randomDraftMessage(),
): DraftMessageUpdatedEvent = DraftMessageUpdatedEvent(
type = EventType.DRAFT_MESSAGE_UPDATED,
createdAt = createdAt,
rawCreatedAt = streamFormatter.format(createdAt),
draftMessage = draftMessage,
)

public fun randomDraftMessageDeletedEvent(
createdAt: Date = randomDate(),
draftMessage: DraftMessage = randomDraftMessage(),
): DraftMessageDeletedEvent = DraftMessageDeletedEvent(
type = EventType.DRAFT_MESSAGE_DELETED,
createdAt = createdAt,
rawCreatedAt = streamFormatter.format(createdAt),
draftMessage = draftMessage,
)

public fun randomPollUpdatedEvent(
createdAt: Date = randomDate(),
cid: String = randomCID(),
Expand Down
10 changes: 10 additions & 0 deletions stream-chat-android-client/api/stream-chat-android-client.api
Original file line number Diff line number Diff line change
Expand Up @@ -3135,6 +3135,8 @@ public abstract interface class io/getstream/chat/android/client/persistance/rep
public abstract fun deleteChannelMessages (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun deleteChannelMessagesBefore (Ljava/lang/String;Ljava/util/Date;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun deleteDraftMessage (Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun deleteDraftMessage (Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun deleteDraftMessage$suspendImpl (Lio/getstream/chat/android/client/persistance/repository/MessageRepository;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun deleteMessages (Ljava/util/List;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun deletePoll (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun evictMessage (Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand Down Expand Up @@ -3259,6 +3261,8 @@ public abstract interface class io/getstream/chat/android/client/plugin/Plugin :
public static synthetic fun onCreateChannelRequest$suspendImpl (Lio/getstream/chat/android/client/plugin/Plugin;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Ljava/util/Map;Lio/getstream/chat/android/models/User;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onCreateChannelResult (Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/result/Result;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun onCreateChannelResult$suspendImpl (Lio/getstream/chat/android/client/plugin/Plugin;Ljava/lang/String;Ljava/lang/String;Ljava/util/List;Lio/getstream/result/Result;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onCreateDraftMessageRequest (Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun onCreateDraftMessageRequest$suspendImpl (Lio/getstream/chat/android/client/plugin/Plugin;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onCreateDraftMessageResult (Lio/getstream/result/Result;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun onCreateDraftMessageResult$suspendImpl (Lio/getstream/chat/android/client/plugin/Plugin;Lio/getstream/result/Result;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onDeleteChannelPrecondition (Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand All @@ -3267,6 +3271,8 @@ public abstract interface class io/getstream/chat/android/client/plugin/Plugin :
public static synthetic fun onDeleteChannelRequest$suspendImpl (Lio/getstream/chat/android/client/plugin/Plugin;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onDeleteChannelResult (Ljava/lang/String;Ljava/lang/String;Lio/getstream/result/Result;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun onDeleteChannelResult$suspendImpl (Lio/getstream/chat/android/client/plugin/Plugin;Ljava/lang/String;Ljava/lang/String;Lio/getstream/result/Result;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onDeleteDraftMessagesRequest (Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun onDeleteDraftMessagesRequest$suspendImpl (Lio/getstream/chat/android/client/plugin/Plugin;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onDeleteDraftMessagesResult (Lio/getstream/result/Result;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun onDeleteDraftMessagesResult$suspendImpl (Lio/getstream/chat/android/client/plugin/Plugin;Lio/getstream/result/Result;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onDeleteReactionPrecondition (Lio/getstream/chat/android/models/User;)Lio/getstream/result/Result;
Expand Down Expand Up @@ -3405,7 +3411,11 @@ public abstract interface class io/getstream/chat/android/client/plugin/listener
}

public abstract interface class io/getstream/chat/android/client/plugin/listeners/DraftMessageListener {
public fun onCreateDraftMessageRequest (Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun onCreateDraftMessageRequest$suspendImpl (Lio/getstream/chat/android/client/plugin/listeners/DraftMessageListener;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun onCreateDraftMessageResult (Lio/getstream/result/Result;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public fun onDeleteDraftMessagesRequest (Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public static synthetic fun onDeleteDraftMessagesRequest$suspendImpl (Lio/getstream/chat/android/client/plugin/listeners/DraftMessageListener;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun onDeleteDraftMessagesResult (Lio/getstream/result/Result;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/DraftMessage;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun onQueryDraftMessagesResult (Lio/getstream/result/Result;Lio/getstream/chat/android/models/FilterObject;ILjava/lang/String;Lio/getstream/chat/android/models/querysort/QuerySorter;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun onQueryDraftMessagesResult (Lio/getstream/result/Result;Ljava/lang/Integer;Ljava/lang/Integer;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2686,6 +2686,12 @@ internal constructor(
return message.ensureId(getCurrentUser() ?: getStoredUser()).let { processedDraftMessage ->
api.createDraftMessage(channelType, channelId, processedDraftMessage)
.retry(userScope, retryPolicy)
.doOnStart(userScope) {
logger.v { "[createDraftMessage] #doOnStart; cid: $channelType:$channelId" }
plugins.forEach { listener ->
listener.onCreateDraftMessageRequest(channelType, channelId, processedDraftMessage)
}
}
.doOnResult(userScope) { result ->
logger.i { "[createDraftMessage] result: ${result.stringify { it.toString() }}" }
plugins.forEach { listener ->
Expand Down Expand Up @@ -2714,6 +2720,12 @@ internal constructor(
): Call<Unit> {
return api.deleteDraftMessage(channelType, channelId, message)
.retry(userScope, retryPolicy)
.doOnStart(userScope) {
logger.v { "[deleteDraftMessages] #doOnStart; cid: $channelType:$channelId" }
plugins.forEach { listener ->
listener.onDeleteDraftMessagesRequest(channelType, channelId, message)
}
}
.doOnResult(userScope) { result ->
logger.i { "[deleteDraftMessages] result: ${result.stringify { it.toString() }}" }
plugins.forEach { listener ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,20 @@ public interface MessageRepository {
*/
public suspend fun deleteDraftMessage(message: DraftMessage)

/**
* Deletes the draft message of a channel, or of a thread when [parentId] is not null. Used when the draft is only
* identified by the channel/thread it belongs to, as happens with the `draft.deleted` event.
*
* The default implementation looks the draft up before deleting it. Override it to delete in a single query.
*/
public suspend fun deleteDraftMessage(cid: String, parentId: String?) {
val draftMessage = when (parentId) {
null -> selectDraftMessagesByCid(cid)
else -> selectDraftMessageByParentId(parentId)
}
draftMessage?.let { deleteDraftMessage(it) }
}

/**
* Evict messages from the repository.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ internal object NoOpMessageRepository : MessageRepository {
override suspend fun selectMessageBySyncState(syncStatus: SyncStatus): List<Message> = emptyList()
override suspend fun selectMessagesWithPoll(pollId: String): List<Message> = emptyList()
override suspend fun deleteDraftMessage(message: DraftMessage) { /* No-Op */ }
override suspend fun deleteDraftMessage(cid: String, parentId: String?) { /* No-Op */ }
override suspend fun selectDraftMessages(): List<DraftMessage> = emptyList()
override suspend fun selectDraftMessagesByCid(cid: String): DraftMessage? = null
override suspend fun selectDraftMessageByParentId(parentId: String): DraftMessage? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,14 @@ public interface Plugin :
/* No-Op */
}

override suspend fun onCreateDraftMessageRequest(
channelType: String,
channelId: String,
message: DraftMessage,
) {
/* No-Op */
}

override suspend fun onCreateDraftMessageResult(
result: Result<DraftMessage>,
channelType: String,
Expand All @@ -468,6 +476,14 @@ public interface Plugin :
/* No-Op */
}

override suspend fun onDeleteDraftMessagesRequest(
channelType: String,
channelId: String,
message: DraftMessage,
) {
/* No-Op */
}

override suspend fun onDeleteDraftMessagesResult(
result: Result<Unit>,
channelType: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,27 @@ import io.getstream.result.Result
*/
public interface DraftMessageListener {

/**
* Side effect to be invoked before the original request is launched.
*
* @param channelType The type of the channel in which message is created.
* @param channelId The id of the channel in which message is created.
* @param message [DraftMessage] to be created.
*/
public suspend fun onCreateDraftMessageRequest(
channelType: String,
channelId: String,
message: DraftMessage,
) {
/* No-Op */
}

/**
* Side effect to be invoked when the original request is completed with a response.
*
* @param result [Result] response from the original request.
* @param channelType The type of the channel in which message is created.
* @param channelId The id of the the channel in which message is created.
* @param channelId The id of the channel in which message is created.
* @param message [DraftMessage] to be created.
*/
public suspend fun onCreateDraftMessageResult(
Expand All @@ -43,13 +58,28 @@ public interface DraftMessageListener {
message: DraftMessage,
)

/**
* Side effect to be invoked before the original request is launched.
*
* @param channelType The type of the channel in which message is deleted.
* @param channelId The id of the channel in which message is deleted.
* @param message [DraftMessage] to be deleted.
*/
public suspend fun onDeleteDraftMessagesRequest(
channelType: String,
channelId: String,
message: DraftMessage,
) {
/* No-Op */
}

/**
* Side effect to be invoked when the original request is completed with a response.
*
* @param result [Result] response from the original request.
* @param channelType The type of the channel in which message is updated.
* @param channelId The id of the the channel in which message is updated.
* @param message [DraftMessage] to be updated.
* @param channelType The type of the channel in which message is deleted.
* @param channelId The id of the channel in which message is deleted.
* @param message [DraftMessage] to be deleted.
*/
public suspend fun onDeleteDraftMessagesResult(
result: Result<Unit>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package io.getstream.chat.android.client

import io.getstream.chat.android.client.chatclient.BaseChatClientTest
import io.getstream.chat.android.client.plugin.Plugin
import io.getstream.chat.android.client.utils.RetroError
import io.getstream.chat.android.client.utils.RetroSuccess
import io.getstream.chat.android.client.utils.verifyNetworkError
Expand All @@ -33,13 +34,55 @@ import org.junit.jupiter.api.Test
import org.mockito.kotlin.any
import org.mockito.kotlin.anyOrNull
import org.mockito.kotlin.doReturn
import org.mockito.kotlin.eq
import org.mockito.kotlin.inOrder
import org.mockito.kotlin.mock
import org.mockito.kotlin.verify
import org.mockito.kotlin.whenever

/**
* Test class for the drafts functionality of the [ChatClient].
*/
internal class ChatClientDraftsApiTests : BaseChatClientTest() {

@Test
fun createDraftNotifiesPluginsBeforeTheResponseArrives() = runTest {
// given
val channelType = randomString()
val channelId = randomString()
val draft = randomDraftMessage()
val plugin = mock<Plugin>()
plugins.add(plugin)
whenever(api.createDraftMessage(any(), any(), any()))
.doReturn(RetroSuccess(draft).toRetrofitCall())
// when
chatClient.createDraftMessage(channelType, channelId, draft).await()
// then
inOrder(plugin).apply {
verify(plugin).onCreateDraftMessageRequest(eq(channelType), eq(channelId), any())
verify(plugin).onCreateDraftMessageResult(any(), eq(channelType), eq(channelId), any())
}
}

@Test
fun deleteDraftNotifiesPluginsBeforeTheResponseArrives() = runTest {
// given
val channelType = randomString()
val channelId = randomString()
val draft = randomDraftMessage()
val plugin = mock<Plugin>()
plugins.add(plugin)
whenever(api.deleteDraftMessage(any(), any(), any()))
.doReturn(RetroSuccess(Unit).toRetrofitCall())
// when
chatClient.deleteDraftMessages(channelType, channelId, draft).await()
// then
inOrder(plugin).apply {
verify(plugin).onDeleteDraftMessagesRequest(eq(channelType), eq(channelId), eq(draft))
verify(plugin).onDeleteDraftMessagesResult(any(), eq(channelType), eq(channelId), eq(draft))
}
}

@Test
fun createDraftSuccess() = runTest {
// given
Expand Down
Loading
Loading