@ -18,6 +18,8 @@ package com.google.samples.apps.nowinandroid.core.data.util
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.update
import java.util.UUID
import javax.inject.Inject
@ -26,12 +28,25 @@ import javax.inject.Inject
* Interface implementation for handling general errors .
* /
class SnackbarErrorMonitor @Inject constructor ( ) : ErrorMonitor {
class SnackbarErrorMonitor @Inject constructor ( val networkMonitor : NetworkMonitor ) : ErrorMonitor {
/ * *
* List of [ ErrorMessage ] to be shown to the user , via Snackbar .
* /
private val _errorMessages = MutableStateFlow < List < ErrorMessage > > ( emptyList ( ) )
override val errorMessages : Flow < List < ErrorMessage > > = _errorMessages
private val errorMessages = MutableStateFlow < List < ErrorMessage > > ( emptyList ( ) )
override val isOffline = networkMonitor . isOnline
. map ( Boolean :: not )
override var offlineMessage : String ? = null
override val errorMessage : Flow < ErrorMessage ? > = combine ( errorMessages , isOffline ) { messages , isOffline ->
// Offline Error Message takes precedence over other messages
if ( isOffline ) {
ErrorMessage ( offlineMessage ?: " You are offline " , duration = MessageDuration . Indefinite )
} else {
messages . firstOrNull ( )
}
}
/ * *
* Creates an [ ErrorMessage ] from String value and adds it to the list .
@ -41,20 +56,32 @@ class SnackbarErrorMonitor @Inject constructor() : ErrorMonitor {
* Returns the ID of the new [ ErrorMessage ] if success
* Returns null if [ error ] is Blank
* /
overrid e fun addErrorMessage ( error : String ) : String ? {
privat e fun addErrorMessage ( error : String , label : String ? , duration : MessageDuration ? , actionPerformed : ( ( ) -> Unit ) ? , actionNotPerformed : ( ( ) -> Unit ) ? ) : String ? {
if ( error . isNotBlank ( ) ) {
val newError = ErrorMessage ( error )
_ errorMessages. update { it + newError }
val newError = ErrorMessage ( error , label = label , duration = duration , actionPerformed = actionPerformed , actionNotPerformed = actionNotPerformed )
errorMessages. update { it + newError }
return newError . id
}
return null
}
override fun addShortErrorMessage ( error : String , label : String ? , successAction : ( ( ) -> Unit ) ? , failureAction : ( ( ) -> Unit ) ? ) : String ? {
return addErrorMessage ( error , label , MessageDuration . Short , successAction , failureAction )
}
override fun addLongErrorMessage ( error : String , label : String ? , successAction : ( ( ) -> Unit ) ? , failureAction : ( ( ) -> Unit ) ? ) : String ? {
return addErrorMessage ( error , label , MessageDuration . Long , successAction , failureAction )
}
override fun addIndefiniteErrorMessage ( error : String , label : String ? , successAction : ( ( ) -> Unit ) ? , failureAction : ( ( ) -> Unit ) ? ) : String ? {
return addErrorMessage ( error , label , MessageDuration . Indefinite , successAction , failureAction )
}
/ * *
* Removes the [ ErrorMessage ] with the specified [ id ] from the list .
* /
override fun clearErrorMessage ( id : String ) {
_errorMessages . update { it . filter { item -> item . id != id } }
errorMessages. update { it . filter { item -> item . id != id } }
}
}
@ -64,4 +91,14 @@ class SnackbarErrorMonitor @Inject constructor() : ErrorMonitor {
data class ErrorMessage (
val message : String ,
val id : String = UUID . randomUUID ( ) . toString ( ) ,
val label : String ? = null ,
val duration : MessageDuration ? = MessageDuration . Short ,
val actionPerformed : ( ( ) -> Unit ) ? = null ,
val actionNotPerformed : ( ( ) -> Unit ) ? = null ,
)
enum class MessageDuration {
Short ,
Long ,
Indefinite ,
}