IM Chat
This guide covers instant messaging features including sending messages, receiving messages, history, revocation, and chat mode control.
Sending Messages
Text Messages
const result = await classroom.sendTextMessage('Hello everyone!');
if (!result.ok) {
console.error('Send failed:', result.message);
}Image Messages
// Send after file selection (auto-uploaded to COS)
const fileInput = document.querySelector<HTMLInputElement>('#image-input');
const file = fileInput?.files?.[0];
if (file) {
const result = await classroom.sendImageMessage(file);
if (!result.ok) console.error('Image send failed:', result.message);
}File Messages
const file = fileInput.files[0];
const result = await classroom.sendFileMessage(file);
if (!result.ok) {
console.error('File send failed:', result.message);
}Custom Messages
// Send custom message (content is serialized to a JSON string)
const result = await classroom.sendCustomMessage({
type: 'emoji',
emojiId: 'thumbs_up',
});Direct Messages (Private)
// Send a directed private message (visible only to the target user)
const result = await classroom.sendDirectedMessage('user_002', 'Hi, I have a question');
if (!result.ok) {
console.error('DM failed:', result.message);
}Receiving Messages
Subscribe to Message List via Reactive State
Subscribe to the full message list (history + real-time messages):
classroom.state.messageList$.subscribe(messages => {
renderMessageList(messages);
});Listen for New Messages via Events
Listen for new messages to trigger notifications, scrolling, etc.:
import { TEvent } from '@tencent-classroom/sdk';
classroom.on(TEvent.RECV_MESSAGE, (message) => {
console.log('New message:', message.content);
scrollToBottom();
showNotification(message);
});Parsing Private Message Indicators
messageList$ contains public messages + private messages relevant to the current user.
Private messages are identified by fields in message.ext (the IM cloudCustomData):
interface MessageExt {
IsPrivateMsg?: boolean; // Whether this is a private message
PrivateInfo?: {
From: { ID: string }; // Sender userId
To: { ID: string }; // Recipient userId
};
}Parsing example:
classroom.state.messageList$.subscribe((messages) => {
for (const msg of messages) {
// Parse ext field
const ext = typeof msg.ext === 'string' ? JSON.parse(msg.ext || '{}') : (msg.ext || {});
if (ext.IsPrivateMsg) {
// This is a private message
const fromId = ext.PrivateInfo?.From?.ID;
const toId = ext.PrivateInfo?.To?.ID;
renderPrivateMessage(msg, fromId, toId);
} else {
// Regular public message
renderPublicMessage(msg);
}
}
});messageList$ Filtering Rules
The SDK ensures messageList$ only contains:
- All public messages (Text / Image / File types)
- Private messages relevant to the current user (where the user is the sender From or recipient To)
Private messages between other users will never appear in the list — no visibility checks are needed at the business layer.
History Messages
// Fetch history messages (incremental, no duplicates)
const result = await classroom.fetchHistoryMessages(20); // default: 20
if (result.ok) {
console.log('History messages:', result.data);
}
// Fetch more
const moreResult = await classroom.fetchHistoryMessages(20);Note: The SDK automatically fetches history messages once on join and writes them to
state.messageList$. Manual calls are usually unnecessary.
Revoking Messages
// Revoke your own message (all roles can revoke their own)
const result = await classroom.revokeMessage(message.id);
if (!result.ok) {
console.error('Revoke failed:', result.message);
}
// Teacher/assistant revoke any message (by IM sequence number)
await classroom.revokeClassMessage(message.seq);Listen for revocation events:
classroom.on(TEvent.MESSAGE_REVOKED, ({ msgId }) => {
console.log('Message revoked:', msgId);
});Unread Management
// Subscribe to unread message count
classroom.state.messageUnreadCount$.subscribe(count => {
updateBadge(count);
});
// Mark all as read
classroom.markAllMessagesAsRead();
// Mark messages up to a specific seq as read
classroom.markMessageAsRead(latestSeq);Chat Mode Control
Teachers/assistants can control the classroom chat mode:
// Set chat mode
await classroom.setSilenceMode('freeChat'); // Free chat
await classroom.setSilenceMode('publicOnly'); // Public messages only
await classroom.setSilenceMode('privateOnly'); // Private messages only
await classroom.setSilenceMode('muteAll'); // Mute all
// Subscribe to silence mode changes
classroom.state.silenceMode$.subscribe(mode => {
console.log('Current chat mode:', mode);
});Check Send Permission
// Check whether the current user can send messages
if (classroom.canSendChatMessage()) {
// Can send
} else {
showToast('You are currently muted');
}Related APIs
- IM API Reference — Full method list
- Events Reference — IM event details
- State Reference — IM-related signals