Replaced nested SplitPane with a custom TripleVerticalSplit
This commit is contained in:
parent
de64d43c15
commit
d06e746c6c
@ -12,9 +12,7 @@ import androidx.compose.ui.Alignment
|
|||||||
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
|
||||||
import androidx.compose.ui.graphics.Color
|
|
||||||
import androidx.compose.ui.input.key.onKeyEvent
|
import androidx.compose.ui.input.key.onKeyEvent
|
||||||
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
|
||||||
import androidx.compose.ui.unit.dp
|
import androidx.compose.ui.unit.dp
|
||||||
import com.jetpackduba.gitnuro.AppConstants
|
import com.jetpackduba.gitnuro.AppConstants
|
||||||
import com.jetpackduba.gitnuro.LocalTabScope
|
import com.jetpackduba.gitnuro.LocalTabScope
|
||||||
@ -24,6 +22,7 @@ import com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState
|
|||||||
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
|
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
|
||||||
import com.jetpackduba.gitnuro.keybindings.matchesBinding
|
import com.jetpackduba.gitnuro.keybindings.matchesBinding
|
||||||
import com.jetpackduba.gitnuro.ui.components.SecondaryButton
|
import com.jetpackduba.gitnuro.ui.components.SecondaryButton
|
||||||
|
import com.jetpackduba.gitnuro.ui.components.TripleVerticalSplit
|
||||||
import com.jetpackduba.gitnuro.ui.components.gitnuroDynamicViewModel
|
import com.jetpackduba.gitnuro.ui.components.gitnuroDynamicViewModel
|
||||||
import com.jetpackduba.gitnuro.ui.dialogs.*
|
import com.jetpackduba.gitnuro.ui.dialogs.*
|
||||||
import com.jetpackduba.gitnuro.ui.diff.Diff
|
import com.jetpackduba.gitnuro.ui.diff.Diff
|
||||||
@ -33,9 +32,6 @@ import com.jetpackduba.gitnuro.viewmodels.TabViewModel
|
|||||||
import org.eclipse.jgit.lib.RepositoryState
|
import org.eclipse.jgit.lib.RepositoryState
|
||||||
import org.eclipse.jgit.revwalk.RevCommit
|
import org.eclipse.jgit.revwalk.RevCommit
|
||||||
import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi
|
import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi
|
||||||
import org.jetbrains.compose.splitpane.HorizontalSplitPane
|
|
||||||
import org.jetbrains.compose.splitpane.SplitterScope
|
|
||||||
import org.jetbrains.compose.splitpane.rememberSplitPaneState
|
|
||||||
|
|
||||||
@Composable
|
@Composable
|
||||||
fun RepositoryOpenPage(
|
fun RepositoryOpenPage(
|
||||||
@ -244,7 +240,6 @@ fun RepoContent(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ExperimentalSplitPaneApi::class)
|
|
||||||
@Composable
|
@Composable
|
||||||
fun MainContentView(
|
fun MainContentView(
|
||||||
tabViewModel: TabViewModel,
|
tabViewModel: TabViewModel,
|
||||||
@ -255,158 +250,125 @@ fun MainContentView(
|
|||||||
) {
|
) {
|
||||||
val rebaseInteractiveState by tabViewModel.rebaseInteractiveState.collectAsState()
|
val rebaseInteractiveState by tabViewModel.rebaseInteractiveState.collectAsState()
|
||||||
|
|
||||||
HorizontalSplitPane(
|
TripleVerticalSplit(
|
||||||
splitPaneState = rememberSplitPaneState(initialPositionPercentage = 0.20f)
|
modifier = Modifier.fillMaxSize(),
|
||||||
) {
|
initialFirstWidth = 220f,
|
||||||
val size = if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction)
|
minFirstWidth = 150f,
|
||||||
1.dp
|
initialThirdWidth = 360f,
|
||||||
else
|
minThirdWidth = 180f,
|
||||||
180.dp
|
first = {
|
||||||
|
|
||||||
first(minSize = size) {
|
|
||||||
SidePanel()
|
SidePanel()
|
||||||
}
|
},
|
||||||
|
second = {
|
||||||
splitter {
|
Box(
|
||||||
this.repositorySplitter()
|
modifier = Modifier
|
||||||
}
|
.fillMaxSize()
|
||||||
|
|
||||||
second {
|
|
||||||
HorizontalSplitPane(
|
|
||||||
splitPaneState = rememberSplitPaneState(0.9f)
|
|
||||||
) {
|
) {
|
||||||
first {
|
if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction && diffSelected == null) {
|
||||||
Box(
|
RebaseInteractive()
|
||||||
modifier = Modifier
|
} else if (blameState is BlameState.Loaded && !blameState.isMinimized) {
|
||||||
.fillMaxSize()
|
Blame(
|
||||||
) {
|
filePath = blameState.filePath,
|
||||||
if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction && diffSelected == null) {
|
blameResult = blameState.blameResult,
|
||||||
RebaseInteractive()
|
onClose = { tabViewModel.resetBlameState() },
|
||||||
} else if (blameState is BlameState.Loaded && !blameState.isMinimized) {
|
onSelectCommit = { tabViewModel.selectCommit(it) }
|
||||||
Blame(
|
)
|
||||||
filePath = blameState.filePath,
|
} else {
|
||||||
blameResult = blameState.blameResult,
|
Column {
|
||||||
onClose = { tabViewModel.resetBlameState() },
|
Box(modifier = Modifier.weight(1f, true)) {
|
||||||
onSelectCommit = { tabViewModel.selectCommit(it) }
|
when (diffSelected) {
|
||||||
)
|
null -> {
|
||||||
} else {
|
Log(
|
||||||
Column {
|
selectedItem = selectedItem,
|
||||||
Box(modifier = Modifier.weight(1f, true)) {
|
repositoryState = repositoryState,
|
||||||
when (diffSelected) {
|
)
|
||||||
null -> {
|
|
||||||
Log(
|
|
||||||
selectedItem = selectedItem,
|
|
||||||
repositoryState = repositoryState,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
val diffViewModel = tabViewModel.diffViewModel
|
|
||||||
|
|
||||||
if (diffViewModel != null) {
|
|
||||||
Diff(
|
|
||||||
diffViewModel = diffViewModel,
|
|
||||||
onCloseDiffView = {
|
|
||||||
tabViewModel.newDiffSelected = null
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (blameState is BlameState.Loaded) { // BlameState.isMinimized is true here
|
else -> {
|
||||||
MinimizedBlame(
|
val diffViewModel = tabViewModel.diffViewModel
|
||||||
filePath = blameState.filePath,
|
|
||||||
onExpand = { tabViewModel.expandBlame() },
|
if (diffViewModel != null) {
|
||||||
onClose = { tabViewModel.resetBlameState() }
|
Diff(
|
||||||
)
|
diffViewModel = diffViewModel,
|
||||||
|
onCloseDiffView = {
|
||||||
|
tabViewModel.newDiffSelected = null
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
splitter {
|
if (blameState is BlameState.Loaded) { // BlameState.isMinimized is true here
|
||||||
this.repositorySplitter()
|
MinimizedBlame(
|
||||||
}
|
filePath = blameState.filePath,
|
||||||
|
onExpand = { tabViewModel.expandBlame() },
|
||||||
second(minSize = 250.dp) {
|
onClose = { tabViewModel.resetBlameState() }
|
||||||
Box(
|
)
|
||||||
modifier = Modifier
|
|
||||||
.fillMaxHeight()
|
|
||||||
) {
|
|
||||||
when (selectedItem) {
|
|
||||||
SelectedItem.UncommittedChanges -> {
|
|
||||||
UncommittedChanges(
|
|
||||||
selectedEntryType = diffSelected,
|
|
||||||
repositoryState = repositoryState,
|
|
||||||
onStagedDiffEntrySelected = { diffEntry ->
|
|
||||||
tabViewModel.minimizeBlame()
|
|
||||||
|
|
||||||
tabViewModel.newDiffSelected = if (diffEntry != null) {
|
|
||||||
if (repositoryState == RepositoryState.SAFE)
|
|
||||||
DiffEntryType.SafeStagedDiff(diffEntry)
|
|
||||||
else
|
|
||||||
DiffEntryType.UnsafeStagedDiff(diffEntry)
|
|
||||||
} else {
|
|
||||||
null
|
|
||||||
}
|
|
||||||
},
|
|
||||||
onUnstagedDiffEntrySelected = { diffEntry ->
|
|
||||||
tabViewModel.minimizeBlame()
|
|
||||||
|
|
||||||
if (repositoryState == RepositoryState.SAFE)
|
|
||||||
tabViewModel.newDiffSelected = DiffEntryType.SafeUnstagedDiff(diffEntry)
|
|
||||||
else
|
|
||||||
tabViewModel.newDiffSelected = DiffEntryType.UnsafeUnstagedDiff(diffEntry)
|
|
||||||
},
|
|
||||||
onBlameFile = { tabViewModel.blameFile(it) },
|
|
||||||
onHistoryFile = { tabViewModel.fileHistory(it) }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
is SelectedItem.CommitBasedItem -> {
|
|
||||||
CommitChanges(
|
|
||||||
selectedItem = selectedItem,
|
|
||||||
diffSelected = diffSelected,
|
|
||||||
onDiffSelected = { diffEntry ->
|
|
||||||
tabViewModel.minimizeBlame()
|
|
||||||
tabViewModel.newDiffSelected = DiffEntryType.CommitDiff(diffEntry)
|
|
||||||
},
|
|
||||||
onBlame = { tabViewModel.blameFile(it) },
|
|
||||||
onHistory = { tabViewModel.fileHistory(it) },
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
SelectedItem.None -> {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
third = {
|
||||||
}
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
) {
|
||||||
|
when (selectedItem) {
|
||||||
|
SelectedItem.UncommittedChanges -> {
|
||||||
|
UncommittedChanges(
|
||||||
|
selectedEntryType = diffSelected,
|
||||||
|
repositoryState = repositoryState,
|
||||||
|
onStagedDiffEntrySelected = { diffEntry ->
|
||||||
|
tabViewModel.minimizeBlame()
|
||||||
|
|
||||||
fun SplitterScope.repositorySplitter() {
|
tabViewModel.newDiffSelected = if (diffEntry != null) {
|
||||||
visiblePart {
|
if (repositoryState == RepositoryState.SAFE)
|
||||||
Box(
|
DiffEntryType.SafeStagedDiff(diffEntry)
|
||||||
Modifier
|
else
|
||||||
.width(8.dp)
|
DiffEntryType.UnsafeStagedDiff(diffEntry)
|
||||||
.fillMaxHeight()
|
} else {
|
||||||
.background(Color.Transparent)
|
null
|
||||||
)
|
}
|
||||||
}
|
},
|
||||||
handle {
|
onUnstagedDiffEntrySelected = { diffEntry ->
|
||||||
Box(
|
tabViewModel.minimizeBlame()
|
||||||
Modifier
|
|
||||||
.markAsHandle()
|
if (repositoryState == RepositoryState.SAFE)
|
||||||
.pointerHoverIcon(resizePointerIconEast)
|
tabViewModel.newDiffSelected = DiffEntryType.SafeUnstagedDiff(diffEntry)
|
||||||
.background(Color.Transparent)
|
else
|
||||||
.width(8.dp)
|
tabViewModel.newDiffSelected = DiffEntryType.UnsafeUnstagedDiff(diffEntry)
|
||||||
.fillMaxHeight()
|
},
|
||||||
)
|
onBlameFile = { tabViewModel.blameFile(it) },
|
||||||
}
|
onHistoryFile = { tabViewModel.fileHistory(it) }
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
is SelectedItem.CommitBasedItem -> {
|
||||||
|
CommitChanges(
|
||||||
|
selectedItem = selectedItem,
|
||||||
|
diffSelected = diffSelected,
|
||||||
|
onDiffSelected = { diffEntry ->
|
||||||
|
tabViewModel.minimizeBlame()
|
||||||
|
tabViewModel.newDiffSelected = DiffEntryType.CommitDiff(diffEntry)
|
||||||
|
},
|
||||||
|
onBlame = { tabViewModel.blameFile(it) },
|
||||||
|
onHistory = { tabViewModel.fileHistory(it) },
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
SelectedItem.None -> {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFirstSizeChanged = {
|
||||||
|
|
||||||
|
},
|
||||||
|
onThirdSizeChanged = {
|
||||||
|
|
||||||
|
},
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
sealed interface SelectedItem {
|
sealed interface SelectedItem {
|
||||||
|
@ -0,0 +1,84 @@
|
|||||||
|
package com.jetpackduba.gitnuro.ui.components
|
||||||
|
|
||||||
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
|
import androidx.compose.foundation.gestures.draggable
|
||||||
|
import androidx.compose.foundation.gestures.rememberDraggableState
|
||||||
|
import androidx.compose.foundation.layout.Box
|
||||||
|
import androidx.compose.foundation.layout.Row
|
||||||
|
import androidx.compose.foundation.layout.fillMaxHeight
|
||||||
|
import androidx.compose.foundation.layout.width
|
||||||
|
import androidx.compose.runtime.*
|
||||||
|
import androidx.compose.ui.Modifier
|
||||||
|
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
||||||
|
import androidx.compose.ui.platform.LocalDensity
|
||||||
|
import androidx.compose.ui.unit.dp
|
||||||
|
import com.jetpackduba.gitnuro.ui.resizePointerIconEast
|
||||||
|
|
||||||
|
@Composable
|
||||||
|
fun TripleVerticalSplit(
|
||||||
|
modifier: Modifier = Modifier,
|
||||||
|
first: @Composable () -> Unit,
|
||||||
|
second: @Composable () -> Unit,
|
||||||
|
third: @Composable () -> Unit,
|
||||||
|
initialFirstWidth: Float,
|
||||||
|
minFirstWidth: Float,
|
||||||
|
initialThirdWidth: Float,
|
||||||
|
minThirdWidth: Float,
|
||||||
|
onFirstSizeChanged: (Float) -> Unit,
|
||||||
|
onThirdSizeChanged: (Float) -> Unit,
|
||||||
|
) {
|
||||||
|
val density = LocalDensity.current.density
|
||||||
|
var firstWidth by remember { mutableStateOf(initialFirstWidth) }
|
||||||
|
var thirdWidth by remember { mutableStateOf(initialThirdWidth) }
|
||||||
|
|
||||||
|
Row(
|
||||||
|
modifier = modifier
|
||||||
|
) {
|
||||||
|
Box(modifier = Modifier.width((firstWidth).dp)) {
|
||||||
|
first()
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
.width(8.dp)
|
||||||
|
.draggable(
|
||||||
|
state = rememberDraggableState {
|
||||||
|
val newWidth = firstWidth + it / density
|
||||||
|
|
||||||
|
if (newWidth > minFirstWidth) {
|
||||||
|
firstWidth = newWidth
|
||||||
|
onFirstSizeChanged(firstWidth)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
orientation = Orientation.Horizontal
|
||||||
|
)
|
||||||
|
.pointerHoverIcon(resizePointerIconEast)
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(Modifier.weight(1f, true)) {
|
||||||
|
second()
|
||||||
|
}
|
||||||
|
|
||||||
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.fillMaxHeight()
|
||||||
|
.width(8.dp)
|
||||||
|
.draggable(
|
||||||
|
rememberDraggableState {
|
||||||
|
val newWidth = thirdWidth - it / density
|
||||||
|
|
||||||
|
if(newWidth > minThirdWidth) {
|
||||||
|
thirdWidth = newWidth
|
||||||
|
onThirdSizeChanged(thirdWidth)
|
||||||
|
}
|
||||||
|
}, Orientation.Horizontal
|
||||||
|
)
|
||||||
|
.pointerHoverIcon(resizePointerIconEast)
|
||||||
|
)
|
||||||
|
|
||||||
|
Box(modifier = Modifier.width(thirdWidth.dp)) {
|
||||||
|
third()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user