Stream Chat Unreal SDK
Loading...
Searching...
No Matches
MessageWidget.h
1// Copyright 2026 Stream.IO, Inc. All Rights Reserved.
2
3#pragma once
4
5#include "AttachmentWidget.h"
6#include "Channel/Message.h"
7#include "Components/Overlay.h"
8#include "CoreMinimal.h"
9#include "MessageHoverMenuWidget.h"
10#include "Reaction/MessageReactionsWidget.h"
11#include "StreamWidget.h"
12#include "TextBubbleWidget.h"
13#include "TimestampWidget.h"
14
15#include "MessageWidget.generated.h"
16
20UCLASS()
21class STREAMCHATUI_API UMessageWidget final : public UStreamWidget
22{
23 GENERATED_BODY()
24
25public:
26 explicit UMessageWidget();
27 UFUNCTION(BlueprintCallable, Category = "Stream Chat")
28 void Setup(const FMessage& InMessage, EMessageSide InSide, EMessagePosition InPosition);
29
30protected:
31 UPROPERTY(meta = (BindWidgetOptional))
32 UTextBubbleWidget* TextBubble;
33
34 // Should contain whatever needs to be horizontally aligned
35 UPROPERTY(meta = (BindWidgetOptional))
36 UVerticalBox* AlignPanel;
37
38 // Where the mouse hover menu will be spawned
39 UPROPERTY(meta = (BindWidgetOptional))
40 UContentWidget* HoverMenuTargetPanel;
41
42 // Where the reactions will be spawned
43 UPROPERTY(meta = (BindWidgetOptional))
44 UContentWidget* ReactionsTargetPanel;
45
46 // Where the timestamp will (maybe) be spawned
47 UPROPERTY(meta = (BindWidgetOptional))
48 UContentWidget* TimestampTargetPanel;
49
50 // Where the avatar will (maybe) be spawned
51 UPROPERTY(meta = (BindWidgetOptional))
52 UContentWidget* AvatarTargetPanel;
53
54 UPROPERTY(EditDefaultsOnly, NoClear, Category = Defaults)
55 TSubclassOf<UMessageHoverMenuWidget> MouseHoverMenuWidgetClass = UMessageHoverMenuWidget::StaticClass();
56
57 UPROPERTY(EditDefaultsOnly, NoClear, Category = Defaults)
58 TSubclassOf<UMessageReactionsWidget> ReactionsWidgetClass = UMessageReactionsWidget::StaticClass();
59
60 UPROPERTY(EditDefaultsOnly, NoClear, Category = Defaults)
61 TSubclassOf<UAvatarWidget> AvatarWidgetClass = UAvatarWidget::StaticClass();
62
63 UPROPERTY(EditDefaultsOnly, NoClear, Category = Defaults)
64 TSubclassOf<UTimestampWidget> TimestampWidgetClass = UTimestampWidget::StaticClass();
65
66 UPROPERTY(EditDefaultsOnly, NoClear, Category = Defaults)
67 TSubclassOf<UAttachmentWidget> AttachmentWidgetClass = UAttachmentWidget::StaticClass();
68
69 UPROPERTY(EditDefaultsOnly, Category = Defaults)
70 int32 AvatarSize = 36;
71
73 UPROPERTY(EditDefaultsOnly, Category = Defaults)
74 FMargin AttachmentPadding = FMargin{0.f, 0.f, 0.f, 2.f};
75
77 UPROPERTY(EditDefaultsOnly, Category = Thread)
78 FMargin ThreadFooterPadding = FMargin{2.f, 2.f, 2.f, 0.f};
79
80 UPROPERTY(EditDefaultsOnly, Category = Thread)
81 int32 ThreadFooterFontSize = 12;
82
89 UPROPERTY(EditDefaultsOnly, Category = "Message Actions")
90 float LongPressSeconds = 0.4f;
91
99 UPROPERTY(EditDefaultsOnly, Category = "Message Actions")
100 float LongPressMoveTolerance = 4.f;
101
103 UPROPERTY(EditDefaultsOnly, Category = Moderation)
104 FMargin ModerationWarningPadding = FMargin{2.f, 2.f, 2.f, 0.f};
105
106 UPROPERTY(EditDefaultsOnly, Category = Moderation)
107 int32 ModerationWarningFontSize = 12;
108
110 UPROPERTY(EditDefaultsOnly, Category = Moderation)
111 FText BouncedMessageText = NSLOCTEXT("StreamChat", "BouncedMessage", "Not sent. Hold to edit, send anyway or delete.");
112
114 UPROPERTY(EditDefaultsOnly, Category = Thread)
115 FText OneReplyText = NSLOCTEXT("StreamChat", "OneReply", "1 reply");
116
118 UPROPERTY(EditDefaultsOnly, Category = Thread)
119 FText ManyRepliesFormat = NSLOCTEXT("StreamChat", "ManyReplies", "{0} replies");
120
121 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Setup)
122 FMessage Message;
123 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Setup)
124 EMessagePosition Position;
125 UPROPERTY(EditAnywhere, BlueprintReadOnly, Category = Setup)
126 EMessageSide Side;
127
128private:
129 virtual void OnSetup() override;
130 virtual void NativeConstruct() override;
131 virtual void NativeDestruct() override;
132
133 virtual void NativeOnMouseEnter(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
134 virtual void NativeOnMouseLeave(const FPointerEvent& InMouseEvent) override;
135 virtual FReply NativeOnMouseButtonDown(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
136 virtual FReply NativeOnMouseButtonUp(const FGeometry& InGeometry, const FPointerEvent& InMouseEvent) override;
137
138 bool ShouldDisplayHoverMenu() const;
139
144 void BeginLongPress();
145 void CancelLongPress();
146 void OnLongPressElapsed();
147 bool ShouldDisplayActionsMenu() const;
148 void CreateActionsMenuAnchor();
149
150 UFUNCTION()
151 UUserWidget* CreateActionsMenu();
153
154 void CreateAttachmentWidgets();
155
162 void CreateThreadFooter();
163 bool ShouldDisplayThreadFooter() const;
164 FText GetThreadFooterText() const;
165
173 void CreateModerationWarning();
174 bool ShouldDisplayModerationWarning() const;
175
176 UFUNCTION()
177 void OnThreadFooterClicked();
178
179 // Only valid while hovered
180 UPROPERTY(Transient)
181 UMessageHoverMenuWidget* MouseHoverMenu;
182
183 // Only valid if message has reactions
184 UPROPERTY(Transient)
185 UMessageReactionsWidget* Reactions;
186
187 // Live in AlignPanel rather than a panel of their own, so tracked here to be replaced on re-setup
188 UPROPERTY(Transient)
189 TArray<UAttachmentWidget*> Attachments;
190
191 // Also lives in AlignPanel, for the same reason: WBP_Message has no slot for it
192 UPROPERTY(Transient)
193 UButton* ThreadFooterButton;
194
195 UPROPERTY(Transient)
196 UTextBlock* ThreadFooterText;
197
199 UPROPERTY(Transient)
200 UTextBlock* ModerationWarningText;
201
204 UPROPERTY(Transient)
205 UMenuAnchor* ActionsMenuAnchor;
206
207 FTimerHandle LongPressTimer;
209 FVector2D PressPosition = FVector2D::ZeroVector;
210};
Encapsulates a text bubble, reactions and the mouse hover menu for a message.
Definition MessageWidget.h:22
Represents a Stream Chat message.
Definition Message.h:70