|
1 | 1 | package com.hoc081098.channeleventbus.sample.android.ui.home.detail |
2 | 2 |
|
| 3 | +import androidx.compose.runtime.Immutable |
3 | 4 | import androidx.lifecycle.SavedStateHandle |
4 | 5 | import androidx.lifecycle.ViewModel |
| 6 | +import androidx.lifecycle.viewModelScope |
5 | 7 | import com.hoc081098.channeleventbus.ChannelEventBus |
| 8 | +import com.hoc081098.channeleventbus.sample.android.common.HasSingleEventFlow |
6 | 9 | import com.hoc081098.channeleventbus.sample.android.common.SafeSavedStateHandle |
7 | 10 | import com.hoc081098.channeleventbus.sample.android.common.SavedStateHandleKey |
| 11 | +import com.hoc081098.channeleventbus.sample.android.common.SingleEventChannel |
8 | 12 | import com.hoc081098.channeleventbus.sample.android.ui.home.DetailResultToHomeEvent |
9 | 13 | import com.hoc081098.channeleventbus.sample.android.utils.NonBlankString.Companion.toNonBlankString |
| 14 | +import com.hoc081098.channeleventbus.sample.android.utils.launchNowIn |
| 15 | +import com.hoc081098.flowext.flowFromSuspend |
| 16 | +import kotlinx.coroutines.ExperimentalCoroutinesApi |
| 17 | +import kotlinx.coroutines.delay |
| 18 | +import kotlinx.coroutines.flow.Flow |
| 19 | +import kotlinx.coroutines.flow.MutableSharedFlow |
10 | 20 | import kotlinx.coroutines.flow.StateFlow |
| 21 | +import kotlinx.coroutines.flow.flatMapLatest |
| 22 | +import kotlinx.coroutines.launch |
| 23 | +import timber.log.Timber |
11 | 24 |
|
| 25 | +@Immutable |
| 26 | +sealed interface DetailSingleEvent { |
| 27 | + data object Complete : DetailSingleEvent |
| 28 | +} |
| 29 | + |
| 30 | +@OptIn(ExperimentalCoroutinesApi::class) |
12 | 31 | class DetailVM( |
13 | 32 | private val channelEventBus: ChannelEventBus, |
| 33 | + private val singleEventChannel: SingleEventChannel<DetailSingleEvent>, |
14 | 34 | savedStateHandle: SavedStateHandle, |
15 | | -) : ViewModel() { |
| 35 | +) : ViewModel(singleEventChannel), |
| 36 | + HasSingleEventFlow<DetailSingleEvent> by singleEventChannel { |
16 | 37 | private val safeSavedStateHandle = SafeSavedStateHandle(savedStateHandle) |
| 38 | + private val sendResultFlow = MutableSharedFlow<Unit>(extraBufferCapacity = 1) |
17 | 39 |
|
18 | 40 | internal val textStateFlow: StateFlow<String> = safeSavedStateHandle.getStateFlow(TextKey) |
19 | 41 |
|
| 42 | + init { |
| 43 | + fun process(): Flow<Unit> = flowFromSuspend { |
| 44 | + delay(500) // simulate a long-running task |
| 45 | + |
| 46 | + textStateFlow.value |
| 47 | + .toNonBlankString() |
| 48 | + .map(::DetailResultToHomeEvent) |
| 49 | + .onSuccess(channelEventBus::send) |
| 50 | + .onSuccess { singleEventChannel.sendEvent(DetailSingleEvent.Complete) } |
| 51 | + .onFailure { Timber.e(it, "Error while sending result to home") } |
| 52 | + } |
| 53 | + |
| 54 | + sendResultFlow |
| 55 | + .flatMapLatest { process() } |
| 56 | + .launchNowIn(viewModelScope) |
| 57 | + } |
| 58 | + |
20 | 59 | internal fun onTextChanged(text: String) { |
21 | 60 | safeSavedStateHandle[TextKey] = text |
22 | 61 | } |
23 | 62 |
|
24 | 63 | internal fun sendResultToHome() { |
25 | | - textStateFlow.value |
26 | | - .toNonBlankString() |
27 | | - .map(::DetailResultToHomeEvent) |
28 | | - .onSuccess(channelEventBus::send) |
| 64 | + viewModelScope.launch { sendResultFlow.emit(Unit) } |
29 | 65 | } |
30 | 66 |
|
31 | 67 | private companion object { |
|
0 commit comments