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.DiffEntry
import org.eclipse.jgit.diff.DiffFormatter import org.eclipse.jgit.diff.DiffFormatter
import org.eclipse.jgit.dircache.DirCacheIterator import org.eclipse.jgit.dircache.DirCacheIterator
import org.eclipse.jgit.lib.Ref
import org.eclipse.jgit.lib.Repository import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.storage.file.FileRepositoryBuilder import org.eclipse.jgit.storage.file.FileRepositoryBuilder
import org.eclipse.jgit.treewalk.FileTreeIterator import org.eclipse.jgit.treewalk.FileTreeIterator
@ -21,6 +22,7 @@ class GitManager {
private val statusManager = StatusManager() private val statusManager = StatusManager()
private val logManager = LogManager() private val logManager = LogManager()
private val remoteOperationsManager = RemoteOperationsManager() private val remoteOperationsManager = RemoteOperationsManager()
private val branchesManager = BranchesManager()
private val managerScope = CoroutineScope(SupervisorJob()) private val managerScope = CoroutineScope(SupervisorJob())
@ -38,6 +40,9 @@ class GitManager {
val logStatus: StateFlow<LogStatus> val logStatus: StateFlow<LogStatus>
get() = logManager.logStatus get() = logManager.logStatus
val branches: StateFlow<List<Ref>>
get() = branchesManager.branches
val latestDirectoryOpened: File? val latestDirectoryOpened: File?
get() = File(preferences.latestOpenedRepositoryPath).parentFile get() = File(preferences.latestOpenedRepositoryPath).parentFile
@ -87,7 +92,7 @@ class GitManager {
_repositorySelectionStatus.value = RepositorySelectionStatus.Open(repository) _repositorySelectionStatus.value = RepositorySelectionStatus.Open(repository)
git = Git(repository) git = Git(repository)
loadLog() refreshRepositoryInfo()
} catch (ex: Exception) { } catch (ex: Exception) {
ex.printStackTrace() ex.printStackTrace()
} }
@ -132,7 +137,7 @@ class GitManager {
val newTree = FileTreeIterator(repo) val newTree = FileTreeIterator(repo)
println(diffEntry) 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(oldTree, newTree)
formatter.format(diffEntry) formatter.format(diffEntry)
formatter.flush() formatter.flush()
@ -148,6 +153,11 @@ class GitManager {
fun push() = managerScope.launch { fun push() = managerScope.launch {
remoteOperationsManager.push(safeGit) 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.animation.Crossfade
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.* import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.text.selection.SelectionContainer 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.runtime.*
import androidx.compose.ui.Alignment import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.font.FontFamily import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import extensions.filePath import extensions.filePath
import git.LogStatus
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.lib.Repository 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.revwalk.RevWalk
import org.eclipse.jgit.treewalk.AbstractTreeIterator import org.eclipse.jgit.treewalk.AbstractTreeIterator
import org.eclipse.jgit.treewalk.CanonicalTreeParser import org.eclipse.jgit.treewalk.CanonicalTreeParser
import theme.backgroundColorLight
import theme.primaryTextColor import theme.primaryTextColor
import theme.secondaryTextColor
import java.io.IOException import java.io.IOException
@Composable @Composable
@ -45,6 +40,13 @@ fun RepositorySelected(gitManager: GitManager, repository: Repository) {
val selectedIndexCommitLog = remember { mutableStateOf(-1) } val selectedIndexCommitLog = remember { mutableStateOf(-1) }
Row { Row {
Box(
modifier = Modifier
.weight(0.15f)
.fillMaxHeight()
) {
Branches(gitManager = gitManager)
}
Box( Box(
modifier = Modifier modifier = Modifier
.weight(0.7f) .weight(0.7f)
@ -94,7 +96,7 @@ fun RepositorySelected(gitManager: GitManager, repository: Repository) {
} }
Box( Box(
modifier = Modifier modifier = Modifier
.weight(0.3f) .weight(0.15f)
.fillMaxHeight() .fillMaxHeight()
) { ) {
if (uncommitedChangesSelected) { if (uncommitedChangesSelected) {
@ -119,6 +121,8 @@ fun RepositorySelected(gitManager: GitManager, repository: Repository) {
} }
} }
@Composable @Composable
fun DiffView(gitManager: GitManager, diffEntry: DiffEntry, onCloseDiffView: () -> Unit) { fun DiffView(gitManager: GitManager, diffEntry: DiffEntry, onCloseDiffView: () -> Unit) {
val text = remember(diffEntry) { val text = remember(diffEntry) {
@ -170,108 +174,3 @@ fun prepareTreeParser(repository: Repository, commit: RevCommit): AbstractTreeIt
return treeParser 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