diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt index 76c8eec..c7ef41d 100644 --- a/src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt @@ -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 @@ -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 @@ -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( @@ -244,7 +240,6 @@ fun RepoContent( } } -@OptIn(ExperimentalSplitPaneApi::class) @Composable fun MainContentView( tabViewModel: TabViewModel, @@ -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, - ) - } - - else -> { - val diffViewModel = tabViewModel.diffViewModel - - if (diffViewModel != null) { - Diff( - diffViewModel = diffViewModel, - onCloseDiffView = { - tabViewModel.newDiffSelected = null - } - ) - } - } - } + 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 (blameState is BlameState.Loaded) { // BlameState.isMinimized is true here - MinimizedBlame( - filePath = blameState.filePath, - onExpand = { tabViewModel.expandBlame() }, - onClose = { tabViewModel.resetBlameState() } - ) + else -> { + val diffViewModel = tabViewModel.diffViewModel + + if (diffViewModel != null) { + Diff( + diffViewModel = diffViewModel, + onCloseDiffView = { + tabViewModel.newDiffSelected = null + } + ) + } } } } - } - } - splitter { - this.repositorySplitter() - } - - 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 -> {} + 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() -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() - ) - } + 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 -> {} + } + } + }, + onFirstSizeChanged = { + + }, + onThirdSizeChanged = { + + }, + ) } sealed interface SelectedItem { diff --git a/src/main/kotlin/com/jetpackduba/gitnuro/ui/components/TripleVerticalSplit.kt b/src/main/kotlin/com/jetpackduba/gitnuro/ui/components/TripleVerticalSplit.kt new file mode 100644 index 0000000..e96b030 --- /dev/null +++ b/src/main/kotlin/com/jetpackduba/gitnuro/ui/components/TripleVerticalSplit.kt @@ -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() + } + } +} \ No newline at end of file