@momo-kits/native-kits 0.161.1-beta.15-debug → 0.161.2-beta.1

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.
Files changed (139) hide show
  1. package/ios/Application/ApplicationEnvironment.swift +2 -6
  2. package/ios/Input/Input.swift +50 -21
  3. package/ios/Input/InputPhoneNumber.swift +17 -17
  4. package/ios/StatusBarTap/StatusBarTap.h +13 -0
  5. package/ios/StatusBarTap/StatusBarTap.m +75 -0
  6. package/ios/Typography/Text.swift +19 -14
  7. package/ios/Typography/Typography.swift +22 -1
  8. package/ios/native-kits.podspec +2 -1
  9. package/package.json +1 -1
  10. package/build.gradle.kts +0 -11
  11. package/compose/build.gradle.kts +0 -180
  12. package/compose/build.gradle.kts.backup +0 -180
  13. package/compose/compose.podspec +0 -47
  14. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -116
  15. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  16. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  17. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  18. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  19. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  20. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  21. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  22. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  23. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  24. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  25. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  26. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  27. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  28. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -57
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -115
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -201
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -222
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -48
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -305
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -720
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -121
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -402
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -85
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -340
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -194
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -357
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -123
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -94
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -136
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -224
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -543
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -23
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -148
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -188
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -116
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -448
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -172
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -255
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -231
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -233
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -254
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -241
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -364
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -92
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -352
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -103
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -338
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -70
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -96
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -348
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -256
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -494
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -131
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -215
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -96
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -531
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -92
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -130
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -214
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -590
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -177
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -192
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -205
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -239
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -191
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -306
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -270
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -2
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -35
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -2
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -57
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -68
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -14
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -50
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -253
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -133
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -99
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -168
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -333
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -552
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -161
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -243
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -187
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -279
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -80
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -306
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -32
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -370
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -131
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -167
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -45
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -62
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -105
  131. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -176
  132. package/gradle/libs.versions.toml +0 -58
  133. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  134. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  135. package/gradle.properties +0 -26
  136. package/gradlew +0 -252
  137. package/gradlew.bat +0 -94
  138. package/local.properties +0 -8
  139. package/settings.gradle.kts +0 -52
