Skip to content

Commit 239c2cb

Browse files
committed
[Jetcaster] Improve scrolling in Home screen
Changes: * Support scrolling entire content in home screen * Fix `PreviewHomeContent` * Remove non-screen composable view model usages
1 parent d04126c commit 239c2cb

File tree

8 files changed

+318
-243
lines changed

8 files changed

+318
-243
lines changed

Jetcaster/app/src/main/java/com/example/jetcaster/ui/home/Home.kt

Lines changed: 122 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.example.jetcaster.ui.home
1818

19+
import android.util.Log
1920
import androidx.compose.foundation.ExperimentalFoundationApi
2021
import androidx.compose.foundation.Image
2122
import androidx.compose.foundation.background
@@ -37,6 +38,7 @@ import androidx.compose.foundation.layout.statusBars
3738
import androidx.compose.foundation.layout.systemBars
3839
import androidx.compose.foundation.layout.windowInsetsPadding
3940
import androidx.compose.foundation.layout.windowInsetsTopHeight
41+
import androidx.compose.foundation.lazy.LazyColumn
4042
import androidx.compose.foundation.pager.HorizontalPager
4143
import androidx.compose.foundation.pager.PagerState
4244
import androidx.compose.foundation.pager.rememberPagerState
@@ -46,6 +48,7 @@ import androidx.compose.material.Icon
4648
import androidx.compose.material.IconButton
4749
import androidx.compose.material.LocalContentAlpha
4850
import androidx.compose.material.MaterialTheme
51+
import androidx.compose.material.Scaffold
4952
import androidx.compose.material.Surface
5053
import androidx.compose.material.Tab
5154
import androidx.compose.material.TabPosition
@@ -74,8 +77,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle
7477
import androidx.lifecycle.viewmodel.compose.viewModel
7578
import coil.compose.AsyncImage
7679
import com.example.jetcaster.R
80+
import com.example.jetcaster.data.Category
7781
import com.example.jetcaster.data.PodcastWithExtraInfo
78-
import com.example.jetcaster.ui.home.discover.Discover
82+
import com.example.jetcaster.ui.home.category.PodcastCategoryViewState
83+
import com.example.jetcaster.ui.home.discover.DiscoverViewState
84+
import com.example.jetcaster.ui.home.discover.discoverItems
7985
import com.example.jetcaster.ui.theme.JetcasterTheme
8086
import com.example.jetcaster.ui.theme.Keyline1
8187
import com.example.jetcaster.ui.theme.MinContrastOfPrimaryVsSurface
@@ -102,9 +108,13 @@ fun Home(
102108
isRefreshing = viewState.refreshing,
103109
homeCategories = viewState.homeCategories,
104110
selectedHomeCategory = viewState.selectedHomeCategory,
105-
onCategorySelected = viewModel::onHomeCategorySelected,
111+
discoverViewState = viewState.discoverViewState,
112+
podcastCategoryViewState = viewState.podcastCategoryViewState,
113+
onHomeCategorySelected = viewModel::onHomeCategorySelected,
114+
onCategorySelected = viewModel::onCategorySelected,
106115
onPodcastUnfollowed = viewModel::onPodcastUnfollowed,
107116
navigateToPlayer = navigateToPlayer,
117+
onTogglePodcastFollowed = viewModel::onTogglePodcastFollowed,
108118
modifier = Modifier.fillMaxSize()
109119
)
110120
}
@@ -163,10 +173,14 @@ fun HomeContent(
163173
isRefreshing: Boolean,
164174
selectedHomeCategory: HomeCategory,
165175
homeCategories: List<HomeCategory>,
176+
discoverViewState: DiscoverViewState,
177+
podcastCategoryViewState: PodcastCategoryViewState,
166178
modifier: Modifier = Modifier,
167179
onPodcastUnfollowed: (String) -> Unit,
168-
onCategorySelected: (HomeCategory) -> Unit,
169-
navigateToPlayer: (String) -> Unit
180+
onHomeCategorySelected: (HomeCategory) -> Unit,
181+
onCategorySelected: (Category) -> Unit,
182+
navigateToPlayer: (String) -> Unit,
183+
onTogglePodcastFollowed: (String) -> Unit,
170184
) {
171185
Column(
172186
modifier = modifier.windowInsetsPadding(
@@ -191,79 +205,114 @@ fun HomeContent(
191205

192206
// When the selected image url changes, call updateColorsFromImageUrl() or reset()
193207
LaunchedEffect(selectedImageUrl) {
208+
Log.d("Jetcaster", "selectedImageUrl: $selectedImageUrl")
194209
if (selectedImageUrl != null) {
195210
dominantColorState.updateColorsFromImageUrl(selectedImageUrl)
196211
} else {
197212
dominantColorState.reset()
198213
}
199214
}
200215

201-
Column(
202-
modifier = Modifier
203-
.fillMaxWidth()
204-
.verticalGradientScrim(
205-
color = MaterialTheme.colors.primary.copy(alpha = 0.38f),
206-
startYPercentage = 1f,
207-
endYPercentage = 0f
208-
)
209-
) {
210-
// Draw a scrim over the status bar which matches the app bar
211-
Spacer(
212-
Modifier
213-
.background(appBarColor)
214-
.fillMaxWidth()
215-
.windowInsetsTopHeight(WindowInsets.statusBars)
216-
)
216+
val scrimColor = MaterialTheme.colors.primary.copy(alpha = 0.38f)
217+
Scaffold(
218+
topBar = {
219+
Column(
220+
modifier = Modifier
221+
.fillMaxWidth()
222+
.background(color = scrimColor)
223+
) {
224+
// Draw a scrim over the status bar which matches the app bar
225+
Spacer(
226+
Modifier
227+
.background(appBarColor)
228+
.fillMaxWidth()
229+
.windowInsetsTopHeight(WindowInsets.statusBars)
230+
)
231+
HomeAppBar(
232+
backgroundColor = appBarColor,
233+
modifier = Modifier.fillMaxWidth()
234+
)
235+
}
236+
},
237+
) { contentPadding ->
238+
LazyColumn(
239+
contentPadding = contentPadding,
240+
modifier = Modifier.fillMaxSize()
241+
) {
242+
if (featuredPodcasts.isNotEmpty()) {
243+
item {
244+
FollowedPodcastItem(
245+
items = featuredPodcasts,
246+
pagerState = pagerState,
247+
onPodcastUnfollowed = onPodcastUnfollowed,
248+
modifier = Modifier
249+
.fillMaxWidth()
250+
.verticalGradientScrim(
251+
color = scrimColor,
252+
startYPercentage = 1f,
253+
endYPercentage = 0f
254+
)
255+
)
256+
}
217257

218-
HomeAppBar(
219-
backgroundColor = appBarColor,
220-
modifier = Modifier.fillMaxWidth()
221-
)
258+
if (isRefreshing) {
259+
// TODO show a progress indicator or similar
260+
}
222261

223-
if (featuredPodcasts.isNotEmpty()) {
224-
Spacer(Modifier.height(16.dp))
262+
stickyHeader {
263+
if (homeCategories.isNotEmpty()) {
264+
HomeCategoryTabs(
265+
categories = homeCategories,
266+
selectedCategory = selectedHomeCategory,
267+
onCategorySelected = onHomeCategorySelected
268+
)
269+
}
270+
}
225271

226-
FollowedPodcasts(
227-
items = featuredPodcasts,
228-
pagerState = pagerState,
229-
onPodcastUnfollowed = onPodcastUnfollowed,
230-
modifier = Modifier
231-
.padding(start = Keyline1, top = 16.dp, end = Keyline1)
232-
.fillMaxWidth()
233-
.height(200.dp)
234-
)
272+
when (selectedHomeCategory) {
273+
HomeCategory.Library -> {
274+
// TODO
275+
}
235276

236-
Spacer(Modifier.height(16.dp))
277+
HomeCategory.Discover -> {
278+
discoverItems(
279+
discoverViewState = discoverViewState,
280+
podcastCategoryViewState = podcastCategoryViewState,
281+
navigateToPlayer = navigateToPlayer,
282+
onCategorySelected = onCategorySelected,
283+
onTogglePodcastFollowed = onTogglePodcastFollowed
284+
)
285+
}
286+
}
287+
}
237288
}
238289
}
239290
}
291+
}
292+
}
240293

241-
if (isRefreshing) {
242-
// TODO show a progress indicator or similar
243-
}
244-
245-
if (homeCategories.isNotEmpty()) {
246-
HomeCategoryTabs(
247-
categories = homeCategories,
248-
selectedCategory = selectedHomeCategory,
249-
onCategorySelected = onCategorySelected
250-
)
251-
}
294+
@OptIn(ExperimentalFoundationApi::class)
295+
@Composable
296+
private fun FollowedPodcastItem(
297+
items: PersistentList<PodcastWithExtraInfo>,
298+
pagerState: PagerState,
299+
onPodcastUnfollowed: (String) -> Unit,
300+
modifier: Modifier = Modifier,
301+
) {
302+
Column(modifier = modifier) {
303+
Spacer(Modifier.height(16.dp))
252304

253-
when (selectedHomeCategory) {
254-
HomeCategory.Library -> {
255-
// TODO
256-
}
305+
FollowedPodcasts(
306+
items = items,
307+
pagerState = pagerState,
308+
onPodcastUnfollowed = onPodcastUnfollowed,
309+
modifier = Modifier
310+
.padding(start = Keyline1, top = 16.dp, end = Keyline1)
311+
.fillMaxWidth()
312+
.height(200.dp)
313+
)
257314

258-
HomeCategory.Discover -> {
259-
Discover(
260-
navigateToPlayer = navigateToPlayer,
261-
Modifier
262-
.fillMaxWidth()
263-
.weight(1f)
264-
)
265-
}
266-
}
315+
Spacer(Modifier.height(16.dp))
267316
}
268317
}
269318

@@ -410,23 +459,31 @@ private fun lastUpdated(updated: OffsetDateTime): String {
410459
}
411460
}
412461

413-
/*
414-
TODO: Fix preview error
415462
@Composable
416463
@Preview
417464
fun PreviewHomeContent() {
418465
JetcasterTheme {
419466
HomeContent(
420467
featuredPodcasts = PreviewPodcastsWithExtraInfo,
421468
isRefreshing = false,
422-
homeCategories = HomeCategory.values().asList(),
469+
homeCategories = HomeCategory.entries,
423470
selectedHomeCategory = HomeCategory.Discover,
471+
discoverViewState = DiscoverViewState(
472+
categories = PreviewCategories,
473+
selectedCategory = PreviewCategories.first(),
474+
),
475+
podcastCategoryViewState = PodcastCategoryViewState(
476+
topPodcasts = PreviewPodcastsWithExtraInfo,
477+
episodes = PreviewEpisodeToPodcasts,
478+
),
424479
onCategorySelected = {},
425-
onPodcastUnfollowed = {}
480+
onPodcastUnfollowed = {},
481+
navigateToPlayer = {},
482+
onHomeCategorySelected = {},
483+
onTogglePodcastFollowed = {}
426484
)
427485
}
428486
}
429-
*/
430487

431488
@Composable
432489
@Preview

0 commit comments

Comments
 (0)