diff --git a/src/app/features/room/message/Message.tsx b/src/app/features/room/message/Message.tsx index c61cba5da..8a5cb3426 100644 --- a/src/app/features/room/message/Message.tsx +++ b/src/app/features/room/message/Message.tsx @@ -1176,6 +1176,18 @@ export const Message = React.memo( }; const isThreadedMessage = mEvent.threadRootId !== undefined; + // [Gitea #165] A root that already has a thread: the same action opens it, + // so say "View Thread (N replies)" rather than "Reply in Thread". + // The SDK gives a thread root its own id as threadRootId, so without this + // a root (the one message that HAS a thread) got no thread action at all. + const isThreadRoot = !!mEvent.getId() && mEvent.threadRootId === mEvent.getId(); + const showThreadAction = !isThreadedMessage || isThreadRoot; + const existingThread = mEvent.getId() ? room.getThread(mEvent.getId()!) : null; + const threadReplies = existingThread?.length ?? 0; + const threadActionLabel = + threadReplies > 0 + ? `View Thread (${threadReplies} ${threadReplies === 1 ? 'reply' : 'replies'})` + : 'Reply in Thread'; // The full action menu, shared by the desktop PopOut and the touch // bottom sheet (#166). @@ -1273,10 +1285,12 @@ export const Message = React.memo( )} - {!isThreadedMessage && ( + {showThreadAction && ( } + after={ + 0 ? Icons.Thread : Icons.ThreadPlus} size="100" /> + } radii="300" data-event-id={mEvent.getId()} onClick={(evt: React.MouseEvent) => { @@ -1285,7 +1299,7 @@ export const Message = React.memo( }} > - Reply in Thread + {threadActionLabel} )} @@ -1465,16 +1479,16 @@ export const Message = React.memo( > - {!isThreadedMessage && ( + {showThreadAction && ( onReplyClick(ev, true)} data-event-id={mEvent.getId()} variant="SurfaceVariant" size="300" radii="300" - aria-label="Reply in thread" + aria-label={threadReplies > 0 ? 'View thread' : 'Reply in thread'} > - + 0 ? Icons.Thread : Icons.ThreadPlus} size="100" /> )} {canEditEventOrCaption(mx, mEvent) && onEditId && (