Added basic branches listing
This commit is contained in:
parent
9c99bd1b10
commit
1e3b6d02b7
6 changed files with 277 additions and 116 deletions
108
src/main/kotlin/Branches.kt
Normal file
108
src/main/kotlin/Branches.kt
Normal file
|
@ -0,0 +1,108 @@
|
|||
import androidx.compose.foundation.border
|
||||
import androidx.compose.foundation.clickable
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.LazyColumn
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Build
|
||||
import androidx.compose.material.icons.filled.MoreVert
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.collectAsState
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.remember
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.ImageBitmap
|
||||
import androidx.compose.ui.graphics.asImageBitmap
|
||||
import androidx.compose.ui.res.useResource
|
||||
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 extensions.filePath
|
||||
import extensions.icon
|
||||
import extensions.toByteArray
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import org.jetbrains.skija.Image
|
||||
|
||||
@Composable
|
||||
fun Branches(gitManager: GitManager) {
|
||||
val branches by gitManager.branches.collectAsState()
|
||||
val branchIcon = remember {
|
||||
useResource("branch.png") {
|
||||
Image.makeFromEncoded(it.toByteArray()).asImageBitmap()
|
||||
}
|
||||
}
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.fillMaxSize()
|
||||
.padding(8.dp)
|
||||
) {
|
||||
Column {
|
||||
Text(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 16.dp)
|
||||
.fillMaxWidth(),
|
||||
text = "Branches",
|
||||
fontWeight = FontWeight.Bold,
|
||||
textAlign = TextAlign.Center,
|
||||
color = MaterialTheme.colors.primary,
|
||||
)
|
||||
|
||||
Divider(modifier = Modifier.fillMaxWidth())
|
||||
|
||||
LazyColumn(modifier = Modifier.weight(5f)) {
|
||||
itemsIndexed(branches) { _, branch ->
|
||||
BranchRow(
|
||||
branch = branch,
|
||||
icon = branchIcon,
|
||||
)
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
private fun BranchRow(branch: Ref, icon: ImageBitmap) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.height(56.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable(onClick = {}),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
|
||||
Icon(
|
||||
bitmap = icon,
|
||||
contentDescription = null,
|
||||
modifier = Modifier
|
||||
.padding(horizontal = 16.dp)
|
||||
.size(24.dp),
|
||||
tint = MaterialTheme.colors.primary,
|
||||
)
|
||||
|
||||
Text(
|
||||
text = branch.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,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@ import org.eclipse.jgit.api.Git
|
|||
import org.eclipse.jgit.diff.DiffEntry
|
||||
import org.eclipse.jgit.diff.DiffFormatter
|
||||
import org.eclipse.jgit.dircache.DirCacheIterator
|
||||
import org.eclipse.jgit.lib.Ref
|
||||
import org.eclipse.jgit.lib.Repository
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder
|
||||
import org.eclipse.jgit.treewalk.FileTreeIterator
|
||||
|
@ -21,6 +22,7 @@ class GitManager {
|
|||
private val statusManager = StatusManager()
|
||||
private val logManager = LogManager()
|
||||
private val remoteOperationsManager = RemoteOperationsManager()
|
||||
private val branchesManager = BranchesManager()
|
||||
|
||||
private val managerScope = CoroutineScope(SupervisorJob())
|
||||
|
||||
|
@ -38,6 +40,9 @@ class GitManager {
|
|||
val logStatus: StateFlow<LogStatus>
|
||||
get() = logManager.logStatus
|
||||
|
||||
val branches: StateFlow<List<Ref>>
|
||||
get() = branchesManager.branches
|
||||
|
||||
val latestDirectoryOpened: File?
|
||||
get() = File(preferences.latestOpenedRepositoryPath).parentFile
|
||||
|
||||
|
@ -87,7 +92,7 @@ class GitManager {
|
|||
_repositorySelectionStatus.value = RepositorySelectionStatus.Open(repository)
|
||||
git = Git(repository)
|
||||
|
||||
loadLog()
|
||||
refreshRepositoryInfo()
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
}
|
||||
|
@ -132,7 +137,7 @@ class GitManager {
|
|||
val newTree = FileTreeIterator(repo)
|
||||
|
||||
println(diffEntry)
|
||||
formatter.scan(oldTree, newTree)
|
||||
formatter.scan(oldTree, newTree) //TODO Should only be set when using diff for unstaged changes
|
||||
// formatter.format(oldTree, newTree)
|
||||
formatter.format(diffEntry)
|
||||
formatter.flush()
|
||||
|
@ -148,6 +153,11 @@ class GitManager {
|
|||
fun push() = managerScope.launch {
|
||||
remoteOperationsManager.push(safeGit)
|
||||
}
|
||||
|
||||
private fun refreshRepositoryInfo() = managerScope.launch {
|
||||
branchesManager.loadBranches(safeGit)
|
||||
loadLog()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
122
src/main/kotlin/Log.kt
Normal file
122
src/main/kotlin/Log.kt
Normal file
|
@ -0,0 +1,122 @@
|
|||
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.itemsIndexed
|
||||
import androidx.compose.material.Card
|
||||
import androidx.compose.material.Divider
|
||||
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.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import git.LogStatus
|
||||
import org.eclipse.jgit.revwalk.RevCommit
|
||||
import theme.primaryTextColor
|
||||
import theme.secondaryTextColor
|
||||
|
||||
@Composable
|
||||
fun Log(
|
||||
gitManager: GitManager,
|
||||
onRevCommitSelected: (RevCommit) -> Unit,
|
||||
onUncommitedChangesSelected: () -> Unit,
|
||||
selectedIndex: MutableState<Int> = remember { mutableStateOf(-1) }
|
||||
) {
|
||||
val logStatusState = gitManager.logStatus.collectAsState()
|
||||
val logStatus = logStatusState.value
|
||||
|
||||
val selectedUncommited = remember { mutableStateOf(false) }
|
||||
|
||||
val log = if (logStatus is LogStatus.Loaded) {
|
||||
logStatus.commits
|
||||
} else
|
||||
listOf()
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.background(MaterialTheme.colors.surface)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.background(MaterialTheme.colors.surface)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
if (gitManager.hasUncommitedChanges())
|
||||
item {
|
||||
val textColor = if (selectedUncommited.value) {
|
||||
MaterialTheme.colors.primary
|
||||
} else
|
||||
MaterialTheme.colors.primaryTextColor
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.height(64.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
selectedIndex.value = -1
|
||||
selectedUncommited.value = true
|
||||
onUncommitedChangesSelected()
|
||||
},
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
|
||||
Text(
|
||||
text = "Uncommited changes",
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
color = textColor,
|
||||
)
|
||||
Text(
|
||||
text = "You",
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
color = MaterialTheme.colors.secondaryTextColor,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
|
||||
itemsIndexed(items = log) { index, item ->
|
||||
val textColor = if (selectedIndex.value == index) {
|
||||
MaterialTheme.colors.primary
|
||||
} else
|
||||
MaterialTheme.colors.primaryTextColor
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.height(64.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
selectedIndex.value = index
|
||||
selectedUncommited.value = false
|
||||
onRevCommitSelected(item)
|
||||
},
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
|
||||
Text(
|
||||
text = item.shortMessage,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
color = textColor,
|
||||
)
|
||||
Text(
|
||||
text = item.authorIdent.name,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
color = MaterialTheme.colors.secondaryTextColor,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,21 +1,18 @@
|
|||
import androidx.compose.animation.Crossfade
|
||||
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.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.*
|
||||
import androidx.compose.material.Button
|
||||
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.graphics.Color
|
||||
import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import extensions.filePath
|
||||
import git.LogStatus
|
||||
import org.eclipse.jgit.api.Git
|
||||
import org.eclipse.jgit.diff.DiffEntry
|
||||
import org.eclipse.jgit.lib.Repository
|
||||
|
@ -24,9 +21,7 @@ import org.eclipse.jgit.revwalk.RevTree
|
|||
import org.eclipse.jgit.revwalk.RevWalk
|
||||
import org.eclipse.jgit.treewalk.AbstractTreeIterator
|
||||
import org.eclipse.jgit.treewalk.CanonicalTreeParser
|
||||
import theme.backgroundColorLight
|
||||
import theme.primaryTextColor
|
||||
import theme.secondaryTextColor
|
||||
import java.io.IOException
|
||||
|
||||
@Composable
|
||||
|
@ -45,6 +40,13 @@ fun RepositorySelected(gitManager: GitManager, repository: Repository) {
|
|||
val selectedIndexCommitLog = remember { mutableStateOf(-1) }
|
||||
|
||||
Row {
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(0.15f)
|
||||
.fillMaxHeight()
|
||||
) {
|
||||
Branches(gitManager = gitManager)
|
||||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(0.7f)
|
||||
|
@ -94,7 +96,7 @@ fun RepositorySelected(gitManager: GitManager, repository: Repository) {
|
|||
}
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.weight(0.3f)
|
||||
.weight(0.15f)
|
||||
.fillMaxHeight()
|
||||
) {
|
||||
if (uncommitedChangesSelected) {
|
||||
|
@ -119,6 +121,8 @@ fun RepositorySelected(gitManager: GitManager, repository: Repository) {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Composable
|
||||
fun DiffView(gitManager: GitManager, diffEntry: DiffEntry, onCloseDiffView: () -> Unit) {
|
||||
val text = remember(diffEntry) {
|
||||
|
@ -169,109 +173,4 @@ fun prepareTreeParser(repository: Repository, commit: RevCommit): AbstractTreeIt
|
|||
walk.dispose()
|
||||
return treeParser
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun Log(
|
||||
gitManager: GitManager,
|
||||
onRevCommitSelected: (RevCommit) -> Unit,
|
||||
onUncommitedChangesSelected: () -> Unit,
|
||||
selectedIndex: MutableState<Int> = remember { mutableStateOf(-1) }
|
||||
) {
|
||||
val logStatusState = gitManager.logStatus.collectAsState()
|
||||
val logStatus = logStatusState.value
|
||||
|
||||
val selectedUncommited = remember { mutableStateOf(false) }
|
||||
|
||||
val log = if (logStatus is LogStatus.Loaded) {
|
||||
logStatus.commits
|
||||
} else
|
||||
listOf()
|
||||
|
||||
Card(
|
||||
modifier = Modifier
|
||||
.padding(8.dp)
|
||||
.background(MaterialTheme.colors.surface)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
LazyColumn(
|
||||
modifier = Modifier
|
||||
.background(MaterialTheme.colors.surface)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
if (gitManager.hasUncommitedChanges())
|
||||
item {
|
||||
val textColor = if (selectedUncommited.value) {
|
||||
MaterialTheme.colors.primary
|
||||
} else
|
||||
MaterialTheme.colors.primaryTextColor
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.height(64.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
selectedIndex.value = -1
|
||||
selectedUncommited.value = true
|
||||
onUncommitedChangesSelected()
|
||||
},
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
|
||||
Text(
|
||||
text = "Uncommited changes",
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
color = textColor,
|
||||
)
|
||||
Text(
|
||||
text = "You",
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
color = MaterialTheme.colors.secondaryTextColor,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
|
||||
itemsIndexed(items = log) { index, item ->
|
||||
val textColor = if (selectedIndex.value == index) {
|
||||
MaterialTheme.colors.primary
|
||||
} else
|
||||
MaterialTheme.colors.primaryTextColor
|
||||
|
||||
Column(
|
||||
modifier = Modifier
|
||||
.height(64.dp)
|
||||
.fillMaxWidth()
|
||||
.clickable {
|
||||
selectedIndex.value = index
|
||||
selectedUncommited.value = false
|
||||
onRevCommitSelected(item)
|
||||
},
|
||||
verticalArrangement = Arrangement.Center,
|
||||
) {
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
|
||||
Text(
|
||||
text = item.shortMessage,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
color = textColor,
|
||||
)
|
||||
Text(
|
||||
text = item.authorIdent.name,
|
||||
modifier = Modifier.padding(start = 16.dp),
|
||||
color = MaterialTheme.colors.secondaryTextColor,
|
||||
)
|
||||
Spacer(modifier = Modifier.weight(2f))
|
||||
|
||||
Divider()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
22
src/main/kotlin/git/BranchesManager.kt
Normal file
22
src/main/kotlin/git/BranchesManager.kt
Normal file
|
@ -0,0 +1,22 @@
|
|||
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.lib.Ref
|
||||
|
||||
class BranchesManager {
|
||||
private val _branches = MutableStateFlow<List<Ref>>(listOf())
|
||||
val branches: StateFlow<List<Ref>>
|
||||
get() = _branches
|
||||
|
||||
suspend fun loadBranches(git: Git) = withContext(Dispatchers.IO) {
|
||||
val branchList = git
|
||||
.branchList()
|
||||
.call()
|
||||
|
||||
_branches.value = branchList
|
||||
}
|
||||
}
|
BIN
src/main/resources/branch.png
Normal file
BIN
src/main/resources/branch.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 58 KiB |
Loading…
Reference in a new issue