diff --git a/stream-chat-android-client/api/stream-chat-android-client.api b/stream-chat-android-client/api/stream-chat-android-client.api index 7255386a6cc..f382ed916a0 100644 --- a/stream-chat-android-client/api/stream-chat-android-client.api +++ b/stream-chat-android-client/api/stream-chat-android-client.api @@ -927,6 +927,87 @@ public abstract class io/getstream/chat/android/client/errors/cause/StreamSdkExc public synthetic fun (Ljava/lang/Throwable;Lkotlin/jvm/internal/DefaultConstructorMarker;)V } +public final class io/getstream/chat/android/client/events/AIIndicatorClearEvent : io/getstream/chat/android/client/events/CidEvent, io/getstream/chat/android/client/events/UserEvent { + public fun (Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/util/Date; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Lio/getstream/chat/android/models/User; + public final fun component5 ()Ljava/lang/String; + public final fun component6 ()Ljava/lang/String; + public final fun component7 ()Ljava/lang/String; + public final fun component8 ()Ljava/util/Date; + public final fun copy (Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;)Lio/getstream/chat/android/client/events/AIIndicatorClearEvent; + public static synthetic fun copy$default (Lio/getstream/chat/android/client/events/AIIndicatorClearEvent;Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;ILjava/lang/Object;)Lio/getstream/chat/android/client/events/AIIndicatorClearEvent; + public fun equals (Ljava/lang/Object;)Z + public fun getChannelId ()Ljava/lang/String; + public fun getChannelLastMessageAt ()Ljava/util/Date; + public fun getChannelType ()Ljava/lang/String; + public fun getCid ()Ljava/lang/String; + public fun getCreatedAt ()Ljava/util/Date; + public fun getRawCreatedAt ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public fun getUser ()Lio/getstream/chat/android/models/User; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class io/getstream/chat/android/client/events/AIIndicatorStopEvent : io/getstream/chat/android/client/events/CidEvent, io/getstream/chat/android/client/events/UserEvent { + public fun (Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;)V + public final fun component1 ()Ljava/lang/String; + public final fun component2 ()Ljava/util/Date; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Lio/getstream/chat/android/models/User; + public final fun component5 ()Ljava/lang/String; + public final fun component6 ()Ljava/lang/String; + public final fun component7 ()Ljava/lang/String; + public final fun component8 ()Ljava/util/Date; + public final fun copy (Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;)Lio/getstream/chat/android/client/events/AIIndicatorStopEvent; + public static synthetic fun copy$default (Lio/getstream/chat/android/client/events/AIIndicatorStopEvent;Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;ILjava/lang/Object;)Lio/getstream/chat/android/client/events/AIIndicatorStopEvent; + public fun equals (Ljava/lang/Object;)Z + public fun getChannelId ()Ljava/lang/String; + public fun getChannelLastMessageAt ()Ljava/util/Date; + public fun getChannelType ()Ljava/lang/String; + public fun getCid ()Ljava/lang/String; + public fun getCreatedAt ()Ljava/util/Date; + public fun getRawCreatedAt ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public fun getUser ()Lio/getstream/chat/android/models/User; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + +public final class io/getstream/chat/android/client/events/AIIndicatorUpdatedEvent : io/getstream/chat/android/client/events/CidEvent, io/getstream/chat/android/client/events/UserEvent { + public fun (Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V + public final fun component1 ()Ljava/lang/String; + public final fun component10 ()Ljava/lang/String; + public final fun component11 ()Ljava/lang/String; + public final fun component2 ()Ljava/util/Date; + public final fun component3 ()Ljava/lang/String; + public final fun component4 ()Lio/getstream/chat/android/models/User; + public final fun component5 ()Ljava/lang/String; + public final fun component6 ()Ljava/lang/String; + public final fun component7 ()Ljava/lang/String; + public final fun component8 ()Ljava/util/Date; + public final fun component9 ()Ljava/lang/String; + public final fun copy (Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Lio/getstream/chat/android/client/events/AIIndicatorUpdatedEvent; + public static synthetic fun copy$default (Lio/getstream/chat/android/client/events/AIIndicatorUpdatedEvent;Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Lio/getstream/chat/android/models/User;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ILjava/lang/Object;)Lio/getstream/chat/android/client/events/AIIndicatorUpdatedEvent; + public fun equals (Ljava/lang/Object;)Z + public final fun getAiMessage ()Ljava/lang/String; + public final fun getAiState ()Ljava/lang/String; + public fun getChannelId ()Ljava/lang/String; + public fun getChannelLastMessageAt ()Ljava/util/Date; + public fun getChannelType ()Ljava/lang/String; + public fun getCid ()Ljava/lang/String; + public fun getCreatedAt ()Ljava/util/Date; + public final fun getMessageId ()Ljava/lang/String; + public fun getRawCreatedAt ()Ljava/lang/String; + public fun getType ()Ljava/lang/String; + public fun getUser ()Lio/getstream/chat/android/models/User; + public fun hashCode ()I + public fun toString ()Ljava/lang/String; +} + public final class io/getstream/chat/android/client/events/AnswerCastedEvent : io/getstream/chat/android/client/events/CidEvent, io/getstream/chat/android/client/events/HasPoll { public fun (Ljava/lang/String;Ljava/util/Date;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lio/getstream/chat/android/models/Poll;Ljava/util/Date;Lio/getstream/chat/android/models/Answer;)V public final fun component1 ()Ljava/lang/String; diff --git a/stream-chat-android-client/detekt-baseline.xml b/stream-chat-android-client/detekt-baseline.xml index 08c1460443a..d9a11a8f0c3 100644 --- a/stream-chat-android-client/detekt-baseline.xml +++ b/stream-chat-android-client/detekt-baseline.xml @@ -8,6 +8,7 @@ LongMethod:ChatClient.kt$ChatClient$private suspend fun handleEvent(event: ChatEvent) LongMethod:ChatClientDebuggerTest.kt$ChatClientDebuggerTest$@BeforeEach fun setUp() LongMethod:ChatSocket.kt$ChatSocket$@Suppress("ComplexMethod") private fun observeSocketStateService(): Job + LongMethod:EventMapping.kt$@Suppress("ComplexMethod") internal fun ChatEventDto.toDomain(currentUserId: UserId?): ChatEvent LongMethod:PinnedMessagesRequest.kt$PinnedMessagesRequest.Companion$fun create( limit: Int, sort: QuerySorter<Message>, pagination: PinnedMessagesPagination, ): PinnedMessagesRequest MagicNumber:AttachmentExtensions.kt$1000 MagicNumber:Identifiers.kt$31 diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/EventMapping.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/EventMapping.kt index 7a064d47ee5..4ac63463cbe 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/EventMapping.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/mapping/EventMapping.kt @@ -18,6 +18,9 @@ package io.getstream.chat.android.client.api2.mapping +import io.getstream.chat.android.client.api2.model.dto.AIIndicatorClearEventDto +import io.getstream.chat.android.client.api2.model.dto.AIIndicatorStopEventDto +import io.getstream.chat.android.client.api2.model.dto.AIIndicatorUpdatedEventDto import io.getstream.chat.android.client.api2.model.dto.AnswerCastedEventDto import io.getstream.chat.android.client.api2.model.dto.ChannelDeletedEventDto import io.getstream.chat.android.client.api2.model.dto.ChannelHiddenEventDto @@ -75,6 +78,9 @@ import io.getstream.chat.android.client.api2.model.dto.UserUpdatedEventDto import io.getstream.chat.android.client.api2.model.dto.VoteCastedEventDto import io.getstream.chat.android.client.api2.model.dto.VoteChangedEventDto import io.getstream.chat.android.client.api2.model.dto.VoteRemovedEventDto +import io.getstream.chat.android.client.events.AIIndicatorClearEvent +import io.getstream.chat.android.client.events.AIIndicatorStopEvent +import io.getstream.chat.android.client.events.AIIndicatorUpdatedEvent import io.getstream.chat.android.client.events.AnswerCastedEvent import io.getstream.chat.android.client.events.ChannelDeletedEvent import io.getstream.chat.android.client.events.ChannelHiddenEvent @@ -201,6 +207,9 @@ internal fun ChatEventDto.toDomain(currentUserId: UserId?): ChatEvent { is VoteChangedEventDto -> toDomain(currentUserId) is AnswerCastedEventDto -> toDomain(currentUserId) is VoteRemovedEventDto -> toDomain(currentUserId) + is AIIndicatorUpdatedEventDto -> toDomain(currentUserId) + is AIIndicatorClearEventDto -> toDomain(currentUserId) + is AIIndicatorStopEventDto -> toDomain(currentUserId) } } @@ -915,6 +924,51 @@ private fun VoteRemovedEventDto.toDomain(currentUserId: UserId?): VoteRemovedEve ) } +private fun AIIndicatorUpdatedEventDto.toDomain(currentUserId: UserId?): AIIndicatorUpdatedEvent { + val (channelType, channelId) = cid.cidToTypeAndId() + return AIIndicatorUpdatedEvent( + type = type, + createdAt = created_at.date, + rawCreatedAt = created_at.rawDate, + cid = cid, + user = user.toDomain(currentUserId), + channelType = channelType, + channelId = channelId, + channelLastMessageAt = channel_last_message_at, + aiState = aiState, + aiMessage = aiMessage, + messageId = messageId, + ) +} + +private fun AIIndicatorClearEventDto.toDomain(currentUserId: UserId?): AIIndicatorClearEvent { + val (channelType, channelId) = cid.cidToTypeAndId() + return AIIndicatorClearEvent( + type = type, + createdAt = created_at.date, + rawCreatedAt = created_at.rawDate, + user = user.toDomain(currentUserId), + cid = cid, + channelType = channelType, + channelId = channelId, + channelLastMessageAt = channel_last_message_at, + ) +} + +private fun AIIndicatorStopEventDto.toDomain(currentUserId: UserId?): AIIndicatorStopEvent { + val (channelType, channelId) = cid.cidToTypeAndId() + return AIIndicatorStopEvent( + type = type, + createdAt = created_at.date, + rawCreatedAt = created_at.rawDate, + cid = cid, + user = user.toDomain(currentUserId), + channelType = channelType, + channelId = channelId, + channelLastMessageAt = channel_last_message_at, + ) +} + private fun ConnectedEventDto.toDomain(currentUserId: UserId?): ConnectedEvent { return ConnectedEvent( type = type, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt index 8ebc347bb6e..ae57c435a81 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/api2/model/dto/EventDtos.kt @@ -582,6 +582,36 @@ internal data class VoteRemovedEventDto( val channel_last_message_at: Date?, ) : ChatEventDto() +@JsonClass(generateAdapter = true) +internal data class AIIndicatorUpdatedEventDto( + val type: String, + val aiState: String, + val cid: String, + val user: DownstreamUserDto, + val created_at: ExactDate, + val messageId: String, + val aiMessage: String, + val channel_last_message_at: Date?, +) : ChatEventDto() + +@JsonClass(generateAdapter = true) +internal data class AIIndicatorClearEventDto( + val type: String, + val cid: String, + val user: DownstreamUserDto, + val created_at: ExactDate, + val channel_last_message_at: Date?, +) : ChatEventDto() + +@JsonClass(generateAdapter = true) +internal data class AIIndicatorStopEventDto( + val type: String, + val cid: String, + val user: DownstreamUserDto, + val created_at: ExactDate, + val channel_last_message_at: Date?, +) : ChatEventDto() + @JsonClass(generateAdapter = true) internal data class ConnectedEventDto( val type: String, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/channel/ChannelClient.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/channel/ChannelClient.kt index db2229299ba..638cb4edda8 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/channel/ChannelClient.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/channel/ChannelClient.kt @@ -24,6 +24,9 @@ import io.getstream.chat.android.client.api.models.PinnedMessagesPagination import io.getstream.chat.android.client.api.models.QueryChannelRequest import io.getstream.chat.android.client.api.models.SendActionRequest import io.getstream.chat.android.client.api.models.WatchChannelRequest +import io.getstream.chat.android.client.events.AIIndicatorClearEvent +import io.getstream.chat.android.client.events.AIIndicatorStopEvent +import io.getstream.chat.android.client.events.AIIndicatorUpdatedEvent import io.getstream.chat.android.client.events.AnswerCastedEvent import io.getstream.chat.android.client.events.ChannelDeletedEvent import io.getstream.chat.android.client.events.ChannelHiddenEvent @@ -262,6 +265,9 @@ public class ChannelClient internal constructor( is VoteRemovedEvent -> event.cid == cid is AnswerCastedEvent -> event.cid == cid is UnknownEvent -> event.rawData["cid"] == cid + is AIIndicatorUpdatedEvent -> event.cid == cid + is AIIndicatorClearEvent -> event.cid == cid + is AIIndicatorStopEvent -> event.cid == cid is HealthEvent, is NotificationChannelMutesUpdatedEvent, is NotificationMutesUpdatedEvent, diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/events/ChatEvent.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/events/ChatEvent.kt index d436cbed429..eaea456a461 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/events/ChatEvent.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/events/ChatEvent.kt @@ -834,6 +834,51 @@ public data class VoteRemovedEvent( val removedVote: Vote, ) : CidEvent(), HasPoll +/** + * Triggered when an ai indicator is updated. + */ +public data class AIIndicatorUpdatedEvent( + override val type: String, + override val createdAt: Date, + override val rawCreatedAt: String?, + override val user: User, + override val cid: String, + override val channelType: String, + override val channelId: String, + override val channelLastMessageAt: Date?, + val aiState: String, + val messageId: String, + val aiMessage: String, +) : CidEvent(), UserEvent + +/** + * Triggered when an ai indicator is cleared. + */ +public data class AIIndicatorClearEvent( + override val type: String, + override val createdAt: Date, + override val rawCreatedAt: String?, + override val user: User, + override val cid: String, + override val channelType: String, + override val channelId: String, + override val channelLastMessageAt: Date?, +) : CidEvent(), UserEvent + +/** + * Triggered when an ai indicator is stopped. + */ +public data class AIIndicatorStopEvent( + override val type: String, + override val createdAt: Date, + override val rawCreatedAt: String?, + override val user: User, + override val cid: String, + override val channelType: String, + override val channelId: String, + override val channelLastMessageAt: Date?, +) : CidEvent(), UserEvent + /** * Triggered when a user gets connected to the WS */ diff --git a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/EventAdapter.kt b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/EventAdapter.kt index 4a097af2ed9..c2577893a1d 100644 --- a/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/EventAdapter.kt +++ b/stream-chat-android-client/src/main/java/io/getstream/chat/android/client/parser2/adapters/EventAdapter.kt @@ -22,6 +22,9 @@ import com.squareup.moshi.JsonWriter import com.squareup.moshi.Moshi import com.squareup.moshi.Types import com.squareup.moshi.rawType +import io.getstream.chat.android.client.api2.model.dto.AIIndicatorClearEventDto +import io.getstream.chat.android.client.api2.model.dto.AIIndicatorStopEventDto +import io.getstream.chat.android.client.api2.model.dto.AIIndicatorUpdatedEventDto import io.getstream.chat.android.client.api2.model.dto.AnswerCastedEventDto import io.getstream.chat.android.client.api2.model.dto.ChannelDeletedEventDto import io.getstream.chat.android.client.api2.model.dto.ChannelHiddenEventDto @@ -151,6 +154,9 @@ internal class EventDtoAdapter( private val voteChangedEventAdapter = moshi.adapter(VoteChangedEventDto::class.java) private val answerCastedEventAdapter = moshi.adapter(AnswerCastedEventDto::class.java) private val voteRemovedEventAdapter = moshi.adapter(VoteRemovedEventDto::class.java) + private val aiTypingIndicatorUpdatedEventAdapter = moshi.adapter(AIIndicatorUpdatedEventDto::class.java) + private val aiTypingIndicatorClearEventAdapter = moshi.adapter(AIIndicatorClearEventDto::class.java) + private val aiTypingIndicatorStopEventAdapter = moshi.adapter(AIIndicatorStopEventDto::class.java) @Suppress("LongMethod", "ComplexMethod", "ReturnCount") override fun fromJson(reader: JsonReader): ChatEventDto? { @@ -231,6 +237,9 @@ internal class EventDtoAdapter( else -> voteChangedEventAdapter } EventType.POLL_VOTE_REMOVED -> voteRemovedEventAdapter + EventType.AI_TYPING_INDICATOR_UPDATED -> aiTypingIndicatorUpdatedEventAdapter + EventType.AI_TYPING_INDICATOR_CLEAR -> aiTypingIndicatorClearEventAdapter + EventType.AI_TYPING_INDICATOR_STOP -> aiTypingIndicatorStopEventAdapter else -> // Custom case, early return return UnknownEventDto( type = type ?: EventType.UNKNOWN, diff --git a/stream-chat-android-core/api/stream-chat-android-core.api b/stream-chat-android-core/api/stream-chat-android-core.api index 9b733350aac..0b8df8fe28e 100644 --- a/stream-chat-android-core/api/stream-chat-android-core.api +++ b/stream-chat-android-core/api/stream-chat-android-core.api @@ -789,6 +789,9 @@ public final class io/getstream/chat/android/models/EqualsFilterObject : io/gets } public final class io/getstream/chat/android/models/EventType { + public static final field AI_TYPING_INDICATOR_CLEAR Ljava/lang/String; + public static final field AI_TYPING_INDICATOR_STOP Ljava/lang/String; + public static final field AI_TYPING_INDICATOR_UPDATED Ljava/lang/String; public static final field CHANNEL_DELETED Ljava/lang/String; public static final field CHANNEL_HIDDEN Ljava/lang/String; public static final field CHANNEL_TRUNCATED Ljava/lang/String; diff --git a/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/EventType.kt b/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/EventType.kt index 5a5b0505728..557cba0f97f 100644 --- a/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/EventType.kt +++ b/stream-chat-android-core/src/main/java/io/getstream/chat/android/models/EventType.kt @@ -69,6 +69,9 @@ public object EventType { public const val POLL_VOTE_REMOVED: String = "poll.vote_removed" public const val POLL_CLOSED: String = "poll.closed" public const val CONNECTION_ERROR: String = "connection.error" + public const val AI_TYPING_INDICATOR_UPDATED: String = "ai_indicator.update" + public const val AI_TYPING_INDICATOR_CLEAR: String = "ai_indicator.clear" + public const val AI_TYPING_INDICATOR_STOP: String = "ai_indicator.stop" /** * Local diff --git a/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelLogic.kt b/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelLogic.kt index 6e665b38a98..e0bef275132 100644 --- a/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelLogic.kt +++ b/stream-chat-android-state/src/main/java/io/getstream/chat/android/state/plugin/logic/channel/internal/ChannelLogic.kt @@ -21,6 +21,9 @@ import io.getstream.chat.android.client.api.models.Pagination import io.getstream.chat.android.client.api.models.QueryChannelRequest import io.getstream.chat.android.client.api.models.WatchChannelRequest import io.getstream.chat.android.client.channel.state.ChannelState +import io.getstream.chat.android.client.events.AIIndicatorClearEvent +import io.getstream.chat.android.client.events.AIIndicatorStopEvent +import io.getstream.chat.android.client.events.AIIndicatorUpdatedEvent import io.getstream.chat.android.client.events.AnswerCastedEvent import io.getstream.chat.android.client.events.ChannelDeletedEvent import io.getstream.chat.android.client.events.ChannelHiddenEvent @@ -629,6 +632,9 @@ internal class ChannelLogic( channelStateLogic.upsertPoll(event.processPoll(currentUserId, channelStateLogic::getPoll)) is VoteRemovedEvent -> channelStateLogic.upsertPoll(event.processPoll(channelStateLogic::getPoll)) is AnswerCastedEvent -> channelStateLogic.upsertPoll(event.processPoll(channelStateLogic::getPoll)) + is AIIndicatorUpdatedEvent, + is AIIndicatorClearEvent, + is AIIndicatorStopEvent, is NotificationChannelDeletedEvent, is NotificationInvitedEvent, -> Unit // Ignore these events