Create a dedicated factory for PollOptionViewState

This commit is contained in:
Maxime NATUREL 2023-01-19 17:22:37 +01:00
parent 96252ec2af
commit 91904a3e8f
3 changed files with 95 additions and 60 deletions

View file

@ -19,7 +19,6 @@ package im.vector.app.features.home.room.detail.timeline.factory
import im.vector.app.R import im.vector.app.R
import im.vector.app.core.resources.StringProvider import im.vector.app.core.resources.StringProvider
import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData import im.vector.app.features.home.room.detail.timeline.item.MessageInformationData
import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState
import im.vector.app.features.home.room.detail.timeline.item.PollResponseData import im.vector.app.features.home.room.detail.timeline.item.PollResponseData
import im.vector.app.features.poll.PollViewState import im.vector.app.features.poll.PollViewState
import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.extensions.orFalse
@ -29,6 +28,7 @@ import javax.inject.Inject
class PollItemViewStateFactory @Inject constructor( class PollItemViewStateFactory @Inject constructor(
private val stringProvider: StringProvider, private val stringProvider: StringProvider,
private val pollOptionViewStateFactory: PollOptionViewStateFactory,
) { ) {
fun create( fun create(
@ -40,7 +40,6 @@ class PollItemViewStateFactory @Inject constructor(
val question = pollCreationInfo?.question?.getBestQuestion().orEmpty() val question = pollCreationInfo?.question?.getBestQuestion().orEmpty()
val pollResponseSummary = informationData.pollResponseAggregatedSummary val pollResponseSummary = informationData.pollResponseAggregatedSummary
val winnerVoteCount = pollResponseSummary?.winnerVoteCount
val totalVotes = pollResponseSummary?.totalVotes ?: 0 val totalVotes = pollResponseSummary?.totalVotes ?: 0
return when { return when {
@ -48,7 +47,7 @@ class PollItemViewStateFactory @Inject constructor(
createSendingPollViewState(question, pollCreationInfo) createSendingPollViewState(question, pollCreationInfo)
} }
informationData.pollResponseAggregatedSummary?.isClosed.orFalse() -> { informationData.pollResponseAggregatedSummary?.isClosed.orFalse() -> {
createEndedPollViewState(question, pollCreationInfo, pollResponseSummary, totalVotes, winnerVoteCount) createEndedPollViewState(question, pollCreationInfo, pollResponseSummary, totalVotes)
} }
pollContent.getBestPollCreationInfo()?.isUndisclosed().orFalse() -> { pollContent.getBestPollCreationInfo()?.isUndisclosed().orFalse() -> {
createUndisclosedPollViewState(question, pollCreationInfo, pollResponseSummary) createUndisclosedPollViewState(question, pollCreationInfo, pollResponseSummary)
@ -67,12 +66,7 @@ class PollItemViewStateFactory @Inject constructor(
question = question, question = question,
votesStatus = stringProvider.getString(R.string.poll_no_votes_cast), votesStatus = stringProvider.getString(R.string.poll_no_votes_cast),
canVote = false, canVote = false,
optionViewStates = pollCreationInfo?.answers?.map { answer -> optionViewStates = pollOptionViewStateFactory.createPollSendingOptions(pollCreationInfo),
PollOptionViewState.PollSending(
optionId = answer.id ?: "",
optionAnswer = answer.getBestAnswer() ?: ""
)
},
) )
} }
@ -81,7 +75,6 @@ class PollItemViewStateFactory @Inject constructor(
pollCreationInfo: PollCreationInfo?, pollCreationInfo: PollCreationInfo?,
pollResponseSummary: PollResponseData?, pollResponseSummary: PollResponseData?,
totalVotes: Int, totalVotes: Int,
winnerVoteCount: Int?,
): PollViewState { ): PollViewState {
val totalVotesText = if (pollResponseSummary?.hasEncryptedRelatedEvents.orFalse()) { val totalVotesText = if (pollResponseSummary?.hasEncryptedRelatedEvents.orFalse()) {
stringProvider.getString(R.string.unable_to_decrypt_some_events_in_poll) stringProvider.getString(R.string.unable_to_decrypt_some_events_in_poll)
@ -92,17 +85,7 @@ class PollItemViewStateFactory @Inject constructor(
question = question, question = question,
votesStatus = totalVotesText, votesStatus = totalVotesText,
canVote = false, canVote = false,
// TODO extract into helper method or mapper optionViewStates = pollOptionViewStateFactory.createPollEndedOptions(pollCreationInfo, pollResponseSummary),
optionViewStates = pollCreationInfo?.answers?.map { answer ->
val voteSummary = pollResponseSummary?.getVoteSummaryOfAnOption(answer.id ?: "")
PollOptionViewState.PollEnded(
optionId = answer.id ?: "",
optionAnswer = answer.getBestAnswer() ?: "",
voteCount = voteSummary?.total ?: 0,
votePercentage = voteSummary?.percentage ?: 0.0,
isWinner = winnerVoteCount != 0 && voteSummary?.total == winnerVoteCount
)
},
) )
} }
@ -115,14 +98,7 @@ class PollItemViewStateFactory @Inject constructor(
question = question, question = question,
votesStatus = stringProvider.getString(R.string.poll_undisclosed_not_ended), votesStatus = stringProvider.getString(R.string.poll_undisclosed_not_ended),
canVote = true, canVote = true,
optionViewStates = pollCreationInfo?.answers?.map { answer -> optionViewStates = pollOptionViewStateFactory.createPollUndisclosedOptions(pollCreationInfo, pollResponseSummary),
val isMyVote = pollResponseSummary?.myVote == answer.id
PollOptionViewState.PollUndisclosed(
optionId = answer.id ?: "",
optionAnswer = answer.getBestAnswer() ?: "",
isSelected = isMyVote
)
},
) )
} }
@ -141,17 +117,7 @@ class PollItemViewStateFactory @Inject constructor(
question = question, question = question,
votesStatus = totalVotesText, votesStatus = totalVotesText,
canVote = true, canVote = true,
optionViewStates = pollCreationInfo?.answers?.map { answer -> optionViewStates = pollOptionViewStateFactory.createPollVotedOptions(pollCreationInfo, pollResponseSummary),
val isMyVote = pollResponseSummary?.myVote == answer.id
val voteSummary = pollResponseSummary?.getVoteSummaryOfAnOption(answer.id ?: "")
PollOptionViewState.PollVoted(
optionId = answer.id ?: "",
optionAnswer = answer.getBestAnswer() ?: "",
voteCount = voteSummary?.total ?: 0,
votePercentage = voteSummary?.percentage ?: 0.0,
isSelected = isMyVote
)
},
) )
} }
@ -169,12 +135,7 @@ class PollItemViewStateFactory @Inject constructor(
question = question, question = question,
votesStatus = totalVotesText, votesStatus = totalVotesText,
canVote = true, canVote = true,
optionViewStates = pollCreationInfo?.answers?.map { answer -> optionViewStates = pollOptionViewStateFactory.createPollReadyOptions(pollCreationInfo),
PollOptionViewState.PollReady(
optionId = answer.id ?: "",
optionAnswer = answer.getBestAnswer() ?: ""
)
},
) )
} }
} }