@@ -1,552 +0,0 @@
1
- package vn.momo.kits.navigation
2
-
3
- import androidx.compose.animation.animateColorAsState
4
- import androidx.compose.animation.core.animateDpAsState
5
- import androidx.compose.foundation.ScrollState
6
- import androidx.compose.foundation.background
7
- import androidx.compose.foundation.border
8
- import androidx.compose.foundation.gestures.ScrollableState
9
- import androidx.compose.foundation.layout.Box
10
- import androidx.compose.foundation.layout.Column
11
- import androidx.compose.foundation.layout.ColumnScope
12
- import androidx.compose.foundation.layout.Spacer
13
- import androidx.compose.foundation.layout.WindowInsets
14
- import androidx.compose.foundation.layout.aspectRatio
15
- import androidx.compose.foundation.layout.fillMaxSize
16
- import androidx.compose.foundation.layout.fillMaxWidth
17
- import androidx.compose.foundation.layout.height
18
- import androidx.compose.foundation.layout.ime
19
- import androidx.compose.foundation.layout.imePadding
20
- import androidx.compose.foundation.layout.offset
21
- import androidx.compose.foundation.layout.padding
22
- import androidx.compose.foundation.lazy.LazyListState
23
- import androidx.compose.foundation.lazy.rememberLazyListState
24
- import androidx.compose.foundation.rememberScrollState
25
- import androidx.compose.foundation.verticalScroll
26
- import androidx.compose.material.ExperimentalMaterialApi
27
- import androidx.compose.runtime.Composable
28
- import androidx.compose.runtime.CompositionLocalProvider
29
- import androidx.compose.runtime.LaunchedEffect
30
- import androidx.compose.runtime.getValue
31
- import androidx.compose.runtime.mutableIntStateOf
32
- import androidx.compose.runtime.mutableStateOf
33
- import androidx.compose.runtime.remember
34
- import androidx.compose.runtime.snapshotFlow
35
- import androidx.compose.runtime.staticCompositionLocalOf
36
- import androidx.compose.ui.Alignment
37
- import androidx.compose.ui.Modifier
38
- import androidx.compose.ui.graphics.Brush
39
- import androidx.compose.ui.graphics.Color
40
- import androidx.compose.ui.graphics.lerp
41
- import androidx.compose.ui.layout.onGloballyPositioned
42
- import androidx.compose.ui.platform.LocalDensity
43
- import androidx.compose.ui.unit.Dp
44
- import androidx.compose.ui.unit.dp
45
- import androidx.compose.ui.unit.min
46
- import androidx.compose.ui.zIndex
47
- import vn.momo.kits.components.InputSearch
48
- import vn.momo.kits.const.AppNavigationBar
49
- import vn.momo.kits.const.AppStatusBar
50
- import vn.momo.kits.const.AppTheme
51
- import vn.momo.kits.application.IsShowBaseLineDebug
52
- import vn.momo.kits.const.Colors
53
- import vn.momo.kits.const.Spacing
54
- import vn.momo.kits.modifier.conditional
55
- import vn.momo.kits.modifier.hideKeyboardOnTap
56
- import vn.momo.kits.navigation.component.FABPosition
57
- import vn.momo.kits.navigation.component.FloatingButton
58
- import vn.momo.kits.navigation.component.HEADER_HEIGHT
59
- import vn.momo.kits.navigation.component.Header
60
- import vn.momo.kits.navigation.component.HeaderBackground
61
- import vn.momo.kits.navigation.component.HeaderRight
62
- import vn.momo.kits.navigation.component.HeaderType
63
- import vn.momo.kits.navigation.component.InputSearchType
64
- import vn.momo.kits.platform.BackHandler
65
- import vn.momo.kits.platform.getOSVersion
66
- import vn.momo.kits.navigation.tracking.ScreenTracker
67
- import vn.momo.kits.navigation.tracking.ScreenTrackingState
68
- import kotlinx.coroutines.delay
69
- import vn.momo.kits.application.ApplicationContext
70
- import kotlin.time.Clock
71
- import kotlin.time.ExperimentalTime
72
-
73
- internal val LocalFooterHeightPx = staticCompositionLocalOf { mutableIntStateOf(0) }
74
- internal val LocalHeaderRightWidthPx = staticCompositionLocalOf { mutableIntStateOf(0) }
75
-
76
- @OptIn(ExperimentalMaterialApi::class, ExperimentalTime::class)
77
- @Composable
78
- internal fun StackScreen(
79
- content: @Composable () -> Unit,
80
- navigationOptions: NavigationOptions? = null,
81
- id: Int = -1,
82
- name: String = "",
83
- bottomTabIndex: Int = -1,
84
- onBackHandler: (() -> Unit)? = null,
85
- ) {
86
- val navigator = LocalNavigator.current
87
- val maxApi = LocalMaxApi.current
88
- val context = ApplicationContext.current
89
- val statusBar = AppStatusBar.current
90
- val density = LocalDensity.current
91
- val navigation = remember { Navigation(id = id, bottomTabIndex = bottomTabIndex, initOptions = navigationOptions) }
92
-
93
- val options by navigation.currentOptions
94
-
95
- // Auto tracking state
96
- val trackingState = remember {
97
- ScreenTrackingState().apply {
98
- startTime = Clock.System.now().toEpochMilliseconds()
99
- }
100
- }
101
-
102
- // Determine action: push or back
103
- val action = remember {
104
- if (ScreenTracker.getLastScreenName() != null) "push" else "back"
105
- }
106
-
107
- // Auto tracking effects
108
- LaunchedEffect(name) {
109
- // Track screen navigated immediately
110
- ScreenTracker.trackScreenNavigated(
111
- maxApi = maxApi,
112
- context = context,
113
- screenName = name,
114
- action = action,
115
- state = trackingState
116
- )
117
-
118
- // Track screen displayed after 2 seconds (debounce)
119
- delay(2000)
120
- val loadTime = Clock.System.now().toEpochMilliseconds() - trackingState.startTime
121
- ScreenTracker.trackScreenDisplayed(
122
- maxApi = maxApi,
123
- context = context,
124
- screenName = name,
125
- duration = loadTime,
126
- state = trackingState
127
- )
128
-
129
- // Track screen interacted after displayed
130
- val interactionTime = Clock.System.now().toEpochMilliseconds() - trackingState.startTime
131
- ScreenTracker.trackScreenInteracted(
132
- maxApi = maxApi,
133
- context = context,
134
- screenName = name,
135
- duration = interactionTime - loadTime,
136
- totalDuration = interactionTime,
137
- state = trackingState
138
- )
139
- }
140
-
141
- val limit = with(density) {
142
- (statusBar).toPx() + HEADER_HEIGHT
143
- }.toInt()
144
-
145
- val (scrollState, scrollInProcess) = if (options.scrollData.scrollState is LazyListState)
146
- (options.scrollData.scrollState as? LazyListState ?: rememberLazyListState()).proxyScrollState(limit, 15)
147
- else
148
- (options.scrollData.scrollState as? ScrollState ?: rememberScrollState()).proxyLimitedScrollState(limit, 15)
149
-
150
- val footerHeightPx = remember { mutableIntStateOf(0) }
151
- val headerRightWidthPx = remember { mutableIntStateOf(0) }
152
-
153
- BackHandler(true) { navigator.onBackSafe() }
154
-
155
- CompositionLocalProvider(
156
- StackScreenScrollableState provides options.scrollData.scrollState,
157
- LocalNavigation provides navigation,
158
- LocalScrollState provides scrollState,
159
- LocalOptions provides options,
160
- LocalFooterHeightPx provides footerHeightPx,
161
- LocalHeaderRightWidthPx provides headerRightWidthPx
162
- ) {
163
- Box(Modifier
164
- .fillMaxSize()
165
- .background(options.backgroundColor ?: AppTheme.current.colors.background.default)
166
- .conditional(options.keyboardOptions.keyboardShouldPersistTaps) {
167
- hideKeyboardOnTap()
168
- }
169
- .conditional(options.keyboardOptions.useAvoidKeyboard && getOSVersion() > 29) {
170
- imePadding()
171
- }
172
- ) {
173
- Box(Modifier.zIndex(1f)) {
174
- HeaderBackground()
175
- }
176
-
177
- Box(Modifier.zIndex(5f)) {
178
- Header(onBackHandler)
179
- }
180
-
181
- Column (Modifier.zIndex(6f)) {
182
- SearchAnimated(isScrollInProgress = scrollInProcess)
183
- }
184
-
185
- Column(Modifier.zIndex(2f).fillMaxSize()) {
186
- MainContent(content = content)
187
- }
188
-
189
- Box(Modifier.zIndex(4f).align(Alignment.BottomCenter)) {
190
- FooterContent()
191
- }
192
-
193
- Box(Modifier.zIndex(7f)){
194
- FloatingContent()
195
- }
196
-
197
- OverplayView(bottomTabIndex = bottomTabIndex, id = id)
198
- }
199
- }
200
- }
201
-
202
- @Composable
203
- fun FloatingContent(){
204
- val options = LocalOptions.current
205
- val density = LocalDensity.current
206
- val footerHeightPx = LocalFooterHeightPx.current
207
- val scrollState = LocalScrollState.current
208
-
209
- val fabProps = options.floatingButtonProps ?: return
210
- val bottomPadding = fabProps.bottom ?:
211
- (Spacing.M + if (options.footerComponent != null) with(density){ footerHeightPx.intValue.toDp() } else 0.dp)
212
-
213
- FloatingButton(
214
- scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
215
- onClick = fabProps.onClick,
216
- containerColor = AppTheme.current.colors.primary,
217
- bottom = bottomPadding,
218
- icon = fabProps.icon,
219
- iconColor = fabProps.iconColor,
220
- text = fabProps.label,
221
- size = fabProps.size,
222
- position = fabProps.position ?: FABPosition.END,
223
- )
224
- }
225
-
226
- @Composable
227
- fun ColumnScope.MainContent(content: @Composable ()-> Unit){
228
- val options = LocalOptions.current
229
- val inputSearchType = getInputSearchType(options)
230
- val density = LocalDensity.current
231
- val scrollState = LocalScrollState.current
232
-
233
- Spacer(Modifier.height(
234
- if (options.headerType is HeaderType.DefaultOrExtended || (options.headerType is HeaderType.Transparent && !options.headerType.isFullScreenContent))
235
- AppStatusBar.current + HEADER_HEIGHT.dp else 0.dp)
236
- )
237
- if (inputSearchType == InputSearchType.Animated){
238
- val scrollDp = with(density) { scrollState.value.toDp() }
239
-
240
- val animatedTopPadding by animateDpAsState(
241
- targetValue = (HEADER_HEIGHT.dp - scrollDp).coerceIn(0.dp, HEADER_HEIGHT.dp),
242
- label = "AnimatedTopPadding"
243
- )
244
- Spacer(Modifier.height(animatedTopPadding))
245
- }
246
- Column (Modifier
247
- .fillMaxWidth()
248
- .weight(1f)
249
- .conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
250
- verticalScroll(scrollState)
251
- }
252
- ) {
253
- ScreenContent(content = content)
254
- }
255
-
256
- if (options.footerComponent != null){
257
- val footerHeight = LocalFooterHeightPx.current
258
- val footerHeightDp = with(density) { footerHeight.value.toDp() }
259
- Spacer(Modifier.height(footerHeightDp))
260
- }
261
- }
262
-
263
- @Composable
264
- fun ScreenContent(content: @Composable () -> Unit){
265
- val scrollState = LocalScrollState.current
266
- val options = LocalOptions.current
267
-
268
- if (options.headerType is HeaderType.Animated){
269
- val animatedHeader = options.headerType
270
- Box {
271
- Box(Modifier.fillMaxWidth().aspectRatio(animatedHeader.aspectRatio.value)){
272
- animatedHeader.composable.invoke(scrollState.value)
273
- }
274
- Box(Modifier.offset(x = 0.dp, y = AppStatusBar.current + HEADER_HEIGHT.dp + animatedHeader.layoutOffSet)){
275
- content()
276
- }
277
- }
278
- } else {
279
- content()
280
- }
281
- }
282
-
283
- @Composable
284
- fun FooterContent(){
285
- val options = LocalOptions.current
286
- if (options.footerComponent != null){
287
- val ime = WindowInsets.ime
288
- val density = LocalDensity.current
289
- val imeBottom = ime.getBottom(density)
290
- val thresholdPx = with(density) { 50.dp.toPx() }
291
- val isKeyboardVisible = imeBottom > thresholdPx
292
- val bottomPadding = if (isKeyboardVisible) 0.dp else AppNavigationBar.current
293
- Footer(footerComponent = options.footerComponent, bottomPadding = bottomPadding)
294
- }
295
- }
296
-
297
- @Composable
298
- fun OverplayView(bottomTabIndex: Int, id: Int){
299
- val overplayType = OverplayComponentRegistry.getOverplayType()
300
-
301
- if (overplayType != null) {
302
- Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 8f).fillMaxSize()){
303
- if (bottomTabIndex != -1) return@Box
304
- if (OverplayComponentRegistry.currentRootId() != id) return@Box
305
- OverplayComponentRegistry.OverlayComponent()
306
- }
307
- }
308
- }
309
-
310
- @Composable
311
- fun Footer(footerComponent: @Composable (() -> Unit)?, bottomPadding: Dp) {
312
- if (footerComponent == null) return
313
-
314
- val footerHeightPx = LocalFooterHeightPx.current
315
-
316
- val shadowBrush = remember {
317
- Brush.verticalGradient(
318
- colors = listOf(Color.Transparent, Color.Black.copy(alpha = 0.05f))
319
- )
320
- }
321
-
322
- Box(Modifier.onGloballyPositioned {
323
- if (footerHeightPx.intValue != it.size.height) footerHeightPx.intValue = it.size.height
324
- }) {
325
- Box(Modifier
326
- .fillMaxWidth()
327
- .background(AppTheme.current.colors.background.surface)
328
- .conditional(IsShowBaseLineDebug) {
329
- border(1.dp, Colors.blue_03)
330
- }
331
- .padding(top = Spacing.S, start = Spacing.M, end = Spacing.M, bottom = bottomPadding + Spacing.S)
332
- ){
333
- footerComponent.invoke()
334
- }
335
-
336
- Box(modifier = Modifier
337
- .fillMaxWidth()
338
- .height(6.dp)
339
- .offset(x = 0.dp, y = (-6).dp)
340
- .background(shadowBrush)
341
- )
342
- }
343
- }
344
-
345
- data class InputSearchLayoutParams(
346
- val topPadding: Dp,
347
- val startPadding: Dp,
348
- val endPadding: Dp
349
- )
350
- @Composable
351
- fun SearchAnimated(
352
- isScrollInProgress: Boolean
353
- ) {
354
- val scrollState = LocalScrollState.current
355
- val options = LocalOptions.current
356
- val navigator = LocalNavigator.current
357
- val density = LocalDensity.current
358
-
359
- val scrollDp = with(density) { scrollState.value.toDp() }
360
-
361
- val inputSearchType = getInputSearchType(options)
362
- val headerRightWidthPx = LocalHeaderRightWidthPx.current
363
- val headerRightWidthDp = with(density) { headerRightWidthPx.intValue.toDp() }
364
-
365
- if (inputSearchType == InputSearchType.None) return
366
- val inputSearchProps = (options.headerType as? HeaderType.DefaultOrExtended)?.inputSearchProps ?: return
367
-
368
- val minTopPadding = AppStatusBar.current
369
- val maxTopPadding = AppStatusBar.current + HEADER_HEIGHT.dp
370
- val minStartPadding = Spacing.M
371
- val maxStartPadding = if (options.hiddenBack) Spacing.M else 52.dp
372
- val minEndPadding = Spacing.M
373
- val maxEndPadding = headerRightWidthDp + if (options.headerRight is HeaderRight.None) Spacing.M else Spacing.M * 2
374
-
375
- val targetColor = lerp(
376
- AppTheme.current.colors.background.surface,
377
- AppTheme.current.colors.background.default,
378
- (scrollDp / minTopPadding).coerceIn(0f, 1f)
379
- )
380
- val animatedColor by animateColorAsState(targetValue = targetColor, label = "BackgroundColor")
381
-
382
- val layoutParams = when (inputSearchType) {
383
- InputSearchType.Header -> {
384
- InputSearchLayoutParams(
385
- topPadding = minTopPadding,
386
- startPadding = maxStartPadding,
387
- endPadding = maxEndPadding
388
- )
389
- }
390
-
391
- InputSearchType.Animated -> {
392
- val animatedTopPadding by animateDpAsState(
393
- targetValue = (maxTopPadding - scrollDp).coerceIn(minTopPadding, maxTopPadding),
394
- label = "AnimatedTopPadding"
395
- )
396
-
397
- val animatedStartPadding by animateDpAsState(
398
- targetValue = (minStartPadding + scrollDp).coerceIn(minStartPadding, maxStartPadding),
399
- label = "AnimatedStartPadding"
400
- )
401
-
402
- val animatedEndPadding by animateDpAsState(
403
- targetValue = (minEndPadding + scrollDp).coerceIn(minEndPadding, maxEndPadding),
404
- label = "AnimatedEndPadding"
405
- )
406
-
407
- val maxPadding = remember(maxTopPadding, maxStartPadding, maxEndPadding) {
408
- maxOf(maxEndPadding, maxStartPadding, maxTopPadding)
409
- }
410
- val snapScrollValue = with(density) { maxPadding.toPx().toInt() }
411
-
412
- LaunchedEffect(isScrollInProgress && scrollState.value != 0 && scrollState.value != snapScrollValue) {
413
- if (scrollDp < maxPadding) {
414
- if (!isScrollInProgress) {
415
- val midpoint = (maxTopPadding - minTopPadding) / 2
416
-
417
- if (scrollDp < midpoint) {
418
- scrollState.animateScrollTo(0)
419
- } else {
420
- scrollState.animateScrollTo(snapScrollValue)
421
- }
422
- }
423
- }
424
- }
425
-
426
- InputSearchLayoutParams(
427
- topPadding = animatedTopPadding,
428
- startPadding = animatedStartPadding,
429
- endPadding = animatedEndPadding
430
- )
431
- }
432
-
433
- InputSearchType.None -> return
434
- }
435
-
436
- Spacer(Modifier.height(layoutParams.topPadding))
437
- Box(
438
- modifier = Modifier
439
- .height(HEADER_HEIGHT.dp)
440
- .fillMaxWidth()
441
- .padding(
442
- start = layoutParams.startPadding,
443
- end = layoutParams.endPadding
444
- ),
445
- contentAlignment = Alignment.Center
446
- ) {
447
- InputSearch(
448
- inputSearchProps = inputSearchProps.copy(
449
- backgroundColor = animatedColor,
450
- onPressButtonText = {
451
- navigator.pop()
452
- }
453
- )
454
- )
455
- }
456
- }
457
-
458
- @Composable
459
- internal fun isKeyboardVisible(): Boolean {
460
- val ime = WindowInsets.ime
461
- val density = LocalDensity.current
462
- return ime.getBottom(density) > 0
463
- }
464
- private fun quantize(value: Int, stepPx: Int): Int {
465
- if (stepPx <= 1) return value
466
- return (value / stepPx) * stepPx
467
- }
468
-
469
- @Composable
470
- fun LazyListState.proxyScrollState(
471
- thresholdPx: Int = 200,
472
- stepPx: Int = 4
473
- ): Pair<ScrollState, Boolean> {
474
- val scrollState = rememberScrollState()
475
- val locked = remember { mutableStateOf(false) }
476
-
477
- LaunchedEffect(this, scrollState, thresholdPx, stepPx) {
478
- snapshotFlow { firstVisibleItemIndex to firstVisibleItemScrollOffset }
479
- .collect { (index, offset) ->
480
- val rawTarget = if (index == 0) offset else SCROLLED_PAST_FIRST_ITEM_THRESHOLD
481
- val shouldLock = rawTarget > thresholdPx
482
- if (locked.value != shouldLock) locked.value = shouldLock
483
-
484
- val desired = if (shouldLock) thresholdPx else quantize(rawTarget, stepPx)
485
-
486
- if (scrollState.value != desired) {
487
- scrollState.scrollTo(desired.coerceAtLeast(0))
488
- }
489
- }
490
- }
491
-
492
- val inProgress = remember { mutableStateOf(false) }
493
- LaunchedEffect(this, thresholdPx) {
494
- snapshotFlow { isScrollInProgress }
495
- .collect { progressing ->
496
- inProgress.value = if (locked.value) false else progressing
497
- }
498
- }
499
-
500
- return scrollState to inProgress.value
501
- }
502
-
503
- @Composable
504
- fun ScrollState.proxyLimitedScrollState(
505
- thresholdPx: Int = 200,
506
- stepPx: Int = 4
507
- ): Pair<ScrollState, Boolean> {
508
- val proxy = rememberScrollState()
509
- val locked = remember { mutableStateOf(false) }
510
-
511
- LaunchedEffect(this, proxy, thresholdPx, stepPx) {
512
- snapshotFlow { value }
513
- .collect { rawTarget ->
514
- val shouldLock = rawTarget > thresholdPx
515
- if (locked.value != shouldLock) locked.value = shouldLock
516
-
517
- val desired = if (shouldLock) thresholdPx else quantize(rawTarget, stepPx)
518
-
519
- if (proxy.value != desired) {
520
- proxy.scrollTo(desired.coerceAtLeast(0))
521
- }
522
- }
523
- }
524
-
525
- val inProgress = remember { mutableStateOf(false) }
526
- LaunchedEffect(this, thresholdPx) {
527
- snapshotFlow { isScrollInProgress }
528
- .collect { progressing ->
529
- inProgress.value = if (locked.value) false else progressing
530
- }
531
- }
532
-
533
- return proxy to inProgress.value
534
- }
535
-
536
- private const val SCROLLED_PAST_FIRST_ITEM_THRESHOLD = 10_000
537
-
538
- internal val LocalScrollState = staticCompositionLocalOf<ScrollState> { error("No Scroll State provided") }
539
- internal val LocalOptions = staticCompositionLocalOf<NavigationOptions> { error("No NavigationOptions provided") }
540
-
541
- val StackScreenScrollableState = staticCompositionLocalOf<ScrollableState?> { null }
542
-
543
- internal fun getInputSearchType(options: NavigationOptions): InputSearchType{
544
- return when (val headerType = options.headerType) {
545
- is HeaderType.DefaultOrExtended -> when {
546
- headerType.inputSearchProps == null -> InputSearchType.None
547
- headerType.useAnimated -> InputSearchType.Animated
548
- else -> InputSearchType.Header
549
- }
550
- else -> InputSearchType.None
551
- }
552
- }