Skip to content

Commit f5ee173

Browse files
committed
Width of triple vertical split pane columns is now persisted
Fixes #176
1 parent b9db9a8 commit f5ee173

File tree

6 files changed

+129
-17
lines changed

6 files changed

+129
-17
lines changed

src/main/kotlin/com/jetpackduba/gitnuro/di/AppComponent.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import com.jetpackduba.gitnuro.managers.TempFilesManager
1313
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
1414
import com.jetpackduba.gitnuro.terminal.ITerminalProvider
1515
import com.jetpackduba.gitnuro.ui.TabsManager
16+
import com.jetpackduba.gitnuro.ui.VerticalSplitPaneConfig
1617
import com.jetpackduba.gitnuro.updates.UpdatesRepository
1718
import com.jetpackduba.gitnuro.viewmodels.SettingsViewModel
1819
import dagger.Component
@@ -34,6 +35,8 @@ interface AppComponent {
3435

3536
fun appPreferences(): AppSettingsRepository
3637

38+
fun verticalSplitPaneConfig(): VerticalSplitPaneConfig
39+
3740
fun appEnvInfo(): AppEnvInfo
3841

3942
fun tabsManager(): TabsManager

src/main/kotlin/com/jetpackduba/gitnuro/repositories/AppSettingsRepository.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ private const val PREF_PROXY_USE_AUTH = "proxyUseAuth"
4343
private const val PREF_PROXY_USER = "proxyHostUser"
4444
private const val PREF_PROXY_PASSWORD = "proxyHostPassword"
4545
private const val PREF_CACHE_CREDENTIALS_IN_MEMORY = "credentialsInMemory"
46+
private const val PREF_FIRST_PANE_WIDTH = "firstPaneWidth"
47+
private const val PREF_THIRD_PANE_WIDTH = "thirdPaneWidth"
4648

4749

4850
private const val PREF_GIT_FF_MERGE = "gitFFMerge"
@@ -57,6 +59,8 @@ private const val DEFAULT_SWAP_UNCOMMITTED_CHANGES = false
5759
private const val DEFAULT_SHOW_CHANGES_AS_TREE = false
5860
private const val DEFAULT_CACHE_CREDENTIALS_IN_MEMORY = true
5961
private const val DEFAULT_VERIFY_SSL = true
62+
private const val DEFAULT_FIRST_PANE_WIDTH = 220f
63+
private const val DEFAULT_THIRD_PANE_WIDTH = 330f
6064
const val DEFAULT_UI_SCALE = -1f
6165

6266
@Singleton
@@ -209,6 +213,22 @@ class AppSettingsRepository @Inject constructor() {
209213
_cacheCredentialsInMemoryFlow.value = value
210214
}
211215

216+
var firstPaneWidth: Float
217+
get() {
218+
return preferences.getFloat(PREF_FIRST_PANE_WIDTH, DEFAULT_FIRST_PANE_WIDTH)
219+
}
220+
set(value) {
221+
preferences.putFloat(PREF_FIRST_PANE_WIDTH, value)
222+
}
223+
224+
var thirdPaneWidth: Float
225+
get() {
226+
return preferences.getFloat(PREF_THIRD_PANE_WIDTH, DEFAULT_THIRD_PANE_WIDTH)
227+
}
228+
set(value) {
229+
preferences.putFloat(PREF_THIRD_PANE_WIDTH, value)
230+
}
231+
212232
var verifySsl: Boolean
213233
get() {
214234
return preferences.getBoolean(PREF_VERIFY_SSL, DEFAULT_VERIFY_SSL)

src/main/kotlin/com/jetpackduba/gitnuro/ui/RepositoryOpen.kt

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ import com.jetpackduba.gitnuro.ui.log.Log
3030
import com.jetpackduba.gitnuro.updates.Update
3131
import com.jetpackduba.gitnuro.viewmodels.BlameState
3232
import com.jetpackduba.gitnuro.viewmodels.TabViewModel
33+
import kotlinx.coroutines.flow.collectLatest
34+
import kotlinx.coroutines.launch
3335
import org.eclipse.jgit.lib.RepositoryState
3436
import org.eclipse.jgit.revwalk.RevCommit
3537
import org.jetbrains.compose.splitpane.ExperimentalSplitPaneApi
@@ -264,9 +266,19 @@ fun MainContentView(
264266
) {
265267
val rebaseInteractiveState by tabViewModel.rebaseInteractiveState.collectAsState()
266268
val density = LocalDensity.current.density
269+
val scope = rememberCoroutineScope()
267270

268-
var firstWidth by remember(tabViewModel) { mutableStateOf(tabViewModel.firstPaneWidth) }
269-
var thirdWidth by remember(tabViewModel) { mutableStateOf(tabViewModel.thirdPaneWidth) }
271+
// We create 2 mutableStates here because using directly the flow makes compose lose some drag events for some reason
272+
var firstWidth by remember(tabViewModel) { mutableStateOf(tabViewModel.firstPaneWidth.value) }
273+
var thirdWidth by remember(tabViewModel) { mutableStateOf(tabViewModel.thirdPaneWidth.value) }
274+
275+
LaunchedEffect(Unit) {
276+
// Update the pane widths if they have been changed in a different tab
277+
tabViewModel.onPanelsWidthPersisted.collectLatest {
278+
firstWidth = tabViewModel.firstPaneWidth.value
279+
thirdWidth = tabViewModel.thirdPaneWidth.value
280+
}
281+
}
270282

271283
TripleVerticalSplitPanel(
272284
modifier = Modifier.fillMaxSize(),
@@ -391,15 +403,25 @@ fun MainContentView(
391403

392404
if (newWidth > 150 && rebaseInteractiveState !is RebaseInteractiveState.AwaitingInteraction) {
393405
firstWidth = newWidth
394-
tabViewModel.firstPaneWidth = firstWidth
406+
tabViewModel.setFirstPaneWidth(newWidth)
407+
}
408+
},
409+
onFirstSizeDragStopped = {
410+
scope.launch {
411+
tabViewModel.persistFirstPaneWidth()
395412
}
396413
},
397414
onThirdSizeDrag = {
398415
val newWidth = thirdWidth - it / density
399416

400417
if (newWidth > 150) {
401418
thirdWidth = newWidth
402-
tabViewModel.thirdPaneWidth = thirdWidth
419+
tabViewModel.setThirdPaneWidth(newWidth)
420+
}
421+
},
422+
onThirdSizeDragStopped = {
423+
scope.launch {
424+
tabViewModel.persistThirdPaneWidth()
403425
}
404426
},
405427
)
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
package com.jetpackduba.gitnuro.ui
2+
3+
import com.jetpackduba.gitnuro.repositories.AppSettingsRepository
4+
import kotlinx.coroutines.flow.MutableSharedFlow
5+
import kotlinx.coroutines.flow.MutableStateFlow
6+
import kotlinx.coroutines.flow.SharedFlow
7+
import kotlinx.coroutines.flow.StateFlow
8+
import javax.inject.Inject
9+
import javax.inject.Singleton
10+
11+
interface IVerticalSplitPaneConfig {
12+
val firstPaneWidth: StateFlow<Float>
13+
val onPanelsWidthPersisted: SharedFlow<Unit>
14+
val thirdPaneWidth: StateFlow<Float>
15+
fun setFirstPaneWidth(firstPaneWidth: Float)
16+
fun setThirdPaneWidth(thirdPaneWidth: Float)
17+
suspend fun persistFirstPaneWidth()
18+
suspend fun persistThirdPaneWidth()
19+
}
20+
21+
@Singleton
22+
class VerticalSplitPaneConfig @Inject constructor(
23+
private val appSettingsRepository: AppSettingsRepository,
24+
) : IVerticalSplitPaneConfig {
25+
private val _firstPaneWidth = MutableStateFlow<Float>(appSettingsRepository.firstPaneWidth)
26+
override val firstPaneWidth: StateFlow<Float> = _firstPaneWidth
27+
28+
private val _thirdPaneWidth = MutableStateFlow<Float>(appSettingsRepository.thirdPaneWidth)
29+
override val thirdPaneWidth: StateFlow<Float> = _thirdPaneWidth
30+
31+
private val _onPanelsWidthPersisted = MutableSharedFlow<Unit>()
32+
override val onPanelsWidthPersisted: SharedFlow<Unit> = _onPanelsWidthPersisted
33+
34+
override fun setFirstPaneWidth(firstPaneWidth: Float) {
35+
this._firstPaneWidth.value = firstPaneWidth
36+
}
37+
38+
override fun setThirdPaneWidth(thirdPaneWidth: Float) {
39+
this._thirdPaneWidth.value = thirdPaneWidth
40+
}
41+
42+
override suspend fun persistFirstPaneWidth() {
43+
appSettingsRepository.firstPaneWidth = _firstPaneWidth.value
44+
_onPanelsWidthPersisted.emit(Unit)
45+
}
46+
47+
override suspend fun persistThirdPaneWidth() {
48+
appSettingsRepository.thirdPaneWidth = _thirdPaneWidth.value
49+
_onPanelsWidthPersisted.emit(Unit)
50+
}
51+
}

src/main/kotlin/com/jetpackduba/gitnuro/ui/components/TripleVerticalSplitPanel.kt

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,7 @@ package com.jetpackduba.gitnuro.ui.components
33
import androidx.compose.foundation.gestures.Orientation
44
import androidx.compose.foundation.gestures.draggable
55
import androidx.compose.foundation.gestures.rememberDraggableState
6-
import androidx.compose.foundation.layout.Box
7-
import androidx.compose.foundation.layout.Row
8-
import androidx.compose.foundation.layout.fillMaxHeight
9-
import androidx.compose.foundation.layout.width
6+
import androidx.compose.foundation.layout.*
107
import androidx.compose.runtime.Composable
118
import androidx.compose.ui.Modifier
129
import androidx.compose.ui.input.pointer.pointerHoverIcon
@@ -22,13 +19,18 @@ fun TripleVerticalSplitPanel(
2219
firstWidth: Float,
2320
thirdWidth: Float,
2421
onFirstSizeDrag: (Float) -> Unit,
22+
onFirstSizeDragStopped: (Float) -> Unit,
2523
onThirdSizeDrag: (Float) -> Unit,
24+
onThirdSizeDragStopped: (Float) -> Unit,
2625
) {
2726
Row(
2827
modifier = modifier
2928
) {
3029
if (firstWidth > 0) {
31-
Box(modifier = Modifier.width(firstWidth.dp)) {
30+
Box(
31+
modifier = Modifier
32+
.width(firstWidth.dp)
33+
) {
3234
first()
3335
}
3436
Box(
@@ -39,13 +41,19 @@ fun TripleVerticalSplitPanel(
3941
state = rememberDraggableState {
4042
onFirstSizeDrag(it)
4143
},
42-
orientation = Orientation.Horizontal
44+
orientation = Orientation.Horizontal,
45+
onDragStopped = {
46+
onFirstSizeDragStopped(it)
47+
},
4348
)
4449
.pointerHoverIcon(resizePointerIconEast)
4550
)
4651
}
4752

48-
Box(Modifier.weight(1f, true)) {
53+
Box(
54+
Modifier
55+
.weight(1f, true)
56+
) {
4957
second()
5058
}
5159

@@ -54,14 +62,21 @@ fun TripleVerticalSplitPanel(
5462
.fillMaxHeight()
5563
.width(8.dp)
5664
.draggable(
57-
rememberDraggableState {
65+
state = rememberDraggableState {
5866
onThirdSizeDrag(it)
59-
}, Orientation.Horizontal
67+
},
68+
orientation = Orientation.Horizontal,
69+
onDragStopped = {
70+
onThirdSizeDragStopped(it)
71+
},
6072
)
6173
.pointerHoverIcon(resizePointerIconEast)
6274
)
6375

64-
Box(modifier = Modifier.width(thirdWidth.dp)) {
76+
Box(
77+
modifier = Modifier
78+
.width(thirdWidth.dp)
79+
) {
6580
third()
6681
}
6782
}

src/main/kotlin/com/jetpackduba/gitnuro/viewmodels/TabViewModel.kt

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ import com.jetpackduba.gitnuro.models.AuthorInfoSimple
2222
import com.jetpackduba.gitnuro.system.OpenFilePickerUseCase
2323
import com.jetpackduba.gitnuro.system.OpenUrlInBrowserUseCase
2424
import com.jetpackduba.gitnuro.system.PickerType
25+
import com.jetpackduba.gitnuro.ui.IVerticalSplitPaneConfig
2526
import com.jetpackduba.gitnuro.ui.SelectedItem
2627
import com.jetpackduba.gitnuro.ui.TabsManager
28+
import com.jetpackduba.gitnuro.ui.VerticalSplitPaneConfig
2729
import com.jetpackduba.gitnuro.updates.Update
2830
import com.jetpackduba.gitnuro.updates.UpdatesRepository
2931
import kotlinx.coroutines.*
@@ -69,10 +71,9 @@ class TabViewModel @Inject constructor(
6971
private val sharedRepositoryStateManager: SharedRepositoryStateManager,
7072
private val tabsManager: TabsManager,
7173
private val tabScope: CoroutineScope,
74+
private val verticalSplitPaneConfig: VerticalSplitPaneConfig,
7275
val tabViewModelsProvider: TabViewModelsProvider,
73-
) {
74-
var firstPaneWidth = 220f
75-
var thirdPaneWidth = 360f
76+
) : IVerticalSplitPaneConfig by verticalSplitPaneConfig {
7677
var initialPath: String? = null // Stores the path that should be opened when the tab is selected
7778
val errorsManager: ErrorsManager = tabState.errorsManager
7879
val selectedItem: StateFlow<SelectedItem> = tabState.selectedItem

0 commit comments

Comments
 (0)