Skip to content

Commit

Permalink
Replaced nested SplitPane with a custom TripleVerticalSplit
Browse files Browse the repository at this point in the history
  • Loading branch information
JetpackDuba committed Jan 9, 2024
1 parent de64d43 commit d06e746
Show file tree
Hide file tree
Showing 2 changed files with 188 additions and 142 deletions.
246 changes: 104 additions & 142 deletions src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,7 @@ import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
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.pointer.pointerHoverIcon
import androidx.compose.ui.unit.dp
import com.jetpackduba.gitnuro.AppConstants
import com.jetpackduba.gitnuro.LocalTabScope
Expand All @@ -24,6 +22,7 @@ import com.jetpackduba.gitnuro.git.rebase.RebaseInteractiveState
import com.jetpackduba.gitnuro.keybindings.KeybindingOption
import com.jetpackduba.gitnuro.keybindings.matchesBinding
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.dialogs.*
import com.jetpackduba.gitnuro.ui.diff.Diff
Expand All @@ -33,9 +32,6 @@ import com.jetpackduba.gitnuro.viewmodels.TabViewModel
import org.eclipse.jgit.lib.RepositoryState
import org.eclipse.jgit.revwalk.RevCommit
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
fun RepositoryOpenPage(
Expand Down Expand Up @@ -244,7 +240,6 @@ fun RepoContent(
}
}

@OptIn(ExperimentalSplitPaneApi::class)
@Composable
fun MainContentView(
tabViewModel: TabViewModel,
Expand All @@ -255,158 +250,125 @@ fun MainContentView(
) {
val rebaseInteractiveState by tabViewModel.rebaseInteractiveState.collectAsState()

HorizontalSplitPane(
splitPaneState = rememberSplitPaneState(initialPositionPercentage = 0.20f)
) {
val size = if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction)
1.dp
else
180.dp

first(minSize = size) {
TripleVerticalSplit(
modifier = Modifier.fillMaxSize(),
initialFirstWidth = 220f,
minFirstWidth = 150f,
initialThirdWidth = 360f,
minThirdWidth = 180f,
first = {
SidePanel()
}

splitter {
this.repositorySplitter()
}

second {
HorizontalSplitPane(
splitPaneState = rememberSplitPaneState(0.9f)
},
second = {
Box(
modifier = Modifier
.fillMaxSize()
) {
first {
Box(
modifier = Modifier
.fillMaxSize()
) {
if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction && diffSelected == null) {
RebaseInteractive()
} else if (blameState is BlameState.Loaded && !blameState.isMinimized) {
Blame(
filePath = blameState.filePath,
blameResult = blameState.blameResult,
onClose = { tabViewModel.resetBlameState() },
onSelectCommit = { tabViewModel.selectCommit(it) }
)
} else {
Column {
Box(modifier = Modifier.weight(1f, true)) {
when (diffSelected) {
null -> {
Log(
selectedItem = selectedItem,
repositoryState = repositoryState,
)
}
if (rebaseInteractiveState == RebaseInteractiveState.AwaitingInteraction && diffSelected == null) {
RebaseInteractive()
} else if (blameState is BlameState.Loaded && !blameState.isMinimized) {
Blame(
filePath = blameState.filePath,
blameResult = blameState.blameResult,
onClose = { tabViewModel.resetBlameState() },
onSelectCommit = { tabViewModel.selectCommit(it) }
)
} else {
Column {
Box(modifier = Modifier.weight(1f, true)) {
when (diffSelected) {
null -> {
Log(
selectedItem = selectedItem,
repositoryState = repositoryState,
)
}

else -> {
val diffViewModel = tabViewModel.diffViewModel
else -> {
val diffViewModel = tabViewModel.diffViewModel

if (diffViewModel != null) {
Diff(
diffViewModel = diffViewModel,
onCloseDiffView = {
tabViewModel.newDiffSelected = null
}
)
if (diffViewModel != null) {
Diff(
diffViewModel = 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() }
)
}
}
}
}
}

splitter {
this.repositorySplitter()
if (blameState is BlameState.Loaded) { // BlameState.isMinimized is true here
MinimizedBlame(
filePath = blameState.filePath,
onExpand = { tabViewModel.expandBlame() },
onClose = { tabViewModel.resetBlameState() }
)
}
}
}
}
},
third = {
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) }
)
}

second(minSize = 250.dp) {
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 -> {}
}
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 = {

fun SplitterScope.repositorySplitter() {
visiblePart {
Box(
Modifier
.width(8.dp)
.fillMaxHeight()
.background(Color.Transparent)
)
}
handle {
Box(
Modifier
.markAsHandle()
.pointerHoverIcon(resizePointerIconEast)
.background(Color.Transparent)
.width(8.dp)
.fillMaxHeight()
)
}
},
onThirdSizeChanged = {

},
)
}

sealed interface SelectedItem {
Expand Down
Original file line number Diff line number Diff line change
@@ -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()
}
}
}

0 comments on commit d06e746

Please sign in to comment.