Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ import {
renderRecommendationReviewPayload,
} from './paperRecommendationUi.js';

// Match the conversation composer’s send icon; Messages retains direct delivery semantics.
const SEND_MESSAGE_ICON = '<svg aria-hidden="true" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 19V5m-7 7 7-7 7 7" /></svg>';

// Message panel state
let _messagesContainer = null;
let _messageListEl = null;
Expand Down Expand Up @@ -443,7 +446,7 @@ function renderMessagesTabContent() {
</div>
<div class="message-compose-row">
<textarea id="messageInput" aria-label="Reply" class="message-input" placeholder="Type your message..." rows="3"></textarea>
<button id="sendMessageBtn" class="send-message-btn" type="button" aria-busy="false" aria-label="Send message" title="Send message"><span aria-hidden="true">↓</span></button>
<button id="sendMessageBtn" class="send-message-btn composer-icon-button" type="button" aria-busy="false" aria-label="Send message" title="Send message">${SEND_MESSAGE_ICON}</button>
</div>
</div>
</div>
Expand Down Expand Up @@ -1325,7 +1328,7 @@ function renderComposePendingUi(scope) {
}
button.disabled = pending || imagesBlocked(attachmentScope(scope)) || (scope === COMPOSE_SCOPE_REPLY && _exchange?.other_participant_ids?.length > 1);
if (scope === COMPOSE_SCOPE_REPLY) {
button.innerHTML = `<span aria-hidden="true">${pending ? '…' : '↓'}</span>`;
button.innerHTML = pending ? '<span aria-hidden="true">…</span>' : SEND_MESSAGE_ICON;
button.setAttribute('aria-label', pending ? 'Sending message' : 'Send message');
button.title = pending ? 'Sending message' : 'Send message';
} else {
Expand Down
6 changes: 4 additions & 2 deletions src/frontend/web/von_interface/static/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -11835,7 +11835,8 @@ body[data-active-tab="settingsTab"] .tab-content-area {
min-height: 44px;
}

.chat-composer .composer-icon-button {
.chat-composer .composer-icon-button,
#sendMessageBtn.composer-icon-button {
display: inline-flex;
align-items: center;
justify-content: center;
Expand Down Expand Up @@ -18656,7 +18657,8 @@ body.settings-body {
.chat-composer-more-actions { display: block; position: static; grid-column: 1 / -1; grid-row: 2; }
.chat-composer #sendButton { grid-column: 3; grid-row: 1; width: 44px; min-width: 44px; }
.chat-composer #sendButton[data-has-draft="false"]:not([aria-busy="true"]) { display: none; }
.chat-composer .composer-icon-button svg { width: 20px; height: 20px; }
.chat-composer .composer-icon-button svg,
#sendMessageBtn.composer-icon-button svg { width: 20px; height: 20px; }
.chat-composer-more-actions > summary {
position: absolute; top: 6px; left: 6px;
width: 44px; height: 44px; justify-content: center;
Expand Down
9 changes: 5 additions & 4 deletions tests/browser/messageUnreadNavigation.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,10 @@ const server = http.createServer(async (req, res) => {
assert.equal(await content.evaluate(el => el.scrollTop), 0, 'default loading preserves the top');
const send = page.getByRole('button', { name: 'Send message', exact: true });
const input = page.locator('#messageInput');
await input.fill('A reply from the down-arrow control.');
await input.fill('A reply from the up-arrow control.');
await expect(send).toBeVisible();
await expect(send).toHaveText('↓');
await expect(send.locator('svg path')).toHaveAttribute('d', await page.locator('#sendButton svg path').getAttribute('d'));
assert.equal(await send.evaluate(el => getComputedStyle(el).borderRadius), '50%');
const latest = page.getByRole('button', { name: 'Scroll to latest message', exact: true });
await expect(latest).toHaveText('Latest message');
const box = await send.boundingBox();
Expand All @@ -86,7 +87,7 @@ const server = http.createServer(async (req, res) => {
await latest.click();
await expect(latest).toBeHidden();
assert.equal(sent.length, 0, 'latest navigation does not send the draft');
await expect(input).toHaveValue('A reply from the down-arrow control.');
await expect(input).toHaveValue('A reply from the up-arrow control.');
await content.evaluate(el => { el.scrollTop = el.scrollHeight - el.clientHeight - 10; });
const bottomPosition = await content.evaluate(el => el.scrollTop);
assert.ok(bottomPosition > 0, 'fixture must overflow');
Expand Down Expand Up @@ -133,7 +134,7 @@ const server = http.createServer(async (req, res) => {
await send.click();
await expect(input).toHaveValue('');
assert.equal(sent.length, 1);
assert.equal(sent[0].content, 'A reply from the down-arrow control.');
assert.equal(sent[0].content, 'A reply from the up-arrow control.');
assert.deepEqual(errors, []);
await page.screenshot({ path: path.join(evidence, `unread-${width}.png`) });
results.push({ width, cursors: [...cursors], sendArrow: true, sendTarget: box, sends: sent.length, labelledLatestNavigation: true, defaultTopPreserved: true, backgroundPosition: bottomPosition, intermediateAnchorOffset: anchor.offset, mostRecentUnreadFocused: true, targetInViewport: true });
Expand Down
4 changes: 2 additions & 2 deletions tests/frontend/messagePanelSendFailure.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ describe('message panel send failure recovery', () => {
await flushUi();

expect(sendButton.disabled).toBe(false);
expect(sendButton.textContent).toBe('↓');
expect(sendButton.querySelector('svg path').getAttribute('d')).toBe('M12 19V5m-7 7 7-7 7 7');
expect(sendButton.getAttribute('aria-label')).toBe('Send message');
expect(sendButton.getAttribute('aria-busy')).toBe('false');
expect(replyInput.value).toBe('Please review this once.');
Expand All @@ -429,7 +429,7 @@ describe('message panel send failure recovery', () => {

expect(replyInput.value).toBe('');
expect(sendButton.disabled).toBe(false);
expect(sendButton.textContent).toBe('↓');
expect(sendButton.querySelector('svg path').getAttribute('d')).toBe('M12 19V5m-7 7 7-7 7 7');
expect(sendButton.getAttribute('aria-label')).toBe('Send message');
});

Expand Down
Loading