Added basic implementation of error manager

This commit is contained in:
Abdelilah El Aissaoui 2021-10-26 18:59:52 +02:00
parent 469fe530ee
commit 40fe4c694f
3 changed files with 157 additions and 37 deletions

View File

@ -0,0 +1,34 @@
package app.app
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import javax.inject.Inject
class ErrorsManager @Inject constructor() {
private val _errorsList = MutableStateFlow(listOf<Error>())
val errorsList: StateFlow<List<Error>>
get() = _errorsList
private val _lastError = MutableStateFlow<Error?>(null)
val lastError: StateFlow<Error?>
get() = _lastError
fun addError(error: Error) {
_errorsList.value = _errorsList.value.toMutableList().apply {
add(error)
}
_lastError.value = error
}
fun removeError(error: Error) {
_errorsList.value = _errorsList.value.toMutableList().apply {
remove(error)
}
}
}
data class Error(val date: Long, val exception: Exception, val message: String)
fun newErrorNow(exception: Exception,message: String) = Error(System.currentTimeMillis(), exception, message)

View File

@ -12,6 +12,9 @@ import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.revwalk.RevCommit import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.storage.file.FileRepositoryBuilder import org.eclipse.jgit.storage.file.FileRepositoryBuilder
import app.AppStateManager import app.AppStateManager
import app.app.Error
import app.app.ErrorsManager
import app.app.newErrorNow
import java.io.File import java.io.File
import javax.inject.Inject import javax.inject.Inject
@ -23,6 +26,7 @@ class GitManager @Inject constructor(
private val branchesManager: BranchesManager, private val branchesManager: BranchesManager,
private val stashManager: StashManager, private val stashManager: StashManager,
private val diffManager: DiffManager, private val diffManager: DiffManager,
val errorsManager: ErrorsManager,
val appStateManager: AppStateManager, val appStateManager: AppStateManager,
) { ) {
val repositoryName: String val repositoryName: String
@ -109,7 +113,7 @@ class GitManager @Inject constructor(
} catch (ex: Exception) { } catch (ex: Exception) {
ex.printStackTrace() ex.printStackTrace()
onRepositoryChanged(null) onRepositoryChanged(null)
errorsManager.addError(newErrorNow(ex, ex.localizedMessage))
} }
} }
} }
@ -192,8 +196,10 @@ class GitManager @Inject constructor(
} }
fun createBranch(branchName: String) = managerScope.launch { fun createBranch(branchName: String) = managerScope.launch {
branchesManager.createBranch(safeGit, branchName) safeProcessing {
coLoadLog() branchesManager.createBranch(safeGit, branchName)
coLoadLog()
}
} }
fun deleteBranch(branch: Ref) = managerScope.launch { fun deleteBranch(branch: Ref) = managerScope.launch {
@ -238,6 +244,8 @@ class GitManager @Inject constructor(
_processing.value = true _processing.value = true
try { try {
callback() callback()
} catch (ex: Exception) {
errorsManager.addError(newErrorNow(ex, ex.localizedMessage))
} finally { } finally {
_processing.value = false _processing.value = false
} }

View File

@ -1,30 +1,63 @@
package app.ui package app.ui
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.Crossfade import androidx.compose.animation.Crossfade
import androidx.compose.animation.ExperimentalAnimationApi
import androidx.compose.foundation.background import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.*
import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.material.Card
import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.LinearProgressIndicator
import androidx.compose.material.MaterialTheme import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.* import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.DefaultAlpha import androidx.compose.ui.graphics.DefaultAlpha
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.DialogManager import app.DialogManager
import app.LoadingRepository import app.LoadingRepository
import app.git.GitManager import app.git.GitManager
import app.git.RepositorySelectionStatus import app.git.RepositorySelectionStatus
import app.ui.components.DialogBox
import kotlinx.coroutines.delay
@OptIn(ExperimentalAnimationApi::class)
@Composable @Composable
fun AppTab(gitManager: GitManager, dialogManager: DialogManager, repositoryPath: String?, tabName: MutableState<String>) { fun AppTab(
gitManager: GitManager,
dialogManager: DialogManager,
repositoryPath: String?,
tabName: MutableState<String>
) {
LaunchedEffect(gitManager) { LaunchedEffect(gitManager) {
if (repositoryPath != null) if (repositoryPath != null)
gitManager.openRepository(repositoryPath) gitManager.openRepository(repositoryPath)
} }
val errorManager = remember(gitManager) { // TODO Is remember here necessary?
gitManager.errorsManager
}
val lastError by errorManager.lastError.collectAsState()
var showError by remember {
mutableStateOf(false)
}
if (lastError != null)
LaunchedEffect(lastError) {
showError = true
delay(5000)
showError = false
}
val repositorySelectionStatus by gitManager.repositorySelectionStatus.collectAsState() val repositorySelectionStatus by gitManager.repositorySelectionStatus.collectAsState()
val isProcessing by gitManager.processing.collectAsState() val isProcessing by gitManager.processing.collectAsState()
@ -33,42 +66,87 @@ fun AppTab(gitManager: GitManager, dialogManager: DialogManager, repositoryPath:
tabName.value = gitManager.repositoryName tabName.value = gitManager.repositoryName
} }
Column( Box {
modifier = Modifier Column(
.background(MaterialTheme.colors.background)
.fillMaxSize()
) {
val linearProgressAlpha = if (isProcessing)
DefaultAlpha
else
0f
LinearProgressIndicator(
modifier = Modifier modifier = Modifier
.fillMaxWidth() .background(MaterialTheme.colors.background)
.alpha(linearProgressAlpha) .fillMaxSize()
) ) {
Box(modifier = Modifier.fillMaxSize()) { val linearProgressAlpha = if (isProcessing)
Crossfade(targetState = repositorySelectionStatus) { DefaultAlpha
else
0f
@Suppress("UnnecessaryVariable") // Don't inline it because smart cast won't work LinearProgressIndicator(
when (repositorySelectionStatus) { modifier = Modifier
RepositorySelectionStatus.None -> { .fillMaxWidth()
WelcomePage(gitManager = gitManager) .alpha(linearProgressAlpha)
)
Box(modifier = Modifier.fillMaxSize()) {
Crossfade(targetState = repositorySelectionStatus) {
@Suppress("UnnecessaryVariable") // Don't inline it because smart cast won't work
when (repositorySelectionStatus) {
RepositorySelectionStatus.None -> {
WelcomePage(gitManager = gitManager)
}
RepositorySelectionStatus.Loading -> {
LoadingRepository()
}
is RepositorySelectionStatus.Open -> {
RepositoryOpenPage(gitManager = gitManager, dialogManager = dialogManager)
}
} }
RepositorySelectionStatus.Loading -> { }
LoadingRepository()
} if (isProcessing)
is RepositorySelectionStatus.Open -> { Box(modifier = Modifier.fillMaxSize()) //TODO this should block of the mouse/keyboard events while visible
RepositoryOpenPage(gitManager = gitManager, dialogManager = dialogManager) }
}
val safeLastError = lastError
if (safeLastError != null) {
AnimatedVisibility(
visible = showError,
modifier = Modifier
.align(Alignment.BottomEnd)
.padding(end = 32.dp, bottom = 32.dp)
) {
val interactionSource = remember { MutableInteractionSource() }
Card(
modifier = Modifier
.defaultMinSize(minWidth = 200.dp, minHeight = 100.dp)
.clickable(
enabled = true,
onClick = {},
interactionSource = interactionSource,
indication = null
),
backgroundColor = MaterialTheme.colors.error,
) {
Column(
modifier = Modifier
.padding(horizontal = 32.dp)
) {
Text(
text = "Error",
fontSize = 20.sp,
fontWeight = FontWeight.Medium,
modifier = Modifier
.padding(top = 16.dp)
) // TODO Add more descriptive title
Text(
text = safeLastError.message,
modifier = Modifier
.padding(top = 8.dp)
)
} }
} }
} }
if (isProcessing)
Box(modifier = Modifier.fillMaxSize()) //TODO this should block of the mouse/keyboard events while visible
} }
} }
} }