Skip to content

Commit 60708b1

Browse files
authored
[Jetcaster] Remove HomeState and reduces lambdas into HomeAction (#1500)
[Merge after #1499] - it served only as a wrapper for parameters without any additional logic - it was unstable and creating new instance each composition, therefore no skipping - Reduces amount of passing and potentially making mistake
2 parents 2a30765 + 3868e6a commit 60708b1

File tree

2 files changed

+87
-111
lines changed

2 files changed

+87
-111
lines changed

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

Lines changed: 60 additions & 105 deletions
Original file line numberDiff line numberDiff line change
@@ -106,13 +106,11 @@ import com.example.jetcaster.R
106106
import com.example.jetcaster.core.domain.testing.PreviewCategories
107107
import com.example.jetcaster.core.domain.testing.PreviewPodcastEpisodes
108108
import com.example.jetcaster.core.domain.testing.PreviewPodcasts
109-
import com.example.jetcaster.core.model.CategoryInfo
110109
import com.example.jetcaster.core.model.EpisodeInfo
111110
import com.example.jetcaster.core.model.FilterableCategoriesModel
112111
import com.example.jetcaster.core.model.LibraryInfo
113112
import com.example.jetcaster.core.model.PodcastCategoryFilterResult
114113
import com.example.jetcaster.core.model.PodcastInfo
115-
import com.example.jetcaster.core.player.model.PlayerEpisode
116114
import com.example.jetcaster.designsystem.component.PodcastImage
117115
import com.example.jetcaster.ui.home.discover.discoverItems
118116
import com.example.jetcaster.ui.home.library.libraryItems
@@ -132,29 +130,6 @@ import kotlinx.collections.immutable.PersistentList
132130
import kotlinx.collections.immutable.toPersistentList
133131
import kotlinx.coroutines.launch
134132

135-
data class HomeState(
136-
val windowSizeClass: WindowSizeClass,
137-
val isLoading: Boolean,
138-
val featuredPodcasts: PersistentList<PodcastInfo>,
139-
val selectedHomeCategory: HomeCategory,
140-
val homeCategories: List<HomeCategory>,
141-
val filterableCategoriesModel: FilterableCategoriesModel,
142-
val podcastCategoryFilterResult: PodcastCategoryFilterResult,
143-
val library: LibraryInfo,
144-
val modifier: Modifier = Modifier,
145-
val onPodcastUnfollowed: (PodcastInfo) -> Unit,
146-
val onHomeCategorySelected: (HomeCategory) -> Unit,
147-
val onCategorySelected: (CategoryInfo) -> Unit,
148-
val navigateToPodcastDetails: (PodcastInfo) -> Unit,
149-
val navigateToPlayer: (EpisodeInfo) -> Unit,
150-
val onTogglePodcastFollowed: (PodcastInfo) -> Unit,
151-
val onLibraryPodcastSelected: (PodcastInfo?) -> Unit,
152-
val onQueueEpisode: (PlayerEpisode) -> Unit,
153-
)
154-
155-
private val HomeState.showHomeCategoryTabs: Boolean
156-
get() = featuredPodcasts.isNotEmpty() && homeCategories.isNotEmpty()
157-
158133
@OptIn(ExperimentalMaterial3AdaptiveApi::class)
159134
private fun <T> ThreePaneScaffoldNavigator<T>.isMainPaneHidden(): Boolean {
160135
return scaffoldValue[SupportingPaneScaffoldRole.Main] == PaneAdaptedValue.Hidden
@@ -293,34 +268,25 @@ private fun HomeScreenReady(
293268
navigator.navigateBack()
294269
}
295270

296-
val homeState = HomeState(
297-
windowSizeClass = windowSizeClass,
298-
isLoading = uiState.isLoading,
299-
featuredPodcasts = uiState.featuredPodcasts,
300-
homeCategories = uiState.homeCategories,
301-
selectedHomeCategory = uiState.selectedHomeCategory,
302-
filterableCategoriesModel = uiState.filterableCategoriesModel,
303-
podcastCategoryFilterResult = uiState.podcastCategoryFilterResult,
304-
library = uiState.library,
305-
onHomeCategorySelected = viewModel::onHomeCategorySelected,
306-
onCategorySelected = viewModel::onCategorySelected,
307-
onPodcastUnfollowed = viewModel::onPodcastUnfollowed,
308-
navigateToPodcastDetails = {
309-
navigator.navigateTo(SupportingPaneScaffoldRole.Supporting, it.uri)
310-
},
311-
navigateToPlayer = navigateToPlayer,
312-
onTogglePodcastFollowed = viewModel::onTogglePodcastFollowed,
313-
onLibraryPodcastSelected = viewModel::onLibraryPodcastSelected,
314-
onQueueEpisode = viewModel::onQueueEpisode
315-
)
316-
317271
Surface {
318272
SupportingPaneScaffold(
319273
value = navigator.scaffoldValue,
320274
directive = navigator.scaffoldDirective,
321275
mainPane = {
322276
HomeScreen(
323-
homeState = homeState,
277+
windowSizeClass = windowSizeClass,
278+
isLoading = uiState.isLoading,
279+
featuredPodcasts = uiState.featuredPodcasts,
280+
homeCategories = uiState.homeCategories,
281+
selectedHomeCategory = uiState.selectedHomeCategory,
282+
filterableCategoriesModel = uiState.filterableCategoriesModel,
283+
podcastCategoryFilterResult = uiState.podcastCategoryFilterResult,
284+
library = uiState.library,
285+
onHomeAction = viewModel::onHomeAction,
286+
navigateToPodcastDetails = {
287+
navigator.navigateTo(SupportingPaneScaffoldRole.Supporting, it.uri)
288+
},
289+
navigateToPlayer = navigateToPlayer,
324290
modifier = Modifier.fillMaxSize()
325291
)
326292
},
@@ -420,13 +386,23 @@ private fun HomeScreenBackground(
420386

421387
@Composable
422388
private fun HomeScreen(
423-
homeState: HomeState,
389+
windowSizeClass: WindowSizeClass,
390+
isLoading: Boolean,
391+
featuredPodcasts: PersistentList<PodcastInfo>,
392+
selectedHomeCategory: HomeCategory,
393+
homeCategories: List<HomeCategory>,
394+
filterableCategoriesModel: FilterableCategoriesModel,
395+
podcastCategoryFilterResult: PodcastCategoryFilterResult,
396+
library: LibraryInfo,
397+
onHomeAction: (HomeAction) -> Unit,
398+
navigateToPodcastDetails: (PodcastInfo) -> Unit,
399+
navigateToPlayer: (EpisodeInfo) -> Unit,
424400
modifier: Modifier = Modifier
425401
) {
426402
// Effect that changes the home category selection when there are no subscribed podcasts
427-
LaunchedEffect(key1 = homeState.featuredPodcasts) {
428-
if (homeState.featuredPodcasts.isEmpty()) {
429-
homeState.onHomeCategorySelected(HomeCategory.Discover)
403+
LaunchedEffect(key1 = featuredPodcasts) {
404+
if (featuredPodcasts.isEmpty()) {
405+
onHomeAction(HomeAction.HomeCategorySelected(HomeCategory.Discover))
430406
}
431407
}
432408

@@ -439,10 +415,10 @@ private fun HomeScreen(
439415
topBar = {
440416
Column {
441417
HomeAppBar(
442-
isExpanded = homeState.windowSizeClass.isCompact,
418+
isExpanded = windowSizeClass.isCompact,
443419
modifier = Modifier.fillMaxWidth(),
444420
)
445-
if (homeState.isLoading) {
421+
if (isLoading) {
446422
LinearProgressIndicator(
447423
Modifier
448424
.fillMaxWidth()
@@ -458,28 +434,26 @@ private fun HomeScreen(
458434
) { contentPadding ->
459435
// Main Content
460436
val snackBarText = stringResource(id = R.string.episode_added_to_your_queue)
437+
val showHomeCategoryTabs = featuredPodcasts.isNotEmpty() && homeCategories.isNotEmpty()
461438
HomeContent(
462-
showHomeCategoryTabs = homeState.showHomeCategoryTabs,
463-
featuredPodcasts = homeState.featuredPodcasts,
464-
selectedHomeCategory = homeState.selectedHomeCategory,
465-
homeCategories = homeState.homeCategories,
466-
filterableCategoriesModel = homeState.filterableCategoriesModel,
467-
podcastCategoryFilterResult = homeState.podcastCategoryFilterResult,
468-
library = homeState.library,
439+
showHomeCategoryTabs = showHomeCategoryTabs,
440+
featuredPodcasts = featuredPodcasts,
441+
selectedHomeCategory = selectedHomeCategory,
442+
homeCategories = homeCategories,
443+
filterableCategoriesModel = filterableCategoriesModel,
444+
podcastCategoryFilterResult = podcastCategoryFilterResult,
445+
library = library,
469446
modifier = Modifier.padding(contentPadding),
470-
onPodcastUnfollowed = homeState.onPodcastUnfollowed,
471-
onHomeCategorySelected = homeState.onHomeCategorySelected,
472-
onCategorySelected = homeState.onCategorySelected,
473-
navigateToPodcastDetails = homeState.navigateToPodcastDetails,
474-
navigateToPlayer = homeState.navigateToPlayer,
475-
onTogglePodcastFollowed = homeState.onTogglePodcastFollowed,
476-
onLibraryPodcastSelected = homeState.onLibraryPodcastSelected,
477-
onQueueEpisode = {
478-
coroutineScope.launch {
479-
snackbarHostState.showSnackbar(snackBarText)
447+
onHomeAction = { action ->
448+
if (action is HomeAction.QueueEpisode) {
449+
coroutineScope.launch {
450+
snackbarHostState.showSnackbar(snackBarText)
451+
}
480452
}
481-
homeState.onQueueEpisode(it)
482-
}
453+
onHomeAction(action)
454+
},
455+
navigateToPodcastDetails = navigateToPodcastDetails,
456+
navigateToPlayer = navigateToPlayer,
483457
)
484458
}
485459
}
@@ -495,21 +469,16 @@ private fun HomeContent(
495469
podcastCategoryFilterResult: PodcastCategoryFilterResult,
496470
library: LibraryInfo,
497471
modifier: Modifier = Modifier,
498-
onPodcastUnfollowed: (PodcastInfo) -> Unit,
499-
onHomeCategorySelected: (HomeCategory) -> Unit,
500-
onCategorySelected: (CategoryInfo) -> Unit,
472+
onHomeAction: (HomeAction) -> Unit,
501473
navigateToPodcastDetails: (PodcastInfo) -> Unit,
502474
navigateToPlayer: (EpisodeInfo) -> Unit,
503-
onTogglePodcastFollowed: (PodcastInfo) -> Unit,
504-
onLibraryPodcastSelected: (PodcastInfo?) -> Unit,
505-
onQueueEpisode: (PlayerEpisode) -> Unit,
506475
) {
507476
val pagerState = rememberPagerState { featuredPodcasts.size }
508477
LaunchedEffect(pagerState, featuredPodcasts) {
509478
snapshotFlow { pagerState.currentPage }
510479
.collect {
511480
val podcast = featuredPodcasts.getOrNull(it)
512-
onLibraryPodcastSelected(podcast)
481+
onHomeAction(HomeAction.LibraryPodcastSelected(podcast))
513482
}
514483
}
515484

@@ -523,13 +492,9 @@ private fun HomeContent(
523492
podcastCategoryFilterResult = podcastCategoryFilterResult,
524493
library = library,
525494
modifier = modifier,
526-
onPodcastUnfollowed = onPodcastUnfollowed,
527-
onHomeCategorySelected = onHomeCategorySelected,
528-
onCategorySelected = onCategorySelected,
495+
onHomeAction = onHomeAction,
529496
navigateToPodcastDetails = navigateToPodcastDetails,
530497
navigateToPlayer = navigateToPlayer,
531-
onTogglePodcastFollowed = onTogglePodcastFollowed,
532-
onQueueEpisode = onQueueEpisode,
533498
)
534499
}
535500

@@ -544,13 +509,9 @@ private fun HomeContentGrid(
544509
podcastCategoryFilterResult: PodcastCategoryFilterResult,
545510
library: LibraryInfo,
546511
modifier: Modifier = Modifier,
547-
onHomeCategorySelected: (HomeCategory) -> Unit,
548-
onPodcastUnfollowed: (PodcastInfo) -> Unit,
549-
onCategorySelected: (CategoryInfo) -> Unit,
512+
onHomeAction: (HomeAction) -> Unit,
550513
navigateToPodcastDetails: (PodcastInfo) -> Unit,
551514
navigateToPlayer: (EpisodeInfo) -> Unit,
552-
onTogglePodcastFollowed: (PodcastInfo) -> Unit,
553-
onQueueEpisode: (PlayerEpisode) -> Unit,
554515
) {
555516
LazyVerticalGrid(
556517
columns = GridCells.Adaptive(362.dp),
@@ -561,7 +522,7 @@ private fun HomeContentGrid(
561522
FollowedPodcastItem(
562523
pagerState = pagerState,
563524
items = featuredPodcasts,
564-
onPodcastUnfollowed = onPodcastUnfollowed,
525+
onPodcastUnfollowed = { onHomeAction(HomeAction.PodcastUnfollowed(it)) },
565526
navigateToPodcastDetails = navigateToPodcastDetails,
566527
modifier = Modifier
567528
.fillMaxWidth()
@@ -576,7 +537,7 @@ private fun HomeContentGrid(
576537
categories = homeCategories,
577538
selectedCategory = selectedHomeCategory,
578539
showHorizontalLine = false,
579-
onCategorySelected = onHomeCategorySelected,
540+
onCategorySelected = { onHomeAction(HomeAction.HomeCategorySelected(it)) },
580541
modifier = Modifier.width(240.dp)
581542
)
582543
}
@@ -588,7 +549,7 @@ private fun HomeContentGrid(
588549
libraryItems(
589550
library = library,
590551
navigateToPlayer = navigateToPlayer,
591-
onQueueEpisode = onQueueEpisode
552+
onQueueEpisode = { onHomeAction(HomeAction.QueueEpisode(it)) }
592553
)
593554
}
594555

@@ -598,9 +559,11 @@ private fun HomeContentGrid(
598559
podcastCategoryFilterResult = podcastCategoryFilterResult,
599560
navigateToPodcastDetails = navigateToPodcastDetails,
600561
navigateToPlayer = navigateToPlayer,
601-
onCategorySelected = onCategorySelected,
602-
onTogglePodcastFollowed = onTogglePodcastFollowed,
603-
onQueueEpisode = onQueueEpisode
562+
onCategorySelected = { onHomeAction(HomeAction.CategorySelected(it)) },
563+
onTogglePodcastFollowed = {
564+
onHomeAction(HomeAction.TogglePodcastFollowed(it))
565+
},
566+
onQueueEpisode = { onHomeAction(HomeAction.QueueEpisode(it)) },
604567
)
605568
}
606569
}
@@ -812,7 +775,7 @@ private val CompactWindowSizeClass = WindowSizeClass.compute(360f, 780f)
812775
@Composable
813776
private fun PreviewHome() {
814777
JetcasterTheme {
815-
val homeState = HomeState(
778+
HomeScreen(
816779
windowSizeClass = CompactWindowSizeClass,
817780
isLoading = true,
818781
featuredPodcasts = PreviewPodcasts.toPersistentList(),
@@ -827,17 +790,9 @@ private fun PreviewHome() {
827790
episodes = PreviewPodcastEpisodes
828791
),
829792
library = LibraryInfo(),
830-
onCategorySelected = {},
831-
onPodcastUnfollowed = {},
793+
onHomeAction = {},
832794
navigateToPodcastDetails = {},
833795
navigateToPlayer = {},
834-
onHomeCategorySelected = {},
835-
onTogglePodcastFollowed = {},
836-
onLibraryPodcastSelected = {},
837-
onQueueEpisode = {}
838-
)
839-
HomeScreen(
840-
homeState = homeState,
841796
)
842797
}
843798
}

Jetcaster/mobile/src/main/java/com/example/jetcaster/ui/home/HomeViewModel.kt

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,31 +154,42 @@ class HomeViewModel @Inject constructor(
154154
}
155155
}
156156

157-
fun onCategorySelected(category: CategoryInfo) {
157+
fun onHomeAction(action: HomeAction) {
158+
when (action) {
159+
is HomeAction.CategorySelected -> onCategorySelected(action.category)
160+
is HomeAction.HomeCategorySelected -> onHomeCategorySelected(action.category)
161+
is HomeAction.LibraryPodcastSelected -> onLibraryPodcastSelected(action.podcast)
162+
is HomeAction.PodcastUnfollowed -> onPodcastUnfollowed(action.podcast)
163+
is HomeAction.QueueEpisode -> onQueueEpisode(action.episode)
164+
is HomeAction.TogglePodcastFollowed -> onTogglePodcastFollowed(action.podcast)
165+
}
166+
}
167+
168+
private fun onCategorySelected(category: CategoryInfo) {
158169
_selectedCategory.value = category
159170
}
160171

161-
fun onHomeCategorySelected(category: HomeCategory) {
172+
private fun onHomeCategorySelected(category: HomeCategory) {
162173
selectedHomeCategory.value = category
163174
}
164175

165-
fun onPodcastUnfollowed(podcast: PodcastInfo) {
176+
private fun onPodcastUnfollowed(podcast: PodcastInfo) {
166177
viewModelScope.launch {
167178
podcastStore.unfollowPodcast(podcast.uri)
168179
}
169180
}
170181

171-
fun onTogglePodcastFollowed(podcast: PodcastInfo) {
182+
private fun onTogglePodcastFollowed(podcast: PodcastInfo) {
172183
viewModelScope.launch {
173184
podcastStore.togglePodcastFollowed(podcast.uri)
174185
}
175186
}
176187

177-
fun onLibraryPodcastSelected(podcast: PodcastInfo?) {
188+
private fun onLibraryPodcastSelected(podcast: PodcastInfo?) {
178189
selectedLibraryPodcast.value = podcast
179190
}
180191

181-
fun onQueueEpisode(episode: PlayerEpisode) {
192+
private fun onQueueEpisode(episode: PlayerEpisode) {
182193
episodePlayer.addToQueue(episode)
183194
}
184195
}
@@ -192,6 +203,16 @@ enum class HomeCategory {
192203
Library, Discover
193204
}
194205

206+
@Immutable
207+
sealed interface HomeAction {
208+
data class CategorySelected(val category: CategoryInfo) : HomeAction
209+
data class HomeCategorySelected(val category: HomeCategory) : HomeAction
210+
data class PodcastUnfollowed(val podcast: PodcastInfo) : HomeAction
211+
data class TogglePodcastFollowed(val podcast: PodcastInfo) : HomeAction
212+
data class LibraryPodcastSelected(val podcast: PodcastInfo?) : HomeAction
213+
data class QueueEpisode(val episode: PlayerEpisode) : HomeAction
214+
}
215+
195216
@Immutable
196217
data class HomeScreenUiState(
197218
val isLoading: Boolean = true,

0 commit comments

Comments
 (0)