Skip to content

Commit 0734470

Browse files
authored
Merge pull request #108 from hoc081098/better_flowredux
better flowredux SideEffect
2 parents 1813bfa + 8e45cb0 commit 0734470

File tree

3 files changed

+33
-22
lines changed

3 files changed

+33
-22
lines changed

flowredux/src/commonMain/kotlin/com/hoc081098/flowredux/SideEffect.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,3 +59,19 @@ public fun <Action, State, Output : Any> allActionsToOutputChannelSideEffect(
5959

6060
return sideEffect to actionChannel
6161
}
62+
63+
/**
64+
* Create a [SideEffect] that consumes all actions.
65+
* The [SideEffect] will be cancelled when the [SideEffect] is cancelled (when calling [FlowReduxStore.close]).
66+
*
67+
* @param consumer A function that consumes an [Action].
68+
*/
69+
public fun <Action, State> allActionsConsumerSideEffect(
70+
consumer: suspend (Action) -> Unit,
71+
): SideEffect<Action, State> = SideEffect { actionFlow, _, coroutineScope ->
72+
actionFlow
73+
.onEach(consumer)
74+
.launchIn(coroutineScope)
75+
76+
emptyFlow()
77+
}

shared/src/commonMain/kotlin/com/hoc081098/github_search_kmm/presentation/GithubSearchSideEffectsContainer.kt

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import com.hoc081098.flowext.flatMapFirst
44
import com.hoc081098.flowext.flowFromSuspend
55
import com.hoc081098.flowext.takeUntil
66
import com.hoc081098.flowredux.SideEffect
7-
import com.hoc081098.flowredux.allActionsToOutputChannelSideEffect
7+
import com.hoc081098.flowredux.allActionsConsumerSideEffect
88
import com.hoc081098.github_search_kmm.domain.usecase.SearchRepoItemsUseCase
99
import com.hoc081098.github_search_kmm.presentation.GithubSearchState.Companion.FIRST_PAGE
10+
import com.hoc081098.github_search_kmm.presentation.common.SingleEventChannel
1011
import com.hoc081098.github_search_kmm.utils.eitherLceFlow
1112
import kotlin.time.Duration
1213
import kotlin.time.Duration.Companion.milliseconds
@@ -24,14 +25,10 @@ import kotlinx.coroutines.flow.shareIn
2425
import kotlinx.coroutines.flow.take
2526

2627
@Suppress("NOTHING_TO_INLINE")
27-
internal class GithubSearchSideEffectsContainer(private val searchRepoItemsUseCase: SearchRepoItemsUseCase) {
28-
private val sendSingleEventSideEffect = allActionsToOutputChannelSideEffect<
29-
GithubSearchAction,
30-
GithubSearchState,
31-
GithubSearchSingleEvent,
32-
> { it.toGithubSearchSingleEventOrNull() }
33-
34-
internal val eventChannel get() = sendSingleEventSideEffect.second
28+
internal class GithubSearchSideEffectsContainer(
29+
private val searchRepoItemsUseCase: SearchRepoItemsUseCase,
30+
private val singleEventChannel: SingleEventChannel<GithubSearchSingleEvent>,
31+
) {
3532

3633
/**
3734
* @return A list of [SideEffect]s contained in this class.
@@ -49,9 +46,15 @@ internal class GithubSearchSideEffectsContainer(private val searchRepoItemsUseCa
4946
// [Retry] -> [SearchLCE]s
5047
retry(),
5148
// Send single event
52-
sendSingleEventSideEffect.first,
49+
sendSingleEvent(),
5350
)
5451

52+
private inline fun sendSingleEvent() = allActionsConsumerSideEffect<GithubSearchAction, GithubSearchState> { action ->
53+
action
54+
.toGithubSearchSingleEventOrNull()
55+
?.let { singleEventChannel.sendEvent(it) }
56+
}
57+
5558
/**
5659
* [GithubSearchAction.Search]s to [SideEffectAction.TextChanged]s
5760
*/

shared/src/commonMain/kotlin/com/hoc081098/github_search_kmm/presentation/GithubSearchViewModel.kt

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -12,19 +12,18 @@ import com.hoc081098.kmp.viewmodel.ViewModel
1212
import com.hoc081098.kmp.viewmodel.wrapper.NonNullFlowWrapper
1313
import com.hoc081098.kmp.viewmodel.wrapper.NonNullStateFlowWrapper
1414
import com.hoc081098.kmp.viewmodel.wrapper.wrap
15-
import kotlinx.coroutines.channels.consumeEach
16-
import kotlinx.coroutines.launch
1715

1816
open class GithubSearchViewModel(
1917
searchRepoItemsUseCase: SearchRepoItemsUseCase,
2018
private val savedStateHandle: SavedStateHandle,
2119
private val singleEventChannel: SingleEventChannel<GithubSearchSingleEvent>,
2220
) : ViewModel(singleEventChannel) {
23-
private val effectsContainer = GithubSearchSideEffectsContainer(searchRepoItemsUseCase)
24-
2521
private val store = viewModelScope.createFlowReduxStore(
2622
initialState = GithubSearchState.initial(),
27-
sideEffects = effectsContainer.sideEffects,
23+
sideEffects = GithubSearchSideEffectsContainer(
24+
searchRepoItemsUseCase = searchRepoItemsUseCase,
25+
singleEventChannel = singleEventChannel,
26+
).sideEffects,
2827
reducer = Reducer(flip(GithubSearchAction::reduce))
2928
.withLogger(githubSearchFlowReduxLogger()),
3029
)
@@ -34,13 +33,6 @@ open class GithubSearchViewModel(
3433
val eventFlow: NonNullFlowWrapper<GithubSearchSingleEvent> = singleEventChannel.singleEventFlow.wrap()
3534

3635
init {
37-
// Forward all events from `effectsContainer.eventChannel` to `singleEventChannel`
38-
viewModelScope.launch {
39-
effectsContainer
40-
.eventChannel
41-
.consumeEach { singleEventChannel.sendEvent(it) }
42-
}
43-
4436
store.dispatch(InitialSearchAction(termStateFlow.value))
4537
}
4638

0 commit comments

Comments
 (0)