Don't use mutable shared flows in UI (#4346)
This commit is contained in:
parent
06f283575d
commit
e865ffafde
7 changed files with 45 additions and 36 deletions
|
@ -15,11 +15,11 @@ interface Event
|
|||
@Singleton
|
||||
class EventHub @Inject constructor() {
|
||||
|
||||
private val sharedEventFlow = MutableSharedFlow<Event>()
|
||||
val events: SharedFlow<Event> = sharedEventFlow.asSharedFlow()
|
||||
private val _events = MutableSharedFlow<Event>()
|
||||
val events: SharedFlow<Event> = _events.asSharedFlow()
|
||||
|
||||
suspend fun dispatch(event: Event) {
|
||||
sharedEventFlow.emit(event)
|
||||
_events.emit(event)
|
||||
}
|
||||
|
||||
// TODO remove as soon as NotificationsFragment is Kotlin
|
||||
|
|
|
@ -28,6 +28,7 @@ import javax.inject.Inject
|
|||
import kotlinx.coroutines.ExperimentalCoroutinesApi
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
|
@ -53,13 +54,13 @@ class ListsForAccountViewModel @Inject constructor(
|
|||
) : ViewModel() {
|
||||
|
||||
private val _states = MutableSharedFlow<List<AccountListState>>(1)
|
||||
val states: SharedFlow<List<AccountListState>> = _states
|
||||
val states: SharedFlow<List<AccountListState>> = _states.asSharedFlow()
|
||||
|
||||
private val _loadError = MutableSharedFlow<Throwable>(1)
|
||||
val loadError: SharedFlow<Throwable> = _loadError
|
||||
val loadError: SharedFlow<Throwable> = _loadError.asSharedFlow()
|
||||
|
||||
private val _actionError = MutableSharedFlow<ActionError>(1)
|
||||
val actionError: SharedFlow<ActionError> = _actionError
|
||||
val actionError: SharedFlow<ActionError> = _actionError.asSharedFlow()
|
||||
|
||||
fun load(accountId: String?) {
|
||||
_loadError.resetReplayCache()
|
||||
|
|
|
@ -47,6 +47,7 @@ import kotlinx.coroutines.flow.SharedFlow
|
|||
import kotlinx.coroutines.flow.SharingStarted
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.first
|
||||
import kotlinx.coroutines.flow.shareIn
|
||||
|
@ -107,12 +108,12 @@ class ComposeViewModel @Inject constructor(
|
|||
private val _media = MutableStateFlow(emptyList<QueuedMedia>())
|
||||
val media: StateFlow<List<QueuedMedia>> = _media.asStateFlow()
|
||||
|
||||
val uploadError =
|
||||
MutableSharedFlow<Throwable>(
|
||||
replay = 0,
|
||||
extraBufferCapacity = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
||||
)
|
||||
private val _uploadError = MutableSharedFlow<Throwable>(
|
||||
replay = 0,
|
||||
extraBufferCapacity = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
||||
)
|
||||
val uploadError: SharedFlow<Throwable> = _uploadError.asSharedFlow()
|
||||
|
||||
private val _closeConfirmation = MutableStateFlow(ConfirmationKind.NONE)
|
||||
val closeConfirmation: StateFlow<ConfirmationKind> = _closeConfirmation.asStateFlow()
|
||||
|
@ -202,7 +203,7 @@ class ComposeViewModel @Inject constructor(
|
|||
)
|
||||
is UploadEvent.ErrorEvent -> {
|
||||
_media.update { mediaList -> mediaList.filter { it.localId != mediaItem.localId } }
|
||||
uploadError.emit(event.error)
|
||||
_uploadError.emit(event.error)
|
||||
return@collect
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,6 +10,8 @@ import at.connyduck.calladapter.networkresult.onFailure
|
|||
import com.keylesspalace.tusky.R
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class DomainBlocksViewModel @Inject constructor(
|
||||
|
@ -18,12 +20,13 @@ class DomainBlocksViewModel @Inject constructor(
|
|||
|
||||
val domainPager = repo.domainPager.cachedIn(viewModelScope)
|
||||
|
||||
val uiEvents = MutableSharedFlow<SnackbarEvent>()
|
||||
private val _uiEvents = MutableSharedFlow<SnackbarEvent>()
|
||||
val uiEvents: SharedFlow<SnackbarEvent> = _uiEvents.asSharedFlow()
|
||||
|
||||
fun block(domain: String) {
|
||||
viewModelScope.launch {
|
||||
repo.block(domain).onFailure { e ->
|
||||
uiEvents.emit(
|
||||
_uiEvents.emit(
|
||||
SnackbarEvent(
|
||||
message = R.string.error_blocking_domain,
|
||||
domain = domain,
|
||||
|
@ -39,7 +42,7 @@ class DomainBlocksViewModel @Inject constructor(
|
|||
fun unblock(domain: String) {
|
||||
viewModelScope.launch {
|
||||
repo.unblock(domain).fold({
|
||||
uiEvents.emit(
|
||||
_uiEvents.emit(
|
||||
SnackbarEvent(
|
||||
message = R.string.confirmation_domain_unmuted,
|
||||
domain = domain,
|
||||
|
@ -49,7 +52,7 @@ class DomainBlocksViewModel @Inject constructor(
|
|||
)
|
||||
)
|
||||
}, { e ->
|
||||
uiEvents.emit(
|
||||
_uiEvents.emit(
|
||||
SnackbarEvent(
|
||||
message = R.string.error_unblocking_domain,
|
||||
domain = domain,
|
||||
|
|
|
@ -11,8 +11,9 @@ import com.keylesspalace.tusky.entity.Filter
|
|||
import com.keylesspalace.tusky.network.MastodonApi
|
||||
import com.keylesspalace.tusky.util.isHttpNotFound
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
class FiltersViewModel @Inject constructor(
|
||||
|
@ -30,8 +31,8 @@ class FiltersViewModel @Inject constructor(
|
|||
|
||||
data class State(val filters: List<Filter>, val loadingState: LoadingState)
|
||||
|
||||
val state: Flow<State> get() = _state
|
||||
private val _state = MutableStateFlow(State(emptyList(), LoadingState.INITIAL))
|
||||
val state: StateFlow<State> = _state.asStateFlow()
|
||||
|
||||
fun load() {
|
||||
this@FiltersViewModel._state.value = _state.value.copy(loadingState = LoadingState.LOADING)
|
||||
|
|
|
@ -51,6 +51,8 @@ import kotlinx.coroutines.channels.BufferOverflow
|
|||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.flow.update
|
||||
import kotlinx.coroutines.launch
|
||||
|
@ -68,14 +70,12 @@ class ViewThreadViewModel @Inject constructor(
|
|||
private val _uiState = MutableStateFlow(ThreadUiState.Loading as ThreadUiState)
|
||||
val uiState: Flow<ThreadUiState> = _uiState.asStateFlow()
|
||||
|
||||
private val _errors =
|
||||
MutableSharedFlow<Throwable>(
|
||||
replay = 0,
|
||||
extraBufferCapacity = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
||||
)
|
||||
val errors: Flow<Throwable>
|
||||
get() = _errors
|
||||
private val _errors = MutableSharedFlow<Throwable>(
|
||||
replay = 0,
|
||||
extraBufferCapacity = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
||||
)
|
||||
val errors: SharedFlow<Throwable> = _errors.asSharedFlow()
|
||||
|
||||
var isInitialLoad: Boolean = true
|
||||
|
||||
|
|
|
@ -27,9 +27,12 @@ import java.io.IOException
|
|||
import java.net.ConnectException
|
||||
import javax.inject.Inject
|
||||
import kotlinx.coroutines.channels.BufferOverflow
|
||||
import kotlinx.coroutines.flow.Flow
|
||||
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||
import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.SharedFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asSharedFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
|
||||
internal class ListsViewModel @Inject constructor(private val api: MastodonApi) : ViewModel() {
|
||||
|
@ -49,15 +52,15 @@ internal class ListsViewModel @Inject constructor(private val api: MastodonApi)
|
|||
|
||||
data class State(val lists: List<MastoList>, val loadingState: LoadingState)
|
||||
|
||||
val state: Flow<State> get() = _state
|
||||
val events: Flow<Event> get() = _events
|
||||
private val _state = MutableStateFlow(State(listOf(), LoadingState.INITIAL))
|
||||
private val _events =
|
||||
MutableSharedFlow<Event>(
|
||||
replay = 0,
|
||||
extraBufferCapacity = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
||||
)
|
||||
val state: StateFlow<State> = _state.asStateFlow()
|
||||
|
||||
private val _events = MutableSharedFlow<Event>(
|
||||
replay = 0,
|
||||
extraBufferCapacity = 1,
|
||||
onBufferOverflow = BufferOverflow.DROP_OLDEST
|
||||
)
|
||||
val events: SharedFlow<Event> = _events.asSharedFlow()
|
||||
|
||||
fun retryLoading() {
|
||||
loadIfNeeded()
|
||||
|
|
Loading…
Reference in a new issue