Documentation Index Fetch the complete documentation index at: https://wukong.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
Sending Messages
Description
Method for sending messages
/**
* Send message
* @param model Message content
* @param channel Channel object (personal channel, group channel)
*/
WKIM . shared . messageManager (). send ( model : WKMessageContent , channel : WKChannel );
Text Messages
// Text message
let textModel : WKTextContent = new WKTextContent ( 'Hello, WuKong' )
// Send to user A
WKIM . shared . messageManager (). send ( textModel , new WKChannel ( 'A' , WKChannelType . personal ));
Image Messages
// Image message
let imageModel : WKImageContent = new WKImageContent ( localPath )
imageModel . width = 100
imageModel . height = 100
// Send to user A
WKIM . shared . messageManager (). send ( imageModel , new WKChannel ( 'A' , WKChannelType . personal ));
Custom Messages
Reference custom messages: Custom Messages
Message Storage Callback (Not Message Send Status)
When sending messages, the SDK will trigger a storage callback after saving the message to the local database. At this point, the message has not been sent yet, and you can display the message in the UI in this listener.
// Listen for message storage
WKIM . shared . messageManager (). addInsertedListener (( msg ) => {
// Display message in UI
})
New Messages
Listen for new message events
// New message listener
newMsgsListener = ( msgs : WKMsg []) => {
// Handle new messages
}
// Listen for new messages
WKIM . shared . messageManager (). addNewMsgListener ( this . newMsgsListener )
// Remove new message listener
WKIM . shared . messageManager (). removeNewMsgListener ( this . newMsgsListener )
Message Refresh
When the SDK updates messages, such as: message send status, someone likes a message, message read receipt, message recall, message editing, etc., the SDK will callback the following event. The UI can determine which specific message has changed through the clientMsgNO of the message object WKMsg.
// Refresh message listener
refreshMsgListener = ( msg : WKMsg ) => {
// Handle refresh message
}
// Listen for refresh messages
WKIM . shared . messageManager (). addRefreshListener ( this . refreshMsgListener )
// Remove refresh message listener
WKIM . shared . messageManager (). removeRefreshListener ( this . refreshMsgListener )
Message Send Status Code (ReasonCode)
When a message is sent, the reasonCode in the WKMsg object returned by the addRefreshListener indicates the result of the message delivery. Below are the descriptions for each status code:
Value Name Description 0 ReasonUnknown Unknown error 1 ReasonSuccess Success 2 ReasonAuthFail Authentication failed 3 ReasonSubscriberNotExist Subscriber does not exist in the channel 4 ReasonInBlacklist In blacklist 5 ReasonChannelNotExist Channel does not exist 6 ReasonUserNotOnNode User is not on node 7 ReasonSenderOffline Sender is offline, message delivery failed 8 ReasonMsgKeyError Message key error, invalid message 9 PayloadDecodeError Payload decoding failed 10 ForwardSendPacketError Forwarding send packet failed 11 NotAllowSend Not allowed to send message 12 ConnectKick Connection kicked 13 NotInWhitelist Not in whitelist 14 QueryTokenError Query user token error 15 SystemError System error 16 ChannelIDError Wrong channel ID 17 NodeMatchError Node matching error 18 NodeNotMatch Node not matched 19 Ban Channel is banned 20 NotSupportHeader Unsupported header 21 ClientKeyIsEmpty clientKey is empty 22 RateLimit Rate limit exceeded 23 NotSupportChannelType Unsupported channel type 24 Disband Channel disbanded 25 SendBan Sending is banned
let option = new ChannelMsgOptions (() => {
// Syncing - show loading as needed
}, ( list ) => {
// Message data
})
option . oldestOrderSeq = 0 // Last message's large orderSeq, pass 0 for first entry into chat
option . contain = false // Whether to include the oldestOrderSeq message
option . pullMode = 1 // Pull mode 0: pull down 1: pull up
option . limit = 20 // Number to get each time
option . aroundMsgOrderSeq = 0 // Query messages around this message, e.g. aroundMsgOrderSeq=20 returns [16,17,19,20,21,22,23,24,25]
// View chat information for a channel
WKIM . shared . messageManager (). getOrSyncHistoryMessages ( channel , option )
Getting history messages is not a synchronous method, as there may be non-continuous data that needs to be synced from the server
Complete Message Management Example
import { WKIM , WKMsg , WKMessageContent , WKTextContent , WKImageContent , WKChannel , WKChannelType , ChannelMsgOptions } from '@wukong/wkim' ;
@ Component
export struct MessageManager {
@ State private messages : WKMsg [] = [];
@ State private isLoading : boolean = false ;
private newMsgsListener = ( msgs : WKMsg []) => {
this . handleNewMessages ( msgs );
}
private refreshMsgListener = ( msg : WKMsg ) => {
this . handleMessageRefresh ( msg );
}
private insertedListener = ( msg : WKMsg ) => {
this . handleMessageInserted ( msg );
}
aboutToAppear (): void {
this . setupMessageListeners ();
}
aboutToDisappear (): void {
this . removeMessageListeners ();
}
private setupMessageListeners (): void {
// Listen for message storage
WKIM . shared . messageManager (). addInsertedListener ( this . insertedListener );
// Listen for new messages
WKIM . shared . messageManager (). addNewMsgListener ( this . newMsgsListener );
// Listen for message refresh
WKIM . shared . messageManager (). addRefreshListener ( this . refreshMsgListener );
}
private removeMessageListeners (): void {
WKIM . shared . messageManager (). removeInsertedListener ( this . insertedListener );
WKIM . shared . messageManager (). removeNewMsgListener ( this . newMsgsListener );
WKIM . shared . messageManager (). removeRefreshListener ( this . refreshMsgListener );
}
private handleMessageInserted ( msg : WKMsg ): void {
// Message saved to database, update UI immediately
console . log ( 'Message inserted:' , msg . clientMsgNo );
this . addMessageToUI ( msg );
}
private handleNewMessages ( msgs : WKMsg []): void {
console . log ( 'Received new messages:' , msgs . length );
msgs . forEach ( msg => {
this . addMessageToUI ( msg );
});
}
private handleMessageRefresh ( msg : WKMsg ): void {
console . log ( 'Message refreshed:' , msg . clientMsgNo );
this . updateMessageInUI ( msg );
}
private addMessageToUI ( msg : WKMsg ): void {
// Check if message already exists
const existingIndex = this . messages . findIndex ( m => m . clientMsgNo === msg . clientMsgNo );
if ( existingIndex >= 0 ) {
// Update existing message
this . messages [ existingIndex ] = msg ;
} else {
// Add new message
this . messages . push ( msg );
}
// Sort messages by timestamp
this . messages . sort (( a , b ) => a . timestamp - b . timestamp );
}
private updateMessageInUI ( msg : WKMsg ): void {
const index = this . messages . findIndex ( m => m . clientMsgNo === msg . clientMsgNo );
if ( index >= 0 ) {
this . messages [ index ] = msg ;
}
}
// Send text message
public sendTextMessage ( text : string , channel : WKChannel ): void {
try {
const textModel = new WKTextContent ( text );
WKIM . shared . messageManager (). send ( textModel , channel );
} catch ( error ) {
console . error ( 'Failed to send text message:' , error );
}
}
// Send image message
public sendImageMessage ( localPath : string , width : number , height : number , channel : WKChannel ): void {
try {
const imageModel = new WKImageContent ( localPath );
imageModel . width = width ;
imageModel . height = height ;
WKIM . shared . messageManager (). send ( imageModel , channel );
} catch ( error ) {
console . error ( 'Failed to send image message:' , error );
}
}
// Load history messages
public loadHistoryMessages ( channel : WKChannel , oldestOrderSeq : number = 0 ): void {
this . isLoading = true ;
const option = new ChannelMsgOptions (
() => {
// Syncing callback
console . log ( 'Syncing messages...' );
},
( list : WKMsg []) => {
// Message data callback
this . isLoading = false ;
this . handleHistoryMessages ( list );
}
);
option . oldestOrderSeq = oldestOrderSeq ;
option . contain = false ;
option . pullMode = 0 ; // Pull down
option . limit = 20 ;
option . aroundMsgOrderSeq = 0 ;
WKIM . shared . messageManager (). getOrSyncHistoryMessages ( channel , option );
}
private handleHistoryMessages ( messages : WKMsg []): void {
console . log ( 'Loaded history messages:' , messages . length );
// Merge with existing messages
messages . forEach ( msg => {
const existingIndex = this . messages . findIndex ( m => m . clientMsgNo === msg . clientMsgNo );
if ( existingIndex < 0 ) {
this . messages . push ( msg );
}
});
// Sort messages by timestamp
this . messages . sort (( a , b ) => a . timestamp - b . timestamp );
}
// Get messages for specific channel
public getMessagesForChannel ( channelId : string , channelType : number ): WKMsg [] {
return this . messages . filter ( msg =>
msg . channelId === channelId && msg . channelType === channelType
);
}
// Clear messages
public clearMessages (): void {
this . messages = [];
}
build () {
Column () {
Text ( 'Message Manager' )
. fontSize ( 20 )
. fontWeight ( FontWeight . Bold )
. margin ({ bottom: 20 })
if ( this . isLoading ) {
Row () {
LoadingProgress ()
. width ( 20 )
. height ( 20 )
. margin ({ right: 10 })
Text ( 'Loading messages...' )
}
. margin ({ bottom: 20 })
}
Text ( `Total Messages: ${ this . messages . length } ` )
. fontSize ( 16 )
. margin ({ bottom: 20 })
List () {
ForEach ( this . messages , ( message : WKMsg ) => {
ListItem () {
this . buildMessageItem ( message )
}
})
}
. layoutWeight ( 1 )
Row () {
TextInput ({ placeholder: 'Enter message...' })
. layoutWeight ( 1 )
. onSubmit (( value : string ) => {
const channel = new WKChannel ( 'test_user' , WKChannelType . personal );
this . sendTextMessage ( value , channel );
})
Button ( 'Send' )
. onClick (() => {
// Send message logic
})
}
. padding ( 10 )
}
. width ( '100%' )
. height ( '100%' )
. padding ( 20 )
}
@ Builder
buildMessageItem ( message : WKMsg ) {
Column () {
Row () {
Text ( message . fromUID )
. fontSize ( 14 )
. fontColor ( Color . Gray )
. margin ({ right: 10 })
Text ( this . formatTimestamp ( message . timestamp ))
. fontSize ( 12 )
. fontColor ( Color . Gray )
}
. width ( '100%' )
. justifyContent ( FlexAlign . SpaceBetween )
. margin ({ bottom: 5 })
Text ( message . content )
. fontSize ( 16 )
. textAlign ( TextAlign . Start )
. width ( '100%' )
if ( message . status === 0 ) {
Text ( 'Sending...' )
. fontSize ( 12 )
. fontColor ( Color . Orange )
. margin ({ top: 5 })
}
}
. alignItems ( HorizontalAlign . Start )
. padding ( 10 )
. margin ({ bottom: 10 })
. backgroundColor ( Color . White )
. borderRadius ( 8 )
}
private formatTimestamp ( timestamp : number ): string {
const date = new Date ( timestamp * 1000 );
return date . toLocaleTimeString ();
}
}
Offline Messages
Need to implement sync channel message data source Channel Message Data Source
Because WuKongIM supports permanent message storage, it will generate massive offline messages. For this, we adopt an on-demand pull mechanism. For example, with 10 conversations each having 100,000 messages, WuKongIM will not pull all 10*100,000=1 million messages to local storage. Instead, it pulls information for these 10 conversations and the corresponding latest 20 messages, which means actually only 200 messages are pulled. Compared to 1 million messages, this greatly improves offline pull speed. Users will only pull messages for a specific conversation when they enter that conversation. These mechanisms are already encapsulated within the SDK, so users don’t need to worry about them. Users only need to focus on recent conversation changes and listen for data retrieval callbacks.
Data Structure Description
Message Structure
export class WKMsg {
// Server unique message ID
messageId = "" ;
// Server message sequence number
messageSeq = 0 ;
// Client message sequence number
clientSeq = 0 ;
// Message timestamp
timestamp = 0 ;
// Expiration time
expireTime = 0 ;
// Expiration timestamp
expireTimestamp = 0 ;
// Client unique number
clientMsgNo = "" ;
// Sender uid
fromUID = "" ;
// Channel ID
channelId = "" ;
// Channel type
channelType = WKChannelType . personal ;
// Message type
contentType = 0 ;
// Message content string
content = "" ;
// Message status 1.sent successfully 0.sending
status = 0 ;
voiceStatus = 0 ;
// Is deleted 1.yes
isDeleted = 0 ;
// Search keyword
searchableWord = "" ;
// Message sender profile
private from ?: WKChannel
// Message channel profile
private channelInfo ?: WKChannel
// Message sender profile in channel (only for group messages)
private memberOfFrom ?: WKChannelMember
// Sort number
orderSeq = 0 ;
// Is read
viewed = 0 ;
// Read time
viewedAt = 0 ;
// Topic ID
topicId = "" ;
// Local extensions
localExtraMap ?: Record < string , object >
// Remote extensions
wkMsgExtra ?: WKMsgExtra
// Message reaction data
reactionList ?: WKMsgReaction []
// Message content
messageContent ?: WKMessageContent
}
Message Content Structure
export class WKMessageContent {
// Message type
contentType : number = 0
// Message content
content : string = ""
// Render message content, e.g., need to render @xxx text when @someone
entities ?: ArrayList < WKMsgEntity >
// Message reply
reply ?: WKReply
// Mention information
mentionInfo ?: WKMentionInfo
}
Next Steps
Channel Management Learn how to manage channels and groups
Conversation Management Handle conversation lists and unread messages
Data Source Configuration Configure message data sources
Advanced Features Explore advanced features and custom messages