Skip to content

Commit 3615d90

Browse files
Introduce Event sink pattern (#48)
* Use eventSink pattern in SubscriptionsScreen * Use eventSink pattern in PodcastDetails Screen * Use eventSink pattern in EpisodeDetails Screen * Use eventSink pattern in Explore Screen
1 parent 6d386f5 commit 3615d90

File tree

13 files changed

+160
-227
lines changed

13 files changed

+160
-227
lines changed

app/src/main/kotlin/com/mr3y/podcaster/ui/presenter/episodedetails/EpisodeDetailsUIState.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,20 @@ sealed interface EpisodeDetailsUIEvent {
2020
data object RefreshResultConsumed : EpisodeDetailsUIEvent
2121

2222
data object Retry : EpisodeDetailsUIEvent
23+
24+
data class PlayEpisode(val episode: Episode) : EpisodeDetailsUIEvent
25+
26+
data object Pause : EpisodeDetailsUIEvent
27+
28+
data class DownloadEpisode(val episode: Episode) : EpisodeDetailsUIEvent
29+
30+
data class ResumeDownloading(val episodeId: Long) : EpisodeDetailsUIEvent
31+
32+
data class PauseDownloading(val episodeId: Long) : EpisodeDetailsUIEvent
33+
34+
data class AddEpisodeToQueue(val episode: Episode) : EpisodeDetailsUIEvent
35+
36+
data class RemoveEpisodeFromQueue(val episodeId: Long) : EpisodeDetailsUIEvent
37+
38+
data object ErrorPlayingStatusConsumed : EpisodeDetailsUIEvent
2339
}

app/src/main/kotlin/com/mr3y/podcaster/ui/presenter/episodedetails/EpisodeDetailsViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ internal fun EpisodeDetailsPresenter(
9696
}
9797
}
9898
EpisodeDetailsUIEvent.RefreshResultConsumed -> refreshResult = null
99+
else -> {}
99100
}
100101
}
101102
}

app/src/main/kotlin/com/mr3y/podcaster/ui/presenter/podcastdetails/PodcastDetailsUIState.kt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,14 @@ sealed interface PodcastDetailsUIEvent {
3232
data object RefreshResultConsumed : PodcastDetailsUIEvent
3333

3434
data object Retry : PodcastDetailsUIEvent
35+
36+
data class PlayEpisode(val episode: Episode) : PodcastDetailsUIEvent
37+
38+
data object Pause : PodcastDetailsUIEvent
39+
40+
data class AddEpisodeToQueue(val episode: Episode) : PodcastDetailsUIEvent
41+
42+
data class RemoveEpisodeFromQueue(val episodeId: Long) : PodcastDetailsUIEvent
43+
44+
data object ErrorPlayingStatusConsumed : PodcastDetailsUIEvent
3545
}

app/src/main/kotlin/com/mr3y/podcaster/ui/presenter/podcastdetails/PodcastDetailsViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ internal fun PodcastDetailsPresenter(
169169
isEpisodesLoading = false
170170
}
171171
}
172+
else -> {}
172173
}
173174
}
174175
}

app/src/main/kotlin/com/mr3y/podcaster/ui/presenter/subscriptions/SubscriptionsUIState.kt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package com.mr3y.podcaster.ui.presenter.subscriptions
22

3+
import com.mr3y.podcaster.core.model.Episode
34
import com.mr3y.podcaster.core.model.EpisodeWithDownloadMetadata
45
import com.mr3y.podcaster.core.model.Podcast
56
import com.mr3y.podcaster.ui.presenter.RefreshResult
@@ -19,4 +20,16 @@ sealed interface SubscriptionsUIEvent {
1920
data object Refresh : SubscriptionsUIEvent
2021

2122
data object RefreshResultConsumed : SubscriptionsUIEvent
23+
24+
data class ToggleAppTheme(val isDark: Boolean) : SubscriptionsUIEvent
25+
26+
data class PlayEpisode(val episode: Episode) : SubscriptionsUIEvent
27+
28+
data object Pause : SubscriptionsUIEvent
29+
30+
data class AddEpisodeToQueue(val episode: Episode) : SubscriptionsUIEvent
31+
32+
data class RemoveEpisodeFromQueue(val episodeId: Long) : SubscriptionsUIEvent
33+
34+
data object ErrorPlayingStatusConsumed : SubscriptionsUIEvent
2235
}

app/src/main/kotlin/com/mr3y/podcaster/ui/presenter/subscriptions/SubscriptionsViewModel.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ internal fun SubscriptionsPresenter(
103103
}
104104
}
105105
is SubscriptionsUIEvent.RefreshResultConsumed -> refreshResult = null
106+
else -> {}
106107
}
107108
}
108109
}

app/src/main/kotlin/com/mr3y/podcaster/ui/screens/EpisodeDetailsScreen.kt

