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 && (