Merge pull request #8136 from vector-im/fix/mna/poll-end-while-no-poll-start

[Poll] Improve rendering of poll end message when poll start event isn't available (PSG-1157)
This commit is contained in:
Maxime NATUREL 2023-02-17 13:51:50 +01:00 committed by GitHub
commit de50577ac3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 70 additions and 30 deletions

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

@ -0,0 +1 @@
[Poll] Improve rendering of poll end message when poll start event isn't available

View File

@ -33,5 +33,9 @@ data class MessageEndPollContent(
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
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
@Json(name = "org.matrix.msc1767.text") val unstableText: String? = null,
@Json(name = "m.text") val text: String? = null,
) : MessageContent {
fun getBestText() = text ?: unstableText
}

View File

@ -242,7 +242,8 @@ internal class LocalEchoEventFactory @Inject constructor(
relatesTo = RelationDefaultContent(
type = RelationType.REFERENCE,
eventId = eventId
)
),
unstableText = "Ended poll",
)
val localId = LocalEcho.createLocalEchoId()
return Event(

View File

@ -114,7 +114,6 @@ import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
import org.matrix.android.sdk.api.session.room.timeline.getRelationContent
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
import org.matrix.android.sdk.api.util.MimeTypes
import timber.log.Timber
import javax.inject.Inject
class MessageItemFactory @Inject constructor(
@ -160,8 +159,8 @@ class MessageItemFactory @Inject constructor(
textRendererFactory.create(roomId)
}
private val useRichTextEditorStyle: Boolean get() =
vectorPreferences.isRichTextEditorEnabled()
private val useRichTextEditorStyle: Boolean
get() = vectorPreferences.isRichTextEditorEnabled()
fun create(params: TimelineItemFactoryParams): VectorEpoxyModel<*>? {
val event = params.event
@ -264,7 +263,7 @@ class MessageItemFactory @Inject constructor(
return PollItem_()
.attributes(attributes)
.eventId(informationData.eventId)
.pollQuestion(createPollQuestion(informationData, pollViewState.question, callback))
.pollTitle(createPollQuestion(informationData, pollViewState.question, callback))
.canVote(pollViewState.canVote)
.votesStatus(pollViewState.votesStatus)
.optionViewStates(pollViewState.optionViewStates.orEmpty())
@ -281,21 +280,37 @@ class MessageItemFactory @Inject constructor(
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
): PollItem? {
pollStartEventId ?: return null.also {
Timber.e("### buildEndedPollItem. Cannot render poll end event because poll start event id is null")
): PollItem {
val pollStartEvent = if (pollStartEventId?.isNotEmpty() == true) {
session.roomService().getRoom(roomId)?.getTimelineEvent(pollStartEventId)
} else {
null
}
val pollStartEvent = session.roomService().getRoom(roomId)?.getTimelineEvent(pollStartEventId)
val pollContent = pollStartEvent?.root?.getClearContent()?.toModel<MessagePollContent>() ?: return null
val pollContent = pollStartEvent?.root?.getClearContent()?.toModel<MessagePollContent>()
return buildPollItem(
pollContent,
informationData,
highlight,
callback,
attributes,
isEnded = true
)
return if (pollContent == null) {
val title = stringProvider.getString(R.string.message_reply_to_ended_poll_preview).toEpoxyCharSequence()
PollItem_()
.attributes(attributes)
.eventId(informationData.eventId)
.pollTitle(title)
.optionViewStates(emptyList())
.edited(informationData.hasBeenEdited)
.ended(true)
.hasContent(false)
.highlighted(highlight)
.leftGuideline(avatarSizeProvider.leftGuideline)
.callback(callback)
} else {
buildPollItem(
pollContent,
informationData,
highlight,
callback,
attributes,
isEnded = true,
)
}
}
private fun createPollQuestion(
@ -487,7 +502,6 @@ class MessageItemFactory @Inject constructor(
highlight,
callback,
attributes,
useRichTextEditorStyle = vectorPreferences.isRichTextEditorEnabled(),
)
}
@ -594,7 +608,7 @@ class MessageItemFactory @Inject constructor(
val replyToContent = messageContent.relatesTo?.inReplyTo
buildFormattedTextItem(matrixFormattedBody, informationData, highlight, callback, attributes, replyToContent)
} else {
buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes, useRichTextEditorStyle)
buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
}
}
@ -618,7 +632,6 @@ class MessageItemFactory @Inject constructor(
highlight,
callback,
attributes,
useRichTextEditorStyle,
)
}
@ -629,7 +642,6 @@ class MessageItemFactory @Inject constructor(
highlight: Boolean,
callback: TimelineEventController.Callback?,
attributes: AbsMessageItem.Attributes,
useRichTextEditorStyle: Boolean,
): MessageTextItem? {
val renderedBody = textRenderer.render(body)
val bindingOptions = spanUtils.getBindingOptions(renderedBody)

View File

@ -16,6 +16,7 @@
package im.vector.app.features.home.room.detail.timeline.item
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import androidx.core.view.children
@ -23,6 +24,7 @@ import androidx.core.view.isVisible
import com.airbnb.epoxy.EpoxyAttribute
import com.airbnb.epoxy.EpoxyModelClass
import im.vector.app.R
import im.vector.app.core.extensions.setTextOrHide
import im.vector.app.features.home.room.detail.RoomDetailAction
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
@ -31,7 +33,7 @@ import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
@EpoxyAttribute
var pollQuestion: EpoxyCharSequence? = null
var pollTitle: EpoxyCharSequence? = null
@EpoxyAttribute
var callback: TimelineEventController.Callback? = null
@ -54,6 +56,9 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
@EpoxyAttribute
var ended: Boolean = false
@EpoxyAttribute
var hasContent: Boolean = true
override fun getViewStubId() = STUB_ID
override fun bind(holder: Holder) {
@ -61,8 +66,8 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
renderSendState(holder.view, holder.questionTextView)
holder.questionTextView.text = pollQuestion?.charSequence
holder.votesStatusTextView.text = votesStatus
holder.questionTextView.text = pollTitle?.charSequence
holder.votesStatusTextView.setTextOrHide(votesStatus)
while (holder.optionsContainer.childCount < optionViewStates.size) {
holder.optionsContainer.addView(PollOptionView(holder.view.context))
@ -80,7 +85,8 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
}
}
holder.endedPollTextView.isVisible = ended
holder.endedPollTextView.isVisible = ended && hasContent
holder.pollIcon.isVisible = ended && hasContent.not()
}
private fun onPollItemClick(optionViewState: PollOptionViewState) {
@ -96,6 +102,7 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
val optionsContainer by bind<LinearLayout>(R.id.optionsContainer)
val votesStatusTextView by bind<TextView>(R.id.optionsVotesStatusTextView)
val endedPollTextView by bind<TextView>(R.id.endedPollTextView)
val pollIcon by bind<ImageView>(R.id.timelinePollIcon)
}
companion object {

View File

@ -21,16 +21,31 @@
<TextView
android:id="@+id/questionTextView"
style="@style/Widget.Vector.TextView.Subtitle"
android:layout_width="wrap_content"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:textColor="?vctr_content_primary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintStart_toEndOf="@id/timelinePollIcon"
app:layout_constraintTop_toBottomOf="@id/endedPollTextView"
tools:text="@sample/poll.json/question" />
<ImageView
android:id="@+id/timelinePollIcon"
android:layout_width="16dp"
android:layout_height="16dp"
android:layout_marginTop="4dp"
android:layout_marginEnd="8dp"
android:importantForAccessibility="no"
android:src="@drawable/ic_attachment_poll"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="@id/questionTextView"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@id/questionTextView"
app:tint="?vctr_content_secondary"
tools:ignore="ContentDescription" />
<LinearLayout
android:id="@+id/optionsContainer"
android:layout_width="0dp"