Merge pull request #7939 from vector-im/feature/ons/fix_edit_poll

Fix rendering of edited polls (PSG-963)
This commit is contained in:
Onuray Sahin 2023-01-13 03:13:53 +03:00 committed by GitHub
commit 1787031cc6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 22 additions and 7 deletions

1
changelog.d/7938.bugfix Normal file
View File

@ -0,0 +1 @@
Fix rendering of edited polls

View File

@ -148,8 +148,8 @@ fun TimelineEvent.getLastMessageContent(): MessageContent? {
// Polls/Beacon are not message contents like others as there is no msgtype subtype to discriminate moshi parsing // Polls/Beacon are not message contents like others as there is no msgtype subtype to discriminate moshi parsing
// 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 -> (getLastPollEditNewContent() ?: root.getClearContent()).toModel<MessagePollContent>()
in EventType.POLL_END.values -> (getLastEditNewContent() ?: root.getClearContent()).toModel<MessageEndPollContent>() in EventType.POLL_END.values -> (getLastPollEditNewContent() ?: 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()
@ -160,6 +160,10 @@ fun TimelineEvent.getLastEditNewContent(): Content? {
return annotations?.editSummary?.latestEdit?.getClearContent()?.toModel<MessageContent>()?.newContent return annotations?.editSummary?.latestEdit?.getClearContent()?.toModel<MessageContent>()?.newContent
} }
private fun TimelineEvent.getLastPollEditNewContent(): Content? {
return annotations?.editSummary?.latestEdit?.getClearContent()?.toModel<MessagePollContent>()?.newContent
}
/** /**
* Returns true if it's a reply. * Returns true if it's a reply.
*/ */

View File

@ -16,13 +16,16 @@
package org.matrix.android.sdk.internal.session.room package org.matrix.android.sdk.internal.session.room
import org.matrix.android.sdk.api.session.events.model.Content
import org.matrix.android.sdk.api.session.events.model.Event 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.LocalEcho
import org.matrix.android.sdk.api.session.events.model.RelationType 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.getRelationContent
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.message.MessageContent import org.matrix.android.sdk.api.session.room.model.message.MessageContent
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore import org.matrix.android.sdk.internal.crypto.store.IMXCryptoStore
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
@ -101,7 +104,7 @@ internal class EventEditValidator @Inject constructor(val cryptoStore: IMXCrypto
if (originalDecrypted.type != replaceDecrypted.type) { if (originalDecrypted.type != replaceDecrypted.type) {
return EditValidity.Invalid("replacement and original events must have the same type") return EditValidity.Invalid("replacement and original events must have the same type")
} }
if (replaceDecrypted.clearContent.toModel<MessageContent>()?.newContent == null) { if (!hasNewContent(replaceDecrypted.type, replaceDecrypted.clearContent)) {
return EditValidity.Invalid("replacement event must have an m.new_content property") return EditValidity.Invalid("replacement event must have an m.new_content property")
} }
} else { } else {
@ -116,11 +119,18 @@ internal class EventEditValidator @Inject constructor(val cryptoStore: IMXCrypto
if (originalEvent.type != replaceEvent.type) { if (originalEvent.type != replaceEvent.type) {
return EditValidity.Invalid("replacement and original events must have the same type") return EditValidity.Invalid("replacement and original events must have the same type")
} }
if (replaceEvent.content.toModel<MessageContent>()?.newContent == null) { if (!hasNewContent(replaceEvent.type, replaceEvent.content)) {
return EditValidity.Invalid("replacement event must have an m.new_content property") return EditValidity.Invalid("replacement event must have an m.new_content property")
} }
} }
return EditValidity.Valid return EditValidity.Valid
} }
private fun hasNewContent(eventType: String?, content: Content?): Boolean {
return when (eventType) {
in EventType.POLL_START.values -> content.toModel<MessagePollContent>()?.newContent != null
else -> content.toModel<MessageContent>()?.newContent != null
}
}
} }

View File

@ -216,8 +216,8 @@ class MessageActionsViewModel @AssistedInject constructor(
noticeEventFormatter.format(timelineEvent, room?.roomSummary()?.isDirect.orFalse()) noticeEventFormatter.format(timelineEvent, room?.roomSummary()?.isDirect.orFalse())
} }
in EventType.POLL_START.values -> { in EventType.POLL_START.values -> {
timelineEvent.root.getClearContent().toModel<MessagePollContent>(catchError = true) (timelineEvent.getVectorLastMessageContent() as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion()
?.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "" ?: stringProvider.getString(R.string.message_reply_to_poll_preview)
} }
else -> null else -> null
} }

View File

@ -130,7 +130,7 @@ class DisplayableEventFormatter @Inject constructor(
span { } span { }
} }
in EventType.POLL_START.values -> { in EventType.POLL_START.values -> {
timelineEvent.root.getClearContent().toModel<MessagePollContent>(catchError = true)?.getBestPollCreationInfo()?.question?.getBestQuestion() (timelineEvent.getVectorLastMessageContent() as? MessagePollContent)?.getBestPollCreationInfo()?.question?.getBestQuestion()
?: stringProvider.getString(R.string.sent_a_poll) ?: stringProvider.getString(R.string.sent_a_poll)
} }
in EventType.POLL_RESPONSE.values -> { in EventType.POLL_RESPONSE.values -> {