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 = ` avatar ${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