@@ -22,6 +22,7 @@ import androidx.activity.compose.BackHandler
2222import androidx.compose.foundation.ExperimentalFoundationApi
2323import androidx.compose.foundation.background
2424import androidx.compose.foundation.clickable
25+ import androidx.compose.foundation.layout.Arrangement
2526import androidx.compose.foundation.layout.Box
2627import androidx.compose.foundation.layout.BoxWithConstraints
2728import androidx.compose.foundation.layout.Column
@@ -75,12 +76,14 @@ import androidx.compose.material3.adaptive.layout.PaneAdaptedValue
7576import androidx.compose.material3.adaptive.layout.PaneScaffoldDirective
7677import androidx.compose.material3.adaptive.layout.SupportingPaneScaffold
7778import androidx.compose.material3.adaptive.layout.SupportingPaneScaffoldRole
79+ import androidx.compose.material3.adaptive.layout.ThreePaneScaffoldValue
7880import androidx.compose.material3.adaptive.navigation.ThreePaneScaffoldNavigator
7981import androidx.compose.material3.adaptive.navigation.rememberSupportingPaneScaffoldNavigator
8082import androidx.compose.material3.adaptive.occludingVerticalHingeBounds
8183import androidx.compose.material3.adaptive.separatingVerticalHingeBounds
8284import androidx.compose.material3.windowsizeclass.ExperimentalMaterial3WindowSizeClassApi
8385import androidx.compose.material3.windowsizeclass.WindowSizeClass
86+ import androidx.compose.material3.windowsizeclass.WindowWidthSizeClass
8487import androidx.compose.runtime.Composable
8588import androidx.compose.runtime.LaunchedEffect
8689import androidx.compose.runtime.getValue
@@ -149,6 +152,18 @@ data class HomeState(
149152 val onQueueEpisode : (PlayerEpisode ) -> Unit ,
150153)
151154
155+ private val HomeState .showHomeCategoryTabs: Boolean
156+ get() = featuredPodcasts.isNotEmpty() && homeCategories.isNotEmpty()
157+
158+ @OptIn(ExperimentalMaterial3AdaptiveApi ::class )
159+ private fun HomeState.showGrid (
160+ scaffoldValue : ThreePaneScaffoldValue
161+ ): Boolean = windowSizeClass.widthSizeClass == WindowWidthSizeClass .Expanded ||
162+ (
163+ windowSizeClass.widthSizeClass == WindowWidthSizeClass .Medium &&
164+ scaffoldValue[SupportingPaneScaffoldRole .Supporting ] == PaneAdaptedValue .Hidden
165+ )
166+
152167@OptIn(ExperimentalMaterial3AdaptiveApi ::class )
153168private fun <T > ThreePaneScaffoldNavigator<T>.isMainPaneHidden (): Boolean {
154169 return scaffoldValue[SupportingPaneScaffoldRole .Main ] == PaneAdaptedValue .Hidden
@@ -263,11 +278,11 @@ fun MainScreen(
263278
264279 Surface {
265280 val podcastUri = navigator.currentDestination?.content
266- ? : viewState.featuredPodcasts.firstOrNull()?.uri
267-
281+ val showGrid = homeState.showGrid(navigator.scaffoldValue)
268282 if (podcastUri.isNullOrEmpty()) {
269283 HomeScreen (
270284 homeState = homeState,
285+ showGrid = showGrid,
271286 modifier = Modifier .fillMaxSize()
272287 )
273288 } else {
@@ -295,6 +310,7 @@ fun MainScreen(
295310 mainPane = {
296311 HomeScreen (
297312 homeState = homeState,
313+ showGrid = showGrid,
298314 modifier = Modifier .fillMaxSize()
299315 )
300316 },
@@ -307,29 +323,17 @@ fun MainScreen(
307323@OptIn(ExperimentalMaterial3Api ::class )
308324@Composable
309325private fun HomeAppBar (
310- selectedHomeCategory : HomeCategory ,
311- homeCategories : List <HomeCategory >,
312- onHomeCategorySelected : (HomeCategory ) -> Unit ,
326+ isExpanded : Boolean ,
313327 modifier : Modifier = Modifier ,
314- showHomeCategoryToggle : Boolean = false,
315328) {
316329 TopAppBar (
317330 title = {
318331 Row (
332+ horizontalArrangement = Arrangement .End ,
319333 modifier = Modifier
320334 .fillMaxWidth()
321335 .padding(end = 16 .dp)
322336 ) {
323- if (showHomeCategoryToggle) {
324- HomeCategoryTabs (
325- categories = homeCategories,
326- selectedCategory = selectedHomeCategory,
327- onCategorySelected = onHomeCategorySelected,
328- modifier = Modifier .width(240 .dp),
329- showHorizontalLine = false
330- )
331- Spacer (modifier = Modifier .weight(1f ))
332- }
333337 SearchBar (
334338 query = " " ,
335339 onQueryChange = {},
@@ -351,6 +355,7 @@ private fun HomeAppBar(
351355 contentDescription = stringResource(R .string.cd_account)
352356 )
353357 },
358+ modifier = if (isExpanded) Modifier else Modifier .fillMaxWidth()
354359 ) { }
355360 }
356361 },
@@ -361,6 +366,7 @@ private fun HomeAppBar(
361366@Composable
362367private fun HomeScreen (
363368 homeState : HomeState ,
369+ showGrid : Boolean ,
364370 modifier : Modifier = Modifier
365371) {
366372 // Effect that changes the home category selection when there are no subscribed podcasts
@@ -378,10 +384,7 @@ private fun HomeScreen(
378384 ),
379385 topBar = {
380386 HomeAppBar (
381- selectedHomeCategory = homeState.selectedHomeCategory,
382- homeCategories = homeState.homeCategories,
383- onHomeCategorySelected = homeState.onHomeCategorySelected,
384- showHomeCategoryToggle = ! homeState.windowSizeClass.isCompact,
387+ isExpanded = homeState.windowSizeClass.isCompact,
385388 modifier = Modifier .fillMaxWidth(),
386389 )
387390 },
@@ -392,7 +395,8 @@ private fun HomeScreen(
392395 // Main Content
393396 val snackBarText = stringResource(id = R .string.episode_added_to_your_queue)
394397 HomeContent (
395- showGrid = ! homeState.windowSizeClass.isCompact,
398+ showGrid = showGrid,
399+ showHomeCategoryTabs = homeState.showHomeCategoryTabs,
396400 featuredPodcasts = homeState.featuredPodcasts,
397401 isRefreshing = homeState.isRefreshing,
398402 selectedHomeCategory = homeState.selectedHomeCategory,
@@ -421,6 +425,7 @@ private fun HomeScreen(
421425@Composable
422426private fun HomeContent (
423427 showGrid : Boolean ,
428+ showHomeCategoryTabs : Boolean ,
424429 featuredPodcasts : PersistentList <PodcastInfo >,
425430 isRefreshing : Boolean ,
426431 selectedHomeCategory : HomeCategory ,
@@ -454,14 +459,17 @@ private fun HomeContent(
454459 if (showGrid) {
455460 HomeContentGrid (
456461 pagerState = pagerState,
462+ showHomeCategoryTabs = showHomeCategoryTabs,
457463 featuredPodcasts = featuredPodcasts,
458464 isRefreshing = isRefreshing,
459465 selectedHomeCategory = selectedHomeCategory,
466+ homeCategories = homeCategories,
460467 filterableCategoriesModel = filterableCategoriesModel,
461468 podcastCategoryFilterResult = podcastCategoryFilterResult,
462469 library = library,
463470 modifier = modifier,
464471 onPodcastUnfollowed = onPodcastUnfollowed,
472+ onHomeCategorySelected = onHomeCategorySelected,
465473 onCategorySelected = onCategorySelected,
466474 navigateToPodcastDetails = navigateToPodcastDetails,
467475 navigateToPlayer = navigateToPlayer,
@@ -471,6 +479,7 @@ private fun HomeContent(
471479 } else {
472480 HomeContentColumn (
473481 pagerState = pagerState,
482+ showHomeCategoryTabs = showHomeCategoryTabs,
474483 featuredPodcasts = featuredPodcasts,
475484 isRefreshing = isRefreshing,
476485 selectedHomeCategory = selectedHomeCategory,
@@ -493,6 +502,7 @@ private fun HomeContent(
493502@OptIn(ExperimentalFoundationApi ::class )
494503@Composable
495504private fun HomeContentColumn (
505+ showHomeCategoryTabs : Boolean ,
496506 pagerState : PagerState ,
497507 featuredPodcasts : PersistentList <PodcastInfo >,
498508 isRefreshing : Boolean ,
@@ -528,11 +538,12 @@ private fun HomeContentColumn(
528538 // TODO show a progress indicator or similar
529539 }
530540
531- if (featuredPodcasts.isNotEmpty() && homeCategories.isNotEmpty() ) {
541+ if (showHomeCategoryTabs ) {
532542 stickyHeader {
533543 HomeCategoryTabs (
534544 categories = homeCategories,
535545 selectedCategory = selectedHomeCategory,
546+ showHorizontalLine = true ,
536547 onCategorySelected = onHomeCategorySelected
537548 )
538549 }
@@ -564,14 +575,17 @@ private fun HomeContentColumn(
564575
565576@Composable
566577private fun HomeContentGrid (
578+ showHomeCategoryTabs : Boolean ,
567579 pagerState : PagerState ,
568580 featuredPodcasts : PersistentList <PodcastInfo >,
569581 isRefreshing : Boolean ,
570582 selectedHomeCategory : HomeCategory ,
583+ homeCategories : List <HomeCategory >,
571584 filterableCategoriesModel : FilterableCategoriesModel ,
572585 podcastCategoryFilterResult : PodcastCategoryFilterResult ,
573586 library : LibraryInfo ,
574587 modifier : Modifier = Modifier ,
588+ onHomeCategorySelected : (HomeCategory ) -> Unit ,
575589 onPodcastUnfollowed : (PodcastInfo ) -> Unit ,
576590 onCategorySelected : (CategoryInfo ) -> Unit ,
577591 navigateToPodcastDetails : (PodcastInfo ) -> Unit ,
@@ -600,6 +614,20 @@ private fun HomeContentGrid(
600614 // TODO show a progress indicator or similar
601615 }
602616
617+ if (showHomeCategoryTabs) {
618+ fullWidthItem {
619+ Row {
620+ HomeCategoryTabs (
621+ categories = homeCategories,
622+ selectedCategory = selectedHomeCategory,
623+ showHorizontalLine = false ,
624+ onCategorySelected = onHomeCategorySelected,
625+ modifier = Modifier .width(240 .dp)
626+ )
627+ }
628+ }
629+ }
630+
603631 when (selectedHomeCategory) {
604632 HomeCategory .Library -> {
605633 libraryItems(
@@ -652,8 +680,8 @@ private fun HomeCategoryTabs(
652680 categories : List <HomeCategory >,
653681 selectedCategory : HomeCategory ,
654682 onCategorySelected : (HomeCategory ) -> Unit ,
683+ showHorizontalLine : Boolean ,
655684 modifier : Modifier = Modifier ,
656- showHorizontalLine : Boolean = true,
657685) {
658686 if (categories.isEmpty()) {
659687 return
@@ -817,9 +845,7 @@ private fun lastUpdated(updated: OffsetDateTime): String {
817845private fun HomeAppBarPreview () {
818846 JetcasterTheme {
819847 HomeAppBar (
820- homeCategories = emptyList(),
821- onHomeCategorySelected = {},
822- selectedHomeCategory = HomeCategory .Discover ,
848+ isExpanded = false
823849 )
824850 }
825851}
@@ -857,7 +883,10 @@ private fun PreviewHomeContent() {
857883 onLibraryPodcastSelected = {},
858884 onQueueEpisode = {}
859885 )
860- HomeScreen (homeState = homeState)
886+ HomeScreen (
887+ homeState = homeState,
888+ showGrid = false
889+ )
861890 }
862891}
863892
@@ -891,7 +920,10 @@ private fun PreviewHomeContentExpanded() {
891920 onLibraryPodcastSelected = {},
892921 onQueueEpisode = {}
893922 )
894- HomeScreen (homeState = homeState)
923+ HomeScreen (
924+ homeState = homeState,
925+ showGrid = true
926+ )
895927 }
896928}
897929
0 commit comments