@momo-kits/native-kits 0.152.4-scale.4 → 0.152.5-klib.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.
- package/README.md +175 -5
- package/ios/native-kits.podspec +18 -16
- package/package.json +2 -4
- package/CODE_OF_CONDUCT.md +0 -133
- package/CONTRIBUTING.md +0 -114
- package/LICENSE +0 -20
- package/build.gradle.kts +0 -32
- package/compose/MoMoComposeKits.podspec +0 -54
- package/compose/build.gradle.kts +0 -149
- package/compose/src/androidMain/AndroidManifest.xml +0 -2
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -105
- package/compose/src/commonMain/composeResources/files/lottie_circle_loader.json +0 -1
- package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
- package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
- package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -57
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -201
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -222
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -48
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -308
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -715
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -214
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -404
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -78
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -27
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -334
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -345
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -90
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -133
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -543
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -23
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -69
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -143
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -179
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -111
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -395
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -164
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -234
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -226
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -227
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -241
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -235
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -364
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -50
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -34
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -85
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -338
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -95
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -64
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -89
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -91
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -91
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -208
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -172
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -199
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -237
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -191
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -306
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -13
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -189
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -293
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -35
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -59
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -68
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -49
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -232
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -111
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -94
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -159
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -302
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScaleSizeScope.kt +0 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -483
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -169
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -217
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -180
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -251
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -80
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -306
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -31
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -385
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -125
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -38
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -62
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -88
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -144
- package/gradle.properties +0 -19
- package/gradlew +0 -240
- package/gradlew.bat +0 -91
- package/ios/Theme.md +0 -18
- package/local.properties +0 -8
- package/settings.gradle.kts +0 -25
|
@@ -1,715 +0,0 @@
|
|
|
1
|
-
package vn.momo.kits.application
|
|
2
|
-
|
|
3
|
-
import androidx.compose.animation.animateContentSize
|
|
4
|
-
import androidx.compose.foundation.ScrollState
|
|
5
|
-
import androidx.compose.foundation.background
|
|
6
|
-
import androidx.compose.foundation.border
|
|
7
|
-
import androidx.compose.foundation.gestures.detectTapGestures
|
|
8
|
-
import androidx.compose.foundation.interaction.FocusInteraction
|
|
9
|
-
import androidx.compose.foundation.interaction.MutableInteractionSource
|
|
10
|
-
import androidx.compose.foundation.layout.Arrangement
|
|
11
|
-
import androidx.compose.foundation.layout.Box
|
|
12
|
-
import androidx.compose.foundation.layout.Column
|
|
13
|
-
import androidx.compose.foundation.layout.Row
|
|
14
|
-
import androidx.compose.foundation.layout.WindowInsets
|
|
15
|
-
import androidx.compose.foundation.layout.asPaddingValues
|
|
16
|
-
import androidx.compose.foundation.layout.fillMaxSize
|
|
17
|
-
import androidx.compose.foundation.layout.fillMaxWidth
|
|
18
|
-
import androidx.compose.foundation.layout.height
|
|
19
|
-
import androidx.compose.foundation.layout.ime
|
|
20
|
-
import androidx.compose.foundation.layout.navigationBars
|
|
21
|
-
import androidx.compose.foundation.layout.offset
|
|
22
|
-
import androidx.compose.foundation.layout.padding
|
|
23
|
-
import androidx.compose.foundation.layout.size
|
|
24
|
-
import androidx.compose.foundation.layout.sizeIn
|
|
25
|
-
import androidx.compose.foundation.rememberScrollState
|
|
26
|
-
import androidx.compose.foundation.shape.CircleShape
|
|
27
|
-
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
28
|
-
import androidx.compose.foundation.text.BasicTextField
|
|
29
|
-
import androidx.compose.foundation.text.KeyboardActions
|
|
30
|
-
import androidx.compose.foundation.text.KeyboardOptions
|
|
31
|
-
import androidx.compose.foundation.verticalScroll
|
|
32
|
-
import androidx.compose.runtime.Composable
|
|
33
|
-
import androidx.compose.runtime.LaunchedEffect
|
|
34
|
-
import androidx.compose.runtime.MutableState
|
|
35
|
-
import androidx.compose.runtime.Stable
|
|
36
|
-
import androidx.compose.runtime.State
|
|
37
|
-
import androidx.compose.runtime.derivedStateOf
|
|
38
|
-
import androidx.compose.runtime.getValue
|
|
39
|
-
import androidx.compose.runtime.mutableStateOf
|
|
40
|
-
import androidx.compose.runtime.produceState
|
|
41
|
-
import androidx.compose.runtime.remember
|
|
42
|
-
import androidx.compose.runtime.rememberUpdatedState
|
|
43
|
-
import androidx.compose.runtime.snapshotFlow
|
|
44
|
-
import androidx.compose.ui.Alignment
|
|
45
|
-
import androidx.compose.ui.Modifier
|
|
46
|
-
import androidx.compose.ui.composed
|
|
47
|
-
import androidx.compose.ui.draw.clip
|
|
48
|
-
import androidx.compose.ui.draw.drawBehind
|
|
49
|
-
import androidx.compose.ui.draw.drawWithContent
|
|
50
|
-
import androidx.compose.ui.geometry.Offset
|
|
51
|
-
import androidx.compose.ui.graphics.Brush
|
|
52
|
-
import androidx.compose.ui.graphics.Color
|
|
53
|
-
import androidx.compose.ui.graphics.graphicsLayer
|
|
54
|
-
import androidx.compose.ui.input.pointer.pointerInput
|
|
55
|
-
import androidx.compose.ui.layout.Layout
|
|
56
|
-
import androidx.compose.ui.layout.Measurable
|
|
57
|
-
import androidx.compose.ui.layout.MeasurePolicy
|
|
58
|
-
import androidx.compose.ui.layout.MeasureResult
|
|
59
|
-
import androidx.compose.ui.layout.MeasureScope
|
|
60
|
-
import androidx.compose.ui.layout.Placeable
|
|
61
|
-
import androidx.compose.ui.layout.layoutId
|
|
62
|
-
import androidx.compose.ui.platform.LocalDensity
|
|
63
|
-
import androidx.compose.ui.platform.LocalFocusManager
|
|
64
|
-
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
|
|
65
|
-
import androidx.compose.ui.text.style.TextOverflow
|
|
66
|
-
import androidx.compose.ui.unit.Constraints
|
|
67
|
-
import androidx.compose.ui.unit.Dp
|
|
68
|
-
import androidx.compose.ui.unit.IntOffset
|
|
69
|
-
import androidx.compose.ui.unit.LayoutDirection
|
|
70
|
-
import androidx.compose.ui.unit.dp
|
|
71
|
-
import androidx.compose.ui.unit.sp
|
|
72
|
-
import kotlinx.coroutines.flow.collectLatest
|
|
73
|
-
import kotlinx.coroutines.flow.mapNotNull
|
|
74
|
-
import vn.momo.kits.components.Icon
|
|
75
|
-
import vn.momo.kits.components.Text
|
|
76
|
-
import vn.momo.kits.const.AppTheme
|
|
77
|
-
import vn.momo.kits.const.Colors
|
|
78
|
-
import vn.momo.kits.const.Radius
|
|
79
|
-
import vn.momo.kits.const.Spacing
|
|
80
|
-
import vn.momo.kits.const.Typography
|
|
81
|
-
import vn.momo.kits.modifier.kitsAutomationId
|
|
82
|
-
import vn.momo.kits.modifier.noFeedbackClickable
|
|
83
|
-
import vn.momo.kits.modifier.setAutomationId
|
|
84
|
-
import vn.momo.kits.modifier.shadow
|
|
85
|
-
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
86
|
-
import kotlin.math.max
|
|
87
|
-
|
|
88
|
-
@Composable
|
|
89
|
-
fun LiteScreen(
|
|
90
|
-
scrollable: Boolean = true,
|
|
91
|
-
scrollState: ScrollState? = null,
|
|
92
|
-
headerType: HeaderType = HeaderType.DEFAULT,
|
|
93
|
-
verticalArrangement: Arrangement.Vertical = Arrangement.Top,
|
|
94
|
-
horizontalAlignment: Alignment.Horizontal = Alignment.Start,
|
|
95
|
-
backgroundColor: Color = AppTheme.current.colors.background.default,
|
|
96
|
-
/* Begin of header props */
|
|
97
|
-
title: String? = null,
|
|
98
|
-
inputSearchProps: LiteInputSearchProps? = null,
|
|
99
|
-
goBack: (() -> Unit)? = null,
|
|
100
|
-
headerRight: @Composable() (() -> Unit)? = null,
|
|
101
|
-
useAnimationSearch: Boolean = true,
|
|
102
|
-
titlePosition: TitlePosition = TitlePosition.LEFT,
|
|
103
|
-
headerRightData: HeaderRightData? = null,
|
|
104
|
-
/* End of header props */
|
|
105
|
-
|
|
106
|
-
screenContent: @Composable () -> Unit,
|
|
107
|
-
) {
|
|
108
|
-
val content by rememberUpdatedState(screenContent)
|
|
109
|
-
|
|
110
|
-
val finalScrollState = scrollState ?: rememberScrollState()
|
|
111
|
-
|
|
112
|
-
Column(
|
|
113
|
-
modifier = Modifier
|
|
114
|
-
.fillMaxSize()
|
|
115
|
-
.background(color = backgroundColor)
|
|
116
|
-
.hideKeyboardOnTap(),
|
|
117
|
-
verticalArrangement = verticalArrangement,
|
|
118
|
-
horizontalAlignment = horizontalAlignment,
|
|
119
|
-
) {
|
|
120
|
-
val contentModifier = remember(scrollable, finalScrollState) {
|
|
121
|
-
var res = Modifier.weight(1f)
|
|
122
|
-
if (scrollable) {
|
|
123
|
-
res = res.verticalScroll(finalScrollState)
|
|
124
|
-
}
|
|
125
|
-
res
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
LiteScreenHeader(
|
|
129
|
-
scrollState = finalScrollState,
|
|
130
|
-
title = title,
|
|
131
|
-
headerRight = headerRight,
|
|
132
|
-
headerType = headerType,
|
|
133
|
-
onGoBack = goBack,
|
|
134
|
-
inputSearchProps = inputSearchProps,
|
|
135
|
-
titlePosition = titlePosition,
|
|
136
|
-
useAnimationSearch = useAnimationSearch,
|
|
137
|
-
headerRightData = headerRightData,
|
|
138
|
-
)
|
|
139
|
-
|
|
140
|
-
Box(
|
|
141
|
-
modifier = contentModifier,
|
|
142
|
-
contentAlignment = Alignment.TopCenter,
|
|
143
|
-
) {
|
|
144
|
-
content()
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
private object HeaderId {
|
|
150
|
-
private const val PACKAGE_NAME = "vn.momo.compose.kits"
|
|
151
|
-
const val BACK_ID = "${PACKAGE_NAME}.back"
|
|
152
|
-
const val HEADER_RIGHT_ID = "${PACKAGE_NAME}.headerRight"
|
|
153
|
-
const val INPUT_SEARCH_ID = "${PACKAGE_NAME}.inputSearch"
|
|
154
|
-
const val TITLE_ID = "${PACKAGE_NAME}.title"
|
|
155
|
-
|
|
156
|
-
val EXTENDED_HEADER_HEIGHT = 154.dp
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
@Composable
|
|
160
|
-
private fun LiteScreenHeader(
|
|
161
|
-
scrollState: ScrollState?,
|
|
162
|
-
title: String? = null,
|
|
163
|
-
tintColor: Color? = null,
|
|
164
|
-
headerRightData: HeaderRightData? = null,
|
|
165
|
-
headerType: HeaderType = HeaderType.DEFAULT,
|
|
166
|
-
titlePosition: TitlePosition = TitlePosition.LEFT,
|
|
167
|
-
useAnimationSearch: Boolean = true,
|
|
168
|
-
onGoBack: (() -> Unit)? = null,
|
|
169
|
-
inputSearchProps: LiteInputSearchProps? = null,
|
|
170
|
-
headerRight: @Composable (() -> Unit)? = null,
|
|
171
|
-
) {
|
|
172
|
-
val statusBarHeight = getAppStatusBarHeight()
|
|
173
|
-
if (headerType == HeaderType.NONE) {
|
|
174
|
-
Box(modifier = Modifier.height(statusBarHeight))
|
|
175
|
-
return
|
|
176
|
-
}
|
|
177
|
-
val theme = AppTheme.current
|
|
178
|
-
val density = LocalDensity.current
|
|
179
|
-
|
|
180
|
-
val isHeaderExtend = remember(headerType) {
|
|
181
|
-
headerType == HeaderType.EXTENDED
|
|
182
|
-
}
|
|
183
|
-
val backgroundHeight = remember(isHeaderExtend, statusBarHeight) {
|
|
184
|
-
if (!isHeaderExtend) statusBarHeight + HEADER_HEIGHT.dp
|
|
185
|
-
else HeaderId.EXTENDED_HEADER_HEIGHT
|
|
186
|
-
}
|
|
187
|
-
val listGradientColors = remember {
|
|
188
|
-
listOf(
|
|
189
|
-
Color(0xFFFDCADE),
|
|
190
|
-
Color(0x00FDCADE),
|
|
191
|
-
)
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
val headerColor = remember(tintColor, theme) {
|
|
195
|
-
if (tintColor == Colors.black_01) HeaderColor(
|
|
196
|
-
tintIconColor = tintColor,
|
|
197
|
-
backgroundButton = Colors.black_20.copy(alpha = 0.6f),
|
|
198
|
-
borderColor = Colors.black_01.copy(alpha = 0.2f)
|
|
199
|
-
)
|
|
200
|
-
else HeaderColor(
|
|
201
|
-
tintIconColor = tintColor ?: theme.colors.text.default,
|
|
202
|
-
backgroundButton = Colors.black_01.copy(alpha = 0.6f),
|
|
203
|
-
borderColor = Colors.black_20.copy(alpha = 0.2f)
|
|
204
|
-
)
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
val scrollPercentage = produceState(
|
|
208
|
-
initialValue = 0f,
|
|
209
|
-
key1 = useAnimationSearch,
|
|
210
|
-
key2 = scrollState,
|
|
211
|
-
key3 = backgroundHeight,
|
|
212
|
-
) {
|
|
213
|
-
if (!useAnimationSearch) return@produceState
|
|
214
|
-
scrollState ?: return@produceState
|
|
215
|
-
val rangePx = with(density) { backgroundHeight.toPx() }
|
|
216
|
-
snapshotFlow { scrollState.value }.collectLatest {
|
|
217
|
-
value = (it / rangePx).coerceIn(0f, 1f)
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
val titleStyle = remember {
|
|
222
|
-
Typography.actionSBold.copy(
|
|
223
|
-
fontSize = 15.sp,
|
|
224
|
-
lineHeight = 22.sp,
|
|
225
|
-
)
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
val titleModifier = remember {
|
|
229
|
-
Modifier
|
|
230
|
-
.kitsAutomationId("title_navigation_header")
|
|
231
|
-
.layoutId(HeaderId.TITLE_ID)
|
|
232
|
-
.graphicsLayer {
|
|
233
|
-
alpha = if (isHeaderExtend && inputSearchProps != null && useAnimationSearch)
|
|
234
|
-
(1 - scrollPercentage.value * 2).coerceIn(0f, 1f)
|
|
235
|
-
else 1f
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
val policy = remember(
|
|
240
|
-
useAnimationSearch,
|
|
241
|
-
isHeaderExtend,
|
|
242
|
-
statusBarHeight,
|
|
243
|
-
titlePosition,
|
|
244
|
-
scrollPercentage,
|
|
245
|
-
) {
|
|
246
|
-
LiteScreenHeaderPolicy(
|
|
247
|
-
useAnimationSearch = useAnimationSearch,
|
|
248
|
-
isHeaderExtend = isHeaderExtend,
|
|
249
|
-
statusBarHeight = statusBarHeight,
|
|
250
|
-
titlePosition = titlePosition,
|
|
251
|
-
scrollPercentage = scrollPercentage,
|
|
252
|
-
)
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
Layout(
|
|
256
|
-
modifier = Modifier
|
|
257
|
-
.animateContentSize()
|
|
258
|
-
.drawBehind {
|
|
259
|
-
val headerHeight = max(
|
|
260
|
-
HeaderId.EXTENDED_HEADER_HEIGHT.toPx(),
|
|
261
|
-
size.height,
|
|
262
|
-
)
|
|
263
|
-
drawRect(color = Colors.black_01)
|
|
264
|
-
drawRect(
|
|
265
|
-
brush = Brush.linearGradient(
|
|
266
|
-
colors = listGradientColors,
|
|
267
|
-
start = Offset.Zero,
|
|
268
|
-
end = Offset(
|
|
269
|
-
x = 0f,
|
|
270
|
-
y = headerHeight * (1 - scrollPercentage.value),
|
|
271
|
-
),
|
|
272
|
-
)
|
|
273
|
-
)
|
|
274
|
-
},
|
|
275
|
-
content = {
|
|
276
|
-
if (onGoBack != null) {
|
|
277
|
-
Box(
|
|
278
|
-
modifier = Modifier
|
|
279
|
-
.size(28.dp)
|
|
280
|
-
.layoutId(HeaderId.BACK_ID)
|
|
281
|
-
.clip(CircleShape)
|
|
282
|
-
.border(
|
|
283
|
-
width = 0.2.dp,
|
|
284
|
-
color = headerColor.borderColor,
|
|
285
|
-
shape = CircleShape,
|
|
286
|
-
)
|
|
287
|
-
.background(color = headerColor.backgroundButton)
|
|
288
|
-
.noFeedbackClickable(onClick = onGoBack)
|
|
289
|
-
.setAutomationId("btn_navigation_back")
|
|
290
|
-
.padding(Spacing.XS),
|
|
291
|
-
) {
|
|
292
|
-
Icon(
|
|
293
|
-
source = "arrow-back",
|
|
294
|
-
color = headerColor.tintIconColor,
|
|
295
|
-
size = 20.dp,
|
|
296
|
-
)
|
|
297
|
-
}
|
|
298
|
-
}
|
|
299
|
-
|
|
300
|
-
Box(
|
|
301
|
-
modifier = Modifier
|
|
302
|
-
.layoutId(HeaderId.HEADER_RIGHT_ID)
|
|
303
|
-
) {
|
|
304
|
-
if (headerRight != null) {
|
|
305
|
-
headerRight()
|
|
306
|
-
} else {
|
|
307
|
-
HeaderRight(
|
|
308
|
-
headerRight = headerRightData,
|
|
309
|
-
tintColor = tintColor,
|
|
310
|
-
)
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
|
|
314
|
-
if (inputSearchProps != null) {
|
|
315
|
-
LiteInputSearch(
|
|
316
|
-
modifier = Modifier.layoutId(HeaderId.INPUT_SEARCH_ID),
|
|
317
|
-
inputSearchProps = inputSearchProps,
|
|
318
|
-
)
|
|
319
|
-
}
|
|
320
|
-
if (title != null && (inputSearchProps == null || isHeaderExtend)) {
|
|
321
|
-
Text(
|
|
322
|
-
text = title,
|
|
323
|
-
color = headerColor.tintIconColor,
|
|
324
|
-
style = titleStyle,
|
|
325
|
-
modifier = titleModifier,
|
|
326
|
-
maxLines = 1,
|
|
327
|
-
overflow = TextOverflow.Ellipsis
|
|
328
|
-
)
|
|
329
|
-
}
|
|
330
|
-
},
|
|
331
|
-
measurePolicy = policy,
|
|
332
|
-
)
|
|
333
|
-
}
|
|
334
|
-
|
|
335
|
-
private class LiteScreenHeaderPolicy(
|
|
336
|
-
private val useAnimationSearch: Boolean,
|
|
337
|
-
private val isHeaderExtend: Boolean,
|
|
338
|
-
private val statusBarHeight: Dp,
|
|
339
|
-
private val scrollPercentage: State<Float>,
|
|
340
|
-
private val titlePosition: TitlePosition,
|
|
341
|
-
) : MeasurePolicy {
|
|
342
|
-
|
|
343
|
-
override fun MeasureScope.measure(
|
|
344
|
-
measurables: List<Measurable>,
|
|
345
|
-
constraints: Constraints
|
|
346
|
-
): MeasureResult {
|
|
347
|
-
val spacing12 = Spacing.M.roundToPx()
|
|
348
|
-
val statusBarPx = statusBarHeight.roundToPx()
|
|
349
|
-
val scrollPercent = scrollPercentage.value
|
|
350
|
-
|
|
351
|
-
val realConstraints = constraints.copy(
|
|
352
|
-
minWidth = 0,
|
|
353
|
-
minHeight = 0,
|
|
354
|
-
maxWidth = (constraints.maxWidth - spacing12 * 2)
|
|
355
|
-
.coerceAtLeast(0),
|
|
356
|
-
)
|
|
357
|
-
val backIconPlaceable =
|
|
358
|
-
measurables.find { it.layoutId == HeaderId.BACK_ID }?.measure(realConstraints)
|
|
359
|
-
val headerRightPlaceable =
|
|
360
|
-
measurables.find { it.layoutId == HeaderId.HEADER_RIGHT_ID }?.measure(
|
|
361
|
-
realConstraints.copy(
|
|
362
|
-
maxWidth = realConstraints.maxWidth / 2,
|
|
363
|
-
)
|
|
364
|
-
)
|
|
365
|
-
val inputSearchConstraints = if (isHeaderExtend) {
|
|
366
|
-
val minWidth =
|
|
367
|
-
if (useAnimationSearch) realConstraints.maxWidth - backIconPlaceable.safeWidth - headerRightPlaceable.safeWidth - spacing12 * 2
|
|
368
|
-
else realConstraints.maxWidth
|
|
369
|
-
realConstraints.copy(
|
|
370
|
-
maxWidth = (realConstraints.maxWidth * (1 - scrollPercent)).toInt()
|
|
371
|
-
.coerceAtLeast(minWidth)
|
|
372
|
-
)
|
|
373
|
-
} else realConstraints.copy(
|
|
374
|
-
maxWidth = realConstraints.maxWidth - backIconPlaceable.safeWidth - headerRightPlaceable.safeWidth - spacing12 * 2
|
|
375
|
-
)
|
|
376
|
-
val inputSearchPlaceable = measurables.find { it.layoutId == HeaderId.INPUT_SEARCH_ID }
|
|
377
|
-
?.measure(inputSearchConstraints)
|
|
378
|
-
val titlePlaceable = measurables.find { it.layoutId == HeaderId.TITLE_ID }?.measure(
|
|
379
|
-
constraints = realConstraints.copy(
|
|
380
|
-
maxWidth = realConstraints.maxWidth - backIconPlaceable.safeWidth - headerRightPlaceable.safeWidth - spacing12 * 2
|
|
381
|
-
)
|
|
382
|
-
)
|
|
383
|
-
|
|
384
|
-
val firstRowMaxHeight = buildList {
|
|
385
|
-
add(backIconPlaceable.safeHeight)
|
|
386
|
-
add(headerRightPlaceable.safeHeight)
|
|
387
|
-
if (!isHeaderExtend) {
|
|
388
|
-
add(inputSearchPlaceable.safeHeight)
|
|
389
|
-
}
|
|
390
|
-
if (isHeaderExtend) {
|
|
391
|
-
add(titlePlaceable.safeHeight)
|
|
392
|
-
}
|
|
393
|
-
}.max()
|
|
394
|
-
|
|
395
|
-
var defaultHeight = statusBarPx + spacing12 + firstRowMaxHeight + spacing12
|
|
396
|
-
if (isHeaderExtend) {
|
|
397
|
-
defaultHeight += inputSearchPlaceable.safeHeight + spacing12
|
|
398
|
-
}
|
|
399
|
-
val height = when {
|
|
400
|
-
!useAnimationSearch && !isHeaderExtend -> defaultHeight
|
|
401
|
-
else -> (defaultHeight - scrollPercent * (defaultHeight - statusBarPx - HEADER_HEIGHT.dp.roundToPx())).toInt()
|
|
402
|
-
}
|
|
403
|
-
|
|
404
|
-
return layout(
|
|
405
|
-
width = constraints.maxWidth,
|
|
406
|
-
height = height,
|
|
407
|
-
) {
|
|
408
|
-
val startX = spacing12
|
|
409
|
-
val startY = statusBarPx + spacing12
|
|
410
|
-
var curX = startX
|
|
411
|
-
var curY = startY
|
|
412
|
-
|
|
413
|
-
if (backIconPlaceable != null) {
|
|
414
|
-
backIconPlaceable.place(
|
|
415
|
-
x = startX,
|
|
416
|
-
y = startY + backIconPlaceable.verticalCenterOffset(firstRowMaxHeight),
|
|
417
|
-
)
|
|
418
|
-
curX += backIconPlaceable.safeWidth + spacing12
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
headerRightPlaceable?.place(
|
|
422
|
-
x = constraints.maxWidth - spacing12 - headerRightPlaceable.safeWidth,
|
|
423
|
-
y = startY + headerRightPlaceable.verticalCenterOffset(firstRowMaxHeight),
|
|
424
|
-
)
|
|
425
|
-
|
|
426
|
-
val titleOffset = IntOffset(
|
|
427
|
-
x = if (titlePosition == TitlePosition.LEFT) curX
|
|
428
|
-
else titlePlaceable.horizontalCenterOffset(
|
|
429
|
-
space = constraints.maxWidth,
|
|
430
|
-
layoutDirection = layoutDirection,
|
|
431
|
-
),
|
|
432
|
-
y = startY + titlePlaceable.verticalCenterOffset(firstRowMaxHeight),
|
|
433
|
-
)
|
|
434
|
-
|
|
435
|
-
titlePlaceable?.place(titleOffset)
|
|
436
|
-
|
|
437
|
-
if (backIconPlaceable != null || headerRightPlaceable != null || titlePlaceable != null) {
|
|
438
|
-
curY += firstRowMaxHeight + spacing12
|
|
439
|
-
}
|
|
440
|
-
|
|
441
|
-
val inputSearchOffset = if (isHeaderExtend) {
|
|
442
|
-
IntOffset(
|
|
443
|
-
x = startX + ((backIconPlaceable.safeWidth + spacing12) * (scrollPercent * 2f).coerceIn(
|
|
444
|
-
0f, 1f
|
|
445
|
-
)).toInt(),
|
|
446
|
-
y = (curY * (1 - scrollPercent)).toInt().coerceAtLeast(
|
|
447
|
-
startY + inputSearchPlaceable.verticalCenterOffset(firstRowMaxHeight)
|
|
448
|
-
),
|
|
449
|
-
)
|
|
450
|
-
} else {
|
|
451
|
-
IntOffset(
|
|
452
|
-
x = curX,
|
|
453
|
-
y = startY + inputSearchPlaceable.verticalCenterOffset(firstRowMaxHeight),
|
|
454
|
-
)
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
inputSearchPlaceable?.place(inputSearchOffset)
|
|
458
|
-
}
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
private val Placeable?.safeHeight
|
|
462
|
-
get() = this?.height ?: 0
|
|
463
|
-
private val Placeable?.safeWidth
|
|
464
|
-
get() = this?.width ?: 0
|
|
465
|
-
|
|
466
|
-
private fun Placeable?.verticalCenterOffset(space: Int): Int {
|
|
467
|
-
if (this == null) return 0
|
|
468
|
-
return Alignment.CenterVertically.align(safeHeight, space)
|
|
469
|
-
}
|
|
470
|
-
|
|
471
|
-
private fun Placeable?.horizontalCenterOffset(
|
|
472
|
-
space: Int,
|
|
473
|
-
layoutDirection: LayoutDirection
|
|
474
|
-
): Int {
|
|
475
|
-
if (this == null) return 0
|
|
476
|
-
return Alignment.CenterHorizontally.align(safeWidth, space, layoutDirection)
|
|
477
|
-
}
|
|
478
|
-
}
|
|
479
|
-
|
|
480
|
-
private val EMPTY_FUNC = {}
|
|
481
|
-
|
|
482
|
-
@Stable
|
|
483
|
-
data class LiteInputSearchProps(
|
|
484
|
-
val textFieldState: MutableState<String>,
|
|
485
|
-
val onValueChange: (String) -> Unit,
|
|
486
|
-
val onClear: () -> Unit = EMPTY_FUNC,
|
|
487
|
-
val clearCondition: (() -> Boolean)? = null,
|
|
488
|
-
val modifier: Modifier = Modifier,
|
|
489
|
-
val onFocused: (() -> Unit) = EMPTY_FUNC,
|
|
490
|
-
val keyboardOptions: KeyboardOptions = KeyboardOptions.Default,
|
|
491
|
-
val keyboardActions: KeyboardActions = KeyboardActions.Default,
|
|
492
|
-
val onKeyboardAction: (() -> Unit) = EMPTY_FUNC,
|
|
493
|
-
|
|
494
|
-
val btnText: String? = null,
|
|
495
|
-
val isShowBtnText: Boolean = !btnText.isNullOrEmpty(),
|
|
496
|
-
val onPressBtnText: (() -> Unit) = EMPTY_FUNC,
|
|
497
|
-
|
|
498
|
-
val disabled: Boolean = false,
|
|
499
|
-
|
|
500
|
-
val placeHolder: String? = null,
|
|
501
|
-
|
|
502
|
-
val iconRightTextField: @Composable ((Modifier) -> Unit)? = null,
|
|
503
|
-
)
|
|
504
|
-
|
|
505
|
-
@Composable
|
|
506
|
-
private fun LiteInputSearch(
|
|
507
|
-
modifier: Modifier = Modifier,
|
|
508
|
-
inputSearchProps: LiteInputSearchProps? = null,
|
|
509
|
-
) {
|
|
510
|
-
inputSearchProps ?: return
|
|
511
|
-
val theme = AppTheme.current
|
|
512
|
-
|
|
513
|
-
val isFocused = remember { mutableStateOf(false) }
|
|
514
|
-
val interactionSource = remember { MutableInteractionSource() }
|
|
515
|
-
val textState by remember { inputSearchProps.textFieldState }
|
|
516
|
-
|
|
517
|
-
val isShowBtnText by remember(inputSearchProps.isShowBtnText, inputSearchProps.btnText) {
|
|
518
|
-
derivedStateOf {
|
|
519
|
-
inputSearchProps.isShowBtnText && inputSearchProps.btnText.isNullOrEmpty()
|
|
520
|
-
}
|
|
521
|
-
}
|
|
522
|
-
val inputFieldStyle = remember(theme) {
|
|
523
|
-
Typography.bodyDefaultRegular.copy(
|
|
524
|
-
color = theme.colors.text.default,
|
|
525
|
-
)
|
|
526
|
-
}
|
|
527
|
-
|
|
528
|
-
LaunchedEffect(inputSearchProps.onFocused) {
|
|
529
|
-
interactionSource.interactions.mapNotNull { it as? FocusInteraction }.collectLatest {
|
|
530
|
-
val isFocus = it is FocusInteraction.Focus
|
|
531
|
-
isFocused.value = isFocus
|
|
532
|
-
if (isFocus) inputSearchProps.onFocused()
|
|
533
|
-
}
|
|
534
|
-
}
|
|
535
|
-
|
|
536
|
-
Row(
|
|
537
|
-
modifier = modifier,
|
|
538
|
-
verticalAlignment = Alignment.CenterVertically,
|
|
539
|
-
) {
|
|
540
|
-
val textFieldModifier = remember(inputSearchProps.modifier) {
|
|
541
|
-
inputSearchProps.modifier
|
|
542
|
-
.weight(1f)
|
|
543
|
-
.sizeIn(minHeight = 36.dp)
|
|
544
|
-
}
|
|
545
|
-
BasicTextField(
|
|
546
|
-
value = textState,
|
|
547
|
-
onValueChange = inputSearchProps.onValueChange,
|
|
548
|
-
enabled = !inputSearchProps.disabled,
|
|
549
|
-
keyboardOptions = inputSearchProps.keyboardOptions,
|
|
550
|
-
keyboardActions = inputSearchProps.keyboardActions,
|
|
551
|
-
modifier = textFieldModifier,
|
|
552
|
-
textStyle = inputFieldStyle,
|
|
553
|
-
singleLine = true,
|
|
554
|
-
interactionSource = interactionSource,
|
|
555
|
-
decorationBox = { innerTextField ->
|
|
556
|
-
val isShowClear by remember(inputSearchProps.clearCondition, isFocused.value) {
|
|
557
|
-
derivedStateOf {
|
|
558
|
-
inputSearchProps.clearCondition?.invoke() == true || (isFocused.value && textState.isNotEmpty())
|
|
559
|
-
}
|
|
560
|
-
}
|
|
561
|
-
val placeHolder by produceState<String?>(null, inputSearchProps.placeHolder) {
|
|
562
|
-
if (inputSearchProps.placeHolder.isNullOrEmpty()) return@produceState
|
|
563
|
-
snapshotFlow { textState }.collectLatest {
|
|
564
|
-
value = if (it.isEmpty()) inputSearchProps.placeHolder else null
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
val iconRightModifier = remember {
|
|
568
|
-
Modifier
|
|
569
|
-
.padding(start = Spacing.L)
|
|
570
|
-
.drawWithContent {
|
|
571
|
-
val offsetX = -Spacing.S.toPx()
|
|
572
|
-
drawLine(
|
|
573
|
-
start = Offset(
|
|
574
|
-
x = offsetX,
|
|
575
|
-
y = 0f,
|
|
576
|
-
),
|
|
577
|
-
end = Offset(
|
|
578
|
-
x = offsetX,
|
|
579
|
-
y = size.height,
|
|
580
|
-
),
|
|
581
|
-
color = theme.colors.primary,
|
|
582
|
-
strokeWidth = 1.dp.toPx(),
|
|
583
|
-
)
|
|
584
|
-
drawContent()
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
|
|
588
|
-
Row(
|
|
589
|
-
modifier = Modifier
|
|
590
|
-
.background(
|
|
591
|
-
color = theme.colors.background.surface,
|
|
592
|
-
shape = RoundedCornerShape(Radius.XL),
|
|
593
|
-
)
|
|
594
|
-
.padding(
|
|
595
|
-
horizontal = Spacing.M,
|
|
596
|
-
vertical = Spacing.S,
|
|
597
|
-
),
|
|
598
|
-
horizontalArrangement = Arrangement.Start,
|
|
599
|
-
verticalAlignment = Alignment.CenterVertically,
|
|
600
|
-
) {
|
|
601
|
-
Icon(
|
|
602
|
-
source = "navigation_search",
|
|
603
|
-
modifier = Modifier.padding(end = Spacing.XS),
|
|
604
|
-
size = 24.dp,
|
|
605
|
-
color = theme.colors.text.hint
|
|
606
|
-
)
|
|
607
|
-
Box(
|
|
608
|
-
modifier = Modifier.weight(1f),
|
|
609
|
-
contentAlignment = Alignment.CenterStart,
|
|
610
|
-
) {
|
|
611
|
-
if (!placeHolder.isNullOrEmpty()) {
|
|
612
|
-
Text(
|
|
613
|
-
text = placeHolder ?: "",
|
|
614
|
-
style = Typography.bodyDefaultRegular,
|
|
615
|
-
maxLines = 1,
|
|
616
|
-
color = theme.colors.text.hint,
|
|
617
|
-
overflow = TextOverflow.Ellipsis
|
|
618
|
-
)
|
|
619
|
-
}
|
|
620
|
-
innerTextField()
|
|
621
|
-
}
|
|
622
|
-
|
|
623
|
-
if (isShowClear) {
|
|
624
|
-
Icon(
|
|
625
|
-
source = "24_navigation_close_circle_full",
|
|
626
|
-
size = 16.dp,
|
|
627
|
-
color = theme.colors.text.hint,
|
|
628
|
-
modifier = Modifier.padding(start = Spacing.XS)
|
|
629
|
-
.noFeedbackClickable(onClick = inputSearchProps.onClear),
|
|
630
|
-
)
|
|
631
|
-
}
|
|
632
|
-
|
|
633
|
-
inputSearchProps.iconRightTextField?.invoke(iconRightModifier)
|
|
634
|
-
}
|
|
635
|
-
}
|
|
636
|
-
)
|
|
637
|
-
|
|
638
|
-
if (isShowBtnText) {
|
|
639
|
-
Text(
|
|
640
|
-
text = inputSearchProps.btnText ?: "",
|
|
641
|
-
style = Typography.actionDefaultBold,
|
|
642
|
-
color = theme.colors.text.default,
|
|
643
|
-
modifier = Modifier.padding(start = Spacing.L)
|
|
644
|
-
.noFeedbackClickable(onClick = inputSearchProps.onPressBtnText)
|
|
645
|
-
)
|
|
646
|
-
}
|
|
647
|
-
}
|
|
648
|
-
}
|
|
649
|
-
|
|
650
|
-
@Composable
|
|
651
|
-
private fun footerOffset(
|
|
652
|
-
useAvoidKeyboard: Boolean = true,
|
|
653
|
-
): State<IntOffset> {
|
|
654
|
-
if (!useAvoidKeyboard) return remember { mutableStateOf(IntOffset.Zero) }
|
|
655
|
-
val density = LocalDensity.current
|
|
656
|
-
val navPaddingValue = WindowInsets.navigationBars.asPaddingValues()
|
|
657
|
-
val keyboardSize = keyboardSizeState()
|
|
658
|
-
|
|
659
|
-
return produceState(IntOffset.Zero, density, navPaddingValue) {
|
|
660
|
-
val navSystemOffset = with(density) { navPaddingValue.calculateBottomPadding().roundToPx() }
|
|
661
|
-
snapshotFlow { keyboardSize.value }.collectLatest {
|
|
662
|
-
value = if (it == 0.dp) IntOffset.Zero
|
|
663
|
-
else IntOffset(
|
|
664
|
-
x = 0, y = with(density) {
|
|
665
|
-
navSystemOffset - it.roundToPx()
|
|
666
|
-
})
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
|
|
671
|
-
@Composable
|
|
672
|
-
fun keyboardSizeState(): State<Dp> {
|
|
673
|
-
val bottom = WindowInsets.ime.asPaddingValues()
|
|
674
|
-
return rememberUpdatedState(bottom.calculateBottomPadding())
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
@Composable
|
|
678
|
-
private fun Footer(
|
|
679
|
-
useAvoidKeyboard: Boolean,
|
|
680
|
-
footerContent: (@Composable () -> Unit)?,
|
|
681
|
-
) {
|
|
682
|
-
footerContent ?: return
|
|
683
|
-
val theme = AppTheme.current
|
|
684
|
-
val navPaddingValue = WindowInsets.navigationBars.asPaddingValues()
|
|
685
|
-
val offsetMove = footerOffset(useAvoidKeyboard)
|
|
686
|
-
|
|
687
|
-
Box(
|
|
688
|
-
modifier = Modifier.padding(navPaddingValue).fillMaxWidth().offset {
|
|
689
|
-
offsetMove.value
|
|
690
|
-
}.shadow(
|
|
691
|
-
color = Colors.black_20.copy(alpha = 0.05f),
|
|
692
|
-
blurRadius = 24f,
|
|
693
|
-
offsetX = 0.dp,
|
|
694
|
-
offsetY = (-4).dp
|
|
695
|
-
).background(theme.colors.background.surface).padding(
|
|
696
|
-
start = Spacing.M,
|
|
697
|
-
top = Spacing.M,
|
|
698
|
-
end = Spacing.M,
|
|
699
|
-
)
|
|
700
|
-
) {
|
|
701
|
-
footerContent()
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
|
|
705
|
-
fun Modifier.hideKeyboardOnTap() = composed {
|
|
706
|
-
val focusManager = LocalFocusManager.current
|
|
707
|
-
val keyboardManager = LocalSoftwareKeyboardController.current
|
|
708
|
-
|
|
709
|
-
pointerInput(Unit) {
|
|
710
|
-
detectTapGestures {
|
|
711
|
-
keyboardManager?.hide()
|
|
712
|
-
focusManager.clearFocus()
|
|
713
|
-
}
|
|
714
|
-
}
|
|
715
|
-
}
|