diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt index f42d55ca2a..1577f3057f 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/EventRelationsAggregationProcessor.kt @@ -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() + ?.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) { diff --git a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt index 8e44314371..3167a5b0b9 100644 --- a/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt +++ b/matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt @@ -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 ) } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 21af8b82cb..48d9efae47 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -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) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollItem.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollItem.kt index 1308fa49c8..0cad02827b 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollItem.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollItem.kt @@ -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() { @EpoxyAttribute - var pollQuestion: String? = null + var pollQuestion: EpoxyCharSequence? = null @EpoxyAttribute var callback: TimelineEventController.Callback? = null @@ -43,6 +44,9 @@ abstract class PollItem : AbsMessageItem() { @EpoxyAttribute var totalVotesText: String? = null + @EpoxyAttribute + var edited: Boolean = false + @EpoxyAttribute lateinit var optionViewStates: List @@ -52,7 +56,7 @@ abstract class PollItem : AbsMessageItem() { renderSendState(holder.view, holder.questionTextView) - holder.questionTextView.text = pollQuestion + holder.questionTextView.text = pollQuestion?.charSequence holder.totalVotesTextView.text = totalVotesText while (holder.optionsContainer.childCount < optionViewStates.size) { diff --git a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollViewModel.kt b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollViewModel.kt index 875dfbe3a8..4ac1b64aef 100644 --- a/vector/src/main/java/im/vector/app/features/poll/create/CreatePollViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/poll/create/CreatePollViewModel.kt @@ -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