Invalidate previous votes for edited polls.

This commit is contained in:
Onuray Sahin 2022-01-23 19:32:13 +03:00
parent 5d07c71dcf
commit 9dd48045f6
5 changed files with 55 additions and 7 deletions

View File

@ -39,6 +39,8 @@ import org.matrix.android.sdk.api.session.room.model.message.MessagePollResponse
import org.matrix.android.sdk.api.session.room.model.message.MessageRelationContent
import org.matrix.android.sdk.api.session.room.model.relation.ReactionContent
import org.matrix.android.sdk.api.session.room.powerlevels.PowerLevelsHelper
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent
import org.matrix.android.sdk.internal.SessionManager
import org.matrix.android.sdk.internal.crypto.model.event.EncryptedEventContent
import org.matrix.android.sdk.internal.crypto.verification.toState
import org.matrix.android.sdk.internal.database.mapper.ContentMapper
@ -56,6 +58,7 @@ import org.matrix.android.sdk.internal.database.model.TimelineEventEntity
import org.matrix.android.sdk.internal.database.query.create
import org.matrix.android.sdk.internal.database.query.getOrCreate
import org.matrix.android.sdk.internal.database.query.where
import org.matrix.android.sdk.internal.di.SessionId
import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.EventInsertLiveProcessor
import org.matrix.android.sdk.internal.session.room.state.StateEventDataSource
@ -64,7 +67,9 @@ import javax.inject.Inject
internal class EventRelationsAggregationProcessor @Inject constructor(
@UserId private val userId: String,
private val stateEventDataSource: StateEventDataSource
private val stateEventDataSource: StateEventDataSource,
@SessionId private val sessionId: String,
private val sessionManager: SessionManager
) : EventInsertLiveProcessor {
private val allowedTypes = listOf(
@ -284,6 +289,20 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
Timber.v("###REPLACE ignoring event for summary, it's known $eventId")
return
}
ContentMapper
.map(eventAnnotationsSummaryEntity.pollResponseSummary?.aggregatedContent)
?.toModel<PollSummaryContent>()
?.apply {
totalVotes = 0
winnerVoteCount = 0
votes = emptyList()
votesSummary = emptyMap()
}
?.apply {
eventAnnotationsSummaryEntity.pollResponseSummary?.aggregatedContent = ContentMapper.map(toContent())
}
val txId = event.unsignedData?.transactionId
// is it a remote echo?
if (!isLocalEcho && existingSummary.editions.any { it.eventId == txId }) {
@ -325,6 +344,16 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
val targetEventId = relatedEventId ?: content.relatesTo?.eventId ?: return
val eventTimestamp = event.originServerTs ?: return
val session = sessionManager.getSessionComponent(sessionId)?.session()
val targetPollEvent = session?.getRoom(roomId)?.getTimeLineEvent(targetEventId) ?: return Unit.also {
Timber.v("## POLL target poll event $targetEventId not found in room $roomId")
}
val targetPollContent = targetPollEvent.getLastMessageContent() as? MessagePollContent ?: return Unit.also {
Timber.v("## POLL target poll event $targetEventId content is malformed")
}
// ok, this is a poll response
var existing = EventAnnotationsSummaryEntity.where(realm, roomId, targetEventId).findFirst()
if (existing == null) {
@ -365,6 +394,12 @@ internal class EventRelationsAggregationProcessor @Inject constructor(
Timber.d("## POLL Ignoring malformed response no option eventId:$eventId content: ${event.content}")
}
// Check if this option is in available options
if (!targetPollContent.pollCreationInfo?.answers?.map { it.id }?.contains(option).orFalse()) {
Timber.v("## POLL $targetEventId doesn't contain option $option")
return
}
val votes = sumModel.votes?.toMutableList() ?: ArrayList()
val existingVoteIndex = votes.indexOfFirst { it.userId == senderId }
if (existingVoteIndex != -1) {

View File

@ -61,6 +61,7 @@ import org.matrix.android.sdk.internal.di.UserId
import org.matrix.android.sdk.internal.session.content.ThumbnailExtractor
import org.matrix.android.sdk.internal.session.permalinks.PermalinkFactory
import org.matrix.android.sdk.internal.session.room.send.pills.TextPillsUtils
import java.util.UUID
import javax.inject.Inject
/**
@ -131,9 +132,9 @@ internal class LocalEchoEventFactory @Inject constructor(
question = PollQuestion(
question = question
),
answers = options.mapIndexed { index, option ->
answers = options.map { option ->
PollAnswer(
id = "$index-$option",
id = UUID.randomUUID().toString(),
answer = option
)
}

View File

@ -220,13 +220,22 @@ class MessageItemFactory @Inject constructor(
)
}
val question = pollContent.pollCreationInfo?.question?.question ?: ""
return PollItem_()
.attributes(attributes)
.eventId(informationData.eventId)
.pollQuestion(pollContent.pollCreationInfo?.question?.question ?: "")
.pollQuestion(
if (informationData.hasBeenEdited) {
annotateWithEdited(question, callback, informationData)
} else {
question
}.toEpoxyCharSequence()
)
.pollSent(isPollSent)
.totalVotesText(totalVotesText)
.optionViewStates(optionViewStates)
.edited(informationData.hasBeenEdited)
.highlighted(highlight)
.leftGuideline(avatarSizeProvider.leftGuideline)
.callback(callback)

View File

@ -22,6 +22,7 @@ import androidx.core.view.children
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.core.epoxy.charsequence.EpoxyCharSequence
import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
@ -29,7 +30,7 @@ import im.vector.app.features.home.room.detail.timeline.TimelineEventController
abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
@EpoxyAttribute
var pollQuestion: String? = null
var pollQuestion: EpoxyCharSequence? = null
@EpoxyAttribute
var callback: TimelineEventController.Callback? = null
@ -43,6 +44,9 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
@EpoxyAttribute
var totalVotesText: String? = null
@EpoxyAttribute
var edited: Boolean = false
@EpoxyAttribute
lateinit var optionViewStates: List<PollOptionViewState>
@ -52,7 +56,7 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
renderSendState(holder.view, holder.questionTextView)
holder.questionTextView.text = pollQuestion
holder.questionTextView.text = pollQuestion?.charSequence
holder.totalVotesTextView.text = totalVotesText
while (holder.optionsContainer.childCount < optionViewStates.size) {

View File

@ -24,7 +24,6 @@ import im.vector.app.core.di.MavericksAssistedViewModelFactory
import im.vector.app.core.di.hiltMavericksViewModelFactory
import im.vector.app.core.platform.VectorViewModel
import org.matrix.android.sdk.api.session.Session
import org.matrix.android.sdk.api.session.events.model.toModel
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.timeline.getLastMessageContent