Create message drafts
MessageDraft represents an unpublished message. Use it to:
- Edit text before publishing
- Add channel references, user mentions, and links
Display message elements (mentions, references, links) in your UI by binding the OnMessageDraftUpdatedWithSuggestions delegate.
note
CreateMessageDraft is always synchronousCreateMessageDraft() is a local, in-memory operation — it does not perform any network requests. It returns a UPubnubChatMessageDraft* directly and has no Async variant. The async/sync split applies to network methods (Send(), SendAsync(), etc.) called on the draft after it is created.
1UPubnubChatMessageDraft* Draft = Channel->CreateMessageDraft(MessageDraftConfig);
- Basics
- Class diagram
- Example
- Internal mention format
Message drafts consist of FPubnubChatMessageElement structs, each containing a Text field (the display text) and optionally a MentionTarget field (for user mentions, channel references, or URLs). Each element also tracks its Start position and Length in the draft.
The FPubnubChatMentionTarget struct has a MentionTargetType enum property. Available types:
EPubnubChatMentionTargetType::PCMTT_UserEPubnubChatMentionTargetType::PCMTT_ChannelEPubnubChatMentionTargetType::PCMTT_UrlEPubnubChatMentionTargetType::PCMTT_None(plain text, no mention)
Store draft messages locally
Unreal Chat SDK does not persist drafts. Implement your own local storage to save drafts across channel switches.
Safe mutations
The SDK validates all draft mutations (InsertText, RemoveText, AppendText, AddMention, RemoveMention). Operations that would corrupt an existing mention or link offset return an error in FPubnubChatOperationResult instead of silently breaking the draft's element structure.
Consider the message Hey, I sent Alex this link on the #offtopic channel. where:
Alexis a reference to the user with the ID ofalex_dlinkis a URL of thewww.pubnub.comwebsite#offtopicis a reference to the channel with the ID ofgroup.offtopic
The list of MessageElement objects returned by the MessageDraftChangeListener is as follows:
The message draft format uses Markdown-like syntax internally, integrating links with the pattern [link text](link target).
| Mention Type | Example |
|---|---|
| user | [John Doe](pn-user://john_doe) |
| channel | [General Chat](pn-channel://group.chat.123) |
| url | [PubNub](https://www.pubnub.com) |
Custom schemas like pn-user:// and pn-channel:// are used to identify user and channel mentions, while traditional URLs are supported as-is.
Adding message elements
This syntax is internal only. To add elements, use AddMention().
Create a draft message
CreateMessageDraft() creates a (MessageDraft object) that can consist of:
- Plain text
- Mentioned users
- Referenced channels
- Links
Method signature
- C++ / Input parameters
- Blueprint
1Channel->CreateMessageDraft(FPubnubChatMessageDraftConfig MessageDraftConfig = FPubnubChatMessageDraftConfig())
| Parameter | Description |
|---|---|
MessageDraftConfigDefault: FPubnubChatMessageDraftConfig() | Configuration for the message draft, including settings such as initial content and metadata. |
FPubnubChatMessageDraftConfig
| Parameter | Description |
|---|---|
UserSuggestionSourceType: EPubnubChatMessageDraftSuggestionSourceDefault: PCMDSS_Global | Source for user mention suggestions. PCMDSS_Channel limits suggestions to channel members; PCMDSS_Global searches all app users. |
IsTypingIndicatorTriggeredType: boolDefault: false | When true, the draft triggers typing indicator events on the channel when text is edited. |
UserLimitType: intDefault: 10 | Maximum number of user mention suggestions to return (max: 100). |
ChannelLimitType: intDefault: 10 | Maximum number of channel reference suggestions to return (max: 100). |
Output
| Parameter | Description |
|---|---|
UPubnubChatMessageDraft*Type: UPubnubChatMessageDraft* | Pointer to the created MessageDraft object, which can be used to edit the draft, insert mentions, and eventually send the message. |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Create a message draft on a channel.
Listen for message draft changes
Bind to delegates on the MessageDraft object to receive notifications when the draft content changes.
Delegate signature
| Delegate | Parameter |
|---|---|
FOnPubnubChatMessageDraftUpdatedType: TArray<FPubnubChatMessageElement> | MessageElements |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Bind the delegate to your message draft.
Actor.h
1
Actor.cpp
1
Listen for message draft changes (with suggestions)
Bind the OnMessageDraftUpdatedWithSuggestions delegate to receive draft changes along with suggestions for user mentions, links, and channel references.
Example: typing #Sup returns channels like Support or Support-Agents. Default: 10 suggestions (max: 100).
Delegate signature
| Delegate | Parameter |
|---|---|
FOnPubnubChatMessageDraftUpdatedWithSuggestionsType: TArray<FPubnubChatMessageElement> | MessageElements |
Type: TArray<FPubnubChatSuggestedMention> | SuggestedMentions |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Bind the delegate to your message draft.
Actor.h
1
Actor.cpp
1
Add message element
AddMention() adds a user mention, channel reference or a link specified by a mention target at a given position.
Method signature
1MessageDraft->AddMention(int Position, int Length, const FPubnubChatMentionTarget MentionTarget)
| Parameter | Description |
|---|---|
Position *Type: intDefault: n/a | Position of a character in a message where the message element you want to insert starts. It's counted from the beginning of the message (including spaces), with 0 as the first character. |
Length *Type: intDefault: n/a | Number of characters the message element should occupy in the draft message's text. |
MentionTarget *Type: FPubnubChatMentionTargetDefault: n/a | Mention target struct. Create using UPubnubChatMessageDraftUtilities factory methods. Available mention types ( EPubnubChatMentionTargetType):
|
Output
| Type | Description |
|---|---|
FPubnubChatOperationResult | Operation result with Error (bool) and ErrorMessage (FString). |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Create the Hello Alex! I have sent you this link on the #offtopic channel. message where Alex is a user mention, link is a URL, and #offtopic is a channel reference.
Actor.h
1
Actor.cpp
1
Remove message element
RemoveMention() removes a user mention, channel reference, or a link at a given position.
Method signature
1MessageDraft->RemoveMention(int Position)
| Parameter | Description |
|---|---|
Position *Type: intDefault: n/a | Position of the first character of the message element you want to remove. |
Position value
If you don't provide the position of the first character of the message element to remove, it isn't removed.
Output
| Type | Description |
|---|---|
FPubnubChatOperationResult | Operation result with Error (bool) and ErrorMessage (FString). |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Remove the URL element from the word link in the Hello Alex! I have sent you this link on the #offtopic channel. message.
Actor.h
1
Actor.cpp
1
Update message text
Update() replaces the text of a draft message with new content.
Removing message elements
The SDK preserves message elements when possible. If element text is modified, that element is removed.
Method signature
1MessageDraft->Update(const FString& NewText)
| Parameter | Description |
|---|---|
NewText *Type: FStringDefault: n/a | The new full draft text. |
Output
| Type | Description |
|---|---|
FPubnubChatOperationResult | Operation result with Error (bool) and ErrorMessage (FString). |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Change the message I sent Alex this picture. to I did not send Alex this picture. where Alex is a user mention.
Actor.h
1
Actor.cpp
1
Mention text changes
If you decided to change the name Alex to some other name, the mention would be removed because your updated text's index coincided with an existing mention.
For more manual control over inserting and removing parts of a message, refer to Insert message text and Remove message text.
Insert suggested message element
Inserts a message element returned by the OnMessageDraftUpdatedWithSuggestions delegate into the MessageDraft.
Text must match
The SuggestedMention must be up to date with the message text, that is, SuggestedMention.ReplaceFrom must match the message draft at position SuggestedMention.ReplaceFrom, otherwise an exception is thrown.
Method signature
1MessageDraft->InsertSuggestedMention(const FPubnubChatSuggestedMention SuggestedMention)
| Parameter | Description |
|---|---|
SuggestedMention *Type: FPubnubChatSuggestedMentionDefault: n/a | A user, channel, or URL suggestion obtained from the OnMessageDraftUpdatedWithSuggestions delegate. The ReplaceFrom text must match the current draft text at Offset. |
Output
| Type | Description |
|---|---|
FPubnubChatOperationResult | Operation result with Error (bool) and ErrorMessage (FString). |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Bind the delegate and insert a suggested element.
Actor.h
1
Actor.cpp
1
Insert message text
InsertText() lets you insert plain text in the draft message at a given position from the beginning of the message.
Removing message elements
Inserting text strictly inside a mention span (not at its start or end position) removes the mention and converts its text to plain text. Inserting at the exact start or end boundary of a mention preserves the mention.
Method signature
1MessageDraft->InsertText(int Position, FString Text)
| Parameter | Description |
|---|---|
Position *Type: intDefault: n/a | Position of a character in a message where the text you want to insert starts. It's counted from the beginning of the message (including spaces), with 0 as the first character. |
Text *Type: FStringDefault: n/a | Text that you want to insert. |
Output
| Type | Description |
|---|---|
FPubnubChatOperationResult | Operation result with Error (bool) and ErrorMessage (FString). |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
In the message Check this support article https://www.support-article.com/., add the word out between the words Check and this.
Actor.h
1
Actor.cpp
1
Append text
AppendText() adds text at the end of the draft message. Equivalent to calling InsertText() at position GetCurrentText().Len().
Method signature
1MessageDraft->AppendText(const FString Text)
| Parameter | Description |
|---|---|
Text *Type: FStringDefault: n/a | Text to append to the end of the draft. Must be non-empty. |
Output
| Type | Description |
|---|---|
FPubnubChatOperationResult | Operation result with Error (bool) and ErrorMessage (FString). |
Remove message text
RemoveText() lets you remove plain text from the draft message at a given position from the beginning of the message.
Removing message elements
If the range overlaps an existing mention or link element, the operation returns an error (FPubnubChatOperationResult.Error = true). Use RemoveMention() to explicitly remove a mention element.
Method signature
1MessageDraft->RemoveText(int Position, int Length)
| Parameter | Description |
|---|---|
Position *Type: intDefault: n/a | Position of a character in a message where the text you want to insert starts. It's counted from the beginning of the message (including spaces), with 0 as the first character. |
Length *Type: intDefault: n/a | How many characters to remove, starting at the given Position. |
Output
| Type | Description |
|---|---|
FPubnubChatOperationResult | Operation result with Error (bool) and ErrorMessage (FString). |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
In the message Check out this support article https://www.support-article.com/., remove the word out.
Actor.h
1
Actor.cpp
1
Send a draft message
Send() publishes the draft message with all mentioned users, links, and referenced channels. Mentioning users also emits mention events.
Method signature
1MessageDraft->Send(FPubnubChatSendTextParams SendTextParams = FPubnubChatSendTextParams())
| Parameter | Description |
|---|---|
SendTextParamsType: FPubnubChatSendTextParamsDefault: FPubnubChatSendTextParams() | Struct providing additional parameters. |
→ StoreInHistoryType: boolDefault: true | If true, the messages are stored in Message Persistence. If not specified, the Message Persistence configuration from the Admin Portal keyset is used. |
→ SendByPostType: boolDefault: false | When true, the SDK uses HTTP POST to publish the messages. |
→ MetaType: FStringDefault: "" | Publish additional metadata with the request. |
User mentions, channel references, and links are not passed in SendTextParams. They are added to the MessageDraft object through AddMention() and serialized automatically when Send() is called. To quote another message, use SetQuotedMessage() before calling Send().
Output
| Type | Description |
|---|---|
FPubnubChatOperationResult | Operation result with Error (bool) and ErrorMessage (FString). |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Send a draft message containing just plain text.
Actor.h
1
Actor.cpp
1
Send a draft message (async)
SendAsync() is the asynchronous variant of Send(). It sends the draft on a background thread and calls the provided delegate when the operation completes.
Method signature
1MessageDraft->SendAsync(FOnPubnubChatOperationResponse OnOperationResponse, FPubnubChatSendTextParams SendTextParams = FPubnubChatSendTextParams())
| Parameter | Description |
|---|---|
OnOperationResponseType: FOnPubnubChatOperationResponse | Callback executed when the operation completes. |
SendTextParamsType: FPubnubChatSendTextParams | Same parameters as Send(). |
Get current draft text
GetCurrentText() returns the current full draft text by concatenating all message elements.
Method signature
1MessageDraft->GetCurrentText()
Output
| Type | Description |
|---|---|
FString | The full draft text string. |
Get message elements
GetMessageElements() returns a copy of the current message elements (text segments and mentions with position and target).
Method signature
1MessageDraft->GetMessageElements()
Output
| Type | Description |
|---|---|
TArray<FPubnubChatMessageElement> | Array of message elements in the draft. |
FPubnubChatMessageElement
| Field | Type | Description |
|---|---|---|
Text | FString | The display text of this element. |
MentionTarget | FPubnubChatMentionTarget | The mention target (user, channel, or URL). MentionTargetType is PCMTT_None for plain text. |
Start | int | Start position (0-based) in the draft. |
Length | int | Length of this element in the draft. |
Get text to send
GetTextToSend() returns the serialized draft text as it would be sent by Send(). Mentions are encoded as markdown links (for example, [Alex](pn-user://alex_d)). Use this to preview or parse the final message format.
Method signature
1MessageDraft->GetTextToSend()
Output
| Type | Description |
|---|---|
FString | Serialized draft text with mentions as markdown links. Empty if the draft is empty. |
Set quoted message
SetQuotedMessage() attaches (or clears) a quoted message on the draft. The quoted message is sent alongside the draft text when Send() is called. Pass nullptr to remove any existing quoted message.
Method signature
1MessageDraft->SetQuotedMessage(UPubnubChatMessage* InQuotedMessage)
| Parameter | Description |
|---|---|
InQuotedMessage *Type: UPubnubChatMessage*Default: n/a | The message to quote, or nullptr to clear the quoted message. |
Sample code
Reference code
This example is a self-contained code snippet ready to be run. Set up your Unreal project and follow the instructions in the lines marked with ACTION REQUIRED before running the code. Use it as a reference when working with other examples in this document.
Quote a message using a message draft.
Actor.h
1
Actor.cpp
1
Get quoted message
GetQuotedMessage() returns the quoted message attached to the draft, if any.
Method signature
1MessageDraft->GetQuotedMessage()
Output
| Type | Description |
|---|---|
UPubnubChatMessage* | The quoted message, or nullptr if none is set. |