Stream Chat Unreal SDK
Loading...
Searching...
No Matches
ChatChannel.h
1// Copyright 2022 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 "User/UserPaginationOptions.h"
19#include "User/UserRef.h"
20
21#include "ChatChannel.generated.h"
22
24struct FChannelEvent;
28struct FMessageEvent;
29struct FMessageNewEvent;
38struct FTypingStopEvent;
39struct FUserBannedEvent;
41
42UENUM(BlueprintType)
43enum class ETypingIndicatorState : uint8
44{
45 StartTyping,
46 StopTyping
47};
48
49UENUM(BlueprintType, meta = (BitFlags))
50enum class EPaginationDirection : uint8
51{
52 None UMETA(Hidden),
53
55 Top = 1 << 0,
57 Bottom = 1 << 1,
58};
59ENUM_CLASS_FLAGS(EPaginationDirection);
60
61UENUM(BlueprintType)
62enum class EHttpRequestState : uint8
63{
64 Started,
65 Ended
66};
67
72UCLASS(BlueprintType)
73class STREAMCHAT_API UChatChannel final : public UObject
74{
75 GENERATED_BODY()
76
77public:
79 static UChatChannel* Create(UObject* Outer, const TSharedRef<FChatApi>, const TSharedRef<IChatSocket>, const FChannelStateResponseFieldsDto&);
81 static UChatChannel* Create(UObject* Outer, const TSharedRef<FChatApi>, const TSharedRef<IChatSocket>);
82
84 bool IsValid() const;
85
90 void Delete(TFunction<void()> Callback = {}) const;
91
98 void PartialUpdate(const TSharedRef<FJsonObject>& Set = {}, const TArray<FString>& Unset = {}, TFunction<void()> Callback = {});
99
106 void Update(const FAdditionalFields& Data, const TOptional<FMessage>& Message = {}, TFunction<void()> Callback = {});
107
116 void Truncate(
117 bool bHardDelete = false,
118 const TOptional<FDateTime>& TruncatedAt = {},
119 const TOptional<FMessage>& Message = {},
120 bool bSkipPush = false,
121 TFunction<void()> Callback = {});
122
132 void QueryMembers(
133 const FFilter& Filter = {},
134 const TArray<FUserSortOption>& Sort = {},
135 const FMessagePaginationOptions& Pagination = {},
136 TFunction<void(const TArray<FMember>&)> Callback = {});
137
144 void AddMembers(const TArray<FString>& MemberIds, const TOptional<FMessage>& Message = {}, TFunction<void()> Callback = {});
145
152 void RemoveMembers(const TArray<FString>& MemberIds, const TOptional<FMessage>& Message = {}, TFunction<void()> Callback = {});
153
160 void Hide(bool bClearHistory = false, TFunction<void()> Callback = {}) const;
161
166 void Show(TFunction<void()> Callback = {}) const;
167
172 void StopWatching(TFunction<void()> Callback = {}) const;
173
175 UPROPERTY(BlueprintReadOnly, Category = "Stream Chat|Channel")
177
179 UPROPERTY(BlueprintReadOnly, Category = "Stream Chat|Channel")
181
182private:
183 void MergeState(const FChannelStateResponseFieldsDto&);
184
185 TSharedPtr<FChatApi> Api;
186 TSharedPtr<IChatSocket> Socket;
187
188#pragma region Event
194public:
196 template <class TEvent>
197 void SendEvent(const TEvent&);
198
200 template <class TEvent>
201 FDelegateHandle On(TEventDelegate<TEvent> Callback);
202
210 template <class TEvent, class UserClass>
211 typename TEnableIf<TIsDerivedFrom<UserClass, UObject>::IsDerived, FDelegateHandle>::Type On(
212 UserClass* Obj,
213 TEventDelegateUObjectMethodPtr<TEvent, UserClass> Method);
214
223 template <class TEvent, class UserClass>
224 typename TEnableIf<!TIsDerivedFrom<UserClass, UObject>::IsDerived, FDelegateHandle>::Type On(
225 UserClass* Obj,
226 TEventDelegateSpMethodPtr<TEvent, UserClass> Method);
227
235 template <class TEvent, typename FunctorType, typename... VarTypes>
236 typename TEnableIf<TIsInvocable<FunctorType, const TEvent&, VarTypes...>::Value, FDelegateHandle>::Type On(FunctorType&& Functor, VarTypes... Vars);
237
244 template <class TEvent>
245 bool Unsubscribe(FDelegateHandle) const;
246
248#pragma endregion Event
249
250#pragma region Message
256public:
262 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message", DisplayName = "Send Message", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo))
263 void SendMessageBP(const FMessage& Message, const UObject* WorldContextObject, FLatentActionInfo LatentInfo, bool& bSuccess);
264 void SendMessage(const FMessage& Message, const TFunction<void(const bool& bSuccess)> = {});
265
270 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message", DisplayName = "Get Message", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo))
271 void GetMessageBP(const FString& MessageId, const UObject* WorldContextObject, FLatentActionInfo LatentInfo, FMessage& OutMessage);
272 void GetMessage(const FString& MessageId, const TFunction<void(const FMessage&)> Callback = {});
273
279 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message")
280 void UpdateMessage(const FMessage& Message);
281
287 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message")
288 void DeleteMessage(const FMessage& Message);
289
298 void QueryAdditionalMessages(EPaginationDirection Direction = EPaginationDirection::Top, int32 Limit = 20, TFunction<void()> Callback = {});
299
304 void MarkRead(const TOptional<FMessage>& Message = {});
309 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Message", meta = (AutoCreateRefTerm = Message))
310 void MarkRead(const FMessage& Message);
311
313 void MarkReadLocal();
314
324 void Query(
326 const TOptional<FMessagePaginationOptions> MessagePagination = {},
327 const TOptional<FUserPaginationOptions> MemberPagination = {},
328 const TOptional<FUserPaginationOptions> WatcherPagination = {},
329 TFunction<void()> Callback = {});
330
342 void SearchMessages(
343 const TOptional<FString>& Query = {},
344 const TOptional<FFilter>& MessageFilter = {},
345 const TArray<FMessageSortOption>& Sort = {},
346 TOptional<uint32> MessageLimit = {},
347 TFunction<void(const TArray<FMessage>&)> Callback = {}) const;
348
360 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel", meta = (Latent, WorldContext = WorldContextObject, LatentInfo = LatentInfo, AutoCreateRefTerm = "Sort,MessageFilter"))
361 void SearchMessages(
362 const FString& Query,
363 const FFilter& MessageFilter,
364 const TArray<FMessageSortOption>& Sort,
365 int32 MessageLimit,
366 const UObject* WorldContextObject,
367 FLatentActionInfo LatentInfo,
368 TArray<FMessage>& OutMessages);
369
370 DECLARE_DYNAMIC_MULTICAST_DELEGATE(FMessagesUpdatedDelegate);
372 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel")
373 FMessagesUpdatedDelegate MessagesUpdated;
374
375 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FMessageDelegate, const FMessage&, Messages);
377 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel")
378 FMessageDelegate MessageSent;
379
381 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel")
382 FMessageDelegate MessageReceived;
383
384 DECLARE_DYNAMIC_MULTICAST_DELEGATE_OneParam(FUnreadChangedDelegate, int32, UnreadCount);
386 UPROPERTY(BlueprintAssignable, Category = "Stream Chat|Channel")
387 FUnreadChangedDelegate UnreadChanged;
388
389private:
390 void AddMessage(const FMessage&);
391 void MarkRead(const TOptional<FString>& MessageId);
392
393 void OnMessageUpdated(const FMessageUpdatedEvent&);
394 void OnMessageDeleted(const FMessageDeletedEvent&);
395
396 void OnMessageNew(const FMessageNewEvent&);
397 void OnNotificationMessageNew(const FNotificationMessageNewEvent&);
398 void HandleNewMessageEvent(const FMessageEvent&);
399
400 void OnMessageRead(const FMessageReadEvent&);
401 void OnNotificationMessageRead(const FNotificationMarkReadEvent&);
402 void UpdateUnread(const FUserRef& User, int32 UnreadCount, const FDateTime& LastRead);
403
405#pragma endregion Message
406
407#pragma region Reaction
413public:
422 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Reaction")
423 FReaction SendReaction(const FMessage& Message, const FName& ReactionType, int32 Score = 1, bool bEnforceUnique = false);
424
432 void GetReactions(const FMessage& Message, const FPaginationOptions& Pagination = {}, TFunction<void(const TArray<FReaction>&)> Callback = {});
433
440 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Reaction")
441 void DeleteReaction(const FMessage& Message, const FReaction& Reaction);
442
443private:
444 void OnReactionNew(const FReactionNewEvent&);
445 void OnReactionUpdated(const FReactionUpdatedEvent&);
446 void OnReactionDeleted(const FReactionDeletedEvent&);
447
449#pragma endregion Reaction
450
451#pragma region Typing
456public:
461 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Typing", meta = (AdvancedDisplay = ParentMessageId))
462 void KeyStroke(const FString& ParentMessageId = TEXT(""));
463
469 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Typing", meta = (AdvancedDisplay = ParentMessageId))
470 void StopTyping(const FString& ParentMessageId = TEXT(""));
471
472 DECLARE_DYNAMIC_MULTICAST_DELEGATE_TwoParams(FTypingIndicatorDelegate, ETypingIndicatorState, TypingState, const FUserRef&, User);
474 UPROPERTY(BlueprintAssignable)
475 FTypingIndicatorDelegate OnTypingIndicator;
476
477private:
478 void SendStopTypingEvent(const FString& ParentMessageId = TEXT(""));
479 void OnTypingStart(const FTypingStartEvent&);
480 void OnTypingStop(const FTypingStopEvent&);
481
482 float TypingTimeout = 2.f;
483 TOptional<FDateTime> LastKeystrokeAt;
484 FTimerHandle TypingTimerHandle;
485
487#pragma endregion Typing
488
489#pragma region Moderation
494public:
504 UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Stream Chat|Channel|Moderation", DisplayName = "Ban Member")
505 void BanMemberBP(const FUserRef& User, FTimespan Timeout, FString Reason, bool bIpBan) const;
506 void BanMember(const FUserRef& User, const TOptional<FTimespan>& Timeout = {}, const TOptional<FString>& Reason = {}, bool bIpBan = false) const;
507
512 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation")
513 void UnbanMember(const FUserRef& User) const;
514
522 UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Stream Chat|Channel|Moderation", DisplayName = "Shadow Ban Member")
523 void ShadowBanMemberBP(const FUserRef& User, FTimespan Timeout) const;
524 void ShadowBanMember(const FUserRef& User, const TOptional<FTimespan>& Timeout = {}) const;
525
530 UFUNCTION(BlueprintCallable, BlueprintPure = false, Category = "Stream Chat|Channel|Moderation")
531 void ShadowUnbanMember(const FUserRef& User) const;
532
537 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation", DisplayName = "Mute")
538 void MuteBP(FTimespan Timeout);
539 void Mute(const TOptional<FTimespan>& Timeout = {});
540
544 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation")
545 void Unmute() const;
546
550 UFUNCTION(BlueprintPure, Category = "Stream Chat|Channel|Moderation")
551 bool IsMuted() const;
552
556 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation")
557 void EnableSlowMode(FTimespan Cooldown);
558
562 UFUNCTION(BlueprintCallable, Category = "Stream Chat|Channel|Moderation")
563 void DisableSlowMode();
564
565private:
566 void OnUserBanned(const FUserBannedEvent&);
567 void OnUserUnbanned(const FUserUnbannedEvent&);
568
570#pragma endregion Moderation
571};
572
573template <class TEvent>
574void UChatChannel::SendEvent(const TEvent& Event)
575{
576 Api->SendChannelEvent(Properties.Type, Properties.Id, Event);
577}
578
579template <class TEvent>
580FDelegateHandle UChatChannel::On(TEventDelegate<TEvent> Callback)
581{
582 return Socket->Events().SubscribeLambda<TEvent>(
583 [this, Callback](const TEvent& Event)
584 {
585 // TODO static assert with nice error message
586 // https://stackoverflow.com/questions/1005476/how-to-detect-whether-there-is-a-specific-member-variable-in-class
587 if (Event.Cid == Properties.Cid)
588 {
589 Callback.ExecuteIfBound(Event);
590 }
591 });
592}
593
594template <class TEvent, class UserClass>
595typename TEnableIf<TIsDerivedFrom<UserClass, UObject>::IsDerived, FDelegateHandle>::Type UChatChannel::On(
596 UserClass* Obj,
597 TEventDelegateUObjectMethodPtr<TEvent, UserClass> Method)
598{
599 const TEventDelegate<TEvent> Delegate = TEventDelegate<TEvent>::CreateUObject(Obj, Method);
600 return On<TEvent>(Delegate);
601}
602
603template <class TEvent, class UserClass>
604typename TEnableIf<!TIsDerivedFrom<UserClass, UObject>::IsDerived, FDelegateHandle>::Type UChatChannel::On(
605 UserClass* Obj,
606 TEventDelegateSpMethodPtr<TEvent, UserClass> Method)
607{
608 const TEventDelegate<TEvent> Delegate = TEventDelegate<TEvent>::CreateSP(Obj, Method);
609 return On<TEvent>(Delegate);
610}
611
612template <class TEvent, typename FunctorType, typename... VarTypes>
613typename TEnableIf<TIsInvocable<FunctorType, const TEvent&, VarTypes...>::Value, FDelegateHandle>::Type UChatChannel::On(
614 FunctorType&& Functor,
615 VarTypes... Vars)
616{
617 const TEventDelegate<TEvent> Delegate = TEventDelegate<TEvent>::CreateLambda(Forward<FunctorType>(Functor), Vars...);
618 return On<TEvent>(Delegate);
619}
620
621template <class TEvent>
622bool UChatChannel::Unsubscribe(const FDelegateHandle Handle) const
623{
624 return Socket->Events().Unsubscribe<TEvent>(Handle);
625}
All Stream Chat REST API requests can be made via this object.
Definition: ChatApi.h:59
Interface to a Stream Chat WebSocket connection.
Definition: IChatSocket.h:17
The client-side representation of a Stream Chat channel.
Definition: ChatChannel.h:74
FChannelProperties Properties
The local static properties of the channel.
Definition: ChatChannel.h:176
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:580
bool Unsubscribe(FDelegateHandle) const
Unsubscribe from a previously subscribed channel event.
Definition: ChatChannel.h:622
void SendEvent(const TEvent &)
Send a custom event on this channel.
Definition: ChatChannel.h:574
A component which allows for connecting to the Stream Chat API. Should be added to a client-side acto...
Definition: StreamChatClientComponent.h:42
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.
@ Query
Matches values by performing text search with the specified value.
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:17
Represents a Stream Chat message.
Definition: Message.h:66
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