Merge branch 'frontend/launch-catching' into 'main'

feat: added a launchCatching

See merge request EmmaVandewalle/writand!34
This commit is contained in:
Emma Vandewalle 2024-07-27 18:33:13 +00:00
commit 1d405d7ec4
2 changed files with 84 additions and 0 deletions

View file

@ -0,0 +1,41 @@
package be.re.writand.screens
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import be.re.writand.utils.SnackbarManager
import be.re.writand.utils.SnackbarMessage.Companion.toSnackbarMessage
import kotlinx.coroutines.CoroutineExceptionHandler
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch
/**
* Custom viewmodel class for this app.
*/
class WViewModel : ViewModel() {
/**
* Function to launch a suspended function in viewmodel scope.
* This function catches possible errors and displays them as a snackbar message.
* @param[snackbar] controls if a snackbar must be shown or not.
* @param[finally] a lambda-function to execute after the [block] is executed.
* @param[block] the code that must be executed in a Coroutine-context.
*/
fun launchCatching(
snackbar: Boolean = true,
finally: () -> Unit = {},
block: suspend CoroutineScope.() -> Unit
) =
viewModelScope.launch(
CoroutineExceptionHandler { _, throwable ->
finally()
if (snackbar) {
SnackbarManager.showMessage(throwable.toSnackbarMessage())
}
},
block = {
block()
finally()
}
)
}

View file

@ -0,0 +1,43 @@
package be.re.writand.utils
import be.re.writand.utils.SnackbarMessage.Companion.toSnackbarMessage
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
/**
* Represents a message to be shown inside a snackbar.
*/
sealed class SnackbarMessage {
class StringSnackbar(val message: String) : SnackbarMessage()
companion object {
fun Throwable.toSnackbarMessage(): String {
return this.message.orEmpty()
}
fun SnackbarMessage.toMessage(): String {
return when (this) {
is StringSnackbar -> this.message
}
}
}
}
/**
* The actual manager of the snackbar's messages.
*/
object SnackbarManager {
private val messages: MutableStateFlow<SnackbarMessage?> = MutableStateFlow(null)
val snackbarMessages: StateFlow<SnackbarMessage?>
get() = messages.asStateFlow()
fun showMessage(message: String) {
messages.value = SnackbarMessage.StringSnackbar(message)
}
fun showMessage(message: Throwable) {
messages.value = SnackbarMessage.StringSnackbar(message.toSnackbarMessage())
}
}