Skip to content

Commit de50577

Browse files
authored
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)
2 parents 7d16c86 + 068a43e commit de50577

File tree

6 files changed

+71
-31
lines changed

6 files changed

+71
-31
lines changed

changelog.d/8129.bugfix

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
[Poll] Improve rendering of poll end message when poll start event isn't available

matrix-sdk-android/src/main/java/org/matrix/android/sdk/api/session/room/model/message/MessageEndPollContent.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,5 +33,9 @@ data class MessageEndPollContent(
3333
override val msgType: String = MessageType.MSGTYPE_POLL_END,
3434
@Json(name = "body") override val body: String = "",
3535
@Json(name = "m.new_content") override val newContent: Content? = null,
36-
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null
37-
) : MessageContent
36+
@Json(name = "m.relates_to") override val relatesTo: RelationDefaultContent? = null,
37+
@Json(name = "org.matrix.msc1767.text") val unstableText: String? = null,
38+
@Json(name = "m.text") val text: String? = null,
39+
) : MessageContent {
40+
fun getBestText() = text ?: unstableText
41+
}

matrix-sdk-android/src/main/java/org/matrix/android/sdk/internal/session/room/send/LocalEchoEventFactory.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -242,7 +242,8 @@ internal class LocalEchoEventFactory @Inject constructor(
242242
relatesTo = RelationDefaultContent(
243243
type = RelationType.REFERENCE,
244244
eventId = eventId
245-
)
245+
),
246+
unstableText = "Ended poll",
246247
)
247248
val localId = LocalEcho.createLocalEchoId()
248249
return Event(

vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt

Lines changed: 34 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,6 @@ import org.matrix.android.sdk.api.session.room.model.relation.ReplyToContent
114114
import org.matrix.android.sdk.api.session.room.timeline.getRelationContent
115115
import org.matrix.android.sdk.api.settings.LightweightSettingsStorage
116116
import org.matrix.android.sdk.api.util.MimeTypes
117-
import timber.log.Timber
118117
import javax.inject.Inject
119118

120119
class MessageItemFactory @Inject constructor(
@@ -160,8 +159,8 @@ class MessageItemFactory @Inject constructor(
160159
textRendererFactory.create(roomId)
161160
}
162161

163-
private val useRichTextEditorStyle: Boolean get() =
164-
vectorPreferences.isRichTextEditorEnabled()
162+
private val useRichTextEditorStyle: Boolean
163+
get() = vectorPreferences.isRichTextEditorEnabled()
165164

166165
fun create(params: TimelineItemFactoryParams): VectorEpoxyModel<*>? {
167166
val event = params.event
@@ -264,7 +263,7 @@ class MessageItemFactory @Inject constructor(
264263
return PollItem_()
265264
.attributes(attributes)
266265
.eventId(informationData.eventId)
267-
.pollQuestion(createPollQuestion(informationData, pollViewState.question, callback))
266+
.pollTitle(createPollQuestion(informationData, pollViewState.question, callback))
268267
.canVote(pollViewState.canVote)
269268
.votesStatus(pollViewState.votesStatus)
270269
.optionViewStates(pollViewState.optionViewStates.orEmpty())
@@ -281,21 +280,37 @@ class MessageItemFactory @Inject constructor(
281280
highlight: Boolean,
282281
callback: TimelineEventController.Callback?,
283282
attributes: AbsMessageItem.Attributes,
284-
): PollItem? {
285-
pollStartEventId ?: return null.also {
286-
Timber.e("### buildEndedPollItem. Cannot render poll end event because poll start event id is null")
283+
): PollItem {
284+
val pollStartEvent = if (pollStartEventId?.isNotEmpty() == true) {
285+
session.roomService().getRoom(roomId)?.getTimelineEvent(pollStartEventId)
286+
} else {
287+
null
288+
}
289+
val pollContent = pollStartEvent?.root?.getClearContent()?.toModel<MessagePollContent>()
290+
291+
return if (pollContent == null) {
292+
val title = stringProvider.getString(R.string.message_reply_to_ended_poll_preview).toEpoxyCharSequence()
293+
PollItem_()
294+
.attributes(attributes)
295+
.eventId(informationData.eventId)
296+
.pollTitle(title)
297+
.optionViewStates(emptyList())
298+
.edited(informationData.hasBeenEdited)
299+
.ended(true)
300+
.hasContent(false)
301+
.highlighted(highlight)
302+
.leftGuideline(avatarSizeProvider.leftGuideline)
303+
.callback(callback)
304+
} else {
305+
buildPollItem(
306+
pollContent,
307+
informationData,
308+
highlight,
309+
callback,
310+
attributes,
311+
isEnded = true,
312+
)
287313
}
288-
val pollStartEvent = session.roomService().getRoom(roomId)?.getTimelineEvent(pollStartEventId)
289-
val pollContent = pollStartEvent?.root?.getClearContent()?.toModel<MessagePollContent>() ?: return null
290-
291-
return buildPollItem(
292-
pollContent,
293-
informationData,
294-
highlight,
295-
callback,
296-
attributes,
297-
isEnded = true
298-
)
299314
}
300315

301316
private fun createPollQuestion(
@@ -487,7 +502,6 @@ class MessageItemFactory @Inject constructor(
487502
highlight,
488503
callback,
489504
attributes,
490-
useRichTextEditorStyle = vectorPreferences.isRichTextEditorEnabled(),
491505
)
492506
}
493507

@@ -594,7 +608,7 @@ class MessageItemFactory @Inject constructor(
594608
val replyToContent = messageContent.relatesTo?.inReplyTo
595609
buildFormattedTextItem(matrixFormattedBody, informationData, highlight, callback, attributes, replyToContent)
596610
} else {
597-
buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes, useRichTextEditorStyle)
611+
buildMessageTextItem(messageContent.body, false, informationData, highlight, callback, attributes)
598612
}
599613
}
600614

@@ -618,7 +632,6 @@ class MessageItemFactory @Inject constructor(
618632
highlight,
619633
callback,
620634
attributes,
621-
useRichTextEditorStyle,
622635
)
623636
}
624637

@@ -629,7 +642,6 @@ class MessageItemFactory @Inject constructor(
629642
highlight: Boolean,
630643
callback: TimelineEventController.Callback?,
631644
attributes: AbsMessageItem.Attributes,
632-
useRichTextEditorStyle: Boolean,
633645
): MessageTextItem? {
634646
val renderedBody = textRenderer.render(body)
635647
val bindingOptions = spanUtils.getBindingOptions(renderedBody)

vector/src/main/java/im/vector/app/features/home/room/detail/timeline/item/PollItem.kt

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,15 @@
1616

1717
package im.vector.app.features.home.room.detail.timeline.item
1818

19+
import android.widget.ImageView
1920
import android.widget.LinearLayout
2021
import android.widget.TextView
2122
import androidx.core.view.children
2223
import androidx.core.view.isVisible
2324
import com.airbnb.epoxy.EpoxyAttribute
2425
import com.airbnb.epoxy.EpoxyModelClass
2526
import im.vector.app.R
27+
import im.vector.app.core.extensions.setTextOrHide
2628
import im.vector.app.features.home.room.detail.RoomDetailAction
2729
import im.vector.app.features.home.room.detail.timeline.TimelineEventController
2830
import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
@@ -31,7 +33,7 @@ import im.vector.lib.core.utils.epoxy.charsequence.EpoxyCharSequence
3133
abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
3234

3335
@EpoxyAttribute
34-
var pollQuestion: EpoxyCharSequence? = null
36+
var pollTitle: EpoxyCharSequence? = null
3537

3638
@EpoxyAttribute
3739
var callback: TimelineEventController.Callback? = null
@@ -54,15 +56,18 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
5456
@EpoxyAttribute
5557
var ended: Boolean = false
5658

59+
@EpoxyAttribute
60+
var hasContent: Boolean = true
61+
5762
override fun getViewStubId() = STUB_ID
5863

5964
override fun bind(holder: Holder) {
6065
super.bind(holder)
6166

6267
renderSendState(holder.view, holder.questionTextView)
6368

64-
holder.questionTextView.text = pollQuestion?.charSequence
65-
holder.votesStatusTextView.text = votesStatus
69+
holder.questionTextView.text = pollTitle?.charSequence
70+
holder.votesStatusTextView.setTextOrHide(votesStatus)
6671

6772
while (holder.optionsContainer.childCount < optionViewStates.size) {
6873
holder.optionsContainer.addView(PollOptionView(holder.view.context))
@@ -80,7 +85,8 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
8085
}
8186
}
8287

83-
holder.endedPollTextView.isVisible = ended
88+
holder.endedPollTextView.isVisible = ended && hasContent
89+
holder.pollIcon.isVisible = ended && hasContent.not()
8490
}
8591

8692
private fun onPollItemClick(optionViewState: PollOptionViewState) {
@@ -96,6 +102,7 @@ abstract class PollItem : AbsMessageItem<PollItem.Holder>() {
96102
val optionsContainer by bind<LinearLayout>(R.id.optionsContainer)
97103
val votesStatusTextView by bind<TextView>(R.id.optionsVotesStatusTextView)
98104
val endedPollTextView by bind<TextView>(R.id.endedPollTextView)
105+
val pollIcon by bind<ImageView>(R.id.timelinePollIcon)
99106
}
100107

101108
companion object {

vector/src/main/res/layout/item_timeline_event_poll.xml

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,31 @@
2121
<TextView
2222
android:id="@+id/questionTextView"
2323
style="@style/Widget.Vector.TextView.Subtitle"
24-
android:layout_width="wrap_content"
24+
android:layout_width="0dp"
2525
android:layout_height="wrap_content"
2626
android:layout_marginTop="8dp"
2727
android:textColor="?vctr_content_primary"
2828
app:layout_constraintEnd_toEndOf="parent"
2929
app:layout_constraintHorizontal_bias="0"
30-
app:layout_constraintStart_toStartOf="parent"
30+
app:layout_constraintStart_toEndOf="@id/timelinePollIcon"
3131
app:layout_constraintTop_toBottomOf="@id/endedPollTextView"
3232
tools:text="@sample/poll.json/question" />
3333

34+
<ImageView
35+
android:id="@+id/timelinePollIcon"
36+
android:layout_width="16dp"
37+
android:layout_height="16dp"
38+
android:layout_marginTop="4dp"
39+
android:layout_marginEnd="8dp"
40+
android:importantForAccessibility="no"
41+
android:src="@drawable/ic_attachment_poll"
42+
android:visibility="gone"
43+
app:layout_constraintEnd_toStartOf="@id/questionTextView"
44+
app:layout_constraintStart_toStartOf="parent"
45+
app:layout_constraintTop_toTopOf="@id/questionTextView"
46+
app:tint="?vctr_content_secondary"
47+
tools:ignore="ContentDescription" />
48+
3449
<LinearLayout
3550
android:id="@+id/optionsContainer"
3651
android:layout_width="0dp"

0 commit comments

Comments
 (0)