Stream Chat Unreal SDK
Loading...
Searching...
No Matches
ChatChannel.h
1// Copyright 2026 Stream.IO, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "ChannelProperties.h"
6#include "ChannelSortOption.h"
7#include "ChannelState.h"
8#include "ChatApi.h"
9#include "ChatSocketEvents.h"
10#include "CoreMinimal.h"
11#include "Engine/EngineTypes.h"
12#include "Engine/LatentActionManager.h"
13#include "Filter.h"
14#include "IChatSocket.h"
15#include "Message.h"
16#include "MessagePaginationOptions.h"
17#include "PaginationOptions.h"
18#include "Templates/IsInvocable.h"
19#include "User/UserPaginationOptions.h"
20#include "User/UserRef.h"
21
22#include "ChatChannel.generated.h"
23
25struct FChannelEvent;
29struct FMessageEvent;
30struct FMessageNewEvent;
39struct FTypingStopEvent;
40struct FUserBannedEvent;
42
43UENUM(BlueprintType)
44enum class ETypingIndicatorState : uint8
45{
46 StartTyping,
47 StopTyping
48};
49
50UENUM(BlueprintType, meta = (BitFlags))
51enum class EPaginationDirection : uint8
52{
53 None UMETA(Hidden),
54
56 Top = 1 << 0,
58 Bottom = 1 << 1,
59};
60ENUM_CLASS_FLAGS(EPaginationDirection);
61
62UENUM(BlueprintType)
63enum class EHttpRequestState : uint8
64{
65 Started,
66 Ended
67};
68
73UCLASS(BlueprintType)
74class STREAMCHAT_API UChatChannel final : public UObject
75{
76 GENERATED_BODY()
77
78public:
80 static UChatChannel* Create(UObject* Outer, const TSharedRef<FChatApi>, const TSharedRef<IChatSocket>, const FChannelStateResponseFieldsDto&);
82 static UChatChannel* Create(UObject* Outer, const TSharedRef<FChatApi>, const TSharedRef<IChatSocket>);
83
85 bool IsValid() const;
86
91 void Delete(TFunction<void()> Callback = {}) const;
92
99 void PartialUpdate(const TSharedRef<FJsonObject>& Set = {}, const TArray<FString>& Unset = {}, TFunction<void()> Callback = {});
100
107 void Update(const FAdditionalFields& Data, const TOptional<FMessage>& Message = {}, TFunction<void()> Callback = {});
108
117 void Truncate(
118 bool bHardDelete = false,
119 const TOptional<FDateTime>& TruncatedAt = {},
120 const TOptional<FMessage>& Message = {},
121 bool bSkipPush = false,
122 TFunction<void()> Callback = {});
123
133 void QueryMembers(
134 const FFilter& Filter = {},
135 const TArray<FUserSortOption>& Sort = {},
136 const FMessagePaginationOptions& Pagination = {},
137 TFunction<void(const TArray<FMember>&)> Callback = {});
138
145 void AddMembers(const TArray<FString>& MemberIds, const TOptional<FMessage>& Message = {}, TFunction<void()> Callback = {});
146
153 void RemoveMembers(const TArray<FString>& MemberIds, const TOptional<FMessage>& Message = {}, TFunction<void()> Callback = {});
154
161 void Hide(bool bClearHistory = false, TFunction<void()> Callback = {}) const;
162
167 void Show(TFunction<void()> Callback = {}) const;
168
173 void StopWatching(TFunction<void()> Callback = {}) const;
174
176 UPROPERTY(BlueprintReadOnly, Category = "Stream Chat|Channel")
178
180 UPROPERTY(BlueprintReadOnly, Category = "Stream Chat|Channel")
182
183private:
184 void MergeState(const FChannelStateResponseFieldsDto&);
185
186 TSharedPtr<FChatApi> Api;
187 TSharedPtr<IChatSocket> Socket;
188
189#pragma region Event
195public:
197 template <class TEvent>
198 void SendEvent(const TEvent&);
199
201 template <class TEvent>
202 FDelegateHandle On(TEventDelegate<TEvent> Callback);
203
211 template <class TEvent, class UserClass>
212 typename TEnableIf<TIsDerivedFrom<UserClass, UObject>::IsDerived, FDelegateHandle>::Type On(
213 UserClass* Obj,
214 TEventDelegateUObjectMethodPtr<TEvent, UserClass> Method);
215
224 template <class TEvent, class UserClass>
225 typename TEnableIf<!TIsDerivedFrom<UserClass, UObject>::IsDerived, FDelegateHandle>::Type On(
226 UserClass* Obj,
227 TEventDelegateSpMethodPtr<TEvent, UserClass> Method);
228
236 template <class TEvent, typename FunctorType, typename... VarTypes>
237 typename TEnableIf<TIsInvocable<FunctorType, const TEvent&, VarTypes...>::Value, FDelegateHandle>::Type On(FunctorType&& Functor, VarTypes... Vars);
238
245 template <class TEvent>
246 bool Unsubscribe(FDelegateHandle) const;
247
249#pragma endregion Event
250
251#pragma region Message
257public:
263 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message", DisplayName = "Send Message", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo))
264 void SendMessageBP(const FMessage& Message, const UObject* WorldContextObject, FLatentActionInfo LatentInfo, bool& bSuccess);
265 void SendMessage(const FMessage& Message, const TFunction<void(const bool& bSuccess)> = {});
266
279 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Attachment", DisplayName = "Upload File", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo))
280 void UploadFileBP(
281 const FString& FileName,
282 const TArray<uint8>& Content,
283 const UObject* WorldContextObject,
284 FLatentActionInfo LatentInfo,
285 FAttachment& OutAttachment);
286 void UploadFile(const FString& FileName, const TArray<uint8>& Content, const TFunction<void(const FAttachment&)> Callback = {});
287
298 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Attachment", DisplayName = "Upload Image", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo))
299 void UploadImageBP(
300 const FString& FileName,
301 const TArray<uint8>& Content,
302 const UObject* WorldContextObject,
303 FLatentActionInfo LatentInfo,
304 FAttachment& OutAttachment);
305 void UploadImage(const FString& FileName, const TArray<uint8>& Content, const TFunction<void(const FAttachment&)> Callback = {});
306
313 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Attachment", DisplayName = "Delete Attachment", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo))
314 void DeleteAttachmentBP(const FAttachment& Attachment, const UObject* WorldContextObject, FLatentActionInfo LatentInfo, bool& bSuccess);
315 void DeleteAttachment(const FAttachment& Attachment, const TFunction<void(const bool& bSuccess)> Callback = {});
316
321 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message", DisplayName = "Get Message", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo))
322 void GetMessageBP(const FString& MessageId, const UObject* WorldContextObject, FLatentActionInfo LatentInfo, FMessage& OutMessage);
323 void GetMessage(const FString& MessageId, const TFunction<void(const FMessage&)> Callback = {});
324
330 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message")
331 void UpdateMessage(const FMessage& Message);
332
345 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message")
346 void ResendMessage(const FMessage& Message);
347
356 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message")
357 void DeleteMessage(const FMessage& Message);
358
367 void QueryAdditionalMessages(EPaginationDirection Direction = EPaginationDirection::Top, int32 Limit = 20, TFunction<void()> Callback = {});
368
373 void MarkRead(const TOptional<FMessage>& Message = {});
378 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message", meta = (AutoCreateRefTerm = Message))
379 void MarkRead(const FMessage& Message);
380
382 void MarkReadLocal();
383
393 void Query(
395 const TOptional<FMessagePaginationOptions> MessagePagination = {},
396 const TOptional<FUserPaginationOptions> MemberPagination = {},
397 const TOptional<FUserPaginationOptions> WatcherPagination = {},
398 TFunction<void()> Callback = {});
399
411 void SearchMessages(
412 const TOptional<FString>& Query = {},
413 const TOptional<FFilter>& MessageFilter = {},
414 const TArray<FMessageSortOption>& Sort = {},
415 TOptional<uint32> MessageLimit = {},
416 TFunction<void(const TArray<FMessage>&)> Callback = {}) const;
417
429 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo, AutoCreateRefTerm = "Sort,MessageFilter"))
430 void SearchMessages(
431 const FString& Query,
432 const FFilter& MessageFilter,
433 const TArray<FMessageSortOption>& Sort,
434 int32 MessageLimit,
435 const UObject* WorldContextObject,
436 FLatentActionInfo LatentInfo,
437 TArray<FMessage>& OutMessages);
438
439 DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMessagesUpdatedDelegate);
441 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel")
442 FMessagesUpdatedDelegate MessagesUpdated;
443
444 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMessageDelegate, const FMessage&, Messages);
446 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel")
447 FMessageDelegate MessageSent;
448
450 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel")
451 FMessageDelegate MessageReceived;
452
453 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FUnreadChangedDelegate, int32, UnreadCount);
455 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel")
456 FUnreadChangedDelegate UnreadChanged;
457
458private:
459 void AddMessage(const FMessage&);
460 void MarkRead(const TOptional<FString>& MessageId);
461
462 void OnMessageUpdated(const FMessageUpdatedEvent&);
463 void OnMessageDeleted(const FMessageDeletedEvent&);
464
465 void OnMessageNew(const FMessageNewEvent&);
466 void OnNotificationMessageNew(const FNotificationMessageNewEvent&);
467 void HandleNewMessageEvent(const FMessageEvent&);
468
469 void OnMessageRead(const FMessageReadEvent&);
470 void OnNotificationMessageRead(const FNotificationMarkReadEvent&);
471 void UpdateUnread(const FUserRef& User, int32 UnreadCount, const FDateTime& LastRead);
472
474#pragma endregion Message
475
476#pragma region Thread
482public:
496 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Thread", DisplayName = "Send Reply", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo))
497 void SendReplyBP(
498 const FMessage& Reply,
499 const FMessage& ParentMessage,
500 bool bAlsoSendInChannel,
501 const UObject* WorldContextObject,
502 FLatentActionInfo LatentInfo,
503 bool& bSuccess);
504 void SendReply(
505 const FMessage& Reply,
506 const FMessage& ParentMessage,
507 bool bAlsoSendInChannel = false,
508 const TFunction<void(const bool& bSuccess)> Callback = {});
509
520 void QueryReplies(const FMessage& ParentMessage, int32 Limit = 20, TFunction<void(const TArray<FMessage>&)> Callback = {});
521
530 void QueryAdditionalReplies(const FMessage& ParentMessage, int32 Limit = 20, TFunction<void(const TArray<FMessage>&)> Callback = {});
531
533 const FMessages& GetReplies(const FMessage& ParentMessage) const;
534
540 UFUNCTION(BlueprintPure, Category = "Stream Chat|Channel|Thread", DisplayName = "Get Replies")
541 TArray<FMessage> GetRepliesBP(const FMessage& ParentMessage) const;
542
543 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FRepliesUpdatedDelegate, const FString&, ParentMessageId);
546 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel|Thread")
547 FRepliesUpdatedDelegate RepliesUpdated;
548
549private:
550 void FetchReplies(const FString& ParentId, const FMessagePaginationOptions&, TFunction<void(const TArray<FMessage>&)> Callback);
551
553#pragma endregion Thread
554
555#pragma region Reaction
561public:
570 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Reaction")
571 FReaction SendReaction(const FMessage& Message, const FName& ReactionType, int32 Score = 1, bool bEnforceUnique = false);
572
580 void GetReactions(const FMessage& Message, const FPaginationOptions& Pagination = {}, TFunction<void(const TArray<FReaction>&)> Callback = {});
581
588 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Reaction")
589 void DeleteReaction(const FMessage& Message, const FReaction& Reaction);
590
591private:
592 void OnReactionNew(const FReactionNewEvent&);
593 void OnReactionUpdated(const FReactionUpdatedEvent&);
594 void OnReactionDeleted(const FReactionDeletedEvent&);
595
597#pragma endregion Reaction
598
599#pragma region Typing
604public:
609 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Typing", meta = (AdvancedDisplay = ParentMessageId))
610 void KeyStroke(const FString& ParentMessageId = TEXT(""));
611
617 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Typing", meta = (AdvancedDisplay = ParentMessageId))
618 void StopTyping(const FString& ParentMessageId = TEXT(""));
619
620 DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FTypingIndicatorDelegate, ETypingIndicatorState, TypingState, const FUserRef&, User);
622 UPROPERTY(BlueprintAssignable)
623 FTypingIndicatorDelegate OnTypingIndicator;
624
625 DECLARE_DYNAMIC_MULTICAST_DELEGATE_ThreeParams(FThreadTypingIndicatorDelegate, ETypingIndicatorState, TypingState, const FUserRef&, User, const FString&, ParentMessageId);
628 UPROPERTY(BlueprintAssignable)
629 FThreadTypingIndicatorDelegate OnThreadTypingIndicator;
630
631private:
632 void SendStopTypingEvent(const FString& ParentMessageId = TEXT(""));
633 void OnTypingStart(const FTypingStartEvent&);
634 void OnTypingStop(const FTypingStopEvent&);
635
636 float TypingTimeout = 2.f;
637 TOptional<FDateTime> LastKeystrokeAt;
638 FTimerHandle TypingTimerHandle;
639
641#pragma endregion Typing
642
643#pragma region Moderation
648public:
658 UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Stream Chat|Channel|Moderation", DisplayName = "Ban Member")
659 void BanMemberBP(const FUserRef& User, FTimespan Timeout, FString Reason, bool bIpBan) const;
660 void BanMember(const FUserRef& User, const TOptional<FTimespan>& Timeout = {}, const TOptional<FString>& Reason = {}, bool bIpBan = false) const;
661
666 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation")
667 void UnbanMember(const FUserRef& User) const;
668
676 UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Stream Chat|Channel|Moderation", DisplayName = "Shadow Ban Member")
677 void ShadowBanMemberBP(const FUserRef& User, FTimespan Timeout) const;
678 void ShadowBanMember(const FUserRef& User, const TOptional<FTimespan>& Timeout = {}) const;
679
684 UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Stream Chat|Channel|Moderation")
685 void ShadowUnbanMember(const FUserRef& User) const;
686
691 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation", DisplayName = "Mute")
692 void MuteBP(FTimespan Timeout);
693 void Mute(const TOptional<FTimespan>& Timeout = {});
694
698 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation")
699 void Unmute() const;
700
704 UFUNCTION(BlueprintPure, Category = "Stream Chat|Channel|Moderation")
705 bool IsMuted() const;
706
710 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation")
711 void EnableSlowMode(FTimespan Cooldown);
712
716 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation")
717 void DisableSlowMode();
718
719private:
720 void OnUserBanned(const FUserBannedEvent&);
721 void OnUserUnbanned(const FUserUnbannedEvent&);
722
724#pragma endregion Moderation
725};
726
727template <class TEvent>
728void UChatChannel::SendEvent(const TEvent& Event)
729{
730 Api->SendChannelEvent(Properties.Type, Properties.Id, Event);
731}
732
733template <class TEvent>
734FDelegateHandle UChatChannel::On(TEventDelegate<TEvent> Callback)
735{
736 return Socket->Events().SubscribeLambda<TEvent>(
737 [this, Callback](const TEvent& Event)
738 {
739 // TODO static assert with nice error message
740 // https://stackoverflow.com/questions/1005476/how-to-detect-whether-there-is-a-specific-member-variable-in-class
741 if (Event.Cid == Properties.Cid)
742 {
743 Callback.ExecuteIfBound(Event);
744 }
745 });
746}
747
748template <class TEvent, class UserClass>
749typename TEnableIf<TIsDerivedFrom<UserClass, UObject>::IsDerived, FDelegateHandle>::Type UChatChannel::On(
750 UserClass* Obj,
751 TEventDelegateUObjectMethodPtr<TEvent, UserClass> Method)
752{
753 const TEventDelegate<TEvent> Delegate = TEventDelegate<TEvent>::CreateUObject(Obj, Method);
754 return On<TEvent>(Delegate);
755}
756
757template <class TEvent, class UserClass>
758typename TEnableIf<!TIsDerivedFrom<UserClass, UObject>::IsDerived, FDelegateHandle>::Type UChatChannel::On(
759 UserClass* Obj,
760 TEventDelegateSpMethodPtr<TEvent, UserClass> Method)
761{
762 const TEventDelegate<TEvent> Delegate = TEventDelegate<TEvent>::CreateSP(Obj, Method);
763 return On<TEvent>(Delegate);
764}
765
766template <class TEvent, typename FunctorType, typename... VarTypes>
767typename TEnableIf<TIsInvocable<FunctorType, const TEvent&, VarTypes...>::Value, FDelegateHandle>::Type UChatChannel::On(
768 FunctorType&& Functor,
769 VarTypes... Vars)
770{
771 const TEventDelegate<TEvent> Delegate = TEventDelegate<TEvent>::CreateLambda(Forward<FunctorType>(Functor), Vars...);
772 return On<TEvent>(Delegate);
773}
774
775template <class TEvent>
776bool UChatChannel::Unsubscribe(const FDelegateHandle Handle) const
777{
778 return Socket->Events().Unsubscribe<TEvent>(Handle);
779}
All Stream Chat REST API requests can be made via this object.
Definition ChatApi.h:67
Interface to a Stream Chat WebSocket connection.
Definition IChatSocket.h:17
The client-side representation of a Stream Chat channel.
Definition ChatChannel.h:75
FChannelProperties Properties
The local static properties of the channel.
Definition ChatChannel.h:177
TEnableIf<!TIsDerivedFrom< UserClass, UObject >::IsDerived, FDelegateHandle >::Type On(UserClass *Obj, TEventDelegateSpMethodPtr< TEvent, UserClass > Method)
Subscribe to a channel event using a shared pointer-based (fast, not thread-safe) member function del...
FDelegateHandle On(TEventDelegate< TEvent > Callback)
Subscribe to a channel event using your own delegate object.
Definition ChatChannel.h:734
bool Unsubscribe(FDelegateHandle) const
Unsubscribe from a previously subscribed channel event.
Definition ChatChannel.h:776
void SendEvent(const TEvent &)
Send a custom event on this channel.
Definition ChatChannel.h:728
A component which allows for connecting to the Stream Chat API. Should be added to a client-side acto...
Definition StreamChatClientComponent.h:45
EChannelFlags
Additional channel actions to perform when requesting channel data from API.
Definition ChannelFlags.h:15
@ State
Return channel state in response.
@ None
Do nothing.
@ Type
Type of the message.
@ ParentId
The parent message ID (if the message is a reply)
@ ParentMessageId
The ID of the message which started the thread.
@ Query
Matches values by performing text search with the specified value.
A file, image or link attached to a message.
Definition Attachment.h:42
Represents an event that happened in a Stream channel.
Definition ChannelEvent.h:17
Encapsulates the static properties of a channel.
Definition ChannelProperties.h:21
FString Id
Definition ChannelProperties.h:69
FString Cid
The cid of this channel.
Definition ChannelProperties.h:73
FString Type
Definition ChannelProperties.h:64
Encapsulates the local state of a channel.
Definition ChannelState.h:20
#/components/schemas/ChannelStateResponse
Definition ChannelStateResponseDto.h:16
#/components/schemas/ChannelStateResponseFields
Definition ChannelStateResponseFieldsDto.h:19
A filter used for querying channels.
Definition Filter.h:75
A message was deleted.
Definition MessageDeletedEvent.h:17
A WebSocket event related to a message.
Definition MessageEvent.h:18
Represents a Stream Chat message.
Definition Message.h:70
A new message was created.
Definition MessageNewEvent.h:17
Options for pagination of messages.
Definition MessagePaginationOptions.h:17
A new message was created.
Definition MessageReadEvent.h:18
The desired sort options for message queries.
Definition ChannelSortOption.h:100
A message's content was updated.
Definition MessageUpdatedEvent.h:17
Notification when a message or entire channel was marked as read.
Definition NotificationMarkReadEvent.h:19
Notification when a new message was created.
Definition NotificationMessageNewEvent.h:17
Options for pagination.
Definition PaginationOptions.h:15
A reaction was deleted.
Definition ReactionDeletedEvent.h:17
An individual reaction to a message.
Definition Reaction.h:18
A new reaction was created.
Definition ReactionNewEvent.h:17
A reaction was updated.
Definition ReactionUpdatedEvent.h:17
A user started typing.
Definition TypingStartEvent.h:18
A user stoped typing.
Definition TypingStopEvent.h:18
#/components/schemas/UserBannedEvent
Definition UserBannedEvent.h:18
A reference to a unique User.
Definition UserRef.h:23
#/components/schemas/UserUnbannedEvent
Definition UserUnbannedEvent.h:18