Skip to content

Commit 94a0eea

Browse files
author
TEYSSANDIER Raphael
committed
feat: Move menu
1 parent 55e1475 commit 94a0eea

File tree

4 files changed

+97
-23
lines changed

4 files changed

+97
-23
lines changed

FloconDesktop/composeApp/src/commonMain/kotlin/io/github/openflocon/flocondesktop/App.kt

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,13 @@ package io.github.openflocon.flocondesktop
55
import androidx.compose.foundation.ComposeFoundationFlags
66
import androidx.compose.foundation.ExperimentalFoundationApi
77
import androidx.compose.foundation.layout.Box
8+
import androidx.compose.foundation.layout.fillMaxHeight
89
import androidx.compose.foundation.layout.fillMaxSize
9-
import androidx.compose.foundation.layout.safeContentPadding
10+
import androidx.compose.foundation.layout.height
11+
import androidx.compose.foundation.layout.width
12+
import androidx.compose.foundation.shape.RoundedCornerShape
13+
import androidx.compose.material.icons.Icons
14+
import androidx.compose.material.icons.outlined.ChevronRight
1015
import androidx.compose.runtime.Composable
1116
import androidx.compose.runtime.CompositionLocalProvider
1217
import androidx.compose.runtime.getValue
@@ -27,7 +32,11 @@ import io.github.openflocon.flocondesktop.features.featuresModule
2732
import io.github.openflocon.flocondesktop.features.network.NetworkRoute
2833
import io.github.openflocon.flocondesktop.features.network.networkNavigation
2934
import io.github.openflocon.flocondesktop.main.di.mainModule
35+
import io.github.openflocon.flocondesktop.main.ui.view.leftpannel.LeftPanelView
36+
import io.github.openflocon.flocondesktop.main.ui.view.leftpannel.PanelMaxWidth
37+
import io.github.openflocon.flocondesktop.main.ui.view.leftpannel.PanelMinWidth
3038
import io.github.openflocon.library.designsystem.FloconTheme
39+
import io.github.openflocon.library.designsystem.components.FloconIcon
3140
import io.github.openflocon.library.designsystem.components.FloconSurface
3241
import io.github.openflocon.library.designsystem.components.panel.FloconPanelDisplayer
3342
import io.github.openflocon.library.designsystem.components.panel.LocalFloconPanelController
@@ -73,6 +82,14 @@ fun App() {
7382
) {
7483
val appViewModel: AppViewModel = koinViewModel()
7584
val navigationState = koinInject<FloconNavigationState>()
85+
val leftPanelState by appViewModel.leftPanelState.collectAsStateWithLifecycle()
86+
var expanded by remember { mutableStateOf(true) }
87+
val width by animateDpAsState(targetValue = if (expanded) PanelMaxWidth else PanelMinWidth)
88+
var windowSize by remember { mutableStateOf(IntSize.Zero) }
89+
val position by animateDpAsState(
90+
targetValue = if (expanded) PanelMaxWidth else PanelMinWidth,
91+
)
92+
val rotate by animateFloatAsState(targetValue = if (expanded) 180f else 0f)
7693

7794
FloconSurface(
7895
modifier = Modifier
@@ -97,10 +114,48 @@ fun App() {
97114
}
98115

99116
FloconSurface(
100-
modifier = Modifier.fillMaxSize()
117+
modifier = Modifier
118+
.fillMaxSize()
119+
.onGloballyPositioned {
120+
windowSize = it.size // TODO Add windowsize lib
121+
},
101122
) {
102123
FloconNavigation(
103124
navigationState = navigationState,
125+
sceneStrategy = MenuSceneStrategy(
126+
menuContent = {
127+
LeftPanelView(
128+
state = leftPanelState,
129+
onClickItem = {},
130+
modifier = Modifier
131+
.width(width)
132+
.fillMaxHeight(),
133+
expanded = expanded
134+
)
135+
},
136+
expander = {
137+
Box(
138+
contentAlignment = Alignment.Center,
139+
modifier = Modifier
140+
.width(20.dp)
141+
.height(60.dp)
142+
.graphicsLayer {
143+
translationX = position.toPx() - size.width / 2 - 8.dp.toPx()
144+
translationY = (windowSize.height / 2) - (size.height / 2)
145+
}
146+
.clip(RoundedCornerShape(4.dp))
147+
.background(FloconTheme.colorPalette.primary)
148+
.clickable(onClick = { expanded = !expanded }),
149+
) {
150+
FloconIcon(
151+
imageVector = Icons.Outlined.ChevronRight,
152+
tint = Color.LightGray,
153+
modifier = Modifier.rotate(rotate),
154+
)
155+
}
156+
}
157+
)
158+
.then(SinglePaneSceneStrategy()),
104159
modifier = Modifier.fillMaxSize()
105160
) {
106161
networkNavigation()

FloconDesktop/composeApp/src/commonMain/kotlin/io/github/openflocon/flocondesktop/app/AppViewModel.kt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,16 @@ import androidx.lifecycle.viewModelScope
55
import io.github.openflocon.domain.common.DispatcherProvider
66
import io.github.openflocon.domain.settings.usecase.InitAdbPathUseCase
77
import io.github.openflocon.domain.settings.usecase.StartAdbForwardUseCase
8+
import io.github.openflocon.flocondesktop.main.ui.buildLeftPanelState
9+
import io.github.openflocon.flocondesktop.main.ui.model.SubScreen
10+
import io.github.openflocon.flocondesktop.main.ui.model.id
811
import io.github.openflocon.flocondesktop.messages.ui.MessagesServerDelegate
912
import kotlinx.coroutines.delay
13+
import kotlinx.coroutines.flow.MutableStateFlow
14+
import kotlinx.coroutines.flow.SharingStarted
15+
import kotlinx.coroutines.flow.flowOn
16+
import kotlinx.coroutines.flow.map
17+
import kotlinx.coroutines.flow.stateIn
1018
import kotlinx.coroutines.isActive
1119
import kotlinx.coroutines.launch
1220

@@ -20,6 +28,19 @@ class AppViewModel(
2028
messagesServerDelegate,
2129
) {
2230

31+
val subScreen = MutableStateFlow(SubScreen.Network)
32+
val leftPanelState = subScreen.map { subScreen ->
33+
buildLeftPanelState(
34+
selectedId = subScreen.id,
35+
)
36+
}
37+
.flowOn(dispatcherProvider.ui)
38+
.stateIn(
39+
scope = viewModelScope,
40+
started = SharingStarted.Eagerly,
41+
initialValue = buildLeftPanelState(subScreen.value.id),
42+
)
43+
2344
init {
2445
viewModelScope.launch(dispatcherProvider.viewModel) {
2546
initAdbPathUseCase().alsoFailure {

FloconDesktop/navigation/src/commonMain/kotlin/io/github/openflocon/navigation/FloconNavigation.kt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,22 +8,22 @@ import androidx.compose.runtime.Composable
88
import androidx.compose.runtime.remember
99
import androidx.compose.ui.Modifier
1010
import androidx.navigation3.runtime.EntryProviderBuilder
11-
import androidx.navigation3.runtime.NavEntry
1211
import androidx.navigation3.runtime.entryProvider
1312
import androidx.navigation3.runtime.rememberSavedStateNavEntryDecorator
13+
import androidx.navigation3.scene.SceneStrategy
1414
import androidx.navigation3.scene.SinglePaneSceneStrategy
1515
import androidx.navigation3.scene.rememberSceneSetupNavEntryDecorator
1616
import androidx.navigation3.ui.NavDisplay
1717
import androidx.navigationevent.NavigationEventDispatcher
1818
import androidx.navigationevent.NavigationEventDispatcherOwner
1919
import androidx.navigationevent.compose.LocalNavigationEventDispatcherOwner
2020
import androidx.navigationevent.compose.NavigationEventDispatcherOwner
21-
import io.github.openflocon.navigation.scene.MenuSceneStrategy
2221

2322
@Composable
2423
fun FloconNavigation(
2524
navigationState: FloconNavigationState,
2625
modifier: Modifier = Modifier,
26+
sceneStrategy: SceneStrategy<FloconRoute> = SinglePaneSceneStrategy(),
2727
builder: EntryProviderBuilder<FloconRoute>.() -> Unit
2828
) {
2929
val dispatcher = remember { NavigationEventDispatcher() }
@@ -45,8 +45,7 @@ fun FloconNavigation(
4545
rememberSceneSetupNavEntryDecorator(),
4646
rememberSavedStateNavEntryDecorator()
4747
),
48-
sceneStrategy = MenuSceneStrategy()
49-
.then(SinglePaneSceneStrategy()),
48+
sceneStrategy = sceneStrategy,
5049
onBack = { navigationState.back(it) },
5150
entryProvider = entryProvider {
5251
entry<LoadingRoute> {

FloconDesktop/navigation/src/commonMain/kotlin/io/github/openflocon/navigation/scene/MenuScene.kt

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,8 @@
11
package io.github.openflocon.navigation.scene
22

3-
import androidx.compose.foundation.background
43
import androidx.compose.foundation.layout.Box
54
import androidx.compose.foundation.layout.Row
6-
import androidx.compose.foundation.layout.fillMaxHeight
7-
import androidx.compose.foundation.layout.width
85
import androidx.compose.runtime.Composable
9-
import androidx.compose.ui.Modifier
10-
import androidx.compose.ui.graphics.Color
11-
import androidx.compose.ui.unit.dp
126
import androidx.navigation3.runtime.NavEntry
137
import androidx.navigation3.scene.Scene
148
import androidx.navigation3.scene.SceneStrategy
@@ -23,18 +17,18 @@ enum class Menu {
2317
class MenuScene(
2418
override val key: String,
2519
override val previousEntries: List<NavEntry<FloconRoute>>,
26-
private val entry: NavEntry<FloconRoute>
20+
private val entry: NavEntry<FloconRoute>,
21+
private val menuContent: @Composable () -> Unit,
22+
private val expander: @Composable (() -> Unit)? = null
2723
) : Scene<FloconRoute> {
2824
override val entries: List<NavEntry<FloconRoute>> = listOf(entry)
2925
override val content: @Composable (() -> Unit) = {
30-
Row {
31-
Box(
32-
modifier = Modifier
33-
.width(300.dp)
34-
.fillMaxHeight()
35-
.background(Color.Blue)
36-
)
37-
entry.Content()
26+
Box {
27+
Row {
28+
menuContent()
29+
entry.Content()
30+
}
31+
expander?.invoke()
3832
}
3933
}
4034

@@ -43,7 +37,10 @@ class MenuScene(
4337
}
4438
}
4539

46-
class MenuSceneStrategy : SceneStrategy<FloconRoute> {
40+
class MenuSceneStrategy(
41+
private val menuContent: @Composable () -> Unit,
42+
private val expander: @Composable (() -> Unit)? = null
43+
) : SceneStrategy<FloconRoute> {
4744

4845
@Composable
4946
override fun calculateScene(
@@ -56,7 +53,9 @@ class MenuSceneStrategy : SceneStrategy<FloconRoute> {
5653
MenuScene(
5754
key = MenuScene.MENU_KEY,
5855
previousEntries = entries.dropLast(1),
59-
entry = lastEntry
56+
entry = lastEntry,
57+
menuContent = menuContent,
58+
expander = expander
6059
)
6160
} else {
6261
null

0 commit comments

Comments
 (0)