Multiple blame improvements

- Clicking on a diff now minimizes the blame
- Clicking on a commit of the blame will select this commit in the log and show the commit changes.
- Unified design of Diff and Blame
This commit is contained in:
Abdelilah El Aissaoui 2022-05-27 19:50:30 +02:00
parent cb3fe17fee
commit eca68aaf07
4 changed files with 125 additions and 27 deletions

View file

@ -1,10 +1,10 @@
@file:Suppress("UNUSED_PARAMETER")
package app.ui
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
@ -18,13 +18,16 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.extensions.lineAt
import app.theme.primaryTextColor
import app.ui.components.PrimaryButton
import app.ui.components.ScrollableLazyColumn
import org.eclipse.jgit.blame.BlameResult
import org.eclipse.jgit.revwalk.RevCommit
@Composable
fun Blame(
filePath: String,
blameResult: BlameResult,
onSelectCommit: (RevCommit) -> Unit,
onClose: () -> Unit,
) {
Column {
@ -45,7 +48,11 @@ fun Blame(
verticalAlignment = Alignment.CenterVertically,
) {
Column(
modifier = Modifier.width(200.dp).fillMaxHeight().background(MaterialTheme.colors.surface),
modifier = Modifier
.width(200.dp)
.fillMaxHeight()
.background(MaterialTheme.colors.surface)
.clickable { onSelectCommit(commit) },
verticalArrangement = Arrangement.Center,
) {
Text(
@ -77,13 +84,68 @@ fun Blame(
}
}
@Composable
fun MinimizedBlame(
filePath: String,
onExpand: () -> Unit,
onClose: () -> Unit,
) {
Row(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.background(MaterialTheme.colors.surface),
verticalAlignment = Alignment.CenterVertically,
) {
Column(
modifier = Modifier
.padding(horizontal = 16.dp)
) {
Text(
text = "Minimized file blame",
color = MaterialTheme.colors.primaryTextColor,
maxLines = 1,
fontSize = 10.sp,
)
Text(
text = filePath,
color = MaterialTheme.colors.primaryTextColor,
maxLines = 1,
fontSize = 12.sp,
)
}
Spacer(modifier = Modifier.weight(1f))
PrimaryButton(
onClick = onExpand,
text = "Show",
)
IconButton(
onClick = onClose,
modifier = Modifier.padding(horizontal = 16.dp)
) {
Image(
painter = painterResource("close.svg"),
contentDescription = "Close blame",
colorFilter = ColorFilter.tint(MaterialTheme.colors.primaryTextColor),
)
}
}
}
@Composable
private fun Header(
filePath: String,
onClose: () -> Unit,
) {
Row(
modifier = Modifier.fillMaxWidth().background(MaterialTheme.colors.surface),
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.padding(start = 8.dp, end = 8.dp, top = 8.dp)
.background(MaterialTheme.colors.surface),
verticalAlignment = Alignment.CenterVertically,
) {
Text(
@ -94,12 +156,13 @@ private fun Header(
)
Spacer(modifier = Modifier.weight(1f))
IconButton(
onClick = onClose
) {
Image(
painter = painterResource("close.svg"),
contentDescription = "Close diff",
contentDescription = "Close blame",
colorFilter = ColorFilter.tint(MaterialTheme.colors.primaryTextColor),
)
}

View file

@ -54,7 +54,6 @@ fun Diff(
Column(
modifier = Modifier
.padding(8.dp)
.background(MaterialTheme.colors.background)
.fillMaxSize()
) {
@ -228,7 +227,7 @@ fun HunkHeader(
Row(
modifier = Modifier
.background(MaterialTheme.colors.surface)
.padding(vertical = 4.dp)
.padding(horizontal = 8.dp, vertical = 4.dp)
.fillMaxWidth(),
verticalAlignment = Alignment.CenterVertically
) {
@ -282,6 +281,8 @@ fun DiffHeader(
Row(
modifier = Modifier
.fillMaxWidth()
.height(50.dp)
.padding(start = 8.dp, end = 8.dp, top = 8.dp)
.background(MaterialTheme.colors.surface),
verticalAlignment = Alignment.CenterVertically,
) {
@ -351,6 +352,7 @@ fun DiffLine(highestLineNumberLength: Int, line: Line) {
}
Row(
modifier = Modifier
.padding(horizontal = 8.dp)
.background(backgroundColor)
.height(IntrinsicSize.Min)
) {

View file

@ -118,25 +118,38 @@ fun RepoContent(
shape = RoundedCornerShape(4.dp)
)
) {
if (blameState is BlameState.Loaded) {
if (blameState is BlameState.Loaded && !blameState.isMinimized) {
Blame(
filePath = blameState.filePath,
blameResult = blameState.blameResult,
onClose = { tabViewModel.resetBlameState() }
onClose = { tabViewModel.resetBlameState() },
onSelectCommit = { tabViewModel.selectCommit(it) }
)
} else {
when (diffSelected) {
null -> {
Log(
logViewModel = tabViewModel.logViewModel,
selectedItem = selectedItem,
repositoryState = repositoryState,
)
Column {
Box(modifier = Modifier.weight(1f, true)) {
when (diffSelected) {
null -> {
Log(
logViewModel = tabViewModel.logViewModel,
selectedItem = selectedItem,
repositoryState = repositoryState,
)
}
else -> {
Diff(
diffViewModel = tabViewModel.diffViewModel,
onCloseDiffView = { tabViewModel.newDiffSelected = null })
}
}
}
else -> {
Diff(
diffViewModel = tabViewModel.diffViewModel,
onCloseDiffView = { tabViewModel.newDiffSelected = null })
if (blameState is BlameState.Loaded) { // BlameState.isMinimized is true here
MinimizedBlame(
filePath = blameState.filePath,
onExpand = { tabViewModel.expandBlame() },
onClose = { tabViewModel.resetBlameState() }
)
}
}
}
@ -155,10 +168,7 @@ fun RepoContent(
selectedEntryType = diffSelected,
repositoryState = repositoryState,
onStagedDiffEntrySelected = { diffEntry ->
// TODO: Instead of resetting the state, create a new one where the blame
// is "on hold". In this state we can show a bar at the bottom so the user
// can click on it and return to the blame
tabViewModel.resetBlameState()
tabViewModel.minimizeBlame()
tabViewModel.newDiffSelected = if (diffEntry != null) {
if (repositoryState == RepositoryState.SAFE)
@ -170,7 +180,7 @@ fun RepoContent(
}
},
onUnstagedDiffEntrySelected = { diffEntry ->
tabViewModel.resetBlameState()
tabViewModel.minimizeBlame()
if (repositoryState == RepositoryState.SAFE)
tabViewModel.newDiffSelected = DiffEntryType.SafeUnstagedDiff(diffEntry)
@ -185,7 +195,7 @@ fun RepoContent(
selectedItem = safeSelectedItem,
diffSelected = diffSelected,
onDiffSelected = { diffEntry ->
tabViewModel.resetBlameState()
tabViewModel.minimizeBlame()
tabViewModel.newDiffSelected = DiffEntryType.CommitDiff(diffEntry)
},
onBlame = { tabViewModel.blameFile(it) }

View file

@ -17,6 +17,7 @@ import org.eclipse.jgit.api.Git
import org.eclipse.jgit.blame.BlameResult
import org.eclipse.jgit.lib.Repository
import org.eclipse.jgit.lib.RepositoryState
import org.eclipse.jgit.revwalk.RevCommit
import java.io.File
import javax.inject.Inject
import javax.inject.Provider
@ -340,6 +341,26 @@ class TabViewModel @Inject constructor(
fun resetBlameState() {
_blameState.value = BlameState.None
}
fun expandBlame() {
val blameState = _blameState.value
if(blameState is BlameState.Loaded && blameState.isMinimized) {
_blameState.value = blameState.copy(isMinimized = false)
}
}
fun minimizeBlame() {
val blameState = _blameState.value
if(blameState is BlameState.Loaded && !blameState.isMinimized) {
_blameState.value = blameState.copy(isMinimized = true)
}
}
fun selectCommit(commit: RevCommit) {
tabState.newSelectedItem(SelectedItem.Commit(commit))
}
}
@ -352,6 +373,8 @@ sealed class RepositorySelectionStatus {
sealed interface BlameState {
data class Loading(val filePath: String) : BlameState
data class Loaded(val filePath: String, val blameResult: BlameResult) : BlameState
data class Loaded(val filePath: String, val blameResult: BlameResult, val isMinimized: Boolean = false) : BlameState
object None : BlameState
}