Added lines numbers in diff view
This commit is contained in:
parent
f20cfbb698
commit
1ed6572170
@ -2,7 +2,11 @@ package app.git.diff
|
||||
|
||||
data class Hunk(val header: String, val lines: List<Line>)
|
||||
|
||||
data class Line(val text: String, val oldLineNumber: Int, val newLineNumber: Int, val lineType: LineType)
|
||||
data class Line(val text: String, val oldLineNumber: Int, val newLineNumber: Int, val lineType: LineType) {
|
||||
// lines numbers are stored based on 0 being the first one but on a file the first line is the 1, so increment it!
|
||||
val displayOldLineNumber: Int = oldLineNumber + 1
|
||||
val displayNewLineNumber: Int = newLineNumber + 1
|
||||
}
|
||||
|
||||
enum class LineType {
|
||||
CONTEXT,
|
||||
|
@ -2,7 +2,8 @@ package app.ui
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.*
|
||||
import androidx.compose.foundation.lazy.itemsIndexed
|
||||
import androidx.compose.foundation.lazy.items
|
||||
import androidx.compose.foundation.text.selection.DisableSelection
|
||||
import androidx.compose.foundation.text.selection.SelectionContainer
|
||||
import androidx.compose.material.ButtonDefaults
|
||||
import androidx.compose.material.MaterialTheme
|
||||
@ -16,12 +17,15 @@ import androidx.compose.ui.text.font.FontFamily
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import app.git.DiffEntryType
|
||||
import app.git.diff.Hunk
|
||||
import app.git.diff.Line
|
||||
import app.git.diff.LineType
|
||||
import app.theme.primaryTextColor
|
||||
import app.ui.components.ScrollableLazyColumn
|
||||
import app.ui.components.SecondaryButton
|
||||
import app.viewmodels.DiffViewModel
|
||||
import org.eclipse.jgit.diff.DiffEntry
|
||||
import kotlin.math.max
|
||||
|
||||
@Composable
|
||||
fun Diff(
|
||||
@ -41,36 +45,7 @@ fun Diff(
|
||||
.background(MaterialTheme.colors.background)
|
||||
.fillMaxSize()
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
val filePath = if(diffEntry.newPath != "/dev/null")
|
||||
diffEntry.newPath
|
||||
else
|
||||
diffEntry.oldPath
|
||||
|
||||
Text(
|
||||
text = filePath,
|
||||
color = MaterialTheme.colors.primaryTextColor,
|
||||
fontSize = 16.sp,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
OutlinedButton(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 8.dp, horizontal = 16.dp),
|
||||
onClick = onCloseDiffView,
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
backgroundColor = MaterialTheme.colors.background,
|
||||
contentColor = MaterialTheme.colors.primary,
|
||||
)
|
||||
) {
|
||||
Text("Close diff")
|
||||
}
|
||||
}
|
||||
DiffHeader(diffEntry, onCloseDiffView)
|
||||
|
||||
val scrollState by diffViewModel.lazyListState.collectAsState()
|
||||
ScrollableLazyColumn(
|
||||
@ -78,14 +53,39 @@ fun Diff(
|
||||
.fillMaxSize(),
|
||||
state = scrollState
|
||||
) {
|
||||
itemsIndexed(hunks) { index, hunk ->
|
||||
val hunksSeparation = if (index == 0)
|
||||
0.dp
|
||||
else
|
||||
16.dp
|
||||
item { Spacer(modifier = Modifier.height(16.dp)) }
|
||||
items(hunks) { hunk ->
|
||||
HunkHeader(
|
||||
hunk = hunk,
|
||||
diffEntryType = diffEntryType,
|
||||
diffViewModel = diffViewModel,
|
||||
)
|
||||
|
||||
SelectionContainer {
|
||||
Column {
|
||||
val oldHighestLineNumber = hunk.lines.maxOf { it.displayOldLineNumber }
|
||||
val newHighestLineNumber = hunk.lines.maxOf { it.displayNewLineNumber }
|
||||
val highestLineNumber = max(oldHighestLineNumber, newHighestLineNumber)
|
||||
val highestLineNumberLength = highestLineNumber.toString().count()
|
||||
|
||||
hunk.lines.forEach { line ->
|
||||
DiffLine(highestLineNumberLength, line)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun HunkHeader(
|
||||
hunk: Hunk,
|
||||
diffEntryType: DiffEntryType,
|
||||
diffViewModel: DiffViewModel,
|
||||
) {
|
||||
Row(
|
||||
modifier = Modifier
|
||||
.padding(top = hunksSeparation)
|
||||
.background(MaterialTheme.colors.surface)
|
||||
.padding(vertical = 4.dp)
|
||||
.fillMaxWidth()
|
||||
@ -123,10 +123,44 @@ fun Diff(
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SelectionContainer {
|
||||
Column {
|
||||
hunk.lines.forEach { line ->
|
||||
@Composable
|
||||
fun DiffHeader(diffEntry: DiffEntry, onCloseDiffView: () -> Unit) {
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
verticalAlignment = Alignment.CenterVertically,
|
||||
) {
|
||||
val filePath = if(diffEntry.newPath != "/dev/null")
|
||||
diffEntry.newPath
|
||||
else
|
||||
diffEntry.oldPath
|
||||
|
||||
Text(
|
||||
text = filePath,
|
||||
color = MaterialTheme.colors.primaryTextColor,
|
||||
fontSize = 16.sp,
|
||||
modifier = Modifier.padding(horizontal = 16.dp),
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(1f))
|
||||
|
||||
OutlinedButton(
|
||||
modifier = Modifier
|
||||
.padding(vertical = 8.dp, horizontal = 16.dp),
|
||||
onClick = onCloseDiffView,
|
||||
colors = ButtonDefaults.buttonColors(
|
||||
backgroundColor = MaterialTheme.colors.background,
|
||||
contentColor = MaterialTheme.colors.primary,
|
||||
)
|
||||
) {
|
||||
Text("Close diff")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun DiffLine(highestLineNumberLength: Int, line: Line) {
|
||||
val backgroundColor = when (line.lineType) {
|
||||
LineType.ADDED -> {
|
||||
Color(0x77a9d49b)
|
||||
@ -138,12 +172,34 @@ fun Diff(
|
||||
MaterialTheme.colors.background
|
||||
}
|
||||
}
|
||||
Row (
|
||||
modifier = Modifier
|
||||
.background(backgroundColor)
|
||||
) {
|
||||
val oldLineText = if(line.lineType == LineType.REMOVED || line.lineType == LineType.CONTEXT) {
|
||||
formattedLineNumber(line.displayOldLineNumber, highestLineNumberLength)
|
||||
} else
|
||||
emptyLineNumber(highestLineNumberLength)
|
||||
|
||||
val newLineText = if(line.lineType == LineType.ADDED || line.lineType == LineType.CONTEXT) {
|
||||
formattedLineNumber(line.displayNewLineNumber, highestLineNumberLength)
|
||||
} else
|
||||
emptyLineNumber(highestLineNumberLength)
|
||||
|
||||
DisableSelection {
|
||||
LineNumber(
|
||||
text = oldLineText,
|
||||
)
|
||||
|
||||
LineNumber(
|
||||
text = newLineText
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = line.text,
|
||||
modifier = Modifier
|
||||
.background(backgroundColor)
|
||||
.padding(start = 16.dp)
|
||||
.padding(start = 8.dp)
|
||||
.fillMaxWidth(),
|
||||
color = MaterialTheme.colors.primaryTextColor,
|
||||
maxLines = 1,
|
||||
@ -152,9 +208,45 @@ fun Diff(
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@Composable
|
||||
fun LineNumber(text: String) {
|
||||
Text(
|
||||
text = text,
|
||||
color = MaterialTheme.colors.primaryTextColor,
|
||||
modifier = Modifier
|
||||
.background(MaterialTheme.colors.surface)
|
||||
.padding(horizontal = 4.dp),
|
||||
fontFamily = FontFamily.Monospace,
|
||||
fontSize = 14.sp,
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
fun formattedLineNumber(number: Int, charactersCount: Int): String {
|
||||
val numberStr = number.toString()
|
||||
return if(numberStr.count() == charactersCount)
|
||||
numberStr
|
||||
else {
|
||||
val lengthDiff = charactersCount - numberStr.count()
|
||||
val numberBuilder = StringBuilder()
|
||||
// Add whitespaces before the numbers
|
||||
repeat(lengthDiff) {
|
||||
numberBuilder.append(" ")
|
||||
}
|
||||
}
|
||||
numberBuilder.append(numberStr)
|
||||
|
||||
numberBuilder.toString()
|
||||
}
|
||||
}
|
||||
|
||||
fun emptyLineNumber(charactersCount: Int): String {
|
||||
val numberBuilder = StringBuilder()
|
||||
// Add whitespaces before the numbers
|
||||
repeat(charactersCount) {
|
||||
numberBuilder.append(" ")
|
||||
}
|
||||
|
||||
return numberBuilder.toString()
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user