Merge pull request #6477 from bxdxnn/feat/polls-max-selections

Support multi-select polls
This commit is contained in:
Benoit Marty
2026-08-31 15:26:35 +02:00
committed by GitHub
49 changed files with 259 additions and 62 deletions
@@ -54,7 +54,7 @@ sealed interface TimelineEvent {
data class SelectPollAnswer(
val pollStartId: EventId,
val answerId: String
val answerIds: List<String>
) : TimelineItemPollEvent
data class EndPoll(
@@ -206,8 +206,10 @@ class TimelinePresenter(
sendPollResponseAction.execute(
timeline = this,
pollStartId = event.pollStartId,
answerId = event.answerId
)
answerIds = event.answerIds
).onFailure { error ->
Timber.tag(tag).e(error, "Failed to send poll response")
}
}
}
is TimelineEvent.EndPoll -> sessionCoroutineScope.launch {
@@ -26,8 +26,8 @@ fun TimelineItemPollView(
eventSink: (TimelineEvent.TimelineItemPollEvent) -> Unit,
modifier: Modifier = Modifier,
) {
fun onSelectAnswer(pollStartId: EventId, answerId: String) {
eventSink(TimelineEvent.SelectPollAnswer(pollStartId, answerId))
fun onSelectAnswer(pollStartId: EventId, answerIds: List<String>) {
eventSink(TimelineEvent.SelectPollAnswer(pollStartId, answerIds))
}
fun onEndPoll(pollStartId: EventId) {
@@ -43,6 +43,8 @@ fun TimelineItemPollView(
question = content.question,
answerItems = content.answerItems.toImmutableList(),
pollKind = content.pollKind,
isMultipleSelection = content.maxSelections > 1u,
maxSelections = content.maxSelections,
isPollEnded = content.isEnded,
isPollEditable = content.isEditable,
isMine = content.isMine,
@@ -33,6 +33,7 @@ class TimelineItemContentPollFactory(
question = pollContentState.question,
answerItems = pollContentState.answerItems,
pollKind = pollContentState.pollKind,
maxSelections = pollContentState.maxSelections,
isEnded = pollContentState.isPollEnded,
isEdited = content.isEdited
)
@@ -19,6 +19,7 @@ data class TimelineItemPollContent(
val question: String,
val answerItems: List<PollAnswerItem>,
val pollKind: PollKind,
val maxSelections: ULong,
val isEnded: Boolean,
override val isEdited: Boolean,
) : TimelineItemEventContent,
@@ -32,12 +32,14 @@ fun aTimelineItemPollContent(
isEditable: Boolean = false,
isEnded: Boolean = false,
isEdited: Boolean = false,
maxSelections: ULong = 1u,
): TimelineItemPollContent {
return TimelineItemPollContent(
eventId = EventId("\$anEventId"),
pollKind = PollKind.Disclosed,
question = question,
answerItems = answerItems,
maxSelections = maxSelections,
isMine = isMine,
isEditable = isEditable,
isEnded = isEnded,
@@ -958,7 +958,7 @@ class TimelinePresenterTest {
)
presenter.test {
val initialState = awaitFirstItem()
initialState.eventSink.invoke(TimelineEvent.SelectPollAnswer(AN_EVENT_ID, "anAnswerId"))
initialState.eventSink.invoke(TimelineEvent.SelectPollAnswer(AN_EVENT_ID, listOf("anAnswerId")))
}
delay(1)
sendPollResponseAction.verifyExecutionCount(1)
@@ -50,7 +50,7 @@ class TimelineItemPollViewTest : RobolectricTest() {
matcher = hasText(answer.text),
useUnmergedTree = true,
).performClick()
eventsRecorder.assertSingle(TimelineEvent.SelectPollAnswer(content.eventId!!, answer.id))
eventsRecorder.assertSingle(TimelineEvent.SelectPollAnswer(content.eventId!!, listOf(answer.id)))
}
@Test