Beginner
Chat
A scrolling transcript with an input row, and the small message struct that travels between machines unchanged.
Introduction
Two Classes
Two classes provide a chat surface. ChatWindow is the whole thing — a scrolling transcript with an input row. ChatBubble renders one message and is managed for you.
ml::ChatWindow chat;
chat.setSize({360.f, 520.f});
chat.onSend([&](const std::string& text){ sendToServer(text); });
You do not normally construct
ChatBubble yourself. ChatWindow builds one per message and lays them out — the class is public so you can render a transcript somewhere else, not because you need it for a chat window.1Data
The Message Struct
A message is a small plain struct, so it travels over the network or into a database without conversion.
struct ChatMessage {
std::string sender;
std::string text;
std::string timestamp;
bool isMine = false;
};
| Field | Meaning |
|---|---|
sender | Display name shown above the bubble. |
text | The message body. Wrapped by the bubble. |
timestamp | Display time. ChatMessage::isoToHM() converts an ISO string, or returns the current time when given nothing. |
isMine | Which side to align to, and which colour to use. |
ml::ChatMessage m;
m.sender = "Amelia";
m.text = "Is the quiz open yet?";
m.timestamp = ml::ChatMessage::isoToHM(); // now, as HH:MM
m.isMine = false;
chat.addMessage(m);
isMine is presentation, not identity. Set it by comparing the sender to the local user when the message arrives — a transcript replayed on another machine needs the flag recomputed, not the stored value.2Wiring
ChatWindow
| Method | Effect |
|---|---|
addMessage(msg) | Append and scroll to it. |
clear() | Empty the transcript. |
onSend(cb) | The user submitted the input row. |
setSize(size) | Resize; bubbles re-wrap to the new width. |
onSend gives you the text and nothing else. The window does not add the message itself — that is deliberate, so you can send it, wait for the server to accept it, and add it only if that succeeded:
chat.onSend([&](const std::string& text){
if (!socket.isOpen()) { showToast("Not connected"); return; }
socket.send(text);
ml::ChatMessage mine{ myName, text, ml::ChatMessage::isoToHM(), true };
chat.addMessage(mine); // echo locally
});
If you echo locally and the server broadcasts back to everyone including the sender, the message appears twice. Either skip the local echo or have the server exclude the sender — decide which before wiring the transport.