View file

@ -0,0 +1,84 @@
/*
* Copyright (c) 2023 New Vector Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package im.vector.app.features.home.room.detail.timeline.factory
import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState
import im.vector.app.features.home.room.detail.timeline.item.PollResponseData
import org.matrix.android.sdk.api.session.room.model.message.PollCreationInfo
import javax.inject.Inject
// TODO add unit tests
class PollOptionViewStateFactory @Inject constructor() {
fun createPollEndedOptions(pollCreationInfo: PollCreationInfo?, pollResponseData: PollResponseData?): List<PollOptionViewState.PollEnded> {
val winnerVoteCount = pollResponseData?.winnerVoteCount
return pollCreationInfo?.answers?.map { answer ->
val voteSummary = pollResponseData?.getVoteSummaryOfAnOption(answer.id ?: "")
PollOptionViewState.PollEnded(
optionId = answer.id.orEmpty(),
optionAnswer = answer.getBestAnswer().orEmpty(),
voteCount = voteSummary?.total ?: 0,
votePercentage = voteSummary?.percentage ?: 0.0,
isWinner = winnerVoteCount != 0 && voteSummary?.total == winnerVoteCount
)
} ?: emptyList()
}
fun createPollSendingOptions(pollCreationInfo: PollCreationInfo?): List<PollOptionViewState.PollSending> {
return pollCreationInfo?.answers?.map { answer ->
PollOptionViewState.PollSending(
optionId = answer.id.orEmpty(),
optionAnswer = answer.getBestAnswer().orEmpty(),
)
} ?: emptyList()
}
fun createPollUndisclosedOptions(pollCreationInfo: PollCreationInfo?, pollResponseData: PollResponseData?): List<PollOptionViewState.PollUndisclosed> {
return pollCreationInfo?.answers?.map { answer ->
val isMyVote = pollResponseData?.myVote == answer.id
PollOptionViewState.PollUndisclosed(
optionId = answer.id.orEmpty(),
optionAnswer = answer.getBestAnswer().orEmpty(),
isSelected = isMyVote
)
} ?: emptyList()
}
fun createPollVotedOptions(pollCreationInfo: PollCreationInfo?, pollResponseData: PollResponseData?): List<PollOptionViewState.PollVoted> {
return pollCreationInfo?.answers?.map { answer ->
val isMyVote = pollResponseData?.myVote == answer.id
val voteSummary = pollResponseData?.getVoteSummaryOfAnOption(answer.id ?: "")
PollOptionViewState.PollVoted(
optionId = answer.id.orEmpty(),
optionAnswer = answer.getBestAnswer().orEmpty(),
voteCount = voteSummary?.total ?: 0,
votePercentage = voteSummary?.percentage ?: 0.0,
isSelected = isMyVote
)
} ?: emptyList()
}
fun createPollReadyOptions(pollCreationInfo: PollCreationInfo?): List<PollOptionViewState.PollReady> {
return pollCreationInfo?.answers?.map { answer ->
PollOptionViewState.PollReady(
optionId = answer.id ?: "",
optionAnswer = answer.getBestAnswer() ?: ""
)
} ?: emptyList()
}
}

View file

@ -17,8 +17,8 @@
package im.vector.app.features.roomprofile.polls.list.ui package im.vector.app.features.roomprofile.polls.list.ui
import im.vector.app.core.extensions.getVectorLastMessageContent import im.vector.app.core.extensions.getVectorLastMessageContent
import im.vector.app.features.home.room.detail.timeline.factory.PollOptionViewStateFactory
import im.vector.app.features.home.room.detail.timeline.helper.PollResponseDataFactory import im.vector.app.features.home.room.detail.timeline.helper.PollResponseDataFactory
import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState
import im.vector.app.features.home.room.detail.timeline.item.PollResponseData import im.vector.app.features.home.room.detail.timeline.item.PollResponseData
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
@ -27,6 +27,7 @@ import javax.inject.Inject
// TODO add unit tests // TODO add unit tests
class PollSummaryMapper @Inject constructor( class PollSummaryMapper @Inject constructor(
private val pollResponseDataFactory: PollResponseDataFactory, private val pollResponseDataFactory: PollResponseDataFactory,
private val pollOptionViewStateFactory: PollOptionViewStateFactory,
) { ) {
fun map(timelineEvent: TimelineEvent): PollSummary { fun map(timelineEvent: TimelineEvent): PollSummary {
@ -42,7 +43,7 @@ class PollSummaryMapper @Inject constructor(
pollResponseData = pollResponseData pollResponseData = pollResponseData
) )
} else { } else {
throw IllegalStateException("expected MessagePollContent") throw IllegalStateException("missing mandatory info about poll event with id=$eventId")
} }
} }
@ -55,23 +56,12 @@ class PollSummaryMapper @Inject constructor(
val pollCreationInfo = messagePollContent.getBestPollCreationInfo() val pollCreationInfo = messagePollContent.getBestPollCreationInfo()
val pollTitle = pollCreationInfo?.question?.getBestQuestion().orEmpty() val pollTitle = pollCreationInfo?.question?.getBestQuestion().orEmpty()
return if (pollResponseData.isClosed) { return if (pollResponseData.isClosed) {
val winnerVoteCount = pollResponseData.winnerVoteCount
PollSummary.EndedPoll( PollSummary.EndedPoll(
id = eventId, id = eventId,
creationTimestamp = creationTimestamp, creationTimestamp = creationTimestamp,
title = pollTitle, title = pollTitle,
totalVotes = pollResponseData.totalVotes, totalVotes = pollResponseData.totalVotes,
// TODO mutualise this with PollItemViewStateFactory winnerOptions = pollOptionViewStateFactory.createPollEndedOptions(pollCreationInfo, pollResponseData)
winnerOptions = pollCreationInfo?.answers?.map { answer ->
val voteSummary = pollResponseData.getVoteSummaryOfAnOption(answer.id ?: "")
PollOptionViewState.PollEnded(
optionId = answer.id ?: "",
optionAnswer = answer.getBestAnswer() ?: "",
voteCount = voteSummary?.total ?: 0,
votePercentage = voteSummary?.percentage ?: 0.0,
isWinner = winnerVoteCount != 0 && voteSummary?.total == winnerVoteCount
)
} ?: emptyList()
) )
} else { } else {
PollSummary.ActivePoll( PollSummary.ActivePoll(