Added basic branches listing

This commit is contained in:
Abdelilah El Aissaoui 2021-09-25 02:48:13 +02:00
parent 9c99bd1b10
commit 1e3b6d02b7
6 changed files with 277 additions and 116 deletions

108
src/main/kotlin/Branches.kt Normal file
View 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,
)
}
}
}

View file

@ -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
View 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()
}
}
}
}
}

View file

@ -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()
}
}
}
}
}

View 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
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB