Added stash detail viewing & selected item state management

This commit is contained in:
Abdelilah El Aissaoui 2021-12-07 01:08:45 +01:00
parent 5493451719
commit 26edec3de3
7 changed files with 77 additions and 72 deletions

View File

@ -0,0 +1,11 @@
package app.extensions
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.revwalk.RevCommit
fun RevCommit.fullData(repository: Repository): RevCommit? {
return if(this.tree == null)
repository.parseCommit(this)
else
this
}

View File

@ -1,16 +1,13 @@
package app.git package app.git
import app.extensions.fullData
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import org.eclipse.jgit.api.Git import org.eclipse.jgit.api.Git
import org.eclipse.jgit.diff.DiffEntry import org.eclipse.jgit.diff.DiffEntry
import org.eclipse.jgit.diff.DiffFormatter import org.eclipse.jgit.diff.DiffFormatter
import org.eclipse.jgit.diff.EditList
import org.eclipse.jgit.dircache.DirCacheIterator import org.eclipse.jgit.dircache.DirCacheIterator
import org.eclipse.jgit.lib.Repository import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.patch.HunkHeader
import org.eclipse.jgit.revplot.PlotCommit
import org.eclipse.jgit.revplot.PlotCommitList
import org.eclipse.jgit.revwalk.RevCommit import org.eclipse.jgit.revwalk.RevCommit
import org.eclipse.jgit.revwalk.RevTree import org.eclipse.jgit.revwalk.RevTree
import org.eclipse.jgit.revwalk.RevWalk import org.eclipse.jgit.revwalk.RevWalk
@ -60,11 +57,14 @@ class DiffManager @Inject constructor() {
suspend fun commitDiffEntries(git: Git, commit: RevCommit): List<DiffEntry> = withContext(Dispatchers.IO) { suspend fun commitDiffEntries(git: Git, commit: RevCommit): List<DiffEntry> = withContext(Dispatchers.IO) {
val fullCommit = commit.fullData(git.repository) ?: return@withContext emptyList()
val repository = git.repository val repository = git.repository
val parent = if (commit.parentCount == 0) {
val parent = if (fullCommit.parentCount == 0) {
null null
} else } else
commit.parents.first() fullCommit.parents.first().fullData(git.repository)
val oldTreeParser = if (parent != null) val oldTreeParser = if (parent != null)
prepareTreeParser(repository, parent) prepareTreeParser(repository, parent)
@ -72,7 +72,7 @@ class DiffManager @Inject constructor() {
CanonicalTreeParser() CanonicalTreeParser()
} }
val newTreeParser = prepareTreeParser(repository, commit) val newTreeParser = prepareTreeParser(repository, fullCommit)
return@withContext git.diff() return@withContext git.diff()
.setNewTree(newTreeParser) .setNewTree(newTreeParser)

View File

@ -23,7 +23,6 @@ class StashManager @Inject constructor() {
} }
suspend fun popStash(git: Git) = withContext(Dispatchers.IO) { suspend fun popStash(git: Git) = withContext(Dispatchers.IO) {
git git
.stashApply() .stashApply()
.call() .call()

View File

@ -26,20 +26,13 @@ import java.awt.Cursor
@OptIn(ExperimentalSplitPaneApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class) @OptIn(ExperimentalSplitPaneApi::class, androidx.compose.ui.ExperimentalComposeUiApi::class)
@Composable @Composable
fun RepositoryOpenPage(gitManager: GitManager) { fun RepositoryOpenPage(gitManager: GitManager) {
var selectedRevCommit by remember {
mutableStateOf<RevCommit?>(null)
}
var diffSelected by remember { var diffSelected by remember {
mutableStateOf<DiffEntryType?>(null) mutableStateOf<DiffEntryType?>(null)
} }
var uncommitedChangesSelected by remember {
mutableStateOf(false)
}
var showNewBranchDialog by remember { mutableStateOf(false) } var showNewBranchDialog by remember { mutableStateOf(false) }
val selectedIndexCommitLog = remember { mutableStateOf(-1) } var (selectedItem, setSelectedItem) = remember { mutableStateOf<SelectedItem>(SelectedItem.None) }
if(showNewBranchDialog) { if(showNewBranchDialog) {
NewBranchDialog( NewBranchDialog(
@ -76,7 +69,12 @@ fun RepositoryOpenPage(gitManager: GitManager) {
) { ) {
Branches(gitManager = gitManager) Branches(gitManager = gitManager)
Tags(gitManager = gitManager) Tags(gitManager = gitManager)
Stashes(gitManager = gitManager) Stashes(
gitManager = gitManager,
onStashSelected = { stash ->
setSelectedItem(SelectedItem.Stash(stash))
}
)
} }
} }
@ -104,7 +102,7 @@ fun RepositoryOpenPage(gitManager: GitManager) {
HorizontalSplitPane( HorizontalSplitPane(
splitPaneState = rememberSplitPaneState(0.9f) splitPaneState = rememberSplitPaneState(0.9f)
) { ) {
first() { first {
Box( Box(
modifier = Modifier modifier = Modifier
.fillMaxSize() .fillMaxSize()
@ -114,14 +112,9 @@ fun RepositoryOpenPage(gitManager: GitManager) {
null -> { null -> {
Log( Log(
gitManager = gitManager, gitManager = gitManager,
selectedIndex = selectedIndexCommitLog, selectedItem = selectedItem,
onRevCommitSelected = { commit -> onItemSelected = {
selectedRevCommit = commit setSelectedItem(it)
uncommitedChangesSelected = false
},
onUncommitedChangesSelected = {
gitManager.statusShouldBeUpdated()
uncommitedChangesSelected = true
}, },
) )
} }
@ -160,7 +153,7 @@ fun RepositoryOpenPage(gitManager: GitManager) {
modifier = Modifier modifier = Modifier
.fillMaxHeight() .fillMaxHeight()
) { ) {
if (uncommitedChangesSelected) { if (selectedItem == SelectedItem.UncommitedChanges) {
UncommitedChanges( UncommitedChanges(
gitManager = gitManager, gitManager = gitManager,
onStagedDiffEntrySelected = { diffEntry -> onStagedDiffEntrySelected = { diffEntry ->
@ -173,16 +166,14 @@ fun RepositoryOpenPage(gitManager: GitManager) {
diffSelected = DiffEntryType.UnstagedDiff(diffEntry) diffSelected = DiffEntryType.UnstagedDiff(diffEntry)
} }
) )
} else { } else if(selectedItem is SelectedItem.CommitBasedItem) {
selectedRevCommit?.let { CommitChanges(
CommitChanges( gitManager = gitManager,
gitManager = gitManager, commit = selectedItem.revCommit,
commit = it, onDiffSelected = { diffEntry ->
onDiffSelected = { diffEntry -> diffSelected = DiffEntryType.CommitDiff(diffEntry)
diffSelected = DiffEntryType.CommitDiff(diffEntry) }
} )
)
}
} }
} }
} }
@ -191,4 +182,12 @@ fun RepositoryOpenPage(gitManager: GitManager) {
} }
} }
} }
}
sealed class SelectedItem {
object None : SelectedItem()
object UncommitedChanges : SelectedItem()
sealed class CommitBasedItem(val revCommit: RevCommit) : SelectedItem()
class Commit(revCommit: RevCommit) : CommitBasedItem(revCommit)
class Stash(revCommit: RevCommit) : CommitBasedItem(revCommit)
} }

View File

@ -1,31 +1,23 @@
package app.ui package app.ui
import androidx.compose.foundation.background import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.clickable import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.material.*
import androidx.compose.runtime.Composable import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState import androidx.compose.runtime.collectAsState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier 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 androidx.compose.ui.unit.sp
import app.ui.components.ScrollableLazyColumn
import app.git.GitManager import app.git.GitManager
import app.git.StashStatus import app.git.StashStatus
import org.eclipse.jgit.revwalk.RevCommit import app.ui.components.ScrollableLazyColumn
import app.theme.headerBackground
import app.theme.headerText
import app.ui.components.SideMenuEntry import app.ui.components.SideMenuEntry
import app.ui.components.SideMenuSubentry import app.ui.components.SideMenuSubentry
import org.eclipse.jgit.revwalk.RevCommit
@Composable @Composable
fun Stashes(gitManager: GitManager) { fun Stashes(
gitManager: GitManager,
onStashSelected: (commit: RevCommit) -> Unit,
) {
val stashStatusState = gitManager.stashStatus.collectAsState() val stashStatusState = gitManager.stashStatus.collectAsState()
val stashStatus = stashStatusState.value val stashStatus = stashStatusState.value
@ -44,8 +36,10 @@ fun Stashes(gitManager: GitManager) {
items(items = stashList) { stash -> items(items = stashList) { stash ->
StashRow( StashRow(
stash = stash, stash = stash,
onClick = {
onStashSelected(stash)
}
) )
} }
} }
} }
@ -53,9 +47,10 @@ fun Stashes(gitManager: GitManager) {
} }
@Composable @Composable
private fun StashRow(stash: RevCommit) { private fun StashRow(stash: RevCommit, onClick: () -> Unit) {
SideMenuSubentry( SideMenuSubentry(
text = stash.name, text = stash.name,
iconResourcePath = "stash.svg", iconResourcePath = "stash.svg",
onClick = onClick,
) )
} }

View File

@ -23,13 +23,14 @@ fun SideMenuSubentry(
text: String, text: String,
iconResourcePath: String, iconResourcePath: String,
bold: Boolean = false, bold: Boolean = false,
onClick: () -> Unit = {},
additionalInfo: @Composable () -> Unit = {} additionalInfo: @Composable () -> Unit = {}
) { ) {
Row( Row(
modifier = Modifier modifier = Modifier
.height(40.dp) .height(40.dp)
.fillMaxWidth() .fillMaxWidth()
.clickable(onClick = {}), .clickable(onClick = onClick),
verticalAlignment = Alignment.CenterVertically, verticalAlignment = Alignment.CenterVertically,
) { ) {
Icon( Icon(

View File

@ -9,7 +9,7 @@ import androidx.compose.foundation.gestures.Orientation
import androidx.compose.foundation.gestures.draggable import androidx.compose.foundation.gestures.draggable
import androidx.compose.foundation.gestures.rememberDraggableState import androidx.compose.foundation.gestures.rememberDraggableState
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon import androidx.compose.material.Icon
@ -40,6 +40,7 @@ import app.theme.headerBackground
import app.theme.headerText import app.theme.headerText
import app.theme.primaryTextColor import app.theme.primaryTextColor
import app.theme.secondaryTextColor import app.theme.secondaryTextColor
import app.ui.SelectedItem
import app.ui.components.ScrollableLazyColumn import app.ui.components.ScrollableLazyColumn
import app.ui.dialogs.MergeDialog import app.ui.dialogs.MergeDialog
import app.ui.dialogs.NewBranchDialog import app.ui.dialogs.NewBranchDialog
@ -69,16 +70,19 @@ private const val CANVAS_MIN_WIDTH = 100
@Composable @Composable
fun Log( fun Log(
gitManager: GitManager, gitManager: GitManager,
onRevCommitSelected: (RevCommit) -> Unit, selectedItem: SelectedItem,
onUncommitedChangesSelected: () -> Unit, onItemSelected: (SelectedItem) -> Unit,
selectedIndex: MutableState<Int> = remember { mutableStateOf(-1) }
) { ) {
val logStatusState = gitManager.logStatus.collectAsState() val logStatusState = gitManager.logStatus.collectAsState()
val logStatus = logStatusState.value val logStatus = logStatusState.value
val selectedUncommited = remember { mutableStateOf(false) }
val showLogDialog = remember { mutableStateOf<LogDialog>(LogDialog.None) } val showLogDialog = remember { mutableStateOf<LogDialog>(LogDialog.None) }
val selectedCommit = if (selectedItem is SelectedItem.Commit) {
selectedItem.revCommit
} else {
null
}
if (logStatus is LogStatus.Loaded) { if (logStatus is LogStatus.Loaded) {
val commitList = logStatus.plotCommitList val commitList = logStatus.plotCommitList
@ -115,23 +119,20 @@ fun Log(
if (hasUncommitedChanges) if (hasUncommitedChanges)
item { item {
UncommitedChangesLine( UncommitedChangesLine(
selected = selectedUncommited.value, selected = selectedItem == SelectedItem.UncommitedChanges,
hasPreviousCommits = commitList.count() > 0, hasPreviousCommits = commitList.count() > 0,
graphWidth = graphWidth, graphWidth = graphWidth,
weightMod = weightMod, weightMod = weightMod,
onUncommitedChangesSelected = { onUncommitedChangesSelected = {
selectedIndex.value = -1 onItemSelected(SelectedItem.UncommitedChanges)
selectedUncommited.value = true
onUncommitedChangesSelected()
} }
) )
} }
items(items = commitList) { graphNode ->
itemsIndexed(items = commitList) { index, graphNode ->
CommitLine( CommitLine(
gitManager = gitManager, gitManager = gitManager,
graphNode = graphNode, graphNode = graphNode,
selected = selectedIndex.value == index, selected = selectedCommit?.name == graphNode.name,
weightMod = weightMod, weightMod = weightMod,
graphWidth = graphWidth, graphWidth = graphWidth,
currentBranch = logStatus.currentBranch, currentBranch = logStatus.currentBranch,
@ -140,9 +141,7 @@ fun Log(
resetBranch = { showLogDialog.value = LogDialog.ResetBranch(graphNode) }, resetBranch = { showLogDialog.value = LogDialog.ResetBranch(graphNode) },
onMergeBranch = { ref -> showLogDialog.value = LogDialog.MergeBranch(ref) }, onMergeBranch = { ref -> showLogDialog.value = LogDialog.MergeBranch(ref) },
onRevCommitSelected = { onRevCommitSelected = {
selectedIndex.value = index onItemSelected(SelectedItem.Commit(graphNode))
selectedUncommited.value = false
onRevCommitSelected(it)
} }
) )
} }
@ -197,7 +196,8 @@ fun LogDialogs(
onResetShowLogDialog() onResetShowLogDialog()
} }
) )
LogDialog.None -> {} LogDialog.None -> {
}
} }
} }