Render ended poll.

This commit is contained in:
Onuray Sahin 2022-12-26 14:41:38 +03:00
parent f6cabfffd9
commit 486968fdc2
6 changed files with 63 additions and 18 deletions

View file

@ -18,6 +18,7 @@ package org.matrix.android.sdk.api.session.room.model.message
import com.squareup.moshi.Json import com.squareup.moshi.Json
import com.squareup.moshi.JsonClass import com.squareup.moshi.JsonClass
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultContent
/** /**
@ -25,5 +26,12 @@ import org.matrix.android.sdk.api.session.room.model.relation.RelationDefaultCon
*/ */
@JsonClass(generateAdapter = true) @JsonClass(generateAdapter = true)
data class MessageEndPollContent( data class MessageEndPollContent(
@Json(name = "m.relates_to") val relatesTo: RelationDefaultContent? = null /**
) * Local message type, not from server.
*/
@Transient
override val msgType: String = MessageType.MSGTYPE_POLL_END,
@Json(name = "body") override val body: String = "",
@Json(name = "m.new_content") override val newContent: Content? = null,
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null
) : MessageContent

View file

@ -36,6 +36,7 @@ object MessageType {
// Because poll events are not message events and they don't have msgtype field // Because poll events are not message events and they don't have msgtype field
const val MSGTYPE_POLL_START = "org.matrix.android.sdk.poll.start" const val MSGTYPE_POLL_START = "org.matrix.android.sdk.poll.start"
const val MSGTYPE_POLL_RESPONSE = "org.matrix.android.sdk.poll.response" const val MSGTYPE_POLL_RESPONSE = "org.matrix.android.sdk.poll.response"
const val MSGTYPE_POLL_END = "org.matrix.android.sdk.poll.end"
const val MSGTYPE_CONFETTI = "nic.custom.confetti" const val MSGTYPE_CONFETTI = "nic.custom.confetti"
const val MSGTYPE_SNOWFALL = "io.element.effect.snowfall" const val MSGTYPE_SNOWFALL = "io.element.effect.snowfall"

View file

@ -35,6 +35,7 @@ import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoCo
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconLocationDataContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody
import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent import org.matrix.android.sdk.api.session.room.model.message.MessageStickerContent
import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent import org.matrix.android.sdk.api.session.room.model.message.MessageTextContent
@ -148,6 +149,7 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? {
// so toModel<MessageContent> won't parse them correctly // so toModel<MessageContent> won't parse them correctly
// It's discriminated on event type instead. Maybe it shouldn't be MessageContent at all to avoid confusion? // It's discriminated on event type instead. Maybe it shouldn't be MessageContent at all to avoid confusion?
in EventType.POLL_START.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessagePollContent>() in EventType.POLL_START.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessagePollContent>()
in EventType.POLL_END.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageEndPollContent>()
in EventType.STATE_ROOM_BEACON_INFO.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconInfoContent>() in EventType.STATE_ROOM_BEACON_INFO.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconInfoContent>()
in EventType.BEACON_LOCATION_DATA.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconLocationDataContent>() in EventType.BEACON_LOCATION_DATA.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageBeaconLocationDataContent>()
else -> (getLastEditNewContent() ?: root.getClearContent()).toModel() else -> (getLastEditNewContent() ?: root.getClearContent()).toModel()

View file

@ -91,11 +91,13 @@ import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent import org.matrix.android.sdk.api.session.events.model.content.EncryptedEventContent
import org.matrix.android.sdk.api.session.events.model.isThread import org.matrix.android.sdk.api.session.events.model.isThread
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.getTimelineEvent
import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent import org.matrix.android.sdk.api.session.room.model.message.MessageAudioContent
import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent import org.matrix.android.sdk.api.session.room.model.message.MessageBeaconInfoContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody import org.matrix.android.sdk.api.session.room.model.message.MessageContentWithFormattedBody
import org.matrix.android.sdk.api.session.room.model.message.MessageEmoteContent import org.matrix.android.sdk.api.session.room.model.message.MessageEmoteContent
import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent
import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent import org.matrix.android.sdk.api.session.room.model.message.MessageFileContent
import org.matrix.android.sdk.api.session.room.model.message.MessageImageInfoContent import org.matrix.android.sdk.api.session.room.model.message.MessageImageInfoContent
import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent import org.matrix.android.sdk.api.session.room.model.message.MessageLocationContent
@ -203,6 +205,7 @@ class MessageItemFactory @Inject constructor(
is MessageAudioContent -> buildAudioContent(params, messageContent, informationData, highlight, attributes) is MessageAudioContent -> buildAudioContent(params, messageContent, informationData, highlight, attributes)
is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes) is MessageVerificationRequestContent -> buildVerificationRequestMessageItem(messageContent, informationData, highlight, callback, attributes)
is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes) is MessagePollContent -> buildPollItem(messageContent, informationData, highlight, callback, attributes)
is MessageEndPollContent -> buildEndedPollItem(messageContent, informationData, highlight, callback, attributes)
is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, attributes) is MessageLocationContent -> buildLocationItem(messageContent, informationData, highlight, attributes)
is MessageBeaconInfoContent -> liveLocationShareMessageItemFactory.create(event, highlight, attributes) is MessageBeaconInfoContent -> liveLocationShareMessageItemFactory.create(event, highlight, attributes)
is MessageVoiceBroadcastInfoContent -> voiceBroadcastItemFactory.create(params, messageContent, highlight, attributes) is MessageVoiceBroadcastInfoContent -> voiceBroadcastItemFactory.create(params, messageContent, highlight, attributes)
@ -261,6 +264,32 @@ class MessageItemFactory @Inject constructor(
.callback(callback) .callback(callback)
} }
private fun buildEndedPollItem(
endedPollContent: MessageEndPollContent,
informationData: MessageInformationData,
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
): PollItem? {
val pollStartEventId = endedPollContent.relatesTo?.eventId ?: return null
val pollStartEvent = session.roomService().getRoom(roomId)?.getTimelineEvent(pollStartEventId)
val pollContent = pollStartEvent?.root?.getClearContent()?.toModel<MessagePollContent>() ?: return null
val aggregatedInformationData = informationData.copy(
pollResponseAggregatedSummary = messageInformationDataFactory.mapPollResponseSummary(pollStartEvent.annotations?.pollResponseSummary)
)
return buildPollItem(
pollContent,
aggregatedInformationData,
highlight,
callback,
attributes
)
}
private fun createPollQuestion( private fun createPollQuestion(
informationData: MessageInformationData, informationData: MessageInformationData,
question: String, question: String,

View file

@ -102,6 +102,7 @@ class TimelineItemFactory @Inject constructor(
// Message itemsX // Message itemsX
EventType.STICKER, EventType.STICKER,
in EventType.POLL_START.values, in EventType.POLL_START.values,
in EventType.POLL_END.values,
EventType.MESSAGE -> messageItemFactory.create(params) EventType.MESSAGE -> messageItemFactory.create(params)
EventType.REDACTION, EventType.REDACTION,
EventType.KEY_VERIFICATION_ACCEPT, EventType.KEY_VERIFICATION_ACCEPT,
@ -114,8 +115,7 @@ class TimelineItemFactory @Inject constructor(
EventType.CALL_SELECT_ANSWER, EventType.CALL_SELECT_ANSWER,
EventType.CALL_NEGOTIATE, EventType.CALL_NEGOTIATE,
EventType.REACTION, EventType.REACTION,
in EventType.POLL_RESPONSE.values, in EventType.POLL_RESPONSE.values -> noticeItemFactory.create(params)
in EventType.POLL_END.values -> noticeItemFactory.create(params)
in EventType.BEACON_LOCATION_DATA.values -> { in EventType.BEACON_LOCATION_DATA.values -> {
if (event.root.isRedacted()) { if (event.root.isRedacted()) {
messageItemFactory.create(params) messageItemFactory.create(params)

View file

@ -38,6 +38,7 @@ import org.matrix.android.sdk.api.session.events.model.isAttachmentMessage
import org.matrix.android.sdk.api.session.events.model.isSticker import org.matrix.android.sdk.api.session.events.model.isSticker
import org.matrix.android.sdk.api.session.events.model.toModel import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.events.model.toValidDecryptedEvent import org.matrix.android.sdk.api.session.events.model.toValidDecryptedEvent
import org.matrix.android.sdk.api.session.room.model.PollResponseAggregatedSummary
import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent
import org.matrix.android.sdk.api.session.room.model.RoomSummary import org.matrix.android.sdk.api.session.room.model.RoomSummary
import org.matrix.android.sdk.api.session.room.model.message.MessageType import org.matrix.android.sdk.api.session.room.model.message.MessageType
@ -99,20 +100,7 @@ class MessageInformationDataFactory @Inject constructor(
memberName = event.senderInfo.disambiguatedDisplayName, memberName = event.senderInfo.disambiguatedDisplayName,
messageLayout = messageLayout, messageLayout = messageLayout,
reactionsSummary = reactionsSummaryFactory.create(event), reactionsSummary = reactionsSummaryFactory.create(event),
pollResponseAggregatedSummary = event.annotations?.pollResponseSummary?.let { pollResponseAggregatedSummary = mapPollResponseSummary(event.annotations?.pollResponseSummary),
PollResponseData(
myVote = it.aggregatedContent?.myVote,
isClosed = it.closedTime != null,
votes = it.aggregatedContent?.votesSummary?.mapValues { votesSummary ->
PollVoteSummaryData(
total = votesSummary.value.total,
percentage = votesSummary.value.percentage
)
},
winnerVoteCount = it.aggregatedContent?.winnerVoteCount ?: 0,
totalVotes = it.aggregatedContent?.totalVotes ?: 0
)
},
hasBeenEdited = event.hasBeenEdited(), hasBeenEdited = event.hasBeenEdited(),
hasPendingEdits = event.annotations?.editSummary?.localEchos?.any() ?: false, hasPendingEdits = event.annotations?.editSummary?.localEchos?.any() ?: false,
referencesInfoData = event.annotations?.referencesAggregatedSummary?.let { referencesAggregatedSummary -> referencesInfoData = event.annotations?.referencesAggregatedSummary?.let { referencesAggregatedSummary ->
@ -133,6 +121,23 @@ class MessageInformationDataFactory @Inject constructor(
) )
} }
fun mapPollResponseSummary(pollResponseSummary: PollResponseAggregatedSummary?): PollResponseData? {
return pollResponseSummary?.let {
PollResponseData(
myVote = it.aggregatedContent?.myVote,
isClosed = it.closedTime != null,
votes = it.aggregatedContent?.votesSummary?.mapValues { votesSummary ->
PollVoteSummaryData(
total = votesSummary.value.total,
percentage = votesSummary.value.percentage
)
},
winnerVoteCount = it.aggregatedContent?.winnerVoteCount ?: 0,
totalVotes = it.aggregatedContent?.totalVotes ?: 0
)
}
}
private fun getSenderId(event: TimelineEvent) = if (event.isEncrypted()) { private fun getSenderId(event: TimelineEvent) = if (event.isEncrypted()) {
event.root.toValidDecryptedEvent()?.let { event.root.toValidDecryptedEvent()?.let {
session.cryptoService().deviceWithIdentityKey(it.cryptoSenderKey, it.algorithm)?.userId session.cryptoService().deviceWithIdentityKey(it.cryptoSenderKey, it.algorithm)?.userId