From 04a9fc2c25502606df19957654948b63a792e2c9 Mon Sep 17 00:00:00 2001 From: Abdelilah El Aissaoui Date: Sun, 26 Sep 2021 14:05:11 +0200 Subject: [PATCH] Implemented stash and refactored hasUncommitedChanges code --- src/main/kotlin/GitManager.kt | 17 ++++- src/main/kotlin/Log.kt | 9 ++- src/main/kotlin/RepositorySelected.kt | 3 +- src/main/kotlin/Stashes.kt | 102 ++++++++++++++++++++++++++ src/main/kotlin/git/StashManager.kt | 46 ++++++++++++ src/main/kotlin/git/StatusManager.kt | 10 ++- src/main/kotlin/main.kt | 16 +++- src/main/resources/branch.svg | 1 + src/main/resources/stash.svg | 1 + 9 files changed, 198 insertions(+), 7 deletions(-) create mode 100644 src/main/kotlin/Stashes.kt create mode 100644 src/main/kotlin/git/StashManager.kt create mode 100644 src/main/resources/branch.svg create mode 100644 src/main/resources/stash.svg diff --git a/src/main/kotlin/GitManager.kt b/src/main/kotlin/GitManager.kt index 3cf8ce3..a05a77b 100644 --- a/src/main/kotlin/GitManager.kt +++ b/src/main/kotlin/GitManager.kt @@ -23,6 +23,7 @@ class GitManager { private val logManager = LogManager() private val remoteOperationsManager = RemoteOperationsManager() private val branchesManager = BranchesManager() + private val stashManager = StashManager() private val managerScope = CoroutineScope(SupervisorJob()) @@ -43,6 +44,9 @@ class GitManager { val branches: StateFlow> get() = branchesManager.branches + val stashStatus: StateFlow + get() = stashManager.stashStatus + val latestDirectoryOpened: File? get() = File(preferences.latestOpenedRepositoryPath).parentFile @@ -124,7 +128,8 @@ class GitManager { logManager.loadLog(safeGit) } - fun hasUncommitedChanges(): Boolean = statusManager.hasUncommitedChanges(safeGit) + val hasUncommitedChanges: StateFlow + get() = statusManager.hasUncommitedChanges fun diffFormat(diffEntry: DiffEntry): String { val byteArrayOutputStream = ByteArrayOutputStream() @@ -155,9 +160,19 @@ class GitManager { } private fun refreshRepositoryInfo() = managerScope.launch { + statusManager.loadHasUncommitedChanges(safeGit) branchesManager.loadBranches(safeGit) + stashManager.loadStashList(safeGit) loadLog() } + + fun stash() = managerScope.launch { + stashManager.stash(safeGit) + } + + fun popStash() = managerScope.launch { + stashManager.popStash(safeGit) + } } diff --git a/src/main/kotlin/Log.kt b/src/main/kotlin/Log.kt index c20cbc8..05449fb 100644 --- a/src/main/kotlin/Log.kt +++ b/src/main/kotlin/Log.kt @@ -9,6 +9,7 @@ import androidx.compose.material.MaterialTheme import androidx.compose.material.Text import androidx.compose.runtime.* import androidx.compose.ui.Modifier +import androidx.compose.ui.text.font.FontStyle import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.dp import git.LogStatus @@ -39,12 +40,15 @@ fun Log( .background(MaterialTheme.colors.surface) .fillMaxSize() ) { + val hasUncommitedChanges by gitManager.hasUncommitedChanges.collectAsState() + LazyColumn( modifier = Modifier .background(MaterialTheme.colors.surface) .fillMaxSize() ) { - if (gitManager.hasUncommitedChanges()) + + if (hasUncommitedChanges) item { val textColor = if (selectedUncommited.value) { MaterialTheme.colors.primary @@ -66,12 +70,13 @@ fun Log( Text( text = "Uncommited changes", - fontWeight = FontWeight.Bold, + fontStyle = FontStyle.Italic, modifier = Modifier.padding(start = 16.dp), color = textColor, ) Text( text = "You", + fontStyle = FontStyle.Italic, modifier = Modifier.padding(start = 16.dp), color = MaterialTheme.colors.secondaryTextColor, ) diff --git a/src/main/kotlin/RepositorySelected.kt b/src/main/kotlin/RepositorySelected.kt index e34f19d..95ddf8d 100644 --- a/src/main/kotlin/RepositorySelected.kt +++ b/src/main/kotlin/RepositorySelected.kt @@ -29,12 +29,13 @@ fun RepositorySelected(gitManager: GitManager, repository: Repository) { val selectedIndexCommitLog = remember { mutableStateOf(-1) } Row { - Box( + Column ( modifier = Modifier .weight(0.15f) .fillMaxHeight() ) { Branches(gitManager = gitManager) + Stashes(gitManager = gitManager) } Box( modifier = Modifier diff --git a/src/main/kotlin/Stashes.kt b/src/main/kotlin/Stashes.kt new file mode 100644 index 0000000..ce8672d --- /dev/null +++ b/src/main/kotlin/Stashes.kt @@ -0,0 +1,102 @@ +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.* +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.items +import androidx.compose.material.* +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.MoreVert +import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign +import androidx.compose.ui.text.style.TextOverflow +import androidx.compose.ui.unit.dp +import git.StashStatus +import org.eclipse.jgit.revwalk.RevCommit +import theme.headerBackground + +@Composable +fun Stashes(gitManager: GitManager) { + val stashStatusState = gitManager.stashStatus.collectAsState() + val stashStatus = stashStatusState.value + + val stashList = if (stashStatus is StashStatus.Loaded) + stashStatus.stashes + else + listOf() + + Card( + modifier = Modifier + .fillMaxWidth() + .fillMaxHeight(0.5f) + .padding(8.dp) + ) { + Column { + Text( + modifier = Modifier + .background(MaterialTheme.colors.headerBackground) + .padding(vertical = 16.dp) + .fillMaxWidth(), + text = "Stashes", + fontWeight = FontWeight.Bold, + textAlign = TextAlign.Center, + color = MaterialTheme.colors.primary, + maxLines = 1, + ) + + LazyColumn(modifier = Modifier.weight(5f)) { + items(items = stashList) { stash -> + StashRow( + stash = stash, + ) + + } + } + } + } +} + +@Composable +private fun StashRow(stash: RevCommit) { + Row( + modifier = Modifier + .height(56.dp) + .fillMaxWidth() + .clickable(onClick = {}), + verticalAlignment = Alignment.CenterVertically, + ) { + + Icon( + painter = painterResource("stash.svg"), + contentDescription = null, + modifier = Modifier + .padding(horizontal = 16.dp) + .size(24.dp), + tint = MaterialTheme.colors.primary, + ) + + Text( + text = stash.name, + modifier = Modifier.weight(1f, fill = true), + maxLines = 1, + overflow = TextOverflow.Ellipsis, + ) + + IconButton( + onClick = {}, + modifier = Modifier + .padding(horizontal = 16.dp) + .size(32.dp) + ) { + Icon( + imageVector = Icons.Default.MoreVert, + contentDescription = null, + tint = MaterialTheme.colors.primary, + ) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/git/StashManager.kt b/src/main/kotlin/git/StashManager.kt new file mode 100644 index 0000000..837d624 --- /dev/null +++ b/src/main/kotlin/git/StashManager.kt @@ -0,0 +1,46 @@ +package git + +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.flow.MutableStateFlow +import kotlinx.coroutines.flow.StateFlow +import kotlinx.coroutines.withContext +import org.eclipse.jgit.api.Git +import org.eclipse.jgit.revwalk.RevCommit + +class StashManager { + private val _stashStatus = MutableStateFlow(StashStatus.Loaded(listOf())) + val stashStatus: StateFlow + get() = _stashStatus + + suspend fun stash(git: Git) = withContext(Dispatchers.IO) { + git + .stashCreate() + .call() + + loadStashList(git) + } + + suspend fun popStash(git: Git) = withContext(Dispatchers.IO) { + git + .stashApply() + .call() + + loadStashList(git) + } + + suspend fun loadStashList(git: Git) = withContext(Dispatchers.IO) { + _stashStatus.value = StashStatus.Loading + + val stashList = git + .stashList() + .call() + + _stashStatus.value = StashStatus.Loaded(stashList.toList()) + } +} + + +sealed class StashStatus { + object Loading : StashStatus() + data class Loaded(val stashes: List) : StashStatus() +} \ No newline at end of file diff --git a/src/main/kotlin/git/StatusManager.kt b/src/main/kotlin/git/StatusManager.kt index a741ca0..4ddd6e4 100644 --- a/src/main/kotlin/git/StatusManager.kt +++ b/src/main/kotlin/git/StatusManager.kt @@ -15,11 +15,17 @@ class StatusManager { val stageStatus: StateFlow get() = _stageStatus - fun hasUncommitedChanges(git: Git): Boolean { - return git + private val _hasUncommitedChanges = MutableStateFlow(false) + val hasUncommitedChanges: StateFlow + get() = _hasUncommitedChanges + + suspend fun loadHasUncommitedChanges(git: Git) = withContext(Dispatchers.IO) { + val hasUncommitedChanges = git .status() .call() .hasUncommittedChanges() + + _hasUncommitedChanges.value = hasUncommitedChanges } suspend fun loadStatus(git: Git) = withContext(Dispatchers.IO) { diff --git a/src/main/kotlin/main.kt b/src/main/kotlin/main.kt index fa9fd61..77d3157 100644 --- a/src/main/kotlin/main.kt +++ b/src/main/kotlin/main.kt @@ -57,7 +57,9 @@ fun Gitnuro(gitManager: GitManager) { gitManager.openRepository(f.selectedFile) }, onPull = { gitManager.pull() }, - onPush = { gitManager.push() } + onPush = { gitManager.push() }, + onStash = { gitManager.stash() }, + onPopStash = { gitManager.popStash() }, ) Crossfade(targetState = repositorySelectionStatus) { @@ -100,6 +102,8 @@ fun GMenu( onRepositoryOpen: () -> Unit, onPull: () -> Unit, onPush: () -> Unit, + onStash: () -> Unit, + onPopStash: () -> Unit, ) { Row( modifier = Modifier @@ -122,5 +126,15 @@ fun GMenu( ) { Text("Push") } + OutlinedButton( + onClick = onStash + ) { + Text("Stash") + } + OutlinedButton( + onClick = onPopStash + ) { + Text("Pop stash") + } } } \ No newline at end of file diff --git a/src/main/resources/branch.svg b/src/main/resources/branch.svg new file mode 100644 index 0000000..32e924c --- /dev/null +++ b/src/main/resources/branch.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/main/resources/stash.svg b/src/main/resources/stash.svg new file mode 100644 index 0000000..0f4467e --- /dev/null +++ b/src/main/resources/stash.svg @@ -0,0 +1 @@ + \ No newline at end of file