Lines changed: 31 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ import com.mr3y.podcaster.ui.components.TopBar
7171
import com.mr3y.podcaster.ui.components.rememberHtmlToAnnotatedString
7272
import com.mr3y.podcaster.ui.presenter.PodcasterAppState
7373
import com.mr3y.podcaster.ui.presenter.RefreshResult
74+
import com.mr3y.podcaster.ui.presenter.episodedetails.EpisodeDetailsUIEvent
7475
import com.mr3y.podcaster.ui.presenter.episodedetails.EpisodeDetailsUIState
7576
import com.mr3y.podcaster.ui.presenter.episodedetails.EpisodeDetailsViewModel
7677
import com.mr3y.podcaster.ui.preview.DynamicColorsParameterProvider
@@ -99,21 +100,25 @@ fun EpisodeDetailsScreen(
99100
EpisodeDetailsScreen(
100101
state = state,
101102
onNavigateUp = onNavigateUp,
102-
onRetry = viewModel::retry,
103-
onRefresh = viewModel::refresh,
104-
onPlayEpisode = appState::play,
105-
onPause = appState::pause,
106-
onAddEpisodeToQueue = appState::addToQueue,
107-
onRemoveEpisodeFromQueue = appState::removeFromQueue,
108-
onDownloadingEpisode = appState::downloadEpisode,
109-
onResumeDownloadingEpisode = appState::resumeDownloading,
110-
onPauseDownloadingEpisode = appState::pauseDownloading,
111103
isSelected = state.episode?.id == currentlyPlayingEpisode?.episode?.id,
112104
playingStatus = currentlyPlayingEpisode?.playingStatus,
113-
onConsumeErrorPlayingStatus = appState::consumeErrorPlayingStatus,
114105
externalContentPadding = contentPadding,
115106
excludedWindowInsets = excludedWindowInsets,
116-
onConsumeResult = viewModel::consumeRefreshResult,
107+
eventSink = { event ->
108+
when(event) {
109+
is EpisodeDetailsUIEvent.Refresh -> viewModel.refresh()
110+
is EpisodeDetailsUIEvent.RefreshResultConsumed -> viewModel.consumeRefreshResult()
111+
is EpisodeDetailsUIEvent.Retry -> viewModel.retry()
112+
is EpisodeDetailsUIEvent.PlayEpisode -> appState.play(event.episode)
113+
is EpisodeDetailsUIEvent.Pause -> appState.pause()
114+
is EpisodeDetailsUIEvent.DownloadEpisode -> appState.downloadEpisode(event.episode)
115+
is EpisodeDetailsUIEvent.ResumeDownloading -> appState.resumeDownloading(event.episodeId)
116+
is EpisodeDetailsUIEvent.PauseDownloading -> appState.pauseDownloading(event.episodeId)
117+
is EpisodeDetailsUIEvent.AddEpisodeToQueue -> appState.addToQueue(event.episode)
118+
is EpisodeDetailsUIEvent.RemoveEpisodeFromQueue -> appState.removeFromQueue(event.episodeId)
119+
is EpisodeDetailsUIEvent.ErrorPlayingStatusConsumed -> appState.consumeErrorPlayingStatus()
120+
}
121+
},
117122
modifier = modifier,
118123
)
119124
}
@@ -122,21 +127,11 @@ fun EpisodeDetailsScreen(
122127
fun EpisodeDetailsScreen(
123128
state: EpisodeDetailsUIState,
124129
onNavigateUp: () -> Unit,
125-
onRetry: () -> Unit,
126-
onRefresh: () -> Unit,
127-
onPlayEpisode: (Episode) -> Unit,
128-
onPause: () -> Unit,
129-
onAddEpisodeToQueue: (Episode) -> Unit,
130-
onRemoveEpisodeFromQueue: (episodeId: Long) -> Unit,
131-
onDownloadingEpisode: (Episode) -> Unit,
132-
onResumeDownloadingEpisode: (episodeId: Long) -> Unit,
133-
onPauseDownloadingEpisode: (episodeId: Long) -> Unit,
134130
isSelected: Boolean,
135131
playingStatus: PlayingStatus?,
136-
onConsumeErrorPlayingStatus: () -> Unit,
137132
externalContentPadding: PaddingValues,
138133
excludedWindowInsets: WindowInsets?,
139-
onConsumeResult: () -> Unit,
134+
eventSink: (EpisodeDetailsUIEvent) -> Unit,
140135
modifier: Modifier = Modifier,
141136
) {
142137
val snackBarHostState = remember { SnackbarHostState() }
@@ -149,13 +144,13 @@ fun EpisodeDetailsScreen(
149144
snackBarHostState.showSnackbar(
150145
message = strings.episode_details_refresh_result_error,
151146
)
152-
onConsumeResult()
147+
eventSink(EpisodeDetailsUIEvent.RefreshResultConsumed)
153148
}
154149
is RefreshResult.Mixed -> {
155150
snackBarHostState.showSnackbar(
156151
message = strings.episode_details_refresh_result_mixed,
157152
)
158-
onConsumeResult()
153+
eventSink(EpisodeDetailsUIEvent.RefreshResultConsumed)
159154
}
160155
is RefreshResult.Ok, null -> {}
161156
}
@@ -164,7 +159,7 @@ fun EpisodeDetailsScreen(
164159
snackBarHostState.showSnackbar(
165160
message = strings.generic_error_message,
166161
)
167-
onConsumeErrorPlayingStatus()
162+
eventSink(EpisodeDetailsUIEvent.ErrorPlayingStatusConsumed)
168163
}
169164
else -> {}
170165
}
@@ -200,7 +195,7 @@ fun EpisodeDetailsScreen(
200195
}
201196
PullToRefresh(
202197
isRefreshingDone = !state.isRefreshing,
203-
onRefresh = onRefresh,
198+
onRefresh = { eventSink(EpisodeDetailsUIEvent.Refresh) },
204199
) {
205200
Scaffold(
206201
topBar = {
@@ -243,7 +238,7 @@ fun EpisodeDetailsScreen(
243238
}
244239
state.episode == null -> {
245240
Error(
246-
onRetry = onRetry,
241+
onRetry = { eventSink(EpisodeDetailsUIEvent.Retry) },
247242
modifier = Modifier
248243
.fillMaxSize()
249244
.align(Alignment.Center),
@@ -257,14 +252,14 @@ fun EpisodeDetailsScreen(
257252
Header(
258253
episode = state.episode,
259254
downloadMetadata = state.downloadMetadata,
260-
onPlay = onPlayEpisode,
261-
onPause = onPause,
255+
onPlay = { eventSink(EpisodeDetailsUIEvent.PlayEpisode(it)) },
256+
onPause = { eventSink(EpisodeDetailsUIEvent.Pause) },
262257
queueEpisodes = state.queueEpisodesIds,
263-
onAddEpisodeToQueue = onAddEpisodeToQueue,
264-
onRemoveEpisodeFromQueue = onRemoveEpisodeFromQueue,
265-
onDownloadingEpisode = onDownloadingEpisode,
266-
onResumeDownloadingEpisode = onResumeDownloadingEpisode,
267-
onPauseDownloadingEpisode = onPauseDownloadingEpisode,
258+
onAddEpisodeToQueue = { eventSink(EpisodeDetailsUIEvent.AddEpisodeToQueue(it)) },
259+
onRemoveEpisodeFromQueue = { eventSink(EpisodeDetailsUIEvent.RemoveEpisodeFromQueue(it)) },
260+
onDownloadingEpisode = { eventSink(EpisodeDetailsUIEvent.DownloadEpisode(it)) },
261+
onResumeDownloadingEpisode = { eventSink(EpisodeDetailsUIEvent.ResumeDownloading(it)) },
262+
onPauseDownloadingEpisode = { eventSink(EpisodeDetailsUIEvent.PauseDownloading(it)) },
268263
isSelected = isSelected,
269264
playingStatus = playingStatus,
270265
dominantColor = dominantColorState.color,
@@ -432,21 +427,11 @@ fun EpisodeDetailsScreenPreview(
432427
downloadMetadata = DownloadMetadata,
433428
),
434429
onNavigateUp = {},
435-
onRetry = {},
436-
onRefresh = {},
437-
onPlayEpisode = {},
438-
onPause = {},
439-
onAddEpisodeToQueue = {},
440-
onRemoveEpisodeFromQueue = {},
441-
onDownloadingEpisode = {},
442-
onResumeDownloadingEpisode = {},
443-
onPauseDownloadingEpisode = {},
444430
isSelected = false,
445431
playingStatus = null,
446-
onConsumeErrorPlayingStatus = {},
447432
externalContentPadding = PaddingValues(0.dp),
448433
excludedWindowInsets = null,
449-
onConsumeResult = {},
434+
eventSink = {},
450435
modifier = Modifier.fillMaxSize(),
451436
)
452437
}
@@ -466,21 +451,11 @@ fun EpisodeDetailsErrorPreview() {
466451
downloadMetadata = null,
467452
),
468453
onNavigateUp = {},
469-
onRetry = {},
470-
onRefresh = {},
471-
onPlayEpisode = {},
472-
onPause = {},
473-
onAddEpisodeToQueue = {},
474-
onRemoveEpisodeFromQueue = {},
475-
onDownloadingEpisode = {},
476-
onResumeDownloadingEpisode = {},
477-
onPauseDownloadingEpisode = {},
478454
isSelected = false,
479455
playingStatus = null,
480-
onConsumeErrorPlayingStatus = {},
481456
externalContentPadding = PaddingValues(0.dp),
482457
excludedWindowInsets = null,
483-
onConsumeResult = {},
458+
eventSink = {},
484459
modifier = Modifier.fillMaxSize(),
485460
)
486461
}

0 commit comments

Comments
 (0)