Aggregate votes and poll end event.

This commit is contained in:
Onuray Sahin 2021-12-03 11:23:47 +03:00
parent a3b11b223a
commit 2a3a55894f
1 changed files with 72 additions and 15 deletions

View File

@ -22,12 +22,14 @@ import org.matrix.android.sdk.api.session.events.model.Event
import org.matrix.android.sdk.api.session.events.model.EventType
import org.matrix.android.sdk.api.session.events.model.LocalEcho
import org.matrix.android.sdk.api.session.events.model.RelationType
import org.matrix.android.sdk.api.session.events.model.getRelationContent
import org.matrix.android.sdk.api.session.events.model.toContent
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.PollSummaryContent
import org.matrix.android.sdk.api.session.room.model.ReferencesAggregatedContent
import org.matrix.android.sdk.api.session.room.model.VoteInfo
import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessageEndPollContent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponseContent
import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent
@ -69,7 +71,9 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
// TODO Add ?
// EventType.KEY_VERIFICATION_READY,
EventType.KEY_VERIFICATION_KEY,
EventType.ENCRYPTED
EventType.ENCRYPTED,
EventType.POLL_RESPONSE,
EventType.POLL_END
)
override fun shouldProcess(eventId: String, eventType: String, insertType: EventInsertType): Boolean {
@ -107,7 +111,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
Timber.v("###REPLACE in room $roomId for event ${event.eventId}")
// A replace!
handleReplace(realm, event, content, roomId, isLocalEcho)
} else if (content?.relatesTo?.type == RelationType.RESPONSE) {
} else if (content is MessagePollResponseContent) {
Timber.v("###RESPONSE in room $roomId for event ${event.eventId}")
handleResponse(realm, event, content, roomId, isLocalEcho)
}
@ -139,7 +143,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
Timber.v("###REPLACE in room $roomId for event ${event.eventId}")
// A replace!
handleReplace(realm, event, it, roomId, isLocalEcho, encryptedEventContent.relatesTo.eventId)
} else if (encryptedEventContent.relatesTo.type == RelationType.RESPONSE) {
} else if (it is MessagePollResponseContent) {
Timber.v("###RESPONSE in room $roomId for event ${event.eventId}")
handleResponse(realm, event, it, roomId, isLocalEcho, encryptedEventContent.relatesTo.eventId)
}
@ -158,6 +162,16 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
handleVerification(realm, event, roomId, isLocalEcho, it)
}
}
EventType.POLL_RESPONSE -> {
event.getClearContent().toModel<MessagePollResponseContent>(catchError = true)?.let {
handleResponse(realm, event, it, roomId, isLocalEcho, event.getRelationContent()?.eventId)
}
}
EventType.POLL_END -> {
event.content.toModel<MessageEndPollContent>(catchError = true)?.let {
handleEndPoll(realm, event, it, roomId, isLocalEcho)
}
}
}
} else if (encryptedEventContent?.relatesTo?.type == RelationType.ANNOTATION) {
// Reaction
@ -188,6 +202,16 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
}
}
}
EventType.POLL_RESPONSE -> {
event.content.toModel<MessagePollResponseContent>(catchError = true)?.let {
handleResponse(realm, event, it, roomId, isLocalEcho)
}
}
EventType.POLL_END -> {
event.content.toModel<MessageEndPollContent>(catchError = true)?.let {
handleEndPoll(realm, event, it, roomId, isLocalEcho)
}
}
else -> Timber.v("UnHandled event ${event.eventId}")
}
} catch (t: Throwable) {
@ -276,7 +300,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
private fun handleResponse(realm: Realm,
event: Event,
content: MessageContent,
content: MessagePollResponseContent,
roomId: String,
isLocalEcho: Boolean,
relatedEventId: String? = null) {
@ -321,11 +345,7 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
return
}
val responseContent = event.content.toModel<MessagePollResponseContent>() ?: return Unit.also {
Timber.d("## POLL Receiving malformed response eventId:$eventId content: ${event.content}")
}
val optionIndex = responseContent.relatesTo?.option ?: return Unit.also {
val option = content.response?.answers?.first() ?: return Unit.also {
Timber.d("## POLL Ignoring malformed response no option eventId:$eventId content: ${event.content}")
}
@ -336,20 +356,20 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
val existingVote = votes[existingVoteIndex]
if (existingVote.voteTimestamp < eventTimestamp) {
// Take the new one
votes[existingVoteIndex] = VoteInfo(senderId, optionIndex, eventTimestamp)
votes[existingVoteIndex] = VoteInfo(senderId, option, eventTimestamp)
if (userId == senderId) {
sumModel.myVote = optionIndex
sumModel.myVote = option
}
Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$targetEventId ")
Timber.v("## POLL adding vote $option for user $senderId in poll :$targetEventId ")
} else {
Timber.v("## POLL Ignoring vote (older than known one) eventId:$eventId ")
}
} else {
votes.add(VoteInfo(senderId, optionIndex, eventTimestamp))
votes.add(VoteInfo(senderId, option, eventTimestamp))
if (userId == senderId) {
sumModel.myVote = optionIndex
sumModel.myVote = option
}
Timber.v("## POLL adding vote $optionIndex for user $senderId in poll :$targetEventId ")
Timber.v("## POLL adding vote $option for user $senderId in poll :$targetEventId ")
}
sumModel.votes = votes
if (isLocalEcho) {
@ -361,6 +381,43 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
existingPollSummary.aggregatedContent = ContentMapper.map(sumModel.toContent())
}
private fun handleEndPoll(realm: Realm,
event: Event,
content: MessageEndPollContent,
roomId: String,
isLocalEcho: Boolean) {
val pollEventId = content.eventId
var existing = EventAnnotationsSummaryEntity.where(realm, roomId, pollEventId).findFirst()
if (existing == null) {
Timber.v("## POLL creating new relation summary for $pollEventId")
existing = EventAnnotationsSummaryEntity.create(realm, roomId, pollEventId)
}
// we have it
val existingPollSummary = existing.pollResponseSummary
?: realm.createObject(PollResponseAggregatedSummaryEntity::class.java).also {
existing.pollResponseSummary = it
}
if (existingPollSummary.closedTime != null) {
Timber.v("## Received poll.end event for already ended poll $pollEventId")
return
}
val txId = event.unsignedData?.transactionId
// is it a remote echo?
if (!isLocalEcho && existingPollSummary.sourceLocalEchoEvents.contains(txId)) {
// ok it has already been managed
Timber.v("## POLL Receiving remote echo of response eventId:$pollEventId")
existingPollSummary.sourceLocalEchoEvents.remove(txId)
existingPollSummary.sourceEvents.add(event.eventId)
return
}
existingPollSummary.closedTime = event.originServerTs
}
private fun handleInitialAggregatedRelations(realm: Realm,
event: Event,
roomId: String,