|
|
|
@ -18,7 +18,7 @@ import androidx.compose.foundation.layout.fillMaxWidth
|
|
|
|
|
import androidx.compose.foundation.layout.height
|
|
|
|
|
import androidx.compose.foundation.layout.width
|
|
|
|
|
import androidx.compose.foundation.lazy.LazyRow
|
|
|
|
|
import androidx.compose.foundation.lazy.itemsIndexed
|
|
|
|
|
import androidx.compose.foundation.lazy.items
|
|
|
|
|
import androidx.compose.foundation.lazy.rememberLazyListState
|
|
|
|
|
import androidx.compose.material.Icon
|
|
|
|
|
import androidx.compose.material.Text
|
|
|
|
@ -33,9 +33,9 @@ import androidx.compose.ui.semantics.semantics
|
|
|
|
|
import androidx.compose.ui.tooling.preview.Preview
|
|
|
|
|
import androidx.compose.ui.tooling.preview.PreviewParameter
|
|
|
|
|
import androidx.compose.ui.tooling.preview.PreviewParameterProvider
|
|
|
|
|
import androidx.compose.ui.unit.Dp
|
|
|
|
|
import androidx.compose.ui.unit.dp
|
|
|
|
|
import androidx.compose.ui.unit.sp
|
|
|
|
|
import mozilla.components.concept.fetch.Client
|
|
|
|
|
import mozilla.components.service.pocket.PocketRecommendedStory
|
|
|
|
|
import mozilla.components.ui.colors.PhotonColors
|
|
|
|
|
import org.mozilla.fenix.R
|
|
|
|
@ -100,13 +100,15 @@ fun PocketStory(
|
|
|
|
|
* to go to Pocket for more recommendations are added.
|
|
|
|
|
*
|
|
|
|
|
* @param stories The list of [PocketRecommendedStory]ies to be displayed. Expect a list with 8 items.
|
|
|
|
|
* @param client [Client] instance to be used for downloading the story header image.
|
|
|
|
|
* @param contentPadding Dimension for padding the content after it has been clipped.
|
|
|
|
|
* This space will be used for shadows and also content rendering when the list is scrolled.
|
|
|
|
|
* @param onExternalLinkClicked Callback for when the user taps an element which contains an
|
|
|
|
|
* external link for where user can go for more recommendations.
|
|
|
|
|
*/
|
|
|
|
|
@Composable
|
|
|
|
|
fun PocketStories(
|
|
|
|
|
@PreviewParameter(PocketStoryProvider::class) stories: List<PocketRecommendedStory>,
|
|
|
|
|
contentPadding: Dp,
|
|
|
|
|
onExternalLinkClicked: (String) -> Unit
|
|
|
|
|
) {
|
|
|
|
|
// Show stories in at most 3 rows but on any number of columns depending on the data received.
|
|
|
|
@ -117,14 +119,14 @@ fun PocketStories(
|
|
|
|
|
val flingBehavior = EagerFlingBehavior(lazyRowState = listState)
|
|
|
|
|
|
|
|
|
|
LazyRow(
|
|
|
|
|
contentPadding = PaddingValues(start = 8.dp, end = 8.dp),
|
|
|
|
|
contentPadding = PaddingValues(horizontal = contentPadding),
|
|
|
|
|
state = listState,
|
|
|
|
|
flingBehavior = flingBehavior,
|
|
|
|
|
horizontalArrangement = Arrangement.spacedBy(8.dp)
|
|
|
|
|
) {
|
|
|
|
|
itemsIndexed(storiesToShow) { _, columnItems ->
|
|
|
|
|
Column {
|
|
|
|
|
columnItems.forEachIndexed { rowIndex, story ->
|
|
|
|
|
items(storiesToShow) { columnItems ->
|
|
|
|
|
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
|
|
|
|
columnItems.forEach { story ->
|
|
|
|
|
if (story == placeholderStory) {
|
|
|
|
|
ListItemTabLargePlaceholder(stringResource(R.string.pocket_stories_placeholder_text)) {
|
|
|
|
|
onExternalLinkClicked("http://getpocket.com/explore")
|
|
|
|
@ -134,10 +136,6 @@ fun PocketStories(
|
|
|
|
|
onExternalLinkClicked(story.url)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (rowIndex < maxRowsNo - 1) {
|
|
|
|
|
Spacer(modifier = Modifier.height(8.dp))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -148,20 +146,25 @@ fun PocketStories(
|
|
|
|
|
* Displays a list of [PocketRecommendedStoriesCategory]s.
|
|
|
|
|
*
|
|
|
|
|
* @param categories The categories needed to be displayed.
|
|
|
|
|
* @param selections List of categories currently selected.
|
|
|
|
|
* @param onCategoryClick Callback for when the user taps a category.
|
|
|
|
|
* @param modifier [Modifier] to be applied to the layout.
|
|
|
|
|
*/
|
|
|
|
|
@Composable
|
|
|
|
|
fun PocketStoriesCategories(
|
|
|
|
|
categories: List<PocketRecommendedStoriesCategory>,
|
|
|
|
|
selections: List<PocketRecommendedStoriesSelectedCategory>,
|
|
|
|
|
onCategoryClick: (PocketRecommendedStoriesCategory) -> Unit
|
|
|
|
|
onCategoryClick: (PocketRecommendedStoriesCategory) -> Unit,
|
|
|
|
|
modifier: Modifier = Modifier
|
|
|
|
|
) {
|
|
|
|
|
StaggeredHorizontalGrid(
|
|
|
|
|
horizontalItemsSpacing = 16.dp
|
|
|
|
|
) {
|
|
|
|
|
categories.filter { it.name != POCKET_STORIES_DEFAULT_CATEGORY_NAME }.forEach { category ->
|
|
|
|
|
SelectableChip(category.name, selections.map { it.name }.contains(category.name)) {
|
|
|
|
|
onCategoryClick(category)
|
|
|
|
|
Box(modifier = modifier) {
|
|
|
|
|
StaggeredHorizontalGrid(
|
|
|
|
|
horizontalItemsSpacing = 16.dp
|
|
|
|
|
) {
|
|
|
|
|
categories.filter { it.name != POCKET_STORIES_DEFAULT_CATEGORY_NAME }.forEach { category ->
|
|
|
|
|
SelectableChip(category.name, selections.map { it.name }.contains(category.name)) {
|
|
|
|
|
onCategoryClick(category)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@ -173,10 +176,12 @@ fun PocketStoriesCategories(
|
|
|
|
|
*
|
|
|
|
|
* @param onExternalLinkClicked Callback invoked when the user clicks the "Learn more" link.
|
|
|
|
|
* Contains the full URL for where the user should be navigated to.
|
|
|
|
|
* @param modifier [Modifier] to be applied to the layout.
|
|
|
|
|
*/
|
|
|
|
|
@Composable
|
|
|
|
|
fun PoweredByPocketHeader(
|
|
|
|
|
onExternalLinkClicked: (String) -> Unit,
|
|
|
|
|
modifier: Modifier = Modifier
|
|
|
|
|
) {
|
|
|
|
|
val color = when (isSystemInDarkTheme()) {
|
|
|
|
|
true -> PhotonColors.LightGrey30
|
|
|
|
@ -189,6 +194,7 @@ fun PoweredByPocketHeader(
|
|
|
|
|
val linkEndIndex = linkStartIndex + link.length
|
|
|
|
|
|
|
|
|
|
Column(
|
|
|
|
|
modifier = modifier,
|
|
|
|
|
horizontalAlignment = Alignment.CenterHorizontally,
|
|
|
|
|
) {
|
|
|
|
|
Row(
|
|
|
|
@ -230,6 +236,7 @@ private fun PocketStoriesComposablesPreview() {
|
|
|
|
|
Column {
|
|
|
|
|
PocketStories(
|
|
|
|
|
stories = getFakePocketStories(8),
|
|
|
|
|
contentPadding = 0.dp,
|
|
|
|
|
onExternalLinkClicked = { }
|
|
|
|
|
)
|
|
|
|
|
Spacer(Modifier.height(10.dp))
|
|
|
|
@ -238,11 +245,12 @@ private fun PocketStoriesComposablesPreview() {
|
|
|
|
|
"Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor".split(" ").map {
|
|
|
|
|
PocketRecommendedStoriesCategory(it)
|
|
|
|
|
},
|
|
|
|
|
emptyList()
|
|
|
|
|
) { }
|
|
|
|
|
emptyList(),
|
|
|
|
|
{ }
|
|
|
|
|
)
|
|
|
|
|
Spacer(Modifier.height(10.dp))
|
|
|
|
|
|
|
|
|
|
PoweredByPocketHeader { }
|
|
|
|
|
PoweredByPocketHeader({ })
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|