Even better names

Change-Id: Ia699c3ce8fd1ce7a6e406b00c81dc196b487ed65
pull/722/head
TJ Dahunsi 2 years ago
parent ce6eaa9d64
commit cb1d50e65e

@ -23,6 +23,7 @@ import androidx.compose.foundation.background
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.Orientation.Horizontal import androidx.compose.foundation.gestures.Orientation.Horizontal
import androidx.compose.foundation.gestures.Orientation.Vertical import androidx.compose.foundation.gestures.Orientation.Vertical
import androidx.compose.foundation.gestures.ScrollableState
import androidx.compose.foundation.interaction.InteractionSource import androidx.compose.foundation.interaction.InteractionSource
import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.interaction.collectIsDraggedAsState import androidx.compose.foundation.interaction.collectIsDraggedAsState
@ -56,18 +57,15 @@ private const val INACTIVE_TO_DORMANT_COOL_DOWN = 2_000L
* Its thumb disappears when the scrolling container is dormant. * Its thumb disappears when the scrolling container is dormant.
* @param modifier a [Modifier] for the [Scrollbar] * @param modifier a [Modifier] for the [Scrollbar]
* @param state the driving state for the [Scrollbar] * @param state the driving state for the [Scrollbar]
* @param scrollInProgress a flag indicating if the scrolling container for the scrollbar is
* currently scrolling
* @param orientation the orientation of the scrollbar * @param orientation the orientation of the scrollbar
* @param onThumbMoved the fast scroll implementation * @param onThumbDisplaced the fast scroll implementation
*/ */
@Composable @Composable
fun FastScrollbar( fun ScrollableState.FastScrollbar(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
state: ScrollbarState, state: ScrollbarState,
scrollInProgress: Boolean,
orientation: Orientation, orientation: Orientation,
onThumbMoved: (Float) -> Unit, onThumbDisplaced: (Float) -> Unit,
) { ) {
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
Scrollbar( Scrollbar(
@ -77,12 +75,11 @@ fun FastScrollbar(
state = state, state = state,
thumb = { thumb = {
FastScrollbarThumb( FastScrollbarThumb(
scrollInProgress = scrollInProgress,
interactionSource = interactionSource, interactionSource = interactionSource,
orientation = orientation, orientation = orientation,
) )
}, },
onThumbDisplaced = onThumbMoved, onThumbDisplaced = onThumbDisplaced,
) )
} }
@ -91,15 +88,12 @@ fun FastScrollbar(
* Its thumb disappears when the scrolling container is dormant. * Its thumb disappears when the scrolling container is dormant.
* @param modifier a [Modifier] for the [Scrollbar] * @param modifier a [Modifier] for the [Scrollbar]
* @param state the driving state for the [Scrollbar] * @param state the driving state for the [Scrollbar]
* @param scrollInProgress a flag indicating if the scrolling container for the scrollbar is
* currently scrolling
* @param orientation the orientation of the scrollbar * @param orientation the orientation of the scrollbar
*/ */
@Composable @Composable
fun DecorativeScrollbar( fun ScrollableState.DecorativeScrollbar(
modifier: Modifier = Modifier, modifier: Modifier = Modifier,
state: ScrollbarState, state: ScrollbarState,
scrollInProgress: Boolean,
orientation: Orientation, orientation: Orientation,
) { ) {
val interactionSource = remember { MutableInteractionSource() } val interactionSource = remember { MutableInteractionSource() }
@ -111,7 +105,6 @@ fun DecorativeScrollbar(
thumb = { thumb = {
DecorativeScrollbarThumb( DecorativeScrollbarThumb(
interactionSource = interactionSource, interactionSource = interactionSource,
scrollInProgress = scrollInProgress,
orientation = orientation, orientation = orientation,
) )
}, },
@ -122,8 +115,7 @@ fun DecorativeScrollbar(
* A scrollbar thumb that is intended to also be a touch target for fast scrolling. * A scrollbar thumb that is intended to also be a touch target for fast scrolling.
*/ */
@Composable @Composable
private fun FastScrollbarThumb( private fun ScrollableState.FastScrollbarThumb(
scrollInProgress: Boolean,
interactionSource: InteractionSource, interactionSource: InteractionSource,
orientation: Orientation, orientation: Orientation,
) { ) {
@ -137,7 +129,6 @@ private fun FastScrollbarThumb(
} }
.background( .background(
color = scrollbarThumbColor( color = scrollbarThumbColor(
scrollInProgress = scrollInProgress,
interactionSource = interactionSource, interactionSource = interactionSource,
), ),
shape = RoundedCornerShape(16.dp), shape = RoundedCornerShape(16.dp),
@ -149,8 +140,7 @@ private fun FastScrollbarThumb(
* A decorative scrollbar thumb for communicating a user's position in a list solely. * A decorative scrollbar thumb for communicating a user's position in a list solely.
*/ */
@Composable @Composable
private fun DecorativeScrollbarThumb( private fun ScrollableState.DecorativeScrollbarThumb(
scrollInProgress: Boolean,
interactionSource: InteractionSource, interactionSource: InteractionSource,
orientation: Orientation, orientation: Orientation,
) { ) {
@ -164,7 +154,6 @@ private fun DecorativeScrollbarThumb(
} }
.background( .background(
color = scrollbarThumbColor( color = scrollbarThumbColor(
scrollInProgress = scrollInProgress,
interactionSource = interactionSource, interactionSource = interactionSource,
), ),
shape = RoundedCornerShape(16.dp), shape = RoundedCornerShape(16.dp),
@ -174,19 +163,18 @@ private fun DecorativeScrollbarThumb(
/** /**
* The color of the scrollbar thumb as a function of its interaction state. * The color of the scrollbar thumb as a function of its interaction state.
* @param scrollInProgress if the scrolling container is currently scrolling
* @param interactionSource source of interactions in the scrolling container * @param interactionSource source of interactions in the scrolling container
*/ */
@Composable @Composable
private fun scrollbarThumbColor( private fun ScrollableState.scrollbarThumbColor(
scrollInProgress: Boolean,
interactionSource: InteractionSource, interactionSource: InteractionSource,
): Color { ): Color {
var state by remember { mutableStateOf(Dormant) } var state by remember { mutableStateOf(Dormant) }
val pressed by interactionSource.collectIsPressedAsState() val pressed by interactionSource.collectIsPressedAsState()
val hovered by interactionSource.collectIsHoveredAsState() val hovered by interactionSource.collectIsHoveredAsState()
val dragged by interactionSource.collectIsDraggedAsState() val dragged by interactionSource.collectIsDraggedAsState()
val active = pressed || hovered || dragged || scrollInProgress val active = (canScrollForward || canScrollForward) &&
(pressed || hovered || dragged || isScrollInProgress)
val color by animateColorAsState( val color by animateColorAsState(
targetValue = when (state) { targetValue = when (state) {
@ -202,7 +190,7 @@ private fun scrollbarThumbColor(
LaunchedEffect(active) { LaunchedEffect(active) {
when (active) { when (active) {
true -> state = Active true -> state = Active
false -> { false -> if (state == Active) {
state = Inactive state = Inactive
delay(INACTIVE_TO_DORMANT_COOL_DOWN) delay(INACTIVE_TO_DORMANT_COOL_DOWN)
state = Dormant state = Dormant

@ -27,36 +27,36 @@ import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.setValue import androidx.compose.runtime.setValue
/** /**
* Remembers a function to react to [Scrollbar] thumb position movements for a [LazyListState] * Remembers a function to react to [Scrollbar] thumb position displacements for a [LazyListState]
* @param itemsAvailable the amount of items in the list. * @param itemsAvailable the amount of items in the list.
*/ */
@Composable @Composable
fun LazyListState.rememberThumbInteractions( fun LazyListState.rememberFastScroller(
itemsAvailable: Int, itemsAvailable: Int,
): (Float) -> Unit = rememberThumbInteractions( ): (Float) -> Unit = rememberFastScroller(
itemsAvailable = itemsAvailable, itemsAvailable = itemsAvailable,
scroll = ::scrollToItem, scroll = ::scrollToItem,
) )
/** /**
* Remembers a function to react to [Scrollbar] thumb position movements for a [LazyGridState] * Remembers a function to react to [Scrollbar] thumb position displacements for a [LazyGridState]
* @param itemsAvailable the amount of items in the grid. * @param itemsAvailable the amount of items in the grid.
*/ */
@Composable @Composable
fun LazyGridState.rememberThumbInteractions( fun LazyGridState.rememberFastScroller(
itemsAvailable: Int, itemsAvailable: Int,
): (Float) -> Unit = rememberThumbInteractions( ): (Float) -> Unit = rememberFastScroller(
itemsAvailable = itemsAvailable, itemsAvailable = itemsAvailable,
scroll = ::scrollToItem, scroll = ::scrollToItem,
) )
/** /**
* Generic function to react to [Scrollbar] thumb interactions in a lazy layout. * Generic function to react to [Scrollbar] thumb displacements in a lazy layout.
* @param itemsAvailable the total amount of items available to scroll in the layout. * @param itemsAvailable the total amount of items available to scroll in the layout.
* @param scroll a function to be invoked when an index has been identified to scroll to. * @param scroll a function to be invoked when an index has been identified to scroll to.
*/ */
@Composable @Composable
private inline fun rememberThumbInteractions( private inline fun rememberFastScroller(
itemsAvailable: Int, itemsAvailable: Int,
crossinline scroll: suspend (index: Int) -> Unit, crossinline scroll: suspend (index: Int) -> Unit,
): (Float) -> Unit { ): (Float) -> Unit {
@ -69,6 +69,6 @@ private inline fun rememberThumbInteractions(
scroll(indexToFind) scroll(indexToFind)
} }
return remember { return remember {
{ percentage = it } { newPercentage -> percentage = newPercentage }
} }
} }

@ -20,6 +20,7 @@ import androidx.annotation.VisibleForTesting
import androidx.compose.foundation.Image import androidx.compose.foundation.Image
import androidx.compose.foundation.gestures.Orientation import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
@ -62,7 +63,7 @@ import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaLoadingWheel import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaLoadingWheel
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberThumbInteractions import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberFastScroller
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState
import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalTintTheme import com.google.samples.apps.nowinandroid.core.designsystem.theme.LocalTintTheme
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
@ -120,12 +121,9 @@ internal fun BookmarksScreen(
val snackBarResult = onShowSnackbar(bookmarkRemovedMessage, undoText) val snackBarResult = onShowSnackbar(bookmarkRemovedMessage, undoText)
if (snackBarResult) { if (snackBarResult) {
undoBookmarkRemoval() undoBookmarkRemoval()
} } else {
clearUndoState()
else {
clearUndoState()
} }
} }
} }
@ -142,19 +140,18 @@ internal fun BookmarksScreen(
} }
when (feedState) { when (feedState) {
Loading -> LoadingState(modifier) Loading -> LoadingState(modifier)
is Success -> if (feedState.feed.isNotEmpty()) { is Success -> if (feedState.feed.isNotEmpty()) {
BookmarksGrid( BookmarksGrid(
feedState, feedState,
removeFromBookmarks, removeFromBookmarks,
onNewsResourceViewed, onNewsResourceViewed,
onTopicClick, onTopicClick,
modifier, modifier,
) )
} else { } else {
EmptyState(modifier) EmptyState(modifier)
} }
} }
@ -213,7 +210,7 @@ private fun BookmarksGrid(
val scrollbarState = scrollableState.scrollbarState( val scrollbarState = scrollableState.scrollbarState(
itemsAvailable = itemsAvailable, itemsAvailable = itemsAvailable,
) )
FastScrollbar( scrollableState.FastScrollbar(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.windowInsetsPadding(WindowInsets.systemBars) .windowInsetsPadding(WindowInsets.systemBars)
@ -221,8 +218,7 @@ private fun BookmarksGrid(
.align(Alignment.CenterEnd), .align(Alignment.CenterEnd),
state = scrollbarState, state = scrollbarState,
orientation = Orientation.Vertical, orientation = Orientation.Vertical,
scrollInProgress = scrollableState.isScrollInProgress, onThumbDisplaced = scrollableState.rememberFastScroller(
onThumbMoved = scrollableState.rememberThumbInteractions(
itemsAvailable = itemsAvailable, itemsAvailable = itemsAvailable,
), ),
) )

@ -93,7 +93,7 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaIconT
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaOverlayLoadingWheel import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaOverlayLoadingWheel
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.DecorativeScrollbar import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.DecorativeScrollbar
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberThumbInteractions import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberFastScroller
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
@ -230,7 +230,7 @@ internal fun ForYouScreen(
) )
} }
} }
FastScrollbar( state.FastScrollbar(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.windowInsetsPadding(WindowInsets.systemBars) .windowInsetsPadding(WindowInsets.systemBars)
@ -238,8 +238,7 @@ internal fun ForYouScreen(
.align(Alignment.CenterEnd), .align(Alignment.CenterEnd),
state = scrollbarState, state = scrollbarState,
orientation = Orientation.Vertical, orientation = Orientation.Vertical,
scrollInProgress = state.isScrollInProgress, onThumbDisplaced = state.rememberFastScroller(
onThumbMoved = state.rememberThumbInteractions(
itemsAvailable = itemsAvailable, itemsAvailable = itemsAvailable,
), ),
) )
@ -365,14 +364,13 @@ private fun TopicSelection(
) )
} }
} }
DecorativeScrollbar( lazyGridState.DecorativeScrollbar(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .fillMaxWidth()
.padding(horizontal = 12.dp) .padding(horizontal = 12.dp)
.align(Alignment.BottomStart), .align(Alignment.BottomStart),
state = lazyGridState.scrollbarState(itemsAvailable = onboardingUiState.topics.size), state = lazyGridState.scrollbarState(itemsAvailable = onboardingUiState.topics.size),
orientation = Orientation.Horizontal, orientation = Orientation.Horizontal,
scrollInProgress = lazyGridState.isScrollInProgress,
) )
} }
} }

@ -36,7 +36,7 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.testTag import androidx.compose.ui.platform.testTag
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberThumbInteractions import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberFastScroller
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
@ -83,7 +83,7 @@ fun TopicsTabContent(
val scrollbarState = scrollableState.scrollbarState( val scrollbarState = scrollableState.scrollbarState(
itemsAvailable = topics.size, itemsAvailable = topics.size,
) )
FastScrollbar( scrollableState.FastScrollbar(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.windowInsetsPadding(WindowInsets.systemBars) .windowInsetsPadding(WindowInsets.systemBars)
@ -91,8 +91,7 @@ fun TopicsTabContent(
.align(Alignment.CenterEnd), .align(Alignment.CenterEnd),
state = scrollbarState, state = scrollbarState,
orientation = Orientation.Vertical, orientation = Orientation.Vertical,
scrollInProgress = scrollableState.isScrollInProgress, onThumbDisplaced = scrollableState.rememberFastScroller(
onThumbMoved = scrollableState.rememberThumbInteractions(
itemsAvailable = topics.size, itemsAvailable = topics.size,
), ),
) )

@ -17,17 +17,22 @@
package com.google.samples.apps.nowinandroid.feature.search package com.google.samples.apps.nowinandroid.feature.search
import androidx.compose.foundation.clickable import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.WindowInsets import androidx.compose.foundation.layout.WindowInsets
import androidx.compose.foundation.layout.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.safeDrawing import androidx.compose.foundation.layout.safeDrawing
import androidx.compose.foundation.layout.systemBars
import androidx.compose.foundation.layout.windowInsetsBottomHeight import androidx.compose.foundation.layout.windowInsetsBottomHeight
import androidx.compose.foundation.layout.windowInsetsPadding
import androidx.compose.foundation.layout.windowInsetsTopHeight import androidx.compose.foundation.layout.windowInsetsTopHeight
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.grid.GridCells.Adaptive import androidx.compose.foundation.lazy.grid.GridCells.Adaptive
@ -75,12 +80,17 @@ import androidx.compose.ui.tooling.preview.PreviewParameter
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel import androidx.hilt.navigation.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.lifecycle.compose.collectAsStateWithLifecycle
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberFastScroller
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic import com.google.samples.apps.nowinandroid.core.model.data.FollowableTopic
import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource import com.google.samples.apps.nowinandroid.core.model.data.UserNewsResource
import com.google.samples.apps.nowinandroid.core.ui.DevicePreviews import com.google.samples.apps.nowinandroid.core.ui.DevicePreviews
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Loading
import com.google.samples.apps.nowinandroid.core.ui.NewsFeedUiState.Success
import com.google.samples.apps.nowinandroid.core.ui.R.string import com.google.samples.apps.nowinandroid.core.ui.R.string
import com.google.samples.apps.nowinandroid.core.ui.TrackScreenViewEvent import com.google.samples.apps.nowinandroid.core.ui.TrackScreenViewEvent
import com.google.samples.apps.nowinandroid.core.ui.newsFeed import com.google.samples.apps.nowinandroid.core.ui.newsFeed
@ -289,81 +299,102 @@ private fun SearchResultBody(
searchQuery: String = "", searchQuery: String = "",
) { ) {
val state = rememberLazyGridState() val state = rememberLazyGridState()
LazyVerticalGrid( Box(
columns = Adaptive(300.dp),
contentPadding = PaddingValues(16.dp),
horizontalArrangement = Arrangement.spacedBy(16.dp),
verticalArrangement = Arrangement.spacedBy(24.dp),
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize(),
.testTag("search:newsResources"),
state = state,
) { ) {
if (topics.isNotEmpty()) { LazyVerticalGrid(
item( columns = Adaptive(300.dp),
span = { contentPadding = PaddingValues(16.dp),
GridItemSpan(maxLineSpan) horizontalArrangement = Arrangement.spacedBy(16.dp),
}, verticalArrangement = Arrangement.spacedBy(24.dp),
) { modifier = Modifier
Text( .fillMaxSize()
text = buildAnnotatedString { .testTag("search:newsResources"),
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) { state = state,
append(stringResource(id = searchR.string.topics)) ) {
} if (topics.isNotEmpty()) {
item(
span = {
GridItemSpan(maxLineSpan)
}, },
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp), ) {
) Text(
text = buildAnnotatedString {
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append(stringResource(id = searchR.string.topics))
}
},
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
)
}
topics.forEach { followableTopic ->
val topicId = followableTopic.topic.id
item(
key = "topic-$topicId", // Append a prefix to distinguish a key for news resources
span = {
GridItemSpan(maxLineSpan)
},
) {
InterestsItem(
name = followableTopic.topic.name,
following = followableTopic.isFollowed,
description = followableTopic.topic.shortDescription,
topicImageUrl = followableTopic.topic.imageUrl,
onClick = {
// Pass the current search query to ViewModel to save it as recent searches
onSearchTriggered(searchQuery)
onTopicClick(topicId)
},
onFollowButtonClick = { onFollowButtonClick(topicId, it) },
)
}
}
} }
topics.forEach { followableTopic ->
val topicId = followableTopic.topic.id if (newsResources.isNotEmpty()) {
item( item(
key = "topic-$topicId", // Append a prefix to distinguish a key for news resources
span = { span = {
GridItemSpan(maxLineSpan) GridItemSpan(maxLineSpan)
}, },
) { ) {
InterestsItem( Text(
name = followableTopic.topic.name, text = buildAnnotatedString {
following = followableTopic.isFollowed, withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
description = followableTopic.topic.shortDescription, append(stringResource(id = searchR.string.updates))
topicImageUrl = followableTopic.topic.imageUrl, }
onClick = {
// Pass the current search query to ViewModel to save it as recent searches
onSearchTriggered(searchQuery)
onTopicClick(topicId)
}, },
onFollowButtonClick = { onFollowButtonClick(topicId, it) }, modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
) )
} }
}
}
if (newsResources.isNotEmpty()) { newsFeed(
item( feedState = Success(feed = newsResources),
span = { onNewsResourcesCheckedChanged = onNewsResourcesCheckedChanged,
GridItemSpan(maxLineSpan) onNewsResourceViewed = onNewsResourceViewed,
}, onTopicClick = onTopicClick,
) { onExpandedCardClick = {
Text( onSearchTriggered(searchQuery)
text = buildAnnotatedString {
withStyle(style = SpanStyle(fontWeight = FontWeight.Bold)) {
append(stringResource(id = searchR.string.updates))
}
}, },
modifier = Modifier.padding(horizontal = 16.dp, vertical = 8.dp),
) )
} }
newsFeed(
feedState = NewsFeedUiState.Success(feed = newsResources),
onNewsResourcesCheckedChanged = onNewsResourcesCheckedChanged,
onNewsResourceViewed = onNewsResourceViewed,
onTopicClick = onTopicClick,
onExpandedCardClick = {
onSearchTriggered(searchQuery)
},
)
} }
val itemsAvailable = topics.size + newsResources.size
val scrollbarState = state.scrollbarState(
itemsAvailable = itemsAvailable,
)
state.FastScrollbar(
modifier = Modifier
.fillMaxHeight()
.windowInsetsPadding(WindowInsets.systemBars)
.padding(horizontal = 2.dp)
.align(Alignment.CenterEnd),
state = scrollbarState,
orientation = Orientation.Vertical,
onThumbDisplaced = state.rememberFastScroller(
itemsAvailable = itemsAvailable,
),
)
} }
} }

@ -55,7 +55,7 @@ import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaBackg
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaFilterChip import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaFilterChip
import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaLoadingWheel import com.google.samples.apps.nowinandroid.core.designsystem.component.NiaLoadingWheel
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.FastScrollbar
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberThumbInteractions import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.rememberFastScroller
import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState import com.google.samples.apps.nowinandroid.core.designsystem.component.scrollbar.scrollbarState
import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons import com.google.samples.apps.nowinandroid.core.designsystem.icon.NiaIcons
import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme import com.google.samples.apps.nowinandroid.core.designsystem.theme.NiaTheme
@ -151,7 +151,7 @@ internal fun TopicScreen(
val scrollbarState = state.scrollbarState( val scrollbarState = state.scrollbarState(
itemsAvailable = itemsAvailable, itemsAvailable = itemsAvailable,
) )
FastScrollbar( state.FastScrollbar(
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
.windowInsetsPadding(WindowInsets.systemBars) .windowInsetsPadding(WindowInsets.systemBars)
@ -159,8 +159,7 @@ internal fun TopicScreen(
.align(Alignment.CenterEnd), .align(Alignment.CenterEnd),
state = scrollbarState, state = scrollbarState,
orientation = Orientation.Vertical, orientation = Orientation.Vertical,
scrollInProgress = state.isScrollInProgress, onThumbDisplaced = state.rememberFastScroller(
onThumbMoved = state.rememberThumbInteractions(
itemsAvailable = itemsAvailable, itemsAvailable = itemsAvailable,
), ),
) )

Loading…
Cancel
Save