Skip to content

Commit 15e903f

Browse files
authored
Fix mark unread action not shown for messages that are root of a thread in the channel view (#1041)
* Fix mark unread action not shown for messages that are root of a thread in the channel view * Update CHANGELOG.md * Fix mark unread action not shown for messages that are root of a thread in the channel view
1 parent f5043c2 commit 15e903f

File tree

3 files changed

+108
-10
lines changed

3 files changed

+108
-10
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
99

1010
### 🐞 Fixed
1111
- Fix composer deleting newly entered text after deleting draft text [#1030](https://github.com/GetStream/stream-chat-swiftui/pull/1030)
12+
- Fix mark unread action not shown for messages that are root of a thread in the channel view [#1041](https://github.com/GetStream/stream-chat-swiftui/pull/1041)
1213

1314
# [4.91.0](https://github.com/GetStream/stream-chat-swiftui/releases/tag/4.91.0)
1415
_October 22, 2025_

Sources/StreamChatSwiftUI/ChatChannel/Reactions/MessageActions/DefaultMessageActions.swift

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -121,16 +121,14 @@ public extension MessageAction {
121121
messageActions.append(copyAction)
122122
}
123123

124-
if message.isRootOfThread {
125-
if isInsideThreadView {
126-
let markThreadUnreadAction = markThreadAsUnreadAction(
127-
messageController: messageController,
128-
message: message,
129-
onFinish: onFinish,
130-
onError: onError
131-
)
132-
messageActions.append(markThreadUnreadAction)
133-
}
124+
if message.isRootOfThread && isInsideThreadView {
125+
let markThreadUnreadAction = markThreadAsUnreadAction(
126+
messageController: messageController,
127+
message: message,
128+
onFinish: onFinish,
129+
onError: onError
130+
)
131+
messageActions.append(markThreadUnreadAction)
134132
} else if !message.isSentByCurrentUser && channel.canReceiveReadEvents {
135133
if !message.isPartOfThread || message.showReplyInChannel {
136134
let markUnreadAction = markAsUnreadAction(

StreamChatSwiftUITests/Tests/ChatChannel/MessageActions_Tests.swift

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,105 @@ class MessageActions_Tests: StreamChatTestCase {
7272
XCTAssert(messageActions[5].title == "Mute User")
7373
}
7474

75+
func test_messageActions_partOfThread() {
76+
// Given
77+
let channel = mockDMChannel
78+
let message = ChatMessage.mock(
79+
id: .unique,
80+
cid: channel.cid,
81+
text: "Test",
82+
author: .mock(id: .unique),
83+
parentMessageId: .unique,
84+
showReplyInChannel: false,
85+
isSentByCurrentUser: false
86+
)
87+
let factory = DefaultViewFactory.shared
88+
89+
// When
90+
let messageActions = MessageAction.defaultActions(
91+
factory: factory,
92+
for: message,
93+
channel: channel,
94+
chatClient: chatClient,
95+
onFinish: { _ in },
96+
onError: { _ in }
97+
)
98+
99+
// Then
100+
XCTAssertEqual(messageActions.count, 4)
101+
XCTAssertEqual(messageActions[0].title, "Reply")
102+
XCTAssertEqual(messageActions[1].title, "Pin to conversation")
103+
XCTAssertEqual(messageActions[2].title, "Copy Message")
104+
XCTAssertEqual(messageActions[3].title, "Mute User")
105+
}
106+
107+
func test_messageActions_partOfThreadButAlsoInChannel() {
108+
// Given
109+
let channel = mockDMChannel
110+
let message = ChatMessage.mock(
111+
id: .unique,
112+
cid: channel.cid,
113+
text: "Test",
114+
author: .mock(id: .unique),
115+
parentMessageId: .unique,
116+
showReplyInChannel: true,
117+
isSentByCurrentUser: false
118+
)
119+
let factory = DefaultViewFactory.shared
120+
121+
// When
122+
let messageActions = MessageAction.defaultActions(
123+
factory: factory,
124+
for: message,
125+
channel: channel,
126+
chatClient: chatClient,
127+
onFinish: { _ in },
128+
onError: { _ in }
129+
)
130+
131+
// Then
132+
XCTAssertEqual(messageActions.count, 5)
133+
XCTAssertEqual(messageActions[0].title, "Reply")
134+
XCTAssertEqual(messageActions[1].title, "Pin to conversation")
135+
XCTAssertEqual(messageActions[2].title, "Copy Message")
136+
XCTAssertEqual(messageActions[3].title, "Mark Unread")
137+
XCTAssertEqual(messageActions[4].title, "Mute User")
138+
}
139+
140+
func test_messageActions_rootOfThreadButAlsoInChannel() {
141+
// Given
142+
let channel = mockDMChannel
143+
let message = ChatMessage.mock(
144+
id: .unique,
145+
cid: channel.cid,
146+
text: "Test",
147+
author: .mock(id: .unique),
148+
parentMessageId: .unique,
149+
showReplyInChannel: true,
150+
replyCount: 3,
151+
isSentByCurrentUser: false
152+
)
153+
let factory = DefaultViewFactory.shared
154+
155+
// When
156+
let messageActions = MessageAction.defaultActions(
157+
factory: factory,
158+
for: message,
159+
channel: channel,
160+
chatClient: chatClient,
161+
onFinish: { _ in },
162+
onError: { _ in }
163+
)
164+
165+
// Then
166+
XCTAssertEqual(messageActions.count, 5)
167+
XCTAssertEqual(messageActions[0].title, "Reply")
168+
XCTAssertEqual(messageActions[1].title, "Pin to conversation")
169+
XCTAssertEqual(messageActions[2].title, "Copy Message")
170+
XCTAssertEqual(messageActions[3].title, "Mark Unread")
171+
XCTAssertEqual(messageActions[4].title, "Mute User")
172+
}
173+
75174
func test_messageActions_otherUserDefaultReadEventsDisabled() {
76175
// Given
77176
let channel = ChatChannel.mockDMChannel(ownCapabilities: [.sendMessage, .uploadFile, .pinMessage])

0 commit comments

Comments
 (0)