Added stash detail viewing & selected item state management
This commit is contained in:
parent
5493451719
commit
26edec3de3
11
src/main/kotlin/app/extensions/RevCommitExtensions.kt
Normal file
11
src/main/kotlin/app/extensions/RevCommitExtensions.kt
Normal 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
|
||||||
|
}
|
@ -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)
|
||||||
|
@ -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()
|
||||||
|
@ -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)
|
}
|
||||||
}
|
)
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,3 +183,11 @@ 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)
|
||||||
|
}
|
@ -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,
|
||||||
)
|
)
|
||||||
}
|
}
|
@ -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(
|
||||||
|
@ -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 -> {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user