Browse Source

Pinned event : hide/show banner on timeline scroll

pull/3259/head
ganfra 2 months ago
parent
commit
03a0e4fa08
  1. 17
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt
  2. 7
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt
  3. 2
      features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt
  4. 46
      libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LazyListState.kt

17
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/MessagesView.kt

@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
package io.element.android.features.messages.impl
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.expandVertically
import androidx.compose.animation.shrinkVertically
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
@ -33,6 +36,7 @@ import androidx.compose.foundation.layout.navigationBarsPadding @@ -33,6 +36,7 @@ import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBars
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.MaterialTheme
@ -101,6 +105,7 @@ import io.element.android.libraries.designsystem.theme.components.Text @@ -101,6 +105,7 @@ import io.element.android.libraries.designsystem.theme.components.Text
import io.element.android.libraries.designsystem.theme.components.TopAppBar
import io.element.android.libraries.designsystem.utils.KeepScreenOn
import io.element.android.libraries.designsystem.utils.OnLifecycleEvent
import io.element.android.libraries.designsystem.utils.isScrollingUp
import io.element.android.libraries.designsystem.utils.snackbar.SnackbarHost
import io.element.android.libraries.designsystem.utils.snackbar.rememberSnackbarHostState
import io.element.android.libraries.matrix.api.core.UserId
@ -375,6 +380,7 @@ private fun MessagesViewContent( @@ -375,6 +380,7 @@ private fun MessagesViewContent(
},
content = { paddingValues ->
Box(modifier = Modifier.padding(paddingValues)) {
val timelineLazyListState = rememberLazyListState()
TimelineView(
state = state.timelineState,
typingNotificationState = state.typingNotificationState,
@ -389,8 +395,17 @@ private fun MessagesViewContent( @@ -389,8 +395,17 @@ private fun MessagesViewContent(
onReadReceiptClick = onReadReceiptClick,
forceJumpToBottomVisibility = forceJumpToBottomVisibility,
onJoinCallClick = onJoinCallClick,
lazyListState = timelineLazyListState,
)
PinnedMessagesBannerView(state = state.pinnedMessagesBannerState)
AnimatedVisibility(
visible = state.pinnedMessagesBannerState.displayBanner && timelineLazyListState.isScrollingUp(),
enter = expandVertically(),
exit = shrinkVertically(),
) {
PinnedMessagesBannerView(
state = state.pinnedMessagesBannerState,
)
}
}
},
sheetContent = { subcomposing: Boolean ->

7
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/pinned/banner/PinnedMessagesBannerView.kt

@ -32,12 +32,15 @@ import androidx.compose.foundation.layout.heightIn @@ -32,12 +32,15 @@ import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.drawBehind
@ -63,8 +66,6 @@ fun PinnedMessagesBannerView( @@ -63,8 +66,6 @@ fun PinnedMessagesBannerView(
state: PinnedMessagesBannerState,
modifier: Modifier = Modifier,
) {
if (!state.displayBanner) return
val borderColor = ElementTheme.colors.pinnedMessageBannerBorder
Row(
modifier = modifier
@ -199,6 +200,6 @@ private fun PinnedMessageItem( @@ -199,6 +200,6 @@ private fun PinnedMessageItem(
@Composable
fun PinnedMessagesBannerViewPreview(@PreviewParameter(PinnedMessagesBannerStateProvider::class) state: PinnedMessagesBannerState) = ElementPreview {
PinnedMessagesBannerView(
state = state
state = state,
)
}

2
features/messages/impl/src/main/kotlin/io/element/android/features/messages/impl/timeline/TimelineView.kt

@ -90,6 +90,7 @@ fun TimelineView( @@ -90,6 +90,7 @@ fun TimelineView(
onReadReceiptClick: (TimelineItem.Event) -> Unit,
onJoinCallClick: () -> Unit,
modifier: Modifier = Modifier,
lazyListState: LazyListState = rememberLazyListState(),
forceJumpToBottomVisibility: Boolean = false
) {
fun clearFocusRequestState() {
@ -109,7 +110,6 @@ fun TimelineView( @@ -109,7 +110,6 @@ fun TimelineView(
}
val context = LocalContext.current
val lazyListState = rememberLazyListState()
// Disable reverse layout when TalkBack is enabled to avoid incorrect ordering issues seen in the current Compose UI version
val useReverseLayout = remember {
val accessibilityManager = context.getSystemService(AccessibilityManager::class.java)

46
libraries/designsystem/src/main/kotlin/io/element/android/libraries/designsystem/utils/LazyListState.kt

@ -0,0 +1,46 @@ @@ -0,0 +1,46 @@
/*
* Copyright (c) 2024 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
*
* https://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.libraries.designsystem.utils
import androidx.compose.foundation.lazy.LazyListState
import androidx.compose.runtime.Composable
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
/**
* Returns whether the lazy list is currently scrolling up.
*/
@Composable
fun LazyListState.isScrollingUp(): Boolean {
var previousIndex by remember(this) { mutableIntStateOf(firstVisibleItemIndex) }
var previousScrollOffset by remember(this) { mutableIntStateOf(firstVisibleItemScrollOffset) }
return remember(this) {
derivedStateOf {
if (previousIndex != firstVisibleItemIndex) {
previousIndex > firstVisibleItemIndex
} else {
previousScrollOffset >= firstVisibleItemScrollOffset
}.also {
previousIndex = firstVisibleItemIndex
previousScrollOffset = firstVisibleItemScrollOffset
}
}
}.value
}
Loading…
Cancel
Save