diff --git a/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/history/PollHistoryEntryPoint.kt b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/history/PollHistoryEntryPoint.kt new file mode 100644 index 0000000000..573ac0ee10 --- /dev/null +++ b/features/poll/api/src/main/kotlin/io/element/android/features/poll/api/history/PollHistoryEntryPoint.kt @@ -0,0 +1,25 @@ +/* + * 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 io.element.android.features.poll.api.history + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import io.element.android.libraries.architecture.FeatureEntryPoint + +interface PollHistoryEntryPoint : FeatureEntryPoint { + fun createNode(parentNode: Node, buildContext: BuildContext): Node +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPoint.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPoint.kt new file mode 100644 index 0000000000..bda4e042ab --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/DefaultPollHistoryEntryPoint.kt @@ -0,0 +1,32 @@ +/* + * 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 io.element.android.features.poll.impl.history + +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.squareup.anvil.annotations.ContributesBinding +import io.element.android.features.poll.api.history.PollHistoryEntryPoint +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.AppScope +import javax.inject.Inject + +@ContributesBinding(AppScope::class) +class DefaultPollHistoryEntryPoint @Inject constructor() : PollHistoryEntryPoint { + override fun createNode(parentNode: Node, buildContext: BuildContext): Node { + return parentNode.createNode(buildContext) + } +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryEvents.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryEvents.kt new file mode 100644 index 0000000000..1eb676b961 --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryEvents.kt @@ -0,0 +1,21 @@ +/* + * 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 io.element.android.features.poll.impl.history + +sealed interface PollHistoryEvents { + data object History : PollHistoryEvents +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryLoadedNode.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryLoadedNode.kt new file mode 100644 index 0000000000..665700e52c --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryLoadedNode.kt @@ -0,0 +1,69 @@ +/* + * 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 io.element.android.features.poll.impl.history + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.lifecycle.subscribe +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.architecture.NodeInputs +import io.element.android.libraries.architecture.inputs +import io.element.android.libraries.di.RoomScope +import io.element.android.libraries.matrix.api.timeline.MatrixTimeline +import io.element.android.services.analytics.api.AnalyticsService + +@ContributesNode(RoomScope::class) +class PollHistoryLoadedNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, + presenterFactory: PollHistoryPresenter.Factory, + analyticsService: AnalyticsService, +) : Node( + buildContext = buildContext, + plugins = plugins +) { + data class Inputs( + val pollHistory: MatrixTimeline, + ) : NodeInputs + + private val inputs: Inputs = inputs() + private val presenter = presenterFactory.create( + inputs.pollHistory, + ) + + init { + lifecycle.subscribe( + onResume = { + // analyticsService.screen(MobileScreen(screenName = MobileScreen.ScreenName.CreatePollView)) // TODO + } + ) + } + + @Composable + override fun View(modifier: Modifier) { + PollHistoryView( + state = presenter.present(), + modifier = modifier, + goBack = this::navigateUp, + ) + } +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryLoadingNode.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryLoadingNode.kt new file mode 100644 index 0000000000..4eddd009e3 --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryLoadingNode.kt @@ -0,0 +1,50 @@ +/* + * 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 io.element.android.features.poll.impl.history + +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator +import io.element.android.libraries.di.RoomScope + +@ContributesNode(RoomScope::class) +class PollHistoryLoadingNode @AssistedInject constructor( + @Assisted buildContext: BuildContext, + @Assisted plugins: List, +) : Node( + buildContext = buildContext, + plugins = plugins +) { + @Composable + override fun View(modifier: Modifier) { + Box( + modifier = Modifier.fillMaxSize(), + contentAlignment = Alignment.Center, + ) { + CircularProgressIndicator() + } + } +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryNode.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryNode.kt new file mode 100644 index 0000000000..2ae20c8e12 --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryNode.kt @@ -0,0 +1,111 @@ +/* + * 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 io.element.android.features.poll.impl.history + +import android.os.Parcelable +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.lifecycle.lifecycleScope +import com.bumble.appyx.core.composable.Children +import com.bumble.appyx.core.lifecycle.subscribe +import com.bumble.appyx.core.modality.BuildContext +import com.bumble.appyx.core.node.Node +import com.bumble.appyx.core.plugin.Plugin +import com.bumble.appyx.navmodel.backstack.BackStack +import com.bumble.appyx.navmodel.backstack.operation.newRoot +import dagger.assisted.Assisted +import dagger.assisted.AssistedInject +import io.element.android.anvilannotations.ContributesNode +import io.element.android.libraries.architecture.BackstackNode +import io.element.android.libraries.architecture.animation.rememberDefaultTransitionHandler +import io.element.android.libraries.architecture.createNode +import io.element.android.libraries.di.RoomScope +import io.element.android.libraries.matrix.api.room.MatrixRoom +import io.element.android.libraries.matrix.api.timeline.MatrixTimeline +import kotlinx.coroutines.launch +import kotlinx.parcelize.Parcelize + +@ContributesNode(RoomScope::class) +class PollHistoryNode @AssistedInject constructor( + private val room: MatrixRoom, + @Assisted buildContext: BuildContext, + @Assisted plugins: List, +) : BackstackNode( + backstack = BackStack( + initialElement = NavTarget.PollHistoryLoading, + savedStateMap = buildContext.savedStateMap, + ), + buildContext = buildContext, + plugins = plugins, +) { + sealed interface NavTarget : Parcelable { + @Parcelize + data object PollHistoryLoading : NavTarget + + @Parcelize + data object PollHistoryLoaded : NavTarget + } + + private var pollHistory: MatrixTimeline? = null + + override fun onBuilt() { + super.onBuilt() + lifecycle.subscribe( + onCreate = { + lifecycleScope.launch { + runCatching { + room.pollHistory() + }.onSuccess { + pollHistory = it + backstack.newRoot(NavTarget.PollHistoryLoaded) + } + } + }, + onDestroy = { + pollHistory?.close() + }, + ) + } + + override fun resolve( + navTarget: NavTarget, + buildContext: BuildContext + ): Node = when (navTarget) { + is NavTarget.PollHistoryLoading -> createNode( + buildContext = buildContext, + ) + is NavTarget.PollHistoryLoaded -> { + createNode( + buildContext = buildContext, + plugins = listOf( + PollHistoryLoadedNode.Inputs( + pollHistory = pollHistory ?: error("Poll history not loaded"), + ) + ), + ) + } + } + + @Composable + override fun View(modifier: Modifier) { + Children( + navModel = backstack, + modifier = modifier, + transitionHandler = rememberDefaultTransitionHandler(), + ) + } +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenter.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenter.kt new file mode 100644 index 0000000000..1025b2184d --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryPresenter.kt @@ -0,0 +1,72 @@ +/* + * 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 io.element.android.features.poll.impl.history + +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import dagger.assisted.Assisted +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import io.element.android.libraries.architecture.Presenter +import io.element.android.libraries.matrix.api.timeline.MatrixTimeline +import io.element.android.libraries.matrix.api.timeline.MatrixTimelineItem +import io.element.android.libraries.matrix.api.timeline.item.event.PollContent +import kotlinx.collections.immutable.toImmutableList +import kotlinx.coroutines.flow.map +import kotlinx.coroutines.flow.onEach + +class PollHistoryPresenter @AssistedInject constructor( + @Assisted private val pollHistory: MatrixTimeline, +) : Presenter { + + @AssistedFactory + interface Factory { + fun create( + pollHistory: MatrixTimeline, + ): PollHistoryPresenter + } + + @Composable + override fun present(): PollHistoryState { + val paginationState by pollHistory.paginationState.collectAsState() + val timelineItemsFlow = remember { + pollHistory.timelineItems.map { items -> + items.filterIsInstance() + .map { it.event.content } + .filterIsInstance() + .reversed() + }.onEach { + if (it.isEmpty()) pollHistory.paginateBackwards(20, 50) + } + } + val items by timelineItemsFlow.collectAsState(initial = emptyList()) + + fun handleEvents(event: PollHistoryEvents) { + when (event) { + is PollHistoryEvents.History -> Unit // TODO which events to handle? + } + } + + return PollHistoryState( + paginationState = paginationState, + matrixTimelineItems = items.toImmutableList(), + eventSink = ::handleEvents, + ) + } +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryState.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryState.kt new file mode 100644 index 0000000000..4354736aba --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryState.kt @@ -0,0 +1,27 @@ +/* + * 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 io.element.android.features.poll.impl.history + +import io.element.android.libraries.matrix.api.timeline.MatrixTimeline +import io.element.android.libraries.matrix.api.timeline.item.event.PollContent +import kotlinx.collections.immutable.ImmutableList + +data class PollHistoryState( + val paginationState: MatrixTimeline.PaginationState, + val matrixTimelineItems: ImmutableList, + val eventSink: (PollHistoryEvents) -> Unit, +) diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryStateProvider.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryStateProvider.kt new file mode 100644 index 0000000000..880b68d178 --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryStateProvider.kt @@ -0,0 +1,24 @@ +/* + * 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 io.element.android.features.poll.impl.history + +import androidx.compose.ui.tooling.preview.PreviewParameterProvider + +class PollHistoryStateProvider : PreviewParameterProvider { + override val values: Sequence + get() = sequenceOf() // TODO +} diff --git a/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryView.kt b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryView.kt new file mode 100644 index 0000000000..93a3e3c90c --- /dev/null +++ b/features/poll/impl/src/main/kotlin/io/element/android/features/poll/impl/history/PollHistoryView.kt @@ -0,0 +1,113 @@ +/* + * 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 io.element.android.features.poll.impl.history + +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.tooling.preview.PreviewParameter +import io.element.android.compound.theme.ElementTheme +import io.element.android.features.poll.api.PollAnswerItem +import io.element.android.features.poll.api.PollContentView +import io.element.android.libraries.designsystem.components.button.BackButton +import io.element.android.libraries.designsystem.preview.ElementPreview +import io.element.android.libraries.designsystem.preview.PreviewsDayNight +import io.element.android.libraries.designsystem.theme.aliasScreenTitle +import io.element.android.libraries.designsystem.theme.components.CircularProgressIndicator +import io.element.android.libraries.designsystem.theme.components.Scaffold +import io.element.android.libraries.designsystem.theme.components.Text +import io.element.android.libraries.designsystem.theme.components.TopAppBar +import io.element.android.libraries.matrix.api.poll.PollAnswer +import kotlinx.collections.immutable.toImmutableList + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun PollHistoryView( + state: PollHistoryState, + modifier: Modifier = Modifier, + goBack: () -> Unit, +) { + Scaffold( + modifier = modifier, + topBar = { + TopAppBar( + title = { + Text( + text = "Polls", // TODO Polls: Localazy + style = ElementTheme.typography.aliasScreenTitle, + ) + }, + navigationIcon = { + BackButton(onClick = goBack) + }, + ) + }, + ) { paddingValues -> + LazyColumn( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues), + reverseLayout = false, + ) { + if (state.paginationState.isBackPaginating) item { + CircularProgressIndicator() + } + items(state.matrixTimelineItems) { pollContent -> + PollContentView( + eventId = null, + question = pollContent.question, + answerItems = pollContent.answers.map { + PollAnswerItem( + answer = PollAnswer( + id = it.id, + text = it.text, + ), + isSelected = false, + isEnabled = false, + isWinner = false, + isDisclosed = false, + votesCount = 9393, + percentage = 4.5f, + ) + }.toImmutableList(), + pollKind = pollContent.kind, + isPollEditable = false, + isPollEnded = false, + isMine = false, + onAnswerSelected = { _, _ -> }, + onPollEdit = {}, + onPollEnd = {}, + ) + } + } + } +} + +@PreviewsDayNight +@Composable +internal fun PollHistoryViewPreview( + @PreviewParameter(PollHistoryStateProvider::class) state: PollHistoryState +) = ElementPreview { + PollHistoryView( + state = state, + goBack = {}, + ) +} diff --git a/features/roomdetails/impl/build.gradle.kts b/features/roomdetails/impl/build.gradle.kts index e35526ec37..5f389bcfe9 100644 --- a/features/roomdetails/impl/build.gradle.kts +++ b/features/roomdetails/impl/build.gradle.kts @@ -52,6 +52,7 @@ dependencies { implementation(libs.coil.compose) implementation(projects.features.leaveroom.api) implementation(projects.services.analytics.api) + implementation(projects.features.poll.api) testImplementation(libs.test.junit) testImplementation(libs.coroutines.test) diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt index 60e302494e..2e58ccfe4e 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsFlowNode.kt @@ -29,6 +29,7 @@ import com.bumble.appyx.navmodel.backstack.operation.push import dagger.assisted.Assisted import dagger.assisted.AssistedInject import io.element.android.anvilannotations.ContributesNode +import io.element.android.features.poll.api.history.PollHistoryEntryPoint import io.element.android.features.roomdetails.api.RoomDetailsEntryPoint import io.element.android.features.roomdetails.impl.edit.RoomDetailsEditNode import io.element.android.features.roomdetails.impl.invite.RoomInviteMembersNode @@ -51,6 +52,7 @@ import kotlinx.parcelize.Parcelize class RoomDetailsFlowNode @AssistedInject constructor( @Assisted buildContext: BuildContext, @Assisted plugins: List, + private val pollHistoryEntryPoint: PollHistoryEntryPoint, ) : BackstackNode( backstack = BackStack( initialElement = plugins.filterIsInstance().first().initialElement.toNavTarget(), @@ -87,6 +89,9 @@ class RoomDetailsFlowNode @AssistedInject constructor( @Parcelize data class MemberAvatarPreview(val userName: String, val avatarUrl: String) : NavTarget + + @Parcelize + data object PollHistory : NavTarget } override fun resolve(navTarget: NavTarget, buildContext: BuildContext): Node { @@ -112,6 +117,10 @@ class RoomDetailsFlowNode @AssistedInject constructor( override fun openAvatarPreview(username: String, url: String) { backstack.push(NavTarget.MemberAvatarPreview(username, url)) } + + override fun openPollHistory() { + backstack.push(NavTarget.PollHistory) + } } createNode(buildContext, listOf(roomDetailsCallback)) } @@ -173,6 +182,10 @@ class RoomDetailsFlowNode @AssistedInject constructor( ) createNode(buildContext, listOf(input)) } + + is NavTarget.PollHistory -> { + pollHistoryEntryPoint.createNode(this, buildContext) + } } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt index f3fa9e2645..d243bcebdf 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsNode.kt @@ -53,6 +53,7 @@ class RoomDetailsNode @AssistedInject constructor( fun editRoomDetails() fun openRoomNotificationSettings() fun openAvatarPreview(username: String, url: String) + fun openPollHistory() } private val callbacks = plugins() @@ -77,6 +78,10 @@ class RoomDetailsNode @AssistedInject constructor( callbacks.forEach { it.openInviteMembers() } } + private fun openPollHistory() { + callbacks.forEach { it.openPollHistory() } + } + private fun onShareRoom(context: Context) { val alias = room.alias ?: room.alternativeAliases.firstOrNull() val permalinkResult = alias?.let { PermalinkBuilder.permalinkForRoomAlias(it) } @@ -146,6 +151,7 @@ class RoomDetailsNode @AssistedInject constructor( openRoomNotificationSettings = ::openRoomNotificationSettings, invitePeople = ::invitePeople, openAvatarPreview = ::openAvatarPreview, + openPollHistory = ::openPollHistory, ) } } diff --git a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt index 9c7151d4af..0f92b466f4 100644 --- a/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt +++ b/features/roomdetails/impl/src/main/kotlin/io/element/android/features/roomdetails/impl/RoomDetailsView.kt @@ -90,6 +90,7 @@ fun RoomDetailsView( openRoomNotificationSettings: () -> Unit, invitePeople: () -> Unit, openAvatarPreview: (username: String, url: String) -> Unit, + openPollHistory: () -> Unit, modifier: Modifier = Modifier, ) { fun onShareMember() { @@ -172,6 +173,10 @@ fun RoomDetailsView( } } + PollsSection( + openPollHistory = openPollHistory + ) + if (state.isEncrypted) { SecuritySection() } @@ -373,6 +378,20 @@ private fun InviteSection( } } +@Composable +private fun PollsSection( + openPollHistory: () -> Unit, + modifier: Modifier = Modifier, +) { + PreferenceCategory(modifier = modifier) { + ListItem( + headlineContent = { Text("Polls") }, // TODO Polls: Localazy + leadingContent = ListItemContent.Icon(IconSource.Vector(CompoundIcons.Polls)), + onClick = openPollHistory, + ) + } +} + @Composable private fun SecuritySection(modifier: Modifier = Modifier) { PreferenceCategory(title = stringResource(R.string.screen_room_details_security_title), modifier = modifier) { @@ -418,5 +437,6 @@ private fun ContentToPreview(state: RoomDetailsState) { openRoomNotificationSettings = {}, invitePeople = {}, openAvatarPreview = { _, _ -> }, + openPollHistory = {}, ) }