From d3df58c607b747563996f3db3c06e3a8bc02c5ba Mon Sep 17 00:00:00 2001 From: Maxime NATUREL <46314705+mnaturel@users.noreply.github.com> Date: Wed, 1 Feb 2023 17:44:48 +0100 Subject: [PATCH] Render the details of the poll --- .../app/core/di/MavericksViewModelModule.kt | 6 ++ .../timeline/factory/MessageItemFactory.kt | 6 +- .../factory/PollItemViewStateFactory.kt | 59 +++++++------ ...{PollViewState.kt => PollItemViewState.kt} | 2 +- .../polls/detail/ui/RoomPollDetail.kt | 9 +- .../polls/detail/ui/RoomPollDetailAction.kt | 23 ----- .../detail/ui/RoomPollDetailController.kt | 31 ++++--- .../polls/detail/ui/RoomPollDetailFragment.kt | 7 +- .../polls/detail/ui/RoomPollDetailItem.kt | 85 +++++++++++++++++++ .../polls/detail/ui/RoomPollDetailMapper.kt | 60 +++++++++++++ .../detail/ui/RoomPollDetailViewModel.kt | 25 +++++- .../detail/ui/RoomPollDetailViewState.kt | 1 + .../res/layout/fragment_room_poll_detail.xml | 3 +- .../factory/PollItemViewStateFactoryTest.kt | 12 +-- 14 files changed, 241 insertions(+), 88 deletions(-) rename vector/src/main/java/im/vector/app/features/poll/{PollViewState.kt => PollItemViewState.kt} (96%) delete mode 100644 vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailAction.kt create mode 100644 vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailItem.kt create mode 100644 vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapper.kt diff --git a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt index 911bbfa4a3..c2e2f9f695 100644 --- a/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt +++ b/vector/src/main/java/im/vector/app/core/di/MavericksViewModelModule.kt @@ -85,6 +85,7 @@ import im.vector.app.features.roomprofile.members.RoomMemberListViewModel import im.vector.app.features.roomprofile.notifications.RoomNotificationSettingsViewModel import im.vector.app.features.roomprofile.permissions.RoomPermissionsViewModel import im.vector.app.features.roomprofile.polls.RoomPollsViewModel +import im.vector.app.features.roomprofile.polls.detail.ui.RoomPollDetailViewModel import im.vector.app.features.roomprofile.settings.RoomSettingsViewModel import im.vector.app.features.roomprofile.settings.joinrule.advanced.RoomJoinRuleChooseRestrictedViewModel import im.vector.app.features.roomprofile.uploads.RoomUploadsViewModel @@ -703,4 +704,9 @@ interface MavericksViewModelModule { @IntoMap @MavericksViewModelKey(RoomPollsViewModel::class) fun roomPollsViewModelFactory(factory: RoomPollsViewModel.Factory): MavericksAssistedViewModelFactory<*, *> + + @Binds + @IntoMap + @MavericksViewModelKey(RoomPollDetailViewModel::class) + fun roomPollDetailViewModelFactory(factory: RoomPollDetailViewModel.Factory): MavericksAssistedViewModelFactory<*, *> } diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt index 9cb1608415..e988e9818c 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/MessageItemFactory.kt @@ -255,7 +255,11 @@ class MessageItemFactory @Inject constructor( attributes: AbsMessageItem.Attributes, isEnded: Boolean, ): PollItem { - val pollViewState = pollItemViewStateFactory.create(pollContent, informationData) + val pollViewState = pollItemViewStateFactory.create( + pollContent = pollContent, + pollResponseData = informationData.pollResponseAggregatedSummary, + isSent = informationData.sendState.isSent(), + ) return PollItem_() .attributes(attributes) diff --git a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactory.kt b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactory.kt index 3c1a1cfd85..63e41d7ad2 100644 --- a/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactory.kt +++ b/vector/src/main/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactory.kt @@ -18,9 +18,8 @@ package im.vector.app.features.home.room.detail.timeline.factory import im.vector.app.R 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.PollResponseData -import im.vector.app.features.poll.PollViewState +import im.vector.app.features.poll.PollItemViewState import org.matrix.android.sdk.api.extensions.orFalse import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent import org.matrix.android.sdk.api.session.room.model.message.PollCreationInfo @@ -33,27 +32,27 @@ class PollItemViewStateFactory @Inject constructor( fun create( pollContent: MessagePollContent, - informationData: MessageInformationData, - ): PollViewState { + pollResponseData: PollResponseData?, + isSent: Boolean, + ): PollItemViewState { val pollCreationInfo = pollContent.getBestPollCreationInfo() val question = pollCreationInfo?.question?.getBestQuestion().orEmpty() - val pollResponseSummary = informationData.pollResponseAggregatedSummary - val totalVotes = pollResponseSummary?.totalVotes ?: 0 + val totalVotes = pollResponseData?.totalVotes ?: 0 return when { - !informationData.sendState.isSent() -> { + !isSent -> { createSendingPollViewState(question, pollCreationInfo) } - informationData.pollResponseAggregatedSummary?.isClosed.orFalse() -> { - createEndedPollViewState(question, pollCreationInfo, pollResponseSummary, totalVotes) + pollResponseData?.isClosed.orFalse() -> { + createEndedPollViewState(question, pollCreationInfo, pollResponseData, totalVotes) } pollContent.getBestPollCreationInfo()?.isUndisclosed().orFalse() -> { - createUndisclosedPollViewState(question, pollCreationInfo, pollResponseSummary) + createUndisclosedPollViewState(question, pollCreationInfo, pollResponseData) } - informationData.pollResponseAggregatedSummary?.myVote?.isNotEmpty().orFalse() -> { - createVotedPollViewState(question, pollCreationInfo, pollResponseSummary, totalVotes) + pollResponseData?.myVote?.isNotEmpty().orFalse() -> { + createVotedPollViewState(question, pollCreationInfo, pollResponseData, totalVotes) } else -> { createReadyPollViewState(question, pollCreationInfo, totalVotes) @@ -61,8 +60,8 @@ class PollItemViewStateFactory @Inject constructor( } } - private fun createSendingPollViewState(question: String, pollCreationInfo: PollCreationInfo?): PollViewState { - return PollViewState( + private fun createSendingPollViewState(question: String, pollCreationInfo: PollCreationInfo?): PollItemViewState { + return PollItemViewState( question = question, votesStatus = stringProvider.getString(R.string.poll_no_votes_cast), canVote = false, @@ -73,51 +72,51 @@ class PollItemViewStateFactory @Inject constructor( private fun createEndedPollViewState( question: String, pollCreationInfo: PollCreationInfo?, - pollResponseSummary: PollResponseData?, + pollResponseData: PollResponseData?, totalVotes: Int, - ): PollViewState { - val totalVotesText = if (pollResponseSummary?.hasEncryptedRelatedEvents.orFalse()) { + ): PollItemViewState { + val totalVotesText = if (pollResponseData?.hasEncryptedRelatedEvents.orFalse()) { stringProvider.getString(R.string.unable_to_decrypt_some_events_in_poll) } else { stringProvider.getQuantityString(R.plurals.poll_total_vote_count_after_ended, totalVotes, totalVotes) } - return PollViewState( + return PollItemViewState( question = question, votesStatus = totalVotesText, canVote = false, - optionViewStates = pollOptionViewStateFactory.createPollEndedOptions(pollCreationInfo, pollResponseSummary), + optionViewStates = pollOptionViewStateFactory.createPollEndedOptions(pollCreationInfo, pollResponseData), ) } private fun createUndisclosedPollViewState( question: String, pollCreationInfo: PollCreationInfo?, - pollResponseSummary: PollResponseData? - ): PollViewState { - return PollViewState( + pollResponseData: PollResponseData? + ): PollItemViewState { + return PollItemViewState( question = question, votesStatus = stringProvider.getString(R.string.poll_undisclosed_not_ended), canVote = true, - optionViewStates = pollOptionViewStateFactory.createPollUndisclosedOptions(pollCreationInfo, pollResponseSummary), + optionViewStates = pollOptionViewStateFactory.createPollUndisclosedOptions(pollCreationInfo, pollResponseData), ) } private fun createVotedPollViewState( question: String, pollCreationInfo: PollCreationInfo?, - pollResponseSummary: PollResponseData?, + pollResponseData: PollResponseData?, totalVotes: Int - ): PollViewState { - val totalVotesText = if (pollResponseSummary?.hasEncryptedRelatedEvents.orFalse()) { + ): PollItemViewState { + val totalVotesText = if (pollResponseData?.hasEncryptedRelatedEvents.orFalse()) { stringProvider.getString(R.string.unable_to_decrypt_some_events_in_poll) } else { stringProvider.getQuantityString(R.plurals.poll_total_vote_count_before_ended_and_voted, totalVotes, totalVotes) } - return PollViewState( + return PollItemViewState( question = question, votesStatus = totalVotesText, canVote = true, - optionViewStates = pollOptionViewStateFactory.createPollVotedOptions(pollCreationInfo, pollResponseSummary), + optionViewStates = pollOptionViewStateFactory.createPollVotedOptions(pollCreationInfo, pollResponseData), ) } @@ -125,13 +124,13 @@ class PollItemViewStateFactory @Inject constructor( question: String, pollCreationInfo: PollCreationInfo?, totalVotes: Int - ): PollViewState { + ): PollItemViewState { val totalVotesText = if (totalVotes == 0) { stringProvider.getString(R.string.poll_no_votes_cast) } else { stringProvider.getQuantityString(R.plurals.poll_total_vote_count_before_ended_and_not_voted, totalVotes, totalVotes) } - return PollViewState( + return PollItemViewState( question = question, votesStatus = totalVotesText, canVote = true, diff --git a/vector/src/main/java/im/vector/app/features/poll/PollViewState.kt b/vector/src/main/java/im/vector/app/features/poll/PollItemViewState.kt similarity index 96% rename from vector/src/main/java/im/vector/app/features/poll/PollViewState.kt rename to vector/src/main/java/im/vector/app/features/poll/PollItemViewState.kt index ecbee7438a..e5b4f71f1d 100644 --- a/vector/src/main/java/im/vector/app/features/poll/PollViewState.kt +++ b/vector/src/main/java/im/vector/app/features/poll/PollItemViewState.kt @@ -18,7 +18,7 @@ package im.vector.app.features.poll import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState -data class PollViewState( +data class PollItemViewState( val question: String, val votesStatus: String, val canVote: Boolean, diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetail.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetail.kt index cbbd09f065..3389a5f473 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetail.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetail.kt @@ -16,14 +16,9 @@ package im.vector.app.features.roomprofile.polls.detail.ui -import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState +import im.vector.app.features.poll.PollItemViewState data class RoomPollDetail( - val eventId: String, - val question: String, - val canVote: Boolean, - val votesStatusSummary: String, - val optionViewStates: List, - val hasBeenEdited: Boolean, val isEnded: Boolean, + val pollItemViewState: PollItemViewState, ) diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailAction.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailAction.kt deleted file mode 100644 index efb20f9144..0000000000 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailAction.kt +++ /dev/null @@ -1,23 +0,0 @@ -/* - * 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.roomprofile.polls.detail.ui - -import im.vector.app.core.platform.VectorViewModelAction - -sealed interface RoomPollDetailAction : VectorViewModelAction { - -} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailController.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailController.kt index 08db09a5b0..a4318151be 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailController.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailController.kt @@ -17,22 +17,29 @@ package im.vector.app.features.roomprofile.polls.detail.ui import com.airbnb.epoxy.TypedEpoxyController -import im.vector.app.features.home.room.detail.timeline.item.PollItem_ import javax.inject.Inject -class RoomPollDetailController @Inject constructor() - : TypedEpoxyController() { +class RoomPollDetailController @Inject constructor() : TypedEpoxyController() { + + interface Callback { + fun vote(pollId: String, optionId: String) + } + + var callback: Callback? = null override fun buildModels(viewState: RoomPollDetailViewState?) { - viewState ?: return + val pollDetail = viewState?.pollDetail ?: return + val pollItemViewState = pollDetail.pollItemViewState + val host = this - PollItem_() - /* - .eventId(pollSummary.id) - .pollQuestion(pollSummary.title.toEpoxyCharSequence()) - .canVote(viewState.canVoteSelectedPoll()) - .optionViewStates(pollSummary.optionViewStates) - .ended(viewState.canVoteSelectedPoll().not()) - */ + roomPollDetailItem { + id(viewState.pollId) + eventId(viewState.pollId) + question(pollItemViewState.question) + canVote(pollItemViewState.canVote) + votesStatus(pollItemViewState.votesStatus) + optionViewStates(pollItemViewState.optionViewStates.orEmpty()) + callback(host.callback) + } } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailFragment.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailFragment.kt index 1589954b35..7d27963023 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailFragment.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailFragment.kt @@ -59,6 +59,7 @@ class RoomPollDetailFragment : VectorBaseFragment roomPollDetailController, hasFixedSize = true, ) + // TODO setup callback in controller for vote action } override fun onDestroyView() { @@ -75,15 +76,13 @@ class RoomPollDetailFragment : VectorBaseFragment setupToolbar(views.roomPollDetailToolbar) .setTitle(title) - .allowBack() + .allowBack(useCross = true) } override fun invalidate() = withState(viewModel) { state -> state.pollDetail ?: return@withState - // TODO should we update the title when the poll status changes? setupToolbar(state.pollDetail.isEnded) - - // TODO update data of the controller + roomPollDetailController.setData(state) } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailItem.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailItem.kt new file mode 100644 index 0000000000..9a80c32640 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailItem.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2020 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.roomprofile.polls.detail.ui + +import android.widget.LinearLayout +import android.widget.TextView +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.epoxy.VectorEpoxyHolder +import im.vector.app.core.epoxy.VectorEpoxyModel +import im.vector.app.features.home.room.detail.timeline.item.PollOptionView +import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState + +@EpoxyModelClass +abstract class RoomPollDetailItem : VectorEpoxyModel(R.layout.item_timeline_event_poll) { + + @EpoxyAttribute + var question: String? = null + + @EpoxyAttribute + var callback: RoomPollDetailController.Callback? = null + + @EpoxyAttribute + var eventId: String? = null + + @EpoxyAttribute + var canVote: Boolean = false + + @EpoxyAttribute + var votesStatus: String? = null + + @EpoxyAttribute + lateinit var optionViewStates: List + + @EpoxyAttribute + var ended: Boolean = false + + override fun bind(holder: Holder) { + super.bind(holder) + + holder.questionTextView.text = question + holder.votesStatusTextView.text = votesStatus + holder.optionsContainer.removeAllViews() + holder.optionsContainer.isVisible = optionViewStates.isNotEmpty() + for (option in optionViewStates) { + val optionView = PollOptionView(holder.view.context) + holder.optionsContainer.addView(optionView) + optionView.render(option) + optionView.setOnClickListener { onOptionClicked(option) } + } + + holder.endedPollTextView.isVisible = false + } + + private fun onOptionClicked(optionViewState: PollOptionViewState) { + val relatedEventId = eventId + + if (canVote && relatedEventId != null) { + callback?.vote(pollId = relatedEventId, optionId = optionViewState.optionId) + } + } + + class Holder : VectorEpoxyHolder() { + val questionTextView by bind(R.id.questionTextView) + val optionsContainer by bind(R.id.optionsContainer) + val votesStatusTextView by bind(R.id.optionsVotesStatusTextView) + val endedPollTextView by bind(R.id.endedPollTextView) + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapper.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapper.kt new file mode 100644 index 0000000000..931b38f243 --- /dev/null +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailMapper.kt @@ -0,0 +1,60 @@ +/* + * 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.roomprofile.polls.detail.ui + +import im.vector.app.core.extensions.getVectorLastMessageContent +import im.vector.app.features.home.room.detail.timeline.factory.PollItemViewStateFactory +import im.vector.app.features.home.room.detail.timeline.helper.PollResponseDataFactory +import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent +import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent +import timber.log.Timber +import javax.inject.Inject + +// TODO add unit tests +class RoomPollDetailMapper @Inject constructor( + private val pollResponseDataFactory: PollResponseDataFactory, + private val pollItemViewStateFactory: PollItemViewStateFactory, +) { + + fun map(timelineEvent: TimelineEvent): RoomPollDetail? { + val eventId = timelineEvent.root.eventId.orEmpty() + val result = runCatching { + val content = timelineEvent.getVectorLastMessageContent() + val pollResponseData = pollResponseDataFactory.create(timelineEvent) + return if (eventId.isNotEmpty() && content is MessagePollContent) { + // we assume poll message has been sent here + val pollItemViewState = pollItemViewStateFactory.create( + pollContent = content, + pollResponseData = pollResponseData, + isSent = true, + ) + RoomPollDetail( + isEnded = pollResponseData?.isClosed == true, + pollItemViewState = pollItemViewState, + ) + } else { + Timber.w("missing mandatory info about poll event with id=$eventId") + null + } + } + + if (result.isFailure) { + Timber.w("failed to map event with id $eventId") + } + return result.getOrNull() + } +} diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailViewModel.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailViewModel.kt index 8227a55881..e3b7631cce 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailViewModel.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailViewModel.kt @@ -16,16 +16,33 @@ package im.vector.app.features.roomprofile.polls.detail.ui +import com.airbnb.mvrx.MavericksViewModelFactory import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import im.vector.app.core.di.MavericksAssistedViewModelFactory +import im.vector.app.core.di.hiltMavericksViewModelFactory import im.vector.app.core.event.GetTimelineEventUseCase +import im.vector.app.core.platform.EmptyAction import im.vector.app.core.platform.VectorViewModel +import im.vector.app.features.auth.ReAuthState +import im.vector.app.features.auth.ReAuthViewModel import kotlinx.coroutines.flow.launchIn +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach class RoomPollDetailViewModel @AssistedInject constructor( @Assisted initialState: RoomPollDetailViewState, private val getTimelineEventUseCase: GetTimelineEventUseCase, -) : VectorViewModel(initialState) { + private val roomPollDetailMapper: RoomPollDetailMapper, +) : VectorViewModel(initialState) { + + @AssistedFactory + interface Factory : MavericksAssistedViewModelFactory { + override fun create(initialState: RoomPollDetailViewState): RoomPollDetailViewModel + } + + companion object : MavericksViewModelFactory by hiltMavericksViewModelFactory() init { observePollDetails( @@ -36,10 +53,12 @@ class RoomPollDetailViewModel @AssistedInject constructor( private fun observePollDetails(pollId: String, roomId: String) { getTimelineEventUseCase.execute(roomId = roomId, eventId = pollId) + .map { roomPollDetailMapper.map(it) } + .onEach { setState { copy(pollDetail = it) } } .launchIn(viewModelScope) } - override fun handle(action: RoomPollDetailAction) { - // TODO handle go to timeline action + override fun handle(action: EmptyAction) { + // do nothing for now } } diff --git a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailViewState.kt b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailViewState.kt index a2906dc88f..a02db41de6 100644 --- a/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailViewState.kt +++ b/vector/src/main/java/im/vector/app/features/roomprofile/polls/detail/ui/RoomPollDetailViewState.kt @@ -17,6 +17,7 @@ package im.vector.app.features.roomprofile.polls.detail.ui import com.airbnb.mvrx.MavericksState +import im.vector.app.features.poll.PollItemViewState data class RoomPollDetailViewState( val pollId: String, diff --git a/vector/src/main/res/layout/fragment_room_poll_detail.xml b/vector/src/main/res/layout/fragment_room_poll_detail.xml index 7ed8d1125e..4f65b2aa0f 100644 --- a/vector/src/main/res/layout/fragment_room_poll_detail.xml +++ b/vector/src/main/res/layout/fragment_room_poll_detail.xml @@ -24,12 +24,13 @@ diff --git a/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactoryTest.kt b/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactoryTest.kt index 512f7c8a17..bafe55f7a1 100644 --- a/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactoryTest.kt +++ b/vector/src/test/java/im/vector/app/features/home/room/detail/timeline/factory/PollItemViewStateFactoryTest.kt @@ -19,7 +19,7 @@ package im.vector.app.features.home.room.detail.timeline.factory import im.vector.app.R import im.vector.app.features.home.room.detail.timeline.item.PollOptionViewState import im.vector.app.features.home.room.detail.timeline.item.PollVoteSummaryData -import im.vector.app.features.poll.PollViewState +import im.vector.app.features.poll.PollItemViewState import im.vector.app.test.fakes.FakeStringProvider import im.vector.app.test.fixtures.PollFixture.A_MESSAGE_INFORMATION_DATA import im.vector.app.test.fixtures.PollFixture.A_POLL_CONTENT @@ -57,7 +57,7 @@ class PollItemViewStateFactoryTest { ) // Then - pollViewState shouldBeEqualTo PollViewState( + pollViewState shouldBeEqualTo PollItemViewState( question = A_POLL_CONTENT.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "", votesStatus = fakeStringProvider.instance.getString(R.string.poll_no_votes_cast), canVote = false, @@ -90,7 +90,7 @@ class PollItemViewStateFactoryTest { ) // Then - pollViewState shouldBeEqualTo PollViewState( + pollViewState shouldBeEqualTo PollItemViewState( question = A_POLL_CONTENT.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "", votesStatus = fakeStringProvider.instance.getQuantityString(R.plurals.poll_total_vote_count_after_ended, 0, 0), canVote = false, @@ -155,7 +155,7 @@ class PollItemViewStateFactoryTest { ) // Then - pollViewState shouldBeEqualTo PollViewState( + pollViewState shouldBeEqualTo PollItemViewState( question = A_POLL_CONTENT.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "", votesStatus = fakeStringProvider.instance.getString(R.string.poll_undisclosed_not_ended), canVote = true, @@ -204,7 +204,7 @@ class PollItemViewStateFactoryTest { ) // Then - pollViewState shouldBeEqualTo PollViewState( + pollViewState shouldBeEqualTo PollItemViewState( question = A_POLL_CONTENT.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "", votesStatus = fakeStringProvider.instance.getQuantityString(R.plurals.poll_total_vote_count_before_ended_and_voted, 1, 1), canVote = true, @@ -286,7 +286,7 @@ class PollItemViewStateFactoryTest { ) // Then - pollViewState shouldBeEqualTo PollViewState( + pollViewState shouldBeEqualTo PollItemViewState( question = A_POLL_CONTENT.getBestPollCreationInfo()?.question?.getBestQuestion() ?: "", votesStatus = fakeStringProvider.instance.getString(R.string.poll_no_votes_cast), canVote = true,