knock requests : branch banner in room
This commit is contained in:
parent
4a7ebcc254
commit
e001fee649
10 changed files with 104 additions and 1 deletions
|
|
@ -6,7 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("io.element.android-library")
|
id("io.element.android-compose-library")
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
|
|
@ -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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 = {},
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -40,5 +40,7 @@ internal fun MessagesViewWithIdentityChangePreview(
|
||||||
onCreatePollClick = {},
|
onCreatePollClick = {},
|
||||||
onJoinCallClick = {},
|
onJoinCallClick = {},
|
||||||
onViewAllPinnedMessagesClick = {},
|
onViewAllPinnedMessagesClick = {},
|
||||||
|
knockRequestsBanner = {}
|
||||||
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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 = {}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue