@momo-kits/native-kits 0.167.1-duo.2-debug → 0.167.1-duo.3-debug
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/scheduled_tasks.lock +1 -0
- package/.claude/settings.local.json +185 -0
- package/CLAUDE.md +8 -3
- package/compose/build.gradle.kts +15 -1
- package/compose/build.gradle.kts.backup +14 -0
- package/compose/compose.podspec +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +2 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +52 -25
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +12 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +45 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +43 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +8 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +34 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +81 -62
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/DuoTabBar.kt +281 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +31 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +27 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +17 -10
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +3 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +4 -0
- package/gradle.properties +1 -1
- package/ios/Application/HeaderRight.swift +25 -12
- package/ios/Application/Layout/ScreenLayout.swift +196 -0
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +30 -9
- package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +5 -2
- package/ios/Application/Navigation/BottomTab/DuoTabBar.swift +275 -0
- package/ios/Application/Navigation/HeaderUser.swift +4 -1
- package/ios/Application/Navigation/NavigationContainer.swift +3 -0
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +41 -4
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +5 -1
- package/ios/Application/Navigation/component/DuoScrollGradient.swift +55 -0
- package/ios/Application/Navigation/component/Header.swift +9 -3
- package/ios/Application/Navigation/component/HeaderBackground.swift +3 -2
- package/ios/Application/Navigation/component/NavigationFooter.swift +1 -1
- package/ios/Application/Navigation/component/NavigationHeaderRight.swift +61 -9
- package/ios/Application/Navigation/component/SideBar.swift +155 -0
- package/ios/Application/StackScreen.swift +135 -18
- package/ios/Popup/PopupDisplay.swift +84 -68
- package/ios/Popup/PopupLayout.swift +45 -0
- package/ios/Popup/PopupNotify.swift +43 -32
- package/ios/Popup/PopupPromotion.swift +17 -5
- package/ios/native-kits.podspec +1 -1
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DuoTabDemo.swift +76 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IPhoneDuoDemo.swift +170 -0
- package/local.properties +8 -0
- package/package.json +1 -1
|
@@ -20,6 +20,7 @@ import androidx.compose.foundation.layout.offset
|
|
|
20
20
|
import androidx.compose.foundation.layout.padding
|
|
21
21
|
import androidx.compose.foundation.layout.size
|
|
22
22
|
import androidx.compose.foundation.layout.width
|
|
23
|
+
import androidx.compose.foundation.layout.absolutePadding
|
|
23
24
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
24
25
|
import androidx.compose.runtime.Composable
|
|
25
26
|
import androidx.compose.runtime.DisposableEffect
|
|
@@ -51,6 +52,10 @@ import vn.momo.kits.modifier.conditional
|
|
|
51
52
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
52
53
|
import vn.momo.kits.platform.BackHandler
|
|
53
54
|
import vn.momo.kits.platform.getScreenHeight
|
|
55
|
+
import vn.momo.kits.layout.getScreenLayout
|
|
56
|
+
|
|
57
|
+
// iPhone Duo inner display: center the sheet instead of spanning the width (RN BottomSheet).
|
|
58
|
+
private val DUO_REGULAR_MIN_WIDTH = 600.dp
|
|
54
59
|
|
|
55
60
|
@Composable
|
|
56
61
|
internal fun BottomSheet(
|
|
@@ -63,7 +68,11 @@ internal fun BottomSheet(
|
|
|
63
68
|
footerComponent: (@Composable () -> Unit)? = null,
|
|
64
69
|
onDismiss: (() -> Unit)?
|
|
65
70
|
) {
|
|
66
|
-
val
|
|
71
|
+
val layout = getScreenLayout()
|
|
72
|
+
val isDuo = layout.isIPhoneDuoDevice
|
|
73
|
+
val isDuoCentered = isDuo && layout.width >= DUO_REGULAR_MIN_WIDTH
|
|
74
|
+
// the screen is the outer display on iPhone Duo, even when unfolded
|
|
75
|
+
val screenHeightDp = if (isDuo) layout.height else getScreenHeight()
|
|
67
76
|
val screenHeightPx = with(LocalDensity.current) { screenHeightDp.toPx() }
|
|
68
77
|
val sheetOffset = remember { Animatable(screenHeightPx) }
|
|
69
78
|
|
|
@@ -148,13 +157,32 @@ internal fun BottomSheet(
|
|
|
148
157
|
}
|
|
149
158
|
) {
|
|
150
159
|
val parentHeight = with(LocalDensity.current) { constraints.maxHeight.toDp() }
|
|
160
|
+
val maxHeight = if (isDuo) {
|
|
161
|
+
parentHeight - maxOf(layout.duoTopInset, Spacing.XL)
|
|
162
|
+
} else {
|
|
163
|
+
parentHeight - 90.dp
|
|
164
|
+
}
|
|
165
|
+
// landscape side buttons span the full height; in portrait the side status bar only covers the top
|
|
166
|
+
val sideInset = isDuo && !isDuoCentered && layout.width > layout.height
|
|
151
167
|
|
|
152
168
|
Box(
|
|
153
169
|
modifier = Modifier
|
|
154
170
|
.align(Alignment.BottomCenter)
|
|
155
171
|
.offset { IntOffset(x = 0, y = sheetOffset.value.toInt()) }
|
|
156
|
-
.
|
|
157
|
-
|
|
172
|
+
.then(
|
|
173
|
+
if (isDuoCentered) {
|
|
174
|
+
// keeps the portrait width in landscape, like system sheets
|
|
175
|
+
Modifier.width(
|
|
176
|
+
minOf(
|
|
177
|
+
minOf(layout.width, layout.height) - Spacing.L * 2,
|
|
178
|
+
layout.width - maxOf(layout.insetLeft, layout.insetRight, Spacing.L) * 2,
|
|
179
|
+
)
|
|
180
|
+
)
|
|
181
|
+
} else {
|
|
182
|
+
Modifier.fillMaxWidth()
|
|
183
|
+
}
|
|
184
|
+
)
|
|
185
|
+
.heightIn(max = maxHeight)
|
|
158
186
|
.background(
|
|
159
187
|
color = if (isSurface) AppTheme.current.colors.background.surface else AppTheme.current.colors.background.default,
|
|
160
188
|
shape = RoundedCornerShape(topStart = Radius.M, topEnd = Radius.M)
|
|
@@ -168,7 +196,13 @@ internal fun BottomSheet(
|
|
|
168
196
|
val bottomInset = if (useBottomInset) {
|
|
169
197
|
(AppNavigationBar.current - keyboardSizeState().value).coerceAtLeast(0.dp)
|
|
170
198
|
} else 0.dp
|
|
171
|
-
Column(
|
|
199
|
+
Column(
|
|
200
|
+
Modifier
|
|
201
|
+
.padding(bottom = bottomInset)
|
|
202
|
+
.conditional(sideInset) {
|
|
203
|
+
absolutePadding(left = layout.insetLeft, right = layout.insetRight)
|
|
204
|
+
}
|
|
205
|
+
) {
|
|
172
206
|
Box(
|
|
173
207
|
modifier = Modifier
|
|
174
208
|
.height(72.dp)
|
|
@@ -249,6 +283,11 @@ internal fun BottomSheet(
|
|
|
249
283
|
content()
|
|
250
284
|
}
|
|
251
285
|
BottomSheetFooter(footerComponent)
|
|
286
|
+
} else if (isDuo) {
|
|
287
|
+
// content shrinks so a tall sheet keeps its header
|
|
288
|
+
Box(Modifier.weight(1f, fill = false)) {
|
|
289
|
+
content()
|
|
290
|
+
}
|
|
252
291
|
} else {
|
|
253
292
|
content()
|
|
254
293
|
}
|
|
@@ -9,6 +9,7 @@ import androidx.compose.foundation.clickable
|
|
|
9
9
|
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
10
10
|
import androidx.compose.foundation.layout.Box
|
|
11
11
|
import androidx.compose.foundation.layout.fillMaxSize
|
|
12
|
+
import androidx.compose.foundation.layout.padding
|
|
12
13
|
import androidx.compose.foundation.layout.wrapContentSize
|
|
13
14
|
import androidx.compose.runtime.*
|
|
14
15
|
import androidx.compose.ui.Alignment
|
|
@@ -25,6 +26,7 @@ import vn.momo.kits.modifier.conditional
|
|
|
25
26
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
26
27
|
import vn.momo.kits.navigation.tracking.ScreenTracker
|
|
27
28
|
import vn.momo.kits.platform.BackHandler
|
|
29
|
+
import vn.momo.kits.layout.getScreenLayout
|
|
28
30
|
|
|
29
31
|
@Composable
|
|
30
32
|
internal fun ModalScreen(
|
|
@@ -100,12 +102,18 @@ internal fun ModalScreen(
|
|
|
100
102
|
closeEvent()
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
val layout = getScreenLayout()
|
|
106
|
+
|
|
103
107
|
Box(
|
|
104
108
|
modifier = Modifier
|
|
105
109
|
.fillMaxSize()
|
|
106
110
|
.background(Color.Black.copy(alpha = 0.6f * alpha.value))
|
|
107
111
|
.noFeedbackClickable {
|
|
108
112
|
if(barrierDismissible) closeEvent()
|
|
113
|
+
}
|
|
114
|
+
// center below the side status bar and above the home indicator
|
|
115
|
+
.conditional(layout.isIPhoneDuoDevice) {
|
|
116
|
+
padding(top = layout.duoTopInset, bottom = layout.insetBottom)
|
|
109
117
|
},
|
|
110
118
|
contentAlignment = Alignment.Center
|
|
111
119
|
) {
|
|
@@ -65,6 +65,8 @@ import vn.momo.kits.navigation.component.Header
|
|
|
65
65
|
import vn.momo.kits.navigation.component.HeaderBackground
|
|
66
66
|
import vn.momo.kits.navigation.component.HeaderRight
|
|
67
67
|
import vn.momo.kits.navigation.component.HeaderSideBar
|
|
68
|
+
import vn.momo.kits.navigation.bottomtab.LocalDuoRailHeight
|
|
69
|
+
import vn.momo.kits.navigation.bottomtab.duoFloatingTabBarInset
|
|
68
70
|
import vn.momo.kits.navigation.component.HeaderType
|
|
69
71
|
import vn.momo.kits.navigation.component.InputSearchType
|
|
70
72
|
import vn.momo.kits.platform.BackHandler
|
|
@@ -75,6 +77,7 @@ import kotlinx.coroutines.delay
|
|
|
75
77
|
import vn.momo.kits.application.LocalContext
|
|
76
78
|
import vn.momo.kits.utils.horizontalSafeAreaPadding
|
|
77
79
|
import vn.momo.kits.layout.LocalScreenLayout
|
|
80
|
+
import vn.momo.kits.layout.ScreenLayout
|
|
78
81
|
import vn.momo.kits.layout.consumeHorizontalInsets
|
|
79
82
|
import vn.momo.kits.layout.getScreenLayout
|
|
80
83
|
import kotlin.time.Clock
|
|
@@ -84,11 +87,19 @@ import kotlin.time.ExperimentalTime
|
|
|
84
87
|
internal val LocalFooterHeightPx = staticCompositionLocalOf { mutableIntStateOf(0) }
|
|
85
88
|
internal val LocalHeaderRightWidthPx = staticCompositionLocalOf { mutableIntStateOf(0) }
|
|
86
89
|
|
|
90
|
+
// Space a tab's content leaves for the tab bar and home indicator. On iPhone Duo the floating bar
|
|
91
|
+
// overlays the content and the rail lives in the side strip, so only their own inset applies.
|
|
87
92
|
@Composable
|
|
88
|
-
private fun
|
|
89
|
-
if (LocalNavigation.current.bottomTabIndex == -1) return 0.dp
|
|
93
|
+
private fun bottomTabChildInset(): Dp {
|
|
90
94
|
val keyboard = keyboardSizeState().value
|
|
91
|
-
|
|
95
|
+
val navigationBar = AppNavigationBar.current
|
|
96
|
+
val layout = getScreenLayout()
|
|
97
|
+
return when {
|
|
98
|
+
layout.isIPhoneDuo && layout.sideBar == null -> (duoFloatingTabBarInset(layout) - keyboard).coerceAtLeast(0.dp)
|
|
99
|
+
layout.isIPhoneDuo -> (navigationBar - keyboard).coerceAtLeast(0.dp)
|
|
100
|
+
else -> (BOTTOM_TAB_BAR_HEIGHT.dp + Spacing.S - keyboard).coerceAtLeast(0.dp) +
|
|
101
|
+
(navigationBar - keyboard).coerceAtLeast(0.dp)
|
|
102
|
+
}
|
|
92
103
|
}
|
|
93
104
|
|
|
94
105
|
@OptIn(ExperimentalMaterialApi::class, ExperimentalTime::class)
|
|
@@ -212,7 +223,10 @@ internal fun StackScreen(
|
|
|
212
223
|
Header(onBackHandler)
|
|
213
224
|
}
|
|
214
225
|
|
|
215
|
-
HeaderSideBar(
|
|
226
|
+
HeaderSideBar(
|
|
227
|
+
bottomInset = maxOf(bottomBarsHeight(isBottomTabChild), if (isBottomTabChild) LocalDuoRailHeight.current else 0.dp),
|
|
228
|
+
modifier = Modifier.zIndex(4f),
|
|
229
|
+
)
|
|
216
230
|
|
|
217
231
|
Column(Modifier.zIndex(5f).horizontalSafeAreaPadding()) {
|
|
218
232
|
SearchAnimated(snapState = snapState)
|
|
@@ -239,7 +253,7 @@ private fun bottomBarsHeight(isBottomTabChild: Boolean): Dp {
|
|
|
239
253
|
val navigationBar = AppNavigationBar.current
|
|
240
254
|
return when {
|
|
241
255
|
options.hasFooter() -> with(LocalDensity.current) { LocalFooterHeightPx.current.intValue.toDp() }
|
|
242
|
-
isBottomTabChild ->
|
|
256
|
+
isBottomTabChild -> bottomTabChildInset()
|
|
243
257
|
else -> navigationBar
|
|
244
258
|
}
|
|
245
259
|
}
|
|
@@ -274,10 +288,11 @@ internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTa
|
|
|
274
288
|
val scrollState = LocalScrollState.current
|
|
275
289
|
val navigationBar = AppNavigationBar.current
|
|
276
290
|
val screenLayout = getScreenLayout()
|
|
291
|
+
val useDuoGlass = options.usesDuoGlassHeader(screenLayout)
|
|
277
292
|
|
|
278
293
|
Spacer(
|
|
279
294
|
Modifier.height(
|
|
280
|
-
if (options.headerType is HeaderType.DefaultOrExtended || (options.headerType is HeaderType.Transparent && !options.headerType.isFullScreenContent))
|
|
295
|
+
if (!useDuoGlass && (options.headerType is HeaderType.DefaultOrExtended || (options.headerType is HeaderType.Transparent && !options.headerType.isFullScreenContent)))
|
|
281
296
|
screenLayout.headerHeight else 0.dp
|
|
282
297
|
)
|
|
283
298
|
)
|
|
@@ -297,10 +312,13 @@ internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTa
|
|
|
297
312
|
.conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
|
|
298
313
|
verticalScroll(scrollState)
|
|
299
314
|
}
|
|
315
|
+
.conditional(useDuoGlass) {
|
|
316
|
+
padding(top = screenLayout.headerHeight)
|
|
317
|
+
}
|
|
300
318
|
.padding(
|
|
301
319
|
bottom = when {
|
|
302
320
|
options.hasFooter() || isBottomTabRoot -> 0.dp
|
|
303
|
-
isBottomTabChild ->
|
|
321
|
+
isBottomTabChild -> bottomTabChildInset()
|
|
304
322
|
!options.scrollData.scrollable && options.scrollData.scrollState == null -> 0.dp
|
|
305
323
|
else -> navigationBar
|
|
306
324
|
}
|
|
@@ -343,7 +361,9 @@ internal fun FooterContent() {
|
|
|
343
361
|
val options = LocalOptions.current
|
|
344
362
|
if (options.hasFooter()) {
|
|
345
363
|
val keyboardSize = keyboardSizeState()
|
|
346
|
-
|
|
364
|
+
// the Duo floating tab bar overlays tab content, so a tab's footer sits above it
|
|
365
|
+
val duoTabInset = if (LocalNavigation.current.bottomTabIndex != -1) duoFloatingTabBarInset(getScreenLayout()) else 0.dp
|
|
366
|
+
val bottomPadding = (maxOf(AppNavigationBar.current, duoTabInset) - keyboardSize.value).coerceAtLeast(0.dp)
|
|
347
367
|
Footer(
|
|
348
368
|
footerComponent = options.footerComponent,
|
|
349
369
|
bottomPadding = bottomPadding,
|
|
@@ -608,6 +628,12 @@ internal val LocalOptions = staticCompositionLocalOf<NavigationOptions> { error(
|
|
|
608
628
|
|
|
609
629
|
val StackScreenScrollableState = staticCompositionLocalOf<ScrollableState?> { null }
|
|
610
630
|
|
|
631
|
+
// iPhone Duo side bar: content scrolls under a glass header instead of starting below it (RN Screen).
|
|
632
|
+
internal fun NavigationOptions.usesDuoGlassHeader(layout: ScreenLayout): Boolean =
|
|
633
|
+
layout.sideBar != null && headerType is HeaderType.DefaultOrExtended &&
|
|
634
|
+
getInputSearchType(this) == InputSearchType.None &&
|
|
635
|
+
scrollData.scrollable && scrollData.scrollState is ScrollState
|
|
636
|
+
|
|
611
637
|
internal fun getInputSearchType(options: NavigationOptions): InputSearchType {
|
|
612
638
|
return when (val headerType = options.headerType) {
|
|
613
639
|
is HeaderType.DefaultOrExtended -> when {
|
|
@@ -8,6 +8,7 @@ import androidx.compose.animation.scaleOut
|
|
|
8
8
|
import androidx.compose.foundation.background
|
|
9
9
|
import androidx.compose.foundation.layout.*
|
|
10
10
|
import androidx.compose.runtime.Composable
|
|
11
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
11
12
|
import androidx.compose.runtime.DisposableEffect
|
|
12
13
|
import androidx.compose.runtime.LaunchedEffect
|
|
13
14
|
import androidx.compose.ui.Alignment
|
|
@@ -27,6 +28,7 @@ import vn.momo.kits.navigation.NavigationOptions
|
|
|
27
28
|
import vn.momo.kits.navigation.StackScreen
|
|
28
29
|
import vn.momo.kits.navigation.component.HeaderType
|
|
29
30
|
import vn.momo.kits.platform.reportFloatingArrowBack
|
|
31
|
+
import vn.momo.kits.layout.getScreenLayout
|
|
30
32
|
|
|
31
33
|
private var bottomTabOptionItems : MutableList<NavigationOptions?> = mutableListOf()
|
|
32
34
|
internal fun setBottomTabOption(index: Int, options: NavigationOptions){
|
|
@@ -78,81 +80,98 @@ fun BottomTab(
|
|
|
78
80
|
}
|
|
79
81
|
}
|
|
80
82
|
|
|
83
|
+
val layout = getScreenLayout()
|
|
84
|
+
val railHeight = if (layout.isIPhoneDuo && layout.sideBar != null) {
|
|
85
|
+
duoRailHeight(items.size, hasQr = floatingButton != null)
|
|
86
|
+
} else 0.dp
|
|
87
|
+
val onTabSelected: (Int) -> Unit = {
|
|
88
|
+
val targetRoute = "option$it"
|
|
89
|
+
if (currentRoute != targetRoute) {
|
|
90
|
+
navController.navigate(targetRoute)
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
81
94
|
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
|
|
82
95
|
Box(modifier = Modifier
|
|
83
96
|
.fillMaxSize()
|
|
84
97
|
) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
98
|
+
CompositionLocalProvider(LocalDuoRailHeight provides railHeight) {
|
|
99
|
+
NavHost(
|
|
100
|
+
navController = navController,
|
|
101
|
+
startDestination = "option0"
|
|
102
|
+
) {
|
|
103
|
+
items.forEachIndexed { index, item ->
|
|
104
|
+
composable(
|
|
105
|
+
route = "option$index",
|
|
106
|
+
enterTransition = {
|
|
107
|
+
fadeIn(animationSpec = tween(200)) +
|
|
108
|
+
scaleIn(
|
|
109
|
+
initialScale = 0.97f,
|
|
110
|
+
animationSpec = tween(200)
|
|
111
|
+
)
|
|
112
|
+
},
|
|
113
|
+
exitTransition = {
|
|
114
|
+
fadeOut(animationSpec = tween(200)) +
|
|
115
|
+
scaleOut(
|
|
116
|
+
targetScale = 0.97f,
|
|
117
|
+
animationSpec = tween(200)
|
|
118
|
+
)
|
|
119
|
+
},
|
|
120
|
+
popEnterTransition = {
|
|
121
|
+
fadeIn(animationSpec = tween(200)) +
|
|
122
|
+
scaleIn(
|
|
123
|
+
initialScale = 0.97f,
|
|
124
|
+
animationSpec = tween(200)
|
|
125
|
+
)
|
|
126
|
+
},
|
|
127
|
+
popExitTransition = {
|
|
128
|
+
fadeOut(animationSpec = tween(200)) +
|
|
129
|
+
scaleOut(
|
|
130
|
+
targetScale = 0.97f,
|
|
131
|
+
animationSpec = tween(200)
|
|
132
|
+
)
|
|
133
|
+
}
|
|
134
|
+
) {
|
|
135
|
+
val option = getBottomTabOption(index)
|
|
122
136
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
StackScreen(
|
|
138
|
+
content = item.screen,
|
|
139
|
+
navigationOptions = option,
|
|
140
|
+
bottomTabIndex = index,
|
|
141
|
+
onBackHandler = {
|
|
142
|
+
if (index != 0) {
|
|
143
|
+
navController.popBackStack(
|
|
144
|
+
navController.graph.startDestinationRoute!!,
|
|
145
|
+
inclusive = false
|
|
146
|
+
)
|
|
147
|
+
} else {
|
|
148
|
+
navigator.pop()
|
|
149
|
+
}
|
|
135
150
|
}
|
|
136
|
-
|
|
137
|
-
|
|
151
|
+
)
|
|
152
|
+
}
|
|
138
153
|
}
|
|
139
154
|
}
|
|
140
155
|
}
|
|
141
156
|
}
|
|
142
|
-
|
|
143
|
-
|
|
157
|
+
if (layout.isIPhoneDuo) {
|
|
158
|
+
DuoTabBar(
|
|
159
|
+
layout = layout,
|
|
144
160
|
items = items,
|
|
145
161
|
floatingButton = floatingButton,
|
|
146
|
-
|
|
147
|
-
onTabSelected =
|
|
148
|
-
val currentRoute = navController.currentBackStackEntry?.destination?.route
|
|
149
|
-
val targetRoute = "option$it"
|
|
150
|
-
if (currentRoute != targetRoute) {
|
|
151
|
-
navController.navigate(targetRoute)
|
|
152
|
-
}
|
|
153
|
-
}
|
|
162
|
+
selectedIndex = items.indices.firstOrNull { "option$it" == currentRoute } ?: 0,
|
|
163
|
+
onTabSelected = onTabSelected,
|
|
154
164
|
)
|
|
155
|
-
|
|
165
|
+
} else {
|
|
166
|
+
Column {
|
|
167
|
+
BottomTabBar(
|
|
168
|
+
items = items,
|
|
169
|
+
floatingButton = floatingButton,
|
|
170
|
+
navController = navController,
|
|
171
|
+
onTabSelected = onTabSelected,
|
|
172
|
+
)
|
|
173
|
+
Spacer(modifier = Modifier.fillMaxWidth().height(AppNavigationBar.current + Spacing.S).background(AppTheme.current.colors.background.surface))
|
|
174
|
+
}
|
|
156
175
|
}
|
|
157
176
|
}
|
|
158
177
|
}
|