Skip to content

Commit ebd35bd

Browse files
authored
Merge pull request #7969 from vector-im/feature/ons/fix_poll_end_reply
Show poll question when rendering reply to a poll end event (PSG-1133)
2 parents 9f4c595 + 48393ee commit ebd35bd

File tree

8 files changed

+138
-39
lines changed

8 files changed

+138
-39
lines changed

matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/summary/RoomSummaryConstants.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,6 @@ object RoomSummaryConstants {
3535
EventType.REACTION
3636
) +
3737
EventType.POLL_START.values +
38+
EventType.POLL_END.values +
3839
EventType.STATE_ROOM_BEACON_INFO.values
3940
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -320,7 +320,7 @@ internal class LocalEchoEventFactory @Inject constructor(
320320
val permalink = permalinkFactory.createPermalink(roomId, originalEvent.root.eventId ?: "", false)
321321
val userLink = originalEvent.root.senderId?.let { permalinkFactory.createPermalink(it, false) } ?: ""
322322

323-
val body = bodyForReply(originalEvent.getLastMessageContent(), originalEvent.isReply())
323+
val body = bodyForReply(timelineEvent = originalEvent)
324324
// As we always supply formatted body for replies we should force the MarkdownParser to produce html.
325325
val newBodyFormatted = markdownParser.parse(newBodyText, force = true, advanced = autoMarkdown).takeFormatted()
326326
// Body of the original message may not have formatted version, so may also have to convert to html.
@@ -613,7 +613,7 @@ internal class LocalEchoEventFactory @Inject constructor(
613613
val userId = eventReplied.root.senderId ?: return null
614614
val userLink = permalinkFactory.createPermalink(userId, false) ?: return null
615615

616-
val body = bodyForReply(eventReplied.getLastMessageContent(), eventReplied.isReply(), isRedactedEvent)
616+
val body = bodyForReply(timelineEvent = eventReplied, isRedactedEvent = isRedactedEvent)
617617

618618
// As we always supply formatted body for replies we should force the MarkdownParser to produce html.
619619
val finalReplyTextFormatted = replyTextFormatted?.toString() ?: markdownParser.parse(replyText, force = true, advanced = autoMarkdown).takeFormatted()
@@ -725,6 +725,20 @@ internal class LocalEchoEventFactory @Inject constructor(
725725
}
726726
}
727727

728+
private fun bodyForReply(timelineEvent: TimelineEvent, isRedactedEvent: Boolean = false): TextContent {
729+
val content = when (timelineEvent.root.getClearType()) {
730+
in EventType.POLL_END.values -> {
731+
// for end poll event, we use the content of the start poll event
732+
localEchoRepository
733+
.getRelatedPollEvent(timelineEvent)
734+
?.getLastMessageContent()
735+
?: timelineEvent.getLastMessageContent()
736+
}
737+
else -> timelineEvent.getLastMessageContent()
738+
}
739+
return bodyForReply(content = content, isReply = timelineEvent.isReply(), isRedactedEvent = isRedactedEvent)
740+
}
741+
728742
/**
729743
* Returns a TextContent used for the fallback event representation in a reply message.
730744
* In case of an edit of a reply the last content is not
@@ -755,6 +769,7 @@ internal class LocalEchoEventFactory @Inject constructor(
755769
MessageType.MSGTYPE_POLL_START -> {
756770
return TextContent((content as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "")
757771
}
772+
MessageType.MSGTYPE_POLL_END -> return TextContent("Ended poll")
758773
else -> {
759774
return if (isRedactedEvent) {
760775
TextContent("message removed.")

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoRepository.kt

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageContent
2525
import org.matrix.android.sdk.api.session.room.model.message.MessageType
2626
import org.matrix.android.sdk.api.session.room.send.SendState
2727
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
28+
import org.matrix.android.sdk.api.session.room.timeline.getRelationContent
2829
import org.matrix.android.sdk.internal.database.RealmSessionProvider
2930
import org.matrix.android.sdk.internal.database.asyncTransaction
3031
import org.matrix.android.sdk.internal.database.mapper.TimelineEventMapper
@@ -228,4 +229,15 @@ internal class LocalEchoRepository @Inject constructor(
228229
EventEntity.where(realm, eventId = rootThreadEventId).findFirst()?.threadSummaryLatestMessage?.eventId
229230
} ?: rootThreadEventId
230231
}
232+
233+
fun getRelatedPollEvent(timelineEvent: TimelineEvent): TimelineEvent? {
234+
val roomId = timelineEvent.roomId
235+
val pollEventId = timelineEvent.getRelationContent()?.eventId ?: return null
236+
237+
return realmSessionProvider.withRealm { realm ->
238+
TimelineEventEntity.where(realm, roomId = roomId, eventId = pollEventId).findFirst()?.let {
239+
timelineEventMapper.map(it)
240+
}
241+
}
242+
}
231243
}

vector/src/main/java/im/vector/app/features/home/room/detail/timeline/action/MessageActionsViewModel.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,9 @@ class MessageActionsViewModel @AssistedInject constructor(
219219
(timelineEvent.getVectorLastMessageContent() as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion()
220220
?: stringProvider.getString(R.string.message_reply_to_poll_preview)
221221
}
222+
in EventType.POLL_END.values -> {
223+
stringProvider.getString(R.string.message_reply_to_ended_poll_preview)
224+
}
222225
else -> null
223226
}
224227
}

vector/src/main/java/im/vector/app/features/home/room/detail/timeline/render/ProcessBodyOfReplyToEventUseCase.kt

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,23 @@ package im.vector.app.features.home.room.detail.timeline.render
1919
import im.vector.app.R
2020
import im.vector.app.core.di.ActiveSessionHolder
2121
import im.vector.app.core.resources.StringProvider
22+
import org.matrix.android.sdk.api.session.events.model.Event
2223
import org.matrix.android.sdk.api.session.events.model.getPollQuestion
24+
import org.matrix.android.sdk.api.session.events.model.getRelationContent
2325
import org.matrix.android.sdk.api.session.events.model.isAudioMessage
2426
import org.matrix.android.sdk.api.session.events.model.isFileMessage
2527
import org.matrix.android.sdk.api.session.events.model.isImageMessage
2628
import org.matrix.android.sdk.api.session.events.model.isLiveLocation
27-
import org.matrix.android.sdk.api.session.events.model.isPoll
2829
import org.matrix.android.sdk.api.session.events.model.isPollEnd
2930
import org.matrix.android.sdk.api.session.events.model.isPollStart
3031
import org.matrix.android.sdk.api.session.events.model.isSticker
3132
import org.matrix.android.sdk.api.session.events.model.isVideoMessage
3233
import org.matrix.android.sdk.api.session.events.model.isVoiceMessage
3334
import org.matrix.android.sdk.api.session.getRoom
3435
import org.matrix.android.sdk.api.session.room.getTimelineEvent
36+
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
3537
import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
38+
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
3639
import javax.inject.Inject
3740

3841
private const val IN_REPLY_TO = "In reply to"
@@ -94,16 +97,22 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor(
9497
stringProvider.getString(R.string.message_reply_to_sender_sent_sticker)
9598
)
9699
}
97-
repliedToEvent.isPoll() -> {
98-
val fallbackText = when {
99-
repliedToEvent.isPollStart() -> stringProvider.getString(R.string.message_reply_to_sender_created_poll)
100-
repliedToEvent.isPollEnd() -> stringProvider.getString(R.string.message_reply_to_sender_ended_poll)
101-
else -> ""
102-
}
100+
repliedToEvent.isPollEnd() -> {
101+
val fallbackText = stringProvider.getString(R.string.message_reply_to_sender_ended_poll)
102+
val repliedText = getPollQuestionFromPollEnd(repliedToEvent)
103103
matrixFormattedBody.replaceRange(
104104
afterBreakingLineIndex,
105105
endOfBlockQuoteIndex,
106-
repliedToEvent.getPollQuestion() ?: fallbackText
106+
repliedText ?: fallbackText,
107+
)
108+
}
109+
repliedToEvent.isPollStart() -> {
110+
val fallbackText = stringProvider.getString(R.string.message_reply_to_sender_created_poll)
111+
val repliedText = repliedToEvent.getPollQuestion()
112+
matrixFormattedBody.replaceRange(
113+
afterBreakingLineIndex,
114+
endOfBlockQuoteIndex,
115+
repliedText ?: fallbackText,
107116
)
108117
}
109118
repliedToEvent.isLiveLocation() -> {
@@ -126,8 +135,25 @@ class ProcessBodyOfReplyToEventUseCase @Inject constructor(
126135
}
127136

128137
private fun getEvent(eventId: String, roomId: String) =
138+
getTimelineEvent(eventId, roomId)
139+
?.root
140+
141+
private fun getTimelineEvent(eventId: String, roomId: String) =
129142
activeSessionHolder.getSafeActiveSession()
130143
?.getRoom(roomId)
131144
?.getTimelineEvent(eventId)
132-
?.root
145+
146+
private fun getPollQuestionFromPollEnd(event: Event): String? {
147+
val eventId = event.getRelationContent()?.eventId.orEmpty()
148+
val roomId = event.roomId.orEmpty()
149+
return if (eventId.isEmpty() || roomId.isEmpty()) {
150+
null
151+
} else {
152+
(getTimelineEvent(eventId, roomId)
153+
?.getLastMessageContent() as? MessagePollContent)
154+
?.getBestPollCreationInfo()
155+
?.question
156+
?.getBestQuestion()
157+
}
158+
}
133159
}

0 commit comments

Comments
 (0)