Fixed text selection when using split diff
This commit is contained in:
parent
81261e42c7
commit
cbcb13d730
@ -34,6 +34,8 @@ import app.theme.secondaryTextColor
|
|||||||
import app.ui.components.AvatarImage
|
import app.ui.components.AvatarImage
|
||||||
import app.ui.components.ScrollableLazyColumn
|
import app.ui.components.ScrollableLazyColumn
|
||||||
import app.ui.components.TooltipText
|
import app.ui.components.TooltipText
|
||||||
|
import app.ui.diff.HunkSplitTextDiff
|
||||||
|
import app.ui.diff.HunkUnifiedTextDiff
|
||||||
import app.viewmodels.HistoryState
|
import app.viewmodels.HistoryState
|
||||||
import app.viewmodels.HistoryViewModel
|
import app.viewmodels.HistoryViewModel
|
||||||
import app.viewmodels.ViewDiffResult
|
import app.viewmodels.ViewDiffResult
|
||||||
|
@ -9,7 +9,6 @@ import androidx.compose.material.MaterialTheme
|
|||||||
import androidx.compose.material.Text
|
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.ExperimentalComposeUiApi
|
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.focus.FocusRequester
|
import androidx.compose.ui.focus.FocusRequester
|
||||||
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.AuthorDialog
|
||||||
import app.ui.dialogs.NewBranchDialog
|
import app.ui.dialogs.NewBranchDialog
|
||||||
import app.ui.dialogs.StashWithMessageDialog
|
import app.ui.dialogs.StashWithMessageDialog
|
||||||
|
import app.ui.diff.Diff
|
||||||
import app.ui.log.Log
|
import app.ui.log.Log
|
||||||
import app.viewmodels.BlameState
|
import app.viewmodels.BlameState
|
||||||
import app.viewmodels.TabViewModel
|
import app.viewmodels.TabViewModel
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
@file:OptIn(ExperimentalComposeUiApi::class)
|
@file:OptIn(ExperimentalComposeUiApi::class)
|
||||||
|
|
||||||
package app.ui
|
package app.ui.diff
|
||||||
|
|
||||||
import androidx.compose.foundation.Image
|
import androidx.compose.foundation.Image
|
||||||
import androidx.compose.foundation.background
|
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.Color
|
||||||
import androidx.compose.ui.graphics.ColorFilter
|
import androidx.compose.ui.graphics.ColorFilter
|
||||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
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.PointerIconDefaults
|
||||||
|
import androidx.compose.ui.input.pointer.onPointerEvent
|
||||||
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
||||||
import androidx.compose.ui.res.loadImageBitmap
|
import androidx.compose.ui.res.loadImageBitmap
|
||||||
import androidx.compose.ui.res.painterResource
|
import androidx.compose.ui.res.painterResource
|
||||||
@ -306,6 +308,7 @@ fun HunkSplitTextDiff(
|
|||||||
onResetHunk: (DiffEntry, Hunk) -> Unit,
|
onResetHunk: (DiffEntry, Hunk) -> Unit,
|
||||||
) {
|
) {
|
||||||
val hunks = diffResult.hunks
|
val hunks = diffResult.hunks
|
||||||
|
var selectableSide by remember { mutableStateOf(SelectableSide.BOTH) }
|
||||||
|
|
||||||
SelectionContainer {
|
SelectionContainer {
|
||||||
ScrollableLazyColumn(
|
ScrollableLazyColumn(
|
||||||
@ -332,28 +335,55 @@ fun HunkSplitTextDiff(
|
|||||||
val highestLineNumberLength = highestLineNumber.toString().count()
|
val highestLineNumberLength = highestLineNumber.toString().count()
|
||||||
|
|
||||||
items(splitHunk.lines) { linesPair ->
|
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
|
@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(
|
Row(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.background(MaterialTheme.colors.secondarySurface)
|
.background(MaterialTheme.colors.secondarySurface)
|
||||||
.height(IntrinsicSize.Min)
|
.height(IntrinsicSize.Min)
|
||||||
) {
|
) {
|
||||||
Box(
|
SplitDiffLineSide(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
.weight(1f)
|
.weight(1f),
|
||||||
) {
|
highestLineNumberLength = highestLineNumberLength,
|
||||||
if (first != null)
|
line = oldLine,
|
||||||
SplitDiffLine(highestLineNumberLength, first, first.oldLineNumber + 1)
|
displayLineNumber = oldLine?.displayOldLineNumber ?: 0,
|
||||||
}
|
currentSelectableSide = selectableSide,
|
||||||
|
lineSelectableSide = SelectableSide.OLD,
|
||||||
|
onChangeSelectableSide = onChangeSelectableSide,
|
||||||
|
)
|
||||||
|
|
||||||
Box(
|
Box(
|
||||||
modifier = Modifier
|
modifier = Modifier
|
||||||
@ -362,13 +392,57 @@ fun SplitDiffLine(highestLineNumberLength: Int, first: Line?, second: Line?) {
|
|||||||
.background(MaterialTheme.colors.secondarySurface)
|
.background(MaterialTheme.colors.secondarySurface)
|
||||||
)
|
)
|
||||||
|
|
||||||
Box(modifier = Modifier.weight(1f)) {
|
SplitDiffLineSide(
|
||||||
if (second != null)
|
modifier = Modifier
|
||||||
SplitDiffLine(highestLineNumberLength, second, second.newLineNumber + 1)
|
.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
|
@Composable
|
||||||
fun HunkHeader(
|
fun HunkHeader(
|
||||||
header: String,
|
header: String,
|
||||||
|
Loading…
Reference in New Issue
Block a user