From 40fe4c694f06377435c11b8ea073e7bda03b3dec Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Tue, 26 Oct 2021 18:59:52 +0200 Subject: [PATCH] Added basic implementation of error manager --- src/main/kotlin/app/ErrorsManager.kt | 34 ++++++ src/main/kotlin/app/git/GitManager.kt | 14 ++- src/main/kotlin/app/ui/AppTab.kt | 146 ++++++++++++++++++++------ 3 files changed, 157 insertions(+), 37 deletions(-) create mode 100644 src/main/kotlin/app/ErrorsManager.kt diff --git a/src/main/kotlin/app/ErrorsManager.kt b/src/main/kotlin/app/ErrorsManager.kt new file mode 100644 index 0000000..f3dede4 --- /dev/null +++ b/src/main/kotlin/app/ErrorsManager.kt @@ -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()) + val errorsList: StateFlow> + get() = _errorsList + + private val _lastError = MutableStateFlow(null) + val lastError: StateFlow + 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) \ No newline at end of file diff --git a/src/main/kotlin/app/git/GitManager.kt b/src/main/kotlin/app/git/GitManager.kt index 5a864df..58df60a 100644 --- a/src/main/kotlin/app/git/GitManager.kt +++ b/src/main/kotlin/app/git/GitManager.kt @@ -12,6 +12,9 @@ import org.eclipse.jgit.lib.Repository import org.eclipse.jgit.revwalk.RevCommit import org.eclipse.jgit.storage.file.FileRepositoryBuilder import app.AppStateManager +import app.app.Error +import app.app.ErrorsManager +import app.app.newErrorNow import java.io.File import javax.inject.Inject @@ -23,6 +26,7 @@ class GitManager @Inject constructor( private val branchesManager: BranchesManager, private val stashManager: StashManager, private val diffManager: DiffManager, + val errorsManager: ErrorsManager, val appStateManager: AppStateManager, ) { val repositoryName: String @@ -109,7 +113,7 @@ class GitManager @Inject constructor( } catch (ex: Exception) { ex.printStackTrace() onRepositoryChanged(null) - + errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) } } } @@ -192,8 +196,10 @@ class GitManager @Inject constructor( } fun createBranch(branchName: String) = managerScope.launch { - branchesManager.createBranch(safeGit, branchName) - coLoadLog() + safeProcessing { + branchesManager.createBranch(safeGit, branchName) + coLoadLog() + } } fun deleteBranch(branch: Ref) = managerScope.launch { @@ -238,6 +244,8 @@ class GitManager @Inject constructor( _processing.value = true try { callback() + } catch (ex: Exception) { + errorsManager.addError(newErrorNow(ex, ex.localizedMessage)) } finally { _processing.value = false } diff --git a/src/main/kotlin/app/ui/AppTab.kt b/src/main/kotlin/app/ui/AppTab.kt index dcdc85f..a32e09c 100644 --- a/src/main/kotlin/app/ui/AppTab.kt +++ b/src/main/kotlin/app/ui/AppTab.kt @@ -1,30 +1,63 @@ package app.ui +import androidx.compose.animation.AnimatedVisibility import androidx.compose.animation.Crossfade +import androidx.compose.animation.ExperimentalAnimationApi import androidx.compose.foundation.background -import androidx.compose.foundation.layout.Box -import androidx.compose.foundation.layout.Column -import androidx.compose.foundation.layout.fillMaxSize -import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.clickable +import androidx.compose.foundation.interaction.MutableInteractionSource +import androidx.compose.foundation.layout.* +import androidx.compose.material.Card import androidx.compose.material.LinearProgressIndicator import androidx.compose.material.MaterialTheme +import androidx.compose.material.Text import androidx.compose.runtime.* +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.draw.alpha +import androidx.compose.ui.graphics.Color 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.LoadingRepository import app.git.GitManager import app.git.RepositorySelectionStatus +import app.ui.components.DialogBox +import kotlinx.coroutines.delay +@OptIn(ExperimentalAnimationApi::class) @Composable -fun AppTab(gitManager: GitManager, dialogManager: DialogManager, repositoryPath: String?, tabName: MutableState) { +fun AppTab( + gitManager: GitManager, + dialogManager: DialogManager, + repositoryPath: String?, + tabName: MutableState +) { LaunchedEffect(gitManager) { if (repositoryPath != null) 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 isProcessing by gitManager.processing.collectAsState() @@ -33,42 +66,87 @@ fun AppTab(gitManager: GitManager, dialogManager: DialogManager, repositoryPath: tabName.value = gitManager.repositoryName } - Column( - modifier = Modifier - .background(MaterialTheme.colors.background) - .fillMaxSize() - ) { - - val linearProgressAlpha = if (isProcessing) - DefaultAlpha - else - 0f - - LinearProgressIndicator( + Box { + Column( modifier = Modifier - .fillMaxWidth() - .alpha(linearProgressAlpha) - ) + .background(MaterialTheme.colors.background) + .fillMaxSize() + ) { - Box(modifier = Modifier.fillMaxSize()) { - Crossfade(targetState = repositorySelectionStatus) { + val linearProgressAlpha = if (isProcessing) + DefaultAlpha + else + 0f - @Suppress("UnnecessaryVariable") // Don't inline it because smart cast won't work - when (repositorySelectionStatus) { - RepositorySelectionStatus.None -> { - WelcomePage(gitManager = gitManager) + LinearProgressIndicator( + modifier = Modifier + .fillMaxWidth() + .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() - } - is RepositorySelectionStatus.Open -> { - RepositoryOpenPage(gitManager = gitManager, dialogManager = dialogManager) + } + + if (isProcessing) + Box(modifier = Modifier.fillMaxSize()) //TODO this should block of the mouse/keyboard events while visible + } + } + + 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 } } } \ No newline at end of file