Width of triple vertical split pane columns is now persisted
Fixes #176
This commit is contained in:
parent
b9db9a8d57
commit
f5ee173453
@ -13,6 +13,7 @@ import com.jetpackduba.gitnuro.managers.TempFilesManager
|
|||||||
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
|
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
|
||||||
import com.jetpackduba.gitnuro.terminal.ITerminalProvider
|
import com.jetpackduba.gitnuro.terminal.ITerminalProvider
|
||||||
import com.jetpackduba.gitnuro.ui.TabsManager
|
import com.jetpackduba.gitnuro.ui.TabsManager
|
||||||
|
import com.jetpackduba.gitnuro.ui.VerticalSplitPaneConfig
|
||||||
import com.jetpackduba.gitnuro.updates.UpdatesRepository
|
import com.jetpackduba.gitnuro.updates.UpdatesRepository
|
||||||
import com.jetpackduba.gitnuro.viewmodels.SettingsViewModel
|
import com.jetpackduba.gitnuro.viewmodels.SettingsViewModel
|
||||||
import dagger.Component
|
import dagger.Component
|
||||||
@ -34,6 +35,8 @@ interface AppComponent {
|
|||||||
|
|
||||||
fun appPreferences(): AppSettingsRepository
|
fun appPreferences(): AppSettingsRepository
|
||||||
|
|
||||||
|
fun verticalSplitPaneConfig(): VerticalSplitPaneConfig
|
||||||
|
|
||||||
fun appEnvInfo(): AppEnvInfo
|
fun appEnvInfo(): AppEnvInfo
|
||||||
|
|
||||||
fun tabsManager(): TabsManager
|
fun tabsManager(): TabsManager
|
||||||
|
@ -43,6 +43,8 @@ private const val PREF_PROXY_USE_AUTH = "proxyUseAuth"
|
|||||||
private const val PREF_PROXY_USER = "proxyHostUser"
|
private const val PREF_PROXY_USER = "proxyHostUser"
|
||||||
private const val PREF_PROXY_PASSWORD = "proxyHostPassword"
|
private const val PREF_PROXY_PASSWORD = "proxyHostPassword"
|
||||||
private const val PREF_CACHE_CREDENTIALS_IN_MEMORY = "credentialsInMemory"
|
private const val PREF_CACHE_CREDENTIALS_IN_MEMORY = "credentialsInMemory"
|
||||||
|
private const val PREF_FIRST_PANE_WIDTH = "firstPaneWidth"
|
||||||
|
private const val PREF_THIRD_PANE_WIDTH = "thirdPaneWidth"
|
||||||
|
|
||||||
|
|
||||||
private const val PREF_GIT_FF_MERGE = "gitFFMerge"
|
private const val PREF_GIT_FF_MERGE = "gitFFMerge"
|
||||||
@ -57,6 +59,8 @@ private const val DEFAULT_SWAP_UNCOMMITTED_CHANGES = false
|
|||||||
private const val DEFAULT_SHOW_CHANGES_AS_TREE = false
|
private const val DEFAULT_SHOW_CHANGES_AS_TREE = false
|
||||||
private const val DEFAULT_CACHE_CREDENTIALS_IN_MEMORY = true
|
private const val DEFAULT_CACHE_CREDENTIALS_IN_MEMORY = true
|
||||||
private const val DEFAULT_VERIFY_SSL = true
|
private const val DEFAULT_VERIFY_SSL = true
|
||||||
|
private const val DEFAULT_FIRST_PANE_WIDTH = 220f
|
||||||
|
private const val DEFAULT_THIRD_PANE_WIDTH = 330f
|
||||||
const val DEFAULT_UI_SCALE = -1f
|
const val DEFAULT_UI_SCALE = -1f
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@ -209,6 +213,22 @@ class AppSettingsRepository @Inject constructor() {
|
|||||||
_cacheCredentialsInMemoryFlow.value = value
|
_cacheCredentialsInMemoryFlow.value = value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var firstPaneWidth: Float
|
||||||
|
get() {
|
||||||
|
return preferences.getFloat(PREF_FIRST_PANE_WIDTH, DEFAULT_FIRST_PANE_WIDTH)
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
preferences.putFloat(PREF_FIRST_PANE_WIDTH, value)
|
||||||
|
}
|
||||||
|
|
||||||
|
var thirdPaneWidth: Float
|
||||||
|
get() {
|
||||||
|
return preferences.getFloat(PREF_THIRD_PANE_WIDTH, DEFAULT_THIRD_PANE_WIDTH)
|
||||||
|
}
|
||||||
|
set(value) {
|
||||||
|
preferences.putFloat(PREF_THIRD_PANE_WIDTH, value)
|
||||||
|
}
|
||||||
|
|
||||||
var verifySsl: Boolean
|
var verifySsl: Boolean
|
||||||
get() {
|
get() {
|
||||||
return preferences.getBoolean(PREF_VERIFY_SSL, DEFAULT_VERIFY_SSL)
|
return preferences.getBoolean(PREF_VERIFY_SSL, DEFAULT_VERIFY_SSL)
|
||||||
|
@ -30,6 +30,8 @@ import com.jetpackduba.gitnuro.ui.log.Log
|
|||||||
import com.jetpackduba.gitnuro.updates.Update
|
import com.jetpackduba.gitnuro.updates.Update
|
||||||
import com.jetpackduba.gitnuro.viewmodels.BlameState
|
import com.jetpackduba.gitnuro.viewmodels.BlameState
|
||||||
import com.jetpackduba.gitnuro.viewmodels.TabViewModel
|
import com.jetpackduba.gitnuro.viewmodels.TabViewModel
|
||||||
|
import kotlinx.coroutines.flow.collectLatest
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
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
|
||||||
@ -264,9 +266,19 @@ fun MainContentView(
|
|||||||
) {
|
) {
|
||||||
val rebaseInteractiveState by tabViewModel.rebaseInteractiveState.collectAsState()
|
val rebaseInteractiveState by tabViewModel.rebaseInteractiveState.collectAsState()
|
||||||
val density = LocalDensity.current.density
|
val density = LocalDensity.current.density
|
||||||
|
val scope = rememberCoroutineScope()
|
||||||
|
|
||||||
var firstWidth by remember(tabViewModel) { mutableStateOf(tabViewModel.firstPaneWidth) }
|
// We create 2 mutableStates here because using directly the flow makes compose lose some drag events for some reason
|
||||||
var thirdWidth by remember(tabViewModel) { mutableStateOf(tabViewModel.thirdPaneWidth) }
|
var firstWidth by remember(tabViewModel) { mutableStateOf(tabViewModel.firstPaneWidth.value) }
|
||||||
|
var thirdWidth by remember(tabViewModel) { mutableStateOf(tabViewModel.thirdPaneWidth.value) }
|
||||||
|
|
||||||
|
LaunchedEffect(Unit) {
|
||||||
|
// Update the pane widths if they have been changed in a different tab
|
||||||
|
tabViewModel.onPanelsWidthPersisted.collectLatest {
|
||||||
|
firstWidth = tabViewModel.firstPaneWidth.value
|
||||||
|
thirdWidth = tabViewModel.thirdPaneWidth.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TripleVerticalSplitPanel(
|
TripleVerticalSplitPanel(
|
||||||
modifier = Modifier.fillMaxSize(),
|
modifier = Modifier.fillMaxSize(),
|
||||||
@ -391,7 +403,12 @@ fun MainContentView(
|
|||||||
|
|
||||||
if (newWidth > 150 && rebaseInteractiveState !is RebaseInteractiveState.AwaitingInteraction) {
|
if (newWidth > 150 && rebaseInteractiveState !is RebaseInteractiveState.AwaitingInteraction) {
|
||||||
firstWidth = newWidth
|
firstWidth = newWidth
|
||||||
tabViewModel.firstPaneWidth = firstWidth
|
tabViewModel.setFirstPaneWidth(newWidth)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onFirstSizeDragStopped = {
|
||||||
|
scope.launch {
|
||||||
|
tabViewModel.persistFirstPaneWidth()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onThirdSizeDrag = {
|
onThirdSizeDrag = {
|
||||||
@ -399,7 +416,12 @@ fun MainContentView(
|
|||||||
|
|
||||||
if (newWidth > 150) {
|
if (newWidth > 150) {
|
||||||
thirdWidth = newWidth
|
thirdWidth = newWidth
|
||||||
tabViewModel.thirdPaneWidth = thirdWidth
|
tabViewModel.setThirdPaneWidth(newWidth)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onThirdSizeDragStopped = {
|
||||||
|
scope.launch {
|
||||||
|
tabViewModel.persistThirdPaneWidth()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -0,0 +1,51 @@
|
|||||||
|
package com.jetpackduba.gitnuro.ui
|
||||||
|
|
||||||
|
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
|
||||||
|
import kotlinx.coroutines.flow.MutableSharedFlow
|
||||||
|
import kotlinx.coroutines.flow.MutableStateFlow
|
||||||
|
import kotlinx.coroutines.flow.SharedFlow
|
||||||
|
import kotlinx.coroutines.flow.StateFlow
|
||||||
|
import javax.inject.Inject
|
||||||
|
import javax.inject.Singleton
|
||||||
|
|
||||||
|
interface IVerticalSplitPaneConfig {
|
||||||
|
val firstPaneWidth: StateFlow<Float>
|
||||||
|
val onPanelsWidthPersisted: SharedFlow<Unit>
|
||||||
|
val thirdPaneWidth: StateFlow<Float>
|
||||||
|
fun setFirstPaneWidth(firstPaneWidth: Float)
|
||||||
|
fun setThirdPaneWidth(thirdPaneWidth: Float)
|
||||||
|
suspend fun persistFirstPaneWidth()
|
||||||
|
suspend fun persistThirdPaneWidth()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
class VerticalSplitPaneConfig @Inject constructor(
|
||||||
|
private val appSettingsRepository: AppSettingsRepository,
|
||||||
|
) : IVerticalSplitPaneConfig {
|
||||||
|
private val _firstPaneWidth = MutableStateFlow<Float>(appSettingsRepository.firstPaneWidth)
|
||||||
|
override val firstPaneWidth: StateFlow<Float> = _firstPaneWidth
|
||||||
|
|
||||||
|
private val _thirdPaneWidth = MutableStateFlow<Float>(appSettingsRepository.thirdPaneWidth)
|
||||||
|
override val thirdPaneWidth: StateFlow<Float> = _thirdPaneWidth
|
||||||
|
|
||||||
|
private val _onPanelsWidthPersisted = MutableSharedFlow<Unit>()
|
||||||
|
override val onPanelsWidthPersisted: SharedFlow<Unit> = _onPanelsWidthPersisted
|
||||||
|
|
||||||
|
override fun setFirstPaneWidth(firstPaneWidth: Float) {
|
||||||
|
this._firstPaneWidth.value = firstPaneWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setThirdPaneWidth(thirdPaneWidth: Float) {
|
||||||
|
this._thirdPaneWidth.value = thirdPaneWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun persistFirstPaneWidth() {
|
||||||
|
appSettingsRepository.firstPaneWidth = _firstPaneWidth.value
|
||||||
|
_onPanelsWidthPersisted.emit(Unit)
|
||||||
|
}
|
||||||
|
|
||||||
|
override suspend fun persistThirdPaneWidth() {
|
||||||
|
appSettingsRepository.thirdPaneWidth = _thirdPaneWidth.value
|
||||||
|
_onPanelsWidthPersisted.emit(Unit)
|
||||||
|
}
|
||||||
|
}
|
@ -3,10 +3,7 @@ package com.jetpackduba.gitnuro.ui.components
|
|||||||
import androidx.compose.foundation.gestures.Orientation
|
import androidx.compose.foundation.gestures.Orientation
|
||||||
import androidx.compose.foundation.gestures.draggable
|
import androidx.compose.foundation.gestures.draggable
|
||||||
import androidx.compose.foundation.gestures.rememberDraggableState
|
import androidx.compose.foundation.gestures.rememberDraggableState
|
||||||
import androidx.compose.foundation.layout.Box
|
import androidx.compose.foundation.layout.*
|
||||||
import androidx.compose.foundation.layout.Row
|
|
||||||
import androidx.compose.foundation.layout.fillMaxHeight
|
|
||||||
import androidx.compose.foundation.layout.width
|
|
||||||
import androidx.compose.runtime.Composable
|
import androidx.compose.runtime.Composable
|
||||||
import androidx.compose.ui.Modifier
|
import androidx.compose.ui.Modifier
|
||||||
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
import androidx.compose.ui.input.pointer.pointerHoverIcon
|
||||||
@ -22,13 +19,18 @@ fun TripleVerticalSplitPanel(
|
|||||||
firstWidth: Float,
|
firstWidth: Float,
|
||||||
thirdWidth: Float,
|
thirdWidth: Float,
|
||||||
onFirstSizeDrag: (Float) -> Unit,
|
onFirstSizeDrag: (Float) -> Unit,
|
||||||
|
onFirstSizeDragStopped: (Float) -> Unit,
|
||||||
onThirdSizeDrag: (Float) -> Unit,
|
onThirdSizeDrag: (Float) -> Unit,
|
||||||
|
onThirdSizeDragStopped: (Float) -> Unit,
|
||||||
) {
|
) {
|
||||||
Row(
|
Row(
|
||||||
modifier = modifier
|
modifier = modifier
|
||||||
) {
|
) {
|
||||||
if (firstWidth > 0) {
|
if (firstWidth > 0) {
|
||||||
Box(modifier = Modifier.width(firstWidth.dp)) {
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(firstWidth.dp)
|
||||||
|
) {
|
||||||
first()
|
first()
|
||||||
}
|
}
|
||||||
Box(
|
Box(
|
||||||
@ -39,13 +41,19 @@ fun TripleVerticalSplitPanel(
|
|||||||
state = rememberDraggableState {
|
state = rememberDraggableState {
|
||||||
onFirstSizeDrag(it)
|
onFirstSizeDrag(it)
|
||||||
},
|
},
|
||||||
orientation = Orientation.Horizontal
|
orientation = Orientation.Horizontal,
|
||||||
|
onDragStopped = {
|
||||||
|
onFirstSizeDragStopped(it)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.pointerHoverIcon(resizePointerIconEast)
|
.pointerHoverIcon(resizePointerIconEast)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
Box(Modifier.weight(1f, true)) {
|
Box(
|
||||||
|
Modifier
|
||||||
|
.weight(1f, true)
|
||||||
|
) {
|
||||||
second()
|
second()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -54,14 +62,21 @@ fun TripleVerticalSplitPanel(
|
|||||||
.fillMaxHeight()
|
.fillMaxHeight()
|
||||||
.width(8.dp)
|
.width(8.dp)
|
||||||
.draggable(
|
.draggable(
|
||||||
rememberDraggableState {
|
state = rememberDraggableState {
|
||||||
onThirdSizeDrag(it)
|
onThirdSizeDrag(it)
|
||||||
}, Orientation.Horizontal
|
},
|
||||||
|
orientation = Orientation.Horizontal,
|
||||||
|
onDragStopped = {
|
||||||
|
onThirdSizeDragStopped(it)
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.pointerHoverIcon(resizePointerIconEast)
|
.pointerHoverIcon(resizePointerIconEast)
|
||||||
)
|
)
|
||||||
|
|
||||||
Box(modifier = Modifier.width(thirdWidth.dp)) {
|
Box(
|
||||||
|
modifier = Modifier
|
||||||
|
.width(thirdWidth.dp)
|
||||||
|
) {
|
||||||
third()
|
third()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,8 +22,10 @@ import com.jetpackduba.gitnuro.models.AuthorInfoSimple
|
|||||||
import com.jetpackduba.gitnuro.system.OpenFilePickerUseCase
|
import com.jetpackduba.gitnuro.system.OpenFilePickerUseCase
|
||||||
import com.jetpackduba.gitnuro.system.OpenUrlInBrowserUseCase
|
import com.jetpackduba.gitnuro.system.OpenUrlInBrowserUseCase
|
||||||
import com.jetpackduba.gitnuro.system.PickerType
|
import com.jetpackduba.gitnuro.system.PickerType
|
||||||
|
import com.jetpackduba.gitnuro.ui.IVerticalSplitPaneConfig
|
||||||
import com.jetpackduba.gitnuro.ui.SelectedItem
|
import com.jetpackduba.gitnuro.ui.SelectedItem
|
||||||
import com.jetpackduba.gitnuro.ui.TabsManager
|
import com.jetpackduba.gitnuro.ui.TabsManager
|
||||||
|
import com.jetpackduba.gitnuro.ui.VerticalSplitPaneConfig
|
||||||
import com.jetpackduba.gitnuro.updates.Update
|
import com.jetpackduba.gitnuro.updates.Update
|
||||||
import com.jetpackduba.gitnuro.updates.UpdatesRepository
|
import com.jetpackduba.gitnuro.updates.UpdatesRepository
|
||||||
import kotlinx.coroutines.*
|
import kotlinx.coroutines.*
|
||||||
@ -69,10 +71,9 @@ class TabViewModel @Inject constructor(
|
|||||||
private val sharedRepositoryStateManager: SharedRepositoryStateManager,
|
private val sharedRepositoryStateManager: SharedRepositoryStateManager,
|
||||||
private val tabsManager: TabsManager,
|
private val tabsManager: TabsManager,
|
||||||
private val tabScope: CoroutineScope,
|
private val tabScope: CoroutineScope,
|
||||||
|
private val verticalSplitPaneConfig: VerticalSplitPaneConfig,
|
||||||
val tabViewModelsProvider: TabViewModelsProvider,
|
val tabViewModelsProvider: TabViewModelsProvider,
|
||||||
) {
|
) : IVerticalSplitPaneConfig by verticalSplitPaneConfig {
|
||||||
var firstPaneWidth = 220f
|
|
||||||
var thirdPaneWidth = 360f
|
|
||||||
var initialPath: String? = null // Stores the path that should be opened when the tab is selected
|
var initialPath: String? = null // Stores the path that should be opened when the tab is selected
|
||||||
val errorsManager: ErrorsManager = tabState.errorsManager
|
val errorsManager: ErrorsManager = tabState.errorsManager
|
||||||
val selectedItem: StateFlow<SelectedItem> = tabState.selectedItem
|
val selectedItem: StateFlow<SelectedItem> = tabState.selectedItem
|
||||||
|
Loading…
Reference in New Issue
Block a user