knock requests : branch banner in room

This commit is contained in:
ganfra 2024-12-06 16:31:24 +01:00
parent 4a7ebcc254
commit e001fee649
10 changed files with 104 additions and 1 deletions

View file

@ -6,7 +6,7 @@
*/ */
plugins { plugins {
id("io.element.android-library") id("io.element.android-compose-library")
} }
android { android {

View file

@ -0,0 +1,16 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.features.knockrequests.api.banner
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
interface KnockRequestsBannerRenderer {
@Composable
fun View(modifier: Modifier, onViewRequestsClick: () -> Unit)
}

View file

@ -0,0 +1,32 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.features.knockrequests.impl.banner
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import com.squareup.anvil.annotations.ContributesBinding
import io.element.android.features.knockrequests.api.banner.KnockRequestsBannerRenderer
import io.element.android.libraries.di.RoomScope
import javax.inject.Inject
@ContributesBinding(RoomScope::class)
class DefaultKnockRequestsBannerRenderer @Inject constructor(
private val presenter: KnockRequestsBannerPresenter,
): KnockRequestsBannerRenderer {
@Composable
override fun View(modifier: Modifier, onViewRequestsClick: () -> Unit) {
val state = presenter.present()
KnockRequestsBannerView(
state = state,
onDismissClick = {},
onViewRequestsClick = onViewRequestsClick,
)
}
}

View file

@ -0,0 +1,19 @@
/*
* Copyright 2024 New Vector Ltd.
*
* SPDX-License-Identifier: AGPL-3.0-only
* Please see LICENSE in the repository root for full details.
*/
package io.element.android.features.knockrequests.impl.banner
import androidx.compose.runtime.Composable
import io.element.android.libraries.architecture.Presenter
import javax.inject.Inject
class KnockRequestsBannerPresenter @Inject constructor(): Presenter<KnockRequestsBannerState> {
@Composable
override fun present(): KnockRequestsBannerState {
return KnockRequestsBannerState.Hidden
}
}

View file

@ -65,6 +65,7 @@ dependencies {
implementation(libs.vanniktech.blurhash) implementation(libs.vanniktech.blurhash)
implementation(libs.telephoto.zoomableimage) implementation(libs.telephoto.zoomableimage)
implementation(libs.matrix.emojibase.bindings) implementation(libs.matrix.emojibase.bindings)
implementation(projects.features.knockrequests.api)
testImplementation(libs.test.junit) testImplementation(libs.test.junit)
testImplementation(libs.coroutines.test) testImplementation(libs.coroutines.test)

View file

@ -26,6 +26,7 @@ import im.vector.app.features.analytics.plan.Interaction
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.features.call.api.CallType import io.element.android.features.call.api.CallType
import io.element.android.features.call.api.ElementCallEntryPoint import io.element.android.features.call.api.ElementCallEntryPoint
import io.element.android.features.knockrequests.api.list.KnockRequestsListEntryPoint
import io.element.android.features.location.api.Location import io.element.android.features.location.api.Location
import io.element.android.features.location.api.SendLocationEntryPoint import io.element.android.features.location.api.SendLocationEntryPoint
import io.element.android.features.location.api.ShowLocationEntryPoint import io.element.android.features.location.api.ShowLocationEntryPoint
@ -95,6 +96,7 @@ class MessagesFlowNode @AssistedInject constructor(
private val mentionSpanTheme: MentionSpanTheme, private val mentionSpanTheme: MentionSpanTheme,
private val pinnedEventsTimelineProvider: PinnedEventsTimelineProvider, private val pinnedEventsTimelineProvider: PinnedEventsTimelineProvider,
private val timelineController: TimelineController, private val timelineController: TimelineController,
private val knockRequestsListEntryPoint: KnockRequestsListEntryPoint,
) : BaseFlowNode<MessagesFlowNode.NavTarget>( ) : BaseFlowNode<MessagesFlowNode.NavTarget>(
backstack = BackStack( backstack = BackStack(
initialElement = plugins.filterIsInstance<MessagesEntryPoint.Params>().first().initialTarget.toNavTarget(), initialElement = plugins.filterIsInstance<MessagesEntryPoint.Params>().first().initialTarget.toNavTarget(),
@ -146,6 +148,9 @@ class MessagesFlowNode @AssistedInject constructor(
@Parcelize @Parcelize
data object PinnedMessagesList : NavTarget data object PinnedMessagesList : NavTarget
@Parcelize
data object KnockRequestsList : NavTarget
} }
private val callbacks = plugins<MessagesEntryPoint.Callback>() private val callbacks = plugins<MessagesEntryPoint.Callback>()
@ -226,6 +231,10 @@ class MessagesFlowNode @AssistedInject constructor(
override fun onViewAllPinnedEvents() { override fun onViewAllPinnedEvents() {
backstack.push(NavTarget.PinnedMessagesList) backstack.push(NavTarget.PinnedMessagesList)
} }
override fun onViewKnockRequests() {
backstack.push(NavTarget.KnockRequestsList)
}
} }
val inputs = MessagesNode.Inputs(focusedEventId = navTarget.focusedEventId) val inputs = MessagesNode.Inputs(focusedEventId = navTarget.focusedEventId)
createNode<MessagesNode>(buildContext, listOf(callback, inputs)) createNode<MessagesNode>(buildContext, listOf(callback, inputs))
@ -326,6 +335,9 @@ class MessagesFlowNode @AssistedInject constructor(
NavTarget.Empty -> { NavTarget.Empty -> {
node(buildContext) {} node(buildContext) {}
} }
NavTarget.KnockRequestsList -> {
knockRequestsListEntryPoint.createNode(this, buildContext)
}
} }
} }

View file

@ -28,6 +28,7 @@ import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
import io.element.android.anvilannotations.ContributesNode import io.element.android.anvilannotations.ContributesNode
import io.element.android.compound.theme.ElementTheme import io.element.android.compound.theme.ElementTheme
import io.element.android.features.knockrequests.api.banner.KnockRequestsBannerRenderer
import io.element.android.features.messages.impl.actionlist.ActionListPresenter import io.element.android.features.messages.impl.actionlist.ActionListPresenter
import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor import io.element.android.features.messages.impl.actionlist.model.TimelineItemActionPostProcessor
import io.element.android.features.messages.impl.attachments.Attachment import io.element.android.features.messages.impl.attachments.Attachment
@ -71,6 +72,7 @@ class MessagesNode @AssistedInject constructor(
private val timelineItemPresenterFactories: TimelineItemPresenterFactories, private val timelineItemPresenterFactories: TimelineItemPresenterFactories,
private val mediaPlayer: MediaPlayer, private val mediaPlayer: MediaPlayer,
private val permalinkParser: PermalinkParser, private val permalinkParser: PermalinkParser,
private val knockRequestsBannerRenderer: KnockRequestsBannerRenderer
) : Node(buildContext, plugins = plugins), MessagesNavigator { ) : Node(buildContext, plugins = plugins), MessagesNavigator {
private val presenter = presenterFactory.create( private val presenter = presenterFactory.create(
navigator = this, navigator = this,
@ -98,6 +100,7 @@ class MessagesNode @AssistedInject constructor(
fun onEditPollClick(eventId: EventId) fun onEditPollClick(eventId: EventId)
fun onJoinCallClick(roomId: RoomId) fun onJoinCallClick(roomId: RoomId)
fun onViewAllPinnedEvents() fun onViewAllPinnedEvents()
fun onViewKnockRequests()
} }
override fun onBuilt() { override fun onBuilt() {
@ -206,6 +209,10 @@ class MessagesNode @AssistedInject constructor(
callbacks.forEach { it.onJoinCallClick(room.roomId) } callbacks.forEach { it.onJoinCallClick(room.roomId) }
} }
private fun onViewKnockRequestsClick() {
callbacks.forEach { it.onViewKnockRequests() }
}
@Composable @Composable
override fun View(modifier: Modifier) { override fun View(modifier: Modifier) {
val activity = LocalContext.current as Activity val activity = LocalContext.current as Activity
@ -231,6 +238,12 @@ class MessagesNode @AssistedInject constructor(
onCreatePollClick = this::onCreatePollClick, onCreatePollClick = this::onCreatePollClick,
onJoinCallClick = this::onJoinCallClick, onJoinCallClick = this::onJoinCallClick,
onViewAllPinnedMessagesClick = this::onViewAllPinnedMessagesClick, onViewAllPinnedMessagesClick = this::onViewAllPinnedMessagesClick,
knockRequestsBanner = { modifier ->
knockRequestsBannerRenderer.View(
modifier = modifier,
onViewRequestsClick = this::onViewKnockRequestsClick
)
},
modifier = modifier, modifier = modifier,
) )

View file

@ -118,6 +118,7 @@ fun MessagesView(
onViewAllPinnedMessagesClick: () -> Unit, onViewAllPinnedMessagesClick: () -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
forceJumpToBottomVisibility: Boolean = false, forceJumpToBottomVisibility: Boolean = false,
knockRequestsBanner: @Composable (Modifier) -> Unit,
) { ) {
OnLifecycleEvent { _, event -> OnLifecycleEvent { _, event ->
state.voiceMessageComposerState.eventSink(VoiceMessageComposerEvents.LifecycleEvent(event)) state.voiceMessageComposerState.eventSink(VoiceMessageComposerEvents.LifecycleEvent(event))
@ -215,6 +216,7 @@ fun MessagesView(
forceJumpToBottomVisibility = forceJumpToBottomVisibility, forceJumpToBottomVisibility = forceJumpToBottomVisibility,
onJoinCallClick = onJoinCallClick, onJoinCallClick = onJoinCallClick,
onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick, onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick,
knockRequestsBanner = knockRequestsBanner,
) )
}, },
snackbarHost = { snackbarHost = {
@ -284,6 +286,7 @@ private fun MessagesViewContent(
forceJumpToBottomVisibility: Boolean, forceJumpToBottomVisibility: Boolean,
onSwipeToReply: (TimelineItem.Event) -> Unit, onSwipeToReply: (TimelineItem.Event) -> Unit,
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
knockRequestsBanner: @Composable (Modifier) -> Unit,
) { ) {
Box( Box(
modifier = modifier modifier = modifier
@ -372,6 +375,9 @@ private fun MessagesViewContent(
onViewAllClick = onViewAllPinnedMessagesClick, onViewAllClick = onViewAllPinnedMessagesClick,
) )
} }
Box(modifier = Modifier.padding(all = 16.dp)) {
knockRequestsBanner(Modifier)
}
} }
}, },
sheetContent = { subcomposing: Boolean -> sheetContent = { subcomposing: Boolean ->
@ -539,5 +545,6 @@ internal fun MessagesViewPreview(@PreviewParameter(MessagesStateProvider::class)
onJoinCallClick = {}, onJoinCallClick = {},
onViewAllPinnedMessagesClick = { }, onViewAllPinnedMessagesClick = { },
forceJumpToBottomVisibility = true, forceJumpToBottomVisibility = true,
knockRequestsBanner = {},
) )
} }

View file

@ -40,5 +40,7 @@ internal fun MessagesViewWithIdentityChangePreview(
onCreatePollClick = {}, onCreatePollClick = {},
onJoinCallClick = {}, onJoinCallClick = {},
onViewAllPinnedMessagesClick = {}, onViewAllPinnedMessagesClick = {},
knockRequestsBanner = {}
) )
} }

View file

@ -533,6 +533,7 @@ private fun <R : TestRule> AndroidComposeTestRule<R, ComponentActivity>.setMessa
onCreatePollClick = onCreatePollClick, onCreatePollClick = onCreatePollClick,
onJoinCallClick = onJoinCallClick, onJoinCallClick = onJoinCallClick,
onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick, onViewAllPinnedMessagesClick = onViewAllPinnedMessagesClick,
knockRequestsBanner = {}
) )
} }
} }