Fixed text selection when using split diff

This commit is contained in:
Abdelilah El Aissaoui 2022-08-24 04:43:05 +02:00
parent 81261e42c7
commit cbcb13d730
3 changed files with 90 additions and 14 deletions

View File

@ -34,6 +34,8 @@ import app.theme.secondaryTextColor
import app.ui.components.AvatarImage
import app.ui.components.ScrollableLazyColumn
import app.ui.components.TooltipText
import app.ui.diff.HunkSplitTextDiff
import app.ui.diff.HunkUnifiedTextDiff
import app.viewmodels.HistoryState
import app.viewmodels.HistoryViewModel
import app.viewmodels.ViewDiffResult

View File

@ -9,7 +9,6 @@ import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
@ -26,6 +25,7 @@ import app.ui.components.ScrollableColumn
import app.ui.dialogs.AuthorDialog
import app.ui.dialogs.NewBranchDialog
import app.ui.dialogs.StashWithMessageDialog
import app.ui.diff.Diff
import app.ui.log.Log
import app.viewmodels.BlameState
import app.viewmodels.TabViewModel

View File

@ -1,6 +1,6 @@
@file:OptIn(ExperimentalComposeUiApi::class)
package app.ui
package app.ui.diff
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
@ -20,7 +20,9 @@ import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.ColorFilter
import androidx.compose.ui.input.key.onPreviewKeyEvent
import androidx.compose.ui.input.pointer.PointerEventType
import androidx.compose.ui.input.pointer.PointerIconDefaults
import androidx.compose.ui.input.pointer.onPointerEvent
import androidx.compose.ui.input.pointer.pointerHoverIcon
import androidx.compose.ui.res.loadImageBitmap
import androidx.compose.ui.res.painterResource
@ -306,6 +308,7 @@ fun HunkSplitTextDiff(
onResetHunk: (DiffEntry, Hunk) -> Unit,
) {
val hunks = diffResult.hunks
var selectableSide by remember { mutableStateOf(SelectableSide.BOTH) }
SelectionContainer {
ScrollableLazyColumn(
@ -332,28 +335,55 @@ fun HunkSplitTextDiff(
val highestLineNumberLength = highestLineNumber.toString().count()
items(splitHunk.lines) { linesPair ->
SplitDiffLine(highestLineNumberLength, linesPair.first, linesPair.second)
SplitDiffLine(
highestLineNumberLength = highestLineNumberLength,
oldLine = linesPair.first,
newLine = linesPair.second,
selectableSide = selectableSide,
onChangeSelectableSide = { newSelectableSide ->
if (newSelectableSide != selectableSide) {
println("newSelectableSide $newSelectableSide")
selectableSide = newSelectableSide
}
}
)
}
}
}
}
}
@Composable
fun SplitDiffLine(highestLineNumberLength: Int, first: Line?, second: Line?) {
fun DynamicSelectionDisable(isDisabled: Boolean, content: @Composable () -> Unit) {
if (isDisabled) {
DisableSelection(content)
} else
content()
}
@Composable
fun SplitDiffLine(
highestLineNumberLength: Int,
oldLine: Line?,
newLine: Line?,
selectableSide: SelectableSide,
onChangeSelectableSide: (SelectableSide) -> Unit,
) {
Row(
modifier = Modifier
.background(MaterialTheme.colors.secondarySurface)
.height(IntrinsicSize.Min)
) {
Box(
SplitDiffLineSide(
modifier = Modifier
.weight(1f)
) {
if (first != null)
SplitDiffLine(highestLineNumberLength, first, first.oldLineNumber + 1)
}
.weight(1f),
highestLineNumberLength = highestLineNumberLength,
line = oldLine,
displayLineNumber = oldLine?.displayOldLineNumber ?: 0,
currentSelectableSide = selectableSide,
lineSelectableSide = SelectableSide.OLD,
onChangeSelectableSide = onChangeSelectableSide,
)
Box(
modifier = Modifier
@ -362,13 +392,57 @@ fun SplitDiffLine(highestLineNumberLength: Int, first: Line?, second: Line?) {
.background(MaterialTheme.colors.secondarySurface)
)
Box(modifier = Modifier.weight(1f)) {
if (second != null)
SplitDiffLine(highestLineNumberLength, second, second.newLineNumber + 1)
SplitDiffLineSide(
modifier = Modifier
.weight(1f),
highestLineNumberLength = highestLineNumberLength,
line = newLine,
displayLineNumber = newLine?.displayNewLineNumber ?: 0,
currentSelectableSide = selectableSide,
lineSelectableSide = SelectableSide.NEW,
onChangeSelectableSide = onChangeSelectableSide,
)
}
}
@Composable
fun SplitDiffLineSide(
modifier: Modifier,
highestLineNumberLength: Int,
line: Line?,
displayLineNumber: Int,
currentSelectableSide: SelectableSide,
lineSelectableSide: SelectableSide,
onChangeSelectableSide: (SelectableSide) -> Unit,
) {
Box(
modifier = modifier
.onPointerEvent(PointerEventType.Press) {
onChangeSelectableSide(lineSelectableSide)
}
.onPointerEvent(PointerEventType.Release) {
onChangeSelectableSide(SelectableSide.BOTH)
}
) {
if (line != null) {
// To avoid both sides being selected, disable one side when the use is interacting with the other
DynamicSelectionDisable(
currentSelectableSide != lineSelectableSide &&
currentSelectableSide != SelectableSide.BOTH
) {
SplitDiffLine(highestLineNumberLength, line, displayLineNumber)
}
}
}
}
enum class SelectableSide {
BOTH,
OLD,
NEW;
}
@Composable
fun HunkHeader(
header: String,