With conversation view off, marking a message unread from the list -- the hover button, the right-click menu -- marked that message. Opening it and pressing Mark as unread in the toolbar above it marked every message in its thread, and so did Move to, Report spam and Delete. The setting already reaches all the way into the reading pane: the list draws one row per message, and `visibleMessages` narrows the pane to the one opened. The toolbar was half converted. Its labels were right -- Mark as unread against Mark as read, the star, the labels shown -- all of those read `messages`, which is the narrowed set. Only `rowIds`, the one thing actually handed to the action, still read `thread.emailIds`. So the button said one message and did the whole conversation. `rowIds` is now the same question `visibleMessages` answers for the pane, asked of the same ids, with the same fallback: an id that names nothing in the thread -- a link from somebody with conversation view on, a stale `m` in the URL -- shows the conversation, so the toolbar takes the conversation. Conversation view on is unchanged: nothing is singled out, so the whole thread comes back as before. No new strings.
This commit is contained in:
@@ -224,7 +224,23 @@ export function ThreadView({ threadId, mailboxId, onBack, actions, onNavigate, h
|
||||
}, [messages, reply]);
|
||||
|
||||
const subject = messages[0]?.subject || emails[thread?.emailIds[0] ?? ""]?.subject || "(no subject)";
|
||||
const rowIds = thread ? thread.emailIds.filter((id) => emails[id]) : [];
|
||||
/*
|
||||
* What the toolbar acts on: the messages the pane is showing, not the thread
|
||||
* they belong to.
|
||||
*
|
||||
* With conversation view off, opening a message opens that message -- the
|
||||
* list shows it alone, the pane renders it alone, and the buttons above it
|
||||
* said so, because `anyUnread` and the rest already read `messages`. Only the
|
||||
* ids handed to the action still named the whole thread, so Mark as unread,
|
||||
* Move to, Report spam and Delete quietly took every message in it (#414).
|
||||
*
|
||||
* Same fallback as the pane's: an id naming nothing in this thread means the
|
||||
* whole conversation, so the buttons keep matching what is on screen.
|
||||
*/
|
||||
const rowIds = useMemo(() => {
|
||||
const loaded = thread ? thread.emailIds.filter((id) => emails[id]).map((id) => ({ id })) : [];
|
||||
return visibleMessages(loaded, messageId).map((m) => m.id);
|
||||
}, [thread, emails, messageId]);
|
||||
const anyUnread = messages.some((e) => !e.keywords.$seen);
|
||||
const anyStarred = messages.some((e) => e.keywords.$flagged);
|
||||
const inJunk = Boolean(mailboxId && mailboxes[mailboxId]?.role === "junk");
|
||||
|
||||
Reference in New Issue
Block a user