diff --git a/frontend/css/style.css b/frontend/css/style.css
index f12640f..be256e7 100644
--- a/frontend/css/style.css
+++ b/frontend/css/style.css
@@ -143,9 +143,21 @@ button {
border-radius: 50%;
}
+.message .user {
+ font-weight: bold; /* differentiate username from message text */
+ margin-right: 0.25rem; /* spacing before the message body */
+}
+
+.message .text {
+ /* Allow the message body to consume remaining space so the
+ timestamp and read receipt align to the right */
+ flex: 1;
+ margin-left: 0.25rem;
+}
+
.message .time {
color: #777;
- margin-left: auto;
+ margin-left: 0.5rem; /* space after the message text */
font-size: 0.8rem;
}
diff --git a/frontend/js/app.js b/frontend/js/app.js
index 5a28355..a7140e4 100644
--- a/frontend/js/app.js
+++ b/frontend/js/app.js
@@ -259,14 +259,16 @@ function appendDirectMessage(m) {
// delivered.
const outgoing = m.from === currentUser.username;
const receipt = outgoing
- ? `${m.isRead ? '✔✔' : (m.isDelivered ? '✔' : '')}`
+ ? `${m.isRead ? '✓✓' : (m.isDelivered ? '✓' : '')}`
: '';
+ // Place the timestamp and read receipt at the end of the flex container so
+ // the layout resembles common chat apps.
div.innerHTML = `
${m.from}
- ${time}
- ${m.text}${receipt}`;
+ ${m.text}
+ ${time}${receipt}`;
list.appendChild(div);
}
@@ -365,6 +367,9 @@ function selectUser(name) {
currentChannel = null; // hide channel context
clearUnread(name);
loadMessages();
+ // Explicitly mark any previously unread messages as read now that
+ // the conversation is open to keep badge counts in sync.
+ markMessagesRead(name);
}
// Verify the user is logged in before showing the dashboard