Create message drafts (v2)
Message drafts v2
For version 1 documentation, refer to Drafts v1.
MessageDraftV2 represents an unpublished message. Use it to:
- Edit text before publishing
- Add channel references, user mentions, and links
- Attach files
Display message elements (mentions, references, links) in your UI by adding a message draft change listener.
- Basics
- Class diagram
- Example
- Internal mention format
Message drafts consist of simple strings and generic link element, which are used for user mentions, channel references, and URLs. Each link element contains a text and a reference to the linked element regardless if it's a user, a channel, or a URL.
Store draft messages locally
Chat SDK does not persist drafts. Implement your own local storage to save drafts across channel switches.
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 MessageDraftV2ChangeListener is as follows:
| Part of Message | Element Type | Code Used to Create |
|---|---|---|
| Hey, I sent | MixedTextTypedElement | messageDraft.update("Hey, I sent Alex this link on the #offtopic channel.") |
| Alex | mention | messageDraft.addMention(12, 4, "mention", "alex_d") |
| this | MixedTextTypedElement | messageDraft.update("Hey, I sent Alex this link on the #offtopic channel.") |
| link | textLink | messageDraft.addMention(22, 4, "textLink", "http://www.pubnub.com") |
| on the | MixedTextTypedElement | messageDraft.update("Hey, I sent Alex this link on the #offtopic channel.") |
| #offtopic | channelReference | messageDraft.addMention(34, 9, "channelReference", "group.offtopic") |
| channel. | MixedTextTypedElement | messageDraft.update("Hey, I sent Alex this link on the #offtopic channel.") |
By internally leveraging a Markdown-like syntax, the message draft format integrates links directly into the message text using the pattern [link text](link target) understood by the Chat SDK.
| 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
createMessageDraftV2() creates a message draft (MessageDraftV2 object) that can consist of:
- Plain text
- Files
- Mentioned users
- Referenced channels
- Links
- Quoted messages
Method signature
This method has the following signature:
1channel.createMessageDraftV2(config?: Partial<MessageDraftConfig>): MessageDraftV2;
Input
| Parameter | Description |
|---|---|
configType: Partial<MessageDraftConfig>Default: n/a | This object holds the configuration options. |
config →userSuggestionSourceType: channel or globalDefault: channel | This parameter refers to the Mentions feature. Data source from which you want to retrieve users. You can choose either the list of channel members (channel) or users on the app's Admin Portal keyset (global). |
config →isTypingIndicatorTriggeredType: booleanDefault: true | This parameter refers to the Typing Indicator feature. Defines if the typing indicator should be enabled when writing the message. |
config →userLimitType: numberDefault: 10 | This parameter refers to the Mentions feature. Maximum number of usernames (name field from the User object) you can mention in one message. The default value is 10, the min is 1, and max is 100. |
config →channelLimitType: numberDefault: 10 | This parameter refers to the References feature. Maximum number of channel names (name field from the Channel object) you can reference in one message. The default value is 10, the min is 1, and max is 100. |
Output
| Type | Description |
|---|---|
MessageDraftV2 | Instance of MessageDraftV2, which represents a draft version of a message with the content, all links, referenced channels, mentioned users and their names. |
Sample code
Create a draft message containing just plain text.
1messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
Add message draft change listener
Add a MessageDraftState listener to receive draft content changes and suggestions for mentions, channel references, and links.
No automatic detection
Parse the message for mentions/links and add them with addMention(). Chat SDK does not auto-detect these.
Method signature
This method has the following signature:
1messageDraft.addChangeListener(listener: (p0: MessageDraftState) => void): void;
Input
| Parameter | Description |
|---|---|
listenerType: MessageDraftState | The listener that receives the most current message elements and suggestions list. |
MessageDraftState
| Parameter | Description |
|---|---|
messageElements()Type: Array<MixedTextTypedElement> | Array of MixedTextTypedElement objects, representing the current state of the message draft. This could contain a mix of plain text and links, channel references, or user mentions. |
suggestedMentions())Type: Promise<Array<SuggestedMention>> | A Promise containing an array of SuggestedMention objects. These are potential suggestions for message elements based on the current text in the draft. |
SuggestedMention
A SuggestedMention represents a potential mention suggestion received from MessageDraftState listener.
| Parameter | Description |
|---|---|
offsetType: number | The position from the start of the message draft where the message elements starts. It's counted from the beginning of the message (including spaces), with 0 as the first character. |
replaceFromType: String | The original text at the given offset in the message draft text. |
replaceWithType: String | The suggested replacement for the replaceFrom text. |
typeType: TextTypes | The message element type. Available types include:
|
targetType: string | The actual mention element in string format:
|
Output
This method doesn't return any data.
Sample code
Add the listener to your message draft.
1// Create a message draft
2messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
3// Add the listener
4messageDraft.addChangeListener(async function(state) {
5 updateUI(state.messageElements) // where updateUI is your function for displaying the message content
6 updateSuggestedMentionsUI(mentions) // where updateSuggestedMentionsUI is your function for displaying mention suggestions
7 })
Remove message draft change listener
Remove a previously added MessageDraftState listener.
Method signature
This method has the following signature:
1removeChangeListener(listener: (p0: MessageDraftState) => void): void;
Input
| Parameter | Description |
|---|---|
listenerType: MessageDraftState | The listener to remove. |
Output
This method doesn't return any data.
Sample code
Remove a listener from your message draft.
1messageDraft.removeChangeListener(listener)
Add message element
addMention() adds a user mention, channel reference or a link specified by a mention target at a given offset.
Method signature
This method has the following signature:
1messageDraft.addMention(
2 offset: number,
3 length: number,
4 mentionType: TextTypes,
5 mentionTarget: string
6): void;
Input
| Parameter | Description |
|---|---|
offset *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. |
mentionType *Type: TextTypesDefault: n/a | The message element type. Available types include:
|
mentionTarget *Type: stringDefault: n/a | The actual mention element in string format:
|
Output
This method returns no output data.
Sample code
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.
1// Create a message draft
2messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
3
4// Add initial text
5messageDraft.update("Hello Alex!")
6
7// Add a user mention to the string "Alex"
8messageDraft.addMention(6, 4, "mention", "alex_d"))
9
10// Change the text
11messageDraft.update("Hello Alex! I have sent you this link on the #offtopic channel.")
12
13// Add a URL mention to the string "link"
14messageDraft.addMention(33, 4, "textLink", "www.pubnub.com")
15
show all 17 linesRemove message element
removeMention() removes a user mention, channel reference, or a link at a given offset.
Method signature
This method has the following signature:
1messageDraft.removeMention(offset: number): void;
Input
| Parameter | Description |
|---|---|
offset *Type: numberDefault: n/a | Position of the first character of the message element you want to remove. |
Offset value
If you don't provide the position of the first character of the message element to remove, it isn't removed.
Output
This method returns no output data.
Sample code
Remove the URL element from the word link in the Hello Alex! I have sent you this link on the #offtopic channel. message.
1// assume the message reads
2// Hello Alex! I have sent you this link on the #offtopic channel.
3
4// remove the link mention
5messageDraft.removeMention(33)
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
This method has the following signature:
1messageDraft.update(text: String)
Input
| Parameter | Description |
|---|---|
text *Type: stringDefault: n/a | Text of the message that you want to update. |
Output
This method returns no output data.
Sample code
Change the message I sent Alex this picture. to I did not send Alex this picture. where Alex is a user mention.
1// the message reads:
2// I sent [Alex] this picture.
3// where [Alex] is a user mention
4messageDraft.update( "I did not send Alex this picture.")
5// the message now reads:
6// I did not send [Alex] this picture.
7// the mention is preserved because its text wasn't changed
Mention text changes
Changing mention text removes that mention. For finer control, use Insert message text and Remove message text.
Insert suggested message element
Insert a message element from the MessageDraftState listener into the MessageDraftV2 object.
Text must match
SuggestedMention.replaceFrom must match the draft text at the specified position, or an exception is thrown.
Method signature
This method has the following signature:
1messageDraft.insertSuggestedMention(
2 mention: SuggestedMention,
3 text: String
4)
Input
| Parameter | Description |
|---|---|
mention *Type: SuggestedMentionDefault: n/a | A user, channel, or URL suggestion obtained from MessageDraftState listener. |
text *Type: stringDefault: n/a | The text you want the message element to display. |
Output
This method returns no output data.
Sample code
Register a listener and insert a suggested element.
1// Create a message draft
2messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
3// Add the listener
4messageDraft.addChangeListener(async function(state) {
5 updateUI(state.messageElements) // where updateUI is your function for displaying the message content
6 let mentions = await state.suggestedMentions
7 messageDraft.insertSuggestedMention(mentions[0], mentions[0].replaceWith)
8 })
Insert message text
insertText() inserts plain text in the draft message at the specified offset.
Removing message elements
Inserting text at an existing message element position removes that element.
Method signature
This method has the following signature:
1messageDraft.insertText(
2 offset: number,
3 text: string
4)
Input
| Parameter | Description |
|---|---|
offset *Type: numberDefault: 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: stringDefault: n/a | Text that you want to insert. |
Output
This method returns no output data.
Sample code
In the message Check this support article https://www.support-article.com/., add the word out between the words Check and this.
1// The message reads:
2// Check this support article https://www.support-article.com/.
3messageDraft.insertText(6, "out")
4// The message now reads:
5// Check out this support article https://www.support-article.com/.
Remove message text
removeText() removes plain text from the draft message at the specified offset.
Removing message elements
Removing text at an existing message element position removes that element.
Method signature
This method has the following signature:
1messageDraft.removeText(
2 offset: number,
3 length: number
4)
Input
| Parameter | Description |
|---|---|
offset *Type: numberDefault: 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: numberDefault: n/a | How many characters to remove, starting at the given offset. |
Output
This method returns no output data.
Sample code
In the message Check out this support article https://www.support-article.com/., remove the word out.
1// The message reads:
2// Check out this support article https://www.support-article.com/.
3messageDraft.removeText(5, 4)
4// The message now reads:
5// Check this support article https://www.support-article.com/.
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
This method has the following signature:
1messageDraft.send(
2 params?: MessageDraftOptions
3): Promise<PubNub.PublishResponse>;
Input
| Parameter | Description |
|---|---|
paramsType: MessageDraftOptionsDefault: n/a | This object holds the configuration options. |
params →storeInHistoryType: booleanDefault: true | If true, the messages are stored in Message Persistence (PubNub storage). If storeInHistory is not specified, the Message Persistence configuration specified on the Admin Portal keyset is used. |
params →sendByPostType: booleanDefault: false | When true, the SDK uses HTTP POST to publish the messages. The message is sent in the BODY of the request instead of the query string when HTTP GET is used. The messages are also compressed to reduce their size. |
params →metaType: anyDefault: n/a | Publish additional details with the request. |
params →ttlType: numberDefault: n/a | Defines if / how long (in hours) the message should be stored in Message Persistence.
|
Output
| Type | Description |
|---|---|
Timetoken | Timetoken of the message. |
Sample code
Send a draft message containing just plain text.
1// Create a message draft
2messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
3
4// Add text
5messageDraft.update("Hello!")
6
7// Send the message
8messageDraft.send()
Add quoted message
addQuote() adds a quoted message to the draft. See Quote message for details.
Sample code
Send a draft message containing just plain text.
1// Create a message draft
2messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
3
4// return a message object
5const message = await channel.getMessage("16200000000000001")
6
7// add a quote to the message
8messageDraft.addQuote(message)
9
10// alternatively, use direct assignment to add or replace a quote
11messageDraft.quotedMessage = message // Add or replace the quote
Remove quoted message
removeQuote() removes the quote from the draft message. See Remove quoted message for details.
Sample code
Send a draft message containing just plain text.
1// Create a message draft
2messageDraft = channel.createMessageDraftV2({ userSuggestionSource: "global" })
3
4// return a message object
5const message = await channel.getMessage("16200000000000001")
6
7// add a quote to the message
8messageDraft.addQuote(message)
9
10// alternatively, use direct assignment to add or replace a quote
11messageDraft.quotedMessage = message // Add or replace the quote
12
13// remove the quote by passing null
14messageDraft.removeQuote()
15
show all 17 lines