@momo-kits/native-kits 0.163.1-sp.2-debug → 0.163.1-sp.2

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 (143) hide show
  1. package/package.json +1 -1
  2. package/build.gradle.kts +0 -11
  3. package/compose/build.gradle.kts +0 -190
  4. package/compose/build.gradle.kts.backup +0 -190
  5. package/compose/compose.podspec +0 -47
  6. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
  7. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +0 -7
  8. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -150
  9. package/compose/src/commonMain/composeResources/font/momosignature.otf +0 -0
  10. package/compose/src/commonMain/composeResources/font/momotrustdisplay.otf +0 -0
  11. package/compose/src/commonMain/composeResources/font/sfprotext_black.otf +0 -0
  12. package/compose/src/commonMain/composeResources/font/sfprotext_black.ttf +0 -0
  13. package/compose/src/commonMain/composeResources/font/sfprotext_bold.ttf +0 -0
  14. package/compose/src/commonMain/composeResources/font/sfprotext_heavy.ttf +0 -0
  15. package/compose/src/commonMain/composeResources/font/sfprotext_light.ttf +0 -0
  16. package/compose/src/commonMain/composeResources/font/sfprotext_medium.ttf +0 -0
  17. package/compose/src/commonMain/composeResources/font/sfprotext_regular.ttf +0 -0
  18. package/compose/src/commonMain/composeResources/font/sfprotext_semibold.ttf +0 -0
  19. package/compose/src/commonMain/composeResources/font/sfprotext_thin.otf +0 -0
  20. package/compose/src/commonMain/composeResources/font/sfprotext_thin.ttf +0 -0
  21. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.otf +0 -0
  22. package/compose/src/commonMain/composeResources/font/sfprotext_ultralight.ttf +0 -0
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
  24. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -106
  25. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
  26. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
  27. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
  28. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  29. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  30. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  31. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
  32. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  33. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -826
  34. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +0 -269
  35. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
  36. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
  37. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +0 -56
  38. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  39. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  40. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -82
  41. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  42. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -338
  43. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -175
  44. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -356
  45. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -113
  46. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -89
  47. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -128
  48. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -209
  49. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -542
  50. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -23
  51. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
  52. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -125
  53. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -231
  54. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -112
  55. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -477
  56. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -114
  57. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -214
  58. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -240
  59. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -216
  60. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -259
  61. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -182
  62. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -343
  63. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  64. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  65. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  66. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -84
  67. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  68. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -328
  69. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -97
  70. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -310
  71. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -59
  72. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  73. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -21
  74. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -90
  75. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -323
  76. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -217
  77. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -473
  78. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -122
  79. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -199
  80. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -91
  81. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -470
  82. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -88
  83. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -131
  84. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -203
  85. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -498
  86. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -175
  87. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -182
  88. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -193
  89. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  90. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -234
  91. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -188
  92. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -325
  93. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
  94. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  95. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  96. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
  97. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -276
  98. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -52
  99. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -36
  100. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -39
  101. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -52
  102. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -66
  103. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  104. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -104
  105. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -48
  106. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  107. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -252
  108. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -129
  109. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -100
  110. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -172
  111. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -360
  112. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
  113. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -581
  114. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -156
  115. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -225
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -169
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -320
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -81
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -309
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -34
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -360
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -132
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -127
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -91
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +0 -9
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -69
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -55
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  131. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -105
  132. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -32
  133. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +0 -66
  134. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -207
  135. package/gradle/libs.versions.toml +0 -69
  136. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  137. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  138. package/gradle.properties +0 -26
  139. package/gradlew +0 -252
  140. package/gradlew.bat +0 -94
  141. package/ios-demo/README.md +0 -120
  142. package/local.properties +0 -8
  143. package/settings.gradle.kts +0 -64
@@ -1,542 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.animation.core.AnimationState
4
- import androidx.compose.animation.core.VectorConverter
5
- import androidx.compose.animation.core.animateTo
6
- import androidx.compose.animation.core.spring
7
- import androidx.compose.foundation.OverscrollEffect
8
- import androidx.compose.material.ExperimentalMaterialApi
9
- import androidx.compose.runtime.Stable
10
- import androidx.compose.runtime.State
11
- import androidx.compose.runtime.getValue
12
- import androidx.compose.runtime.mutableStateOf
13
- import androidx.compose.runtime.setValue
14
- import androidx.compose.ui.Modifier
15
- import androidx.compose.ui.geometry.Offset
16
- import androidx.compose.ui.geometry.Rect
17
- import androidx.compose.ui.geometry.Size
18
- import androidx.compose.ui.geometry.toRect
19
- import androidx.compose.ui.graphics.drawscope.ContentDrawScope
20
- import androidx.compose.ui.graphics.drawscope.clipRect
21
- import androidx.compose.ui.input.nestedscroll.NestedScrollSource
22
- import androidx.compose.ui.input.pointer.PointerEvent
23
- import androidx.compose.ui.input.pointer.PointerEventPass
24
- import androidx.compose.ui.input.pointer.PointerEventType
25
- import androidx.compose.ui.layout.Measurable
26
- import androidx.compose.ui.layout.MeasureResult
27
- import androidx.compose.ui.layout.MeasureScope
28
- import androidx.compose.ui.node.DelegatableNode
29
- import androidx.compose.ui.node.DrawModifierNode
30
- import androidx.compose.ui.node.LayoutAwareModifierNode
31
- import androidx.compose.ui.node.LayoutModifierNode
32
- import androidx.compose.ui.node.PointerInputModifierNode
33
- import androidx.compose.ui.unit.Constraints
34
- import androidx.compose.ui.unit.Density
35
- import androidx.compose.ui.unit.Dp
36
- import androidx.compose.ui.unit.IntOffset
37
- import androidx.compose.ui.unit.IntSize
38
- import androidx.compose.ui.unit.Velocity
39
- import androidx.compose.ui.unit.dp
40
- import androidx.compose.ui.unit.round
41
- import androidx.compose.ui.unit.toOffset
42
- import androidx.compose.ui.unit.toSize
43
- import kotlinx.coroutines.CoroutineScope
44
- import kotlinx.coroutines.cancel
45
- import kotlinx.coroutines.currentCoroutineContext
46
- import kotlinx.coroutines.isActive
47
- import kotlin.math.abs
48
- import kotlin.math.sign
49
-
50
- private enum class CupertinoScrollSource {
51
- DRAG, FLING
52
- }
53
-
54
- private enum class CupertinoOverscrollDirection {
55
- UNKNOWN, VERTICAL, HORIZONTAL
56
- }
57
-
58
- private enum class CupertinoSpringAnimationReason {
59
- FLING_FROM_OVERSCROLL, POSSIBLE_SPRING_IN_THE_END
60
- }
61
-
62
-
63
- private data class CupertinoOverscrollAvailableDelta(
64
-
65
- val availableDelta: Float,
66
-
67
-
68
- val newOverscrollValue: Float
69
- )
70
-
71
- data class PullToRefreshCustomState(
72
- val refreshingState: State<Boolean>,
73
- val onRefresh: () -> Unit,
74
- val threadHold: Dp = 140.dp,
75
- val refreshOffset: Dp = 100.dp,
76
- val sendHaptic: (() -> Unit)? = null,
77
- ) {
78
- val position = mutableStateOf(0f)
79
-
80
- fun updatePercentage(percentage: Float) {
81
- position.value = percentage.coerceIn(0f, 1f)
82
- }
83
- }
84
-
85
- /**
86
- * CupertinoOverscrollEffect
87
- *
88
- * @param density to be taken into consideration during computations;
89
- * Cupertino formulas use DPs, and scroll machinery uses raw values.
90
- *
91
- * @param applyClip Some consumers of overscroll effect apply clip by themselves and some don't,
92
- * thus this flag is needed to update our modifier chain and make the clipping correct in every case while avoiding redundancy
93
- */
94
- internal class CupertinoOverscrollEffect(
95
- val pullRefreshState: PullToRefreshCustomState? = null,
96
- private val density: Float,
97
- val applyClip: Boolean
98
- ) : OverscrollEffect {
99
- /*
100
- * Direction of scrolling for this overscroll effect, derived from arguments during
101
- * [applyToScroll] calls. Technically this effect supports both dimensions, but current API requires
102
- * that different stages of animations spawned by this effect for both dimensions
103
- * end at the same time, which is not the case:
104
- * Spring->Fling->Spring, Fling->Spring, Spring->Fling effects can have different timing per dimension
105
- * (see Notes of https://github.com/JetBrains/compose-multiplatform-core/pull/609),
106
- * which is not possible to express without changing API. Hence, this effect will be fixed to latest
107
- * received delta.
108
- */
109
- private var direction: CupertinoOverscrollDirection = CupertinoOverscrollDirection.UNKNOWN
110
-
111
- /*
112
- * Size of container is taking into consideration when computing rubber banding
113
- */
114
- private var scrollSize: Size = Size.Zero
115
-
116
- /*
117
- * Current offset in overscroll area
118
- * Negative for bottom-right
119
- * Positive for top-left
120
- * Zero if within the scrollable range
121
- * It will be mapped to the actual visible offset using the rubber banding rule inside
122
- * [Modifier.offset] within [effectModifier]
123
- */
124
- private var overscrollOffsetState = mutableStateOf(Offset.Zero)
125
- private var overscrollOffset: Offset
126
- get() = overscrollOffsetState.value
127
- set(value) {
128
- overscrollOffsetState.value = value
129
- drawCallScheduledByOffsetChange = true
130
- }
131
- private var drawCallScheduledByOffsetChange = true
132
-
133
- private var lastFlingUnconsumedDelta: Offset = Offset.Zero
134
- private val visibleOverscrollOffset: IntOffset
135
- get() = overscrollOffsetState.value.rubberBanded().round()
136
-
137
- override val isInProgress: Boolean
138
- get() =
139
- // If visible overscroll offset has at least one pixel
140
- // this effect is considered to be in progress
141
- visibleOverscrollOffset.toOffset().getDistance() > 0.5f
142
-
143
- @OptIn(ExperimentalMaterialApi::class)
144
- private val overscrollNode = CupertinoOverscrollNode(
145
- pullRefreshState = pullRefreshState,
146
- offset = { visibleOverscrollOffset },
147
- onNodeRemeasured = { scrollSize = it.toSize() },
148
- onDraw = ::onDraw,
149
- applyClip = applyClip
150
- )
151
- override val node: DelegatableNode get() = overscrollNode
152
-
153
- private fun onDraw() {
154
- // Fix an issue where scrolling was canceled but the overscroll effect was not completed.
155
- // Reset the overscroll effect when no ongoing animation or interaction is applied.
156
- if (!drawCallScheduledByOffsetChange && isInProgress && overscrollNode.pointersDown == 0) {
157
- overscrollOffsetState.value = Offset.Zero
158
- }
159
-
160
- drawCallScheduledByOffsetChange = false
161
- }
162
-
163
- private fun NestedScrollSource.toCupertinoScrollSource(): CupertinoScrollSource? =
164
- when (this) {
165
- NestedScrollSource.UserInput -> CupertinoScrollSource.DRAG
166
- NestedScrollSource.SideEffect -> CupertinoScrollSource.FLING
167
- else -> null
168
- }
169
-
170
- /*
171
- * Takes input scroll delta, current overscroll value, and scroll source, return [CupertinoOverscrollAvailableDelta]
172
- */
173
- @Stable
174
- private fun availableDelta(
175
- delta: Float,
176
- overscroll: Float,
177
- source: CupertinoScrollSource
178
- ): CupertinoOverscrollAvailableDelta {
179
- // if source is fling:
180
- // 1. no delta will be consumed
181
- // 2. overscroll will stay the same
182
- if (source == CupertinoScrollSource.FLING) {
183
- return CupertinoOverscrollAvailableDelta(delta, overscroll)
184
- }
185
-
186
- val newOverscroll = overscroll + delta
187
-
188
- return if (delta >= 0f && overscroll <= 0f) {
189
- if (newOverscroll > 0f) {
190
- CupertinoOverscrollAvailableDelta(newOverscroll, 0f)
191
- } else {
192
- CupertinoOverscrollAvailableDelta(0f, newOverscroll)
193
- }
194
- } else if (delta <= 0f && overscroll >= 0f) {
195
- if (newOverscroll < 0f) {
196
- CupertinoOverscrollAvailableDelta(newOverscroll, 0f)
197
- } else {
198
- CupertinoOverscrollAvailableDelta(0f, newOverscroll)
199
- }
200
- } else {
201
- CupertinoOverscrollAvailableDelta(0f, newOverscroll)
202
- }
203
- }
204
-
205
- /*
206
- * Returns the amount of scroll delta available after user performed scroll inside overscroll area
207
- * It will update [overscroll] resulting in visual change because of [Modifier.offset] depending on it
208
- */
209
- private fun availableDelta(delta: Offset, source: CupertinoScrollSource): Offset {
210
- val (x, overscrollX) = availableDelta(delta.x, overscrollOffset.x, source)
211
- val (y, overscrollY) = availableDelta(delta.y, overscrollOffset.y, source)
212
- overscrollOffset = Offset(overscrollX, overscrollY)
213
-
214
- return Offset(x, y)
215
- }
216
-
217
- /*
218
- * Semantics of this method match the [OverscrollEffect.applyToScroll] one,
219
- * The only difference is NestedScrollSource being remapped to CupertinoScrollSource to narrow
220
- * processed states invariant
221
- */
222
- private fun applyToScroll(
223
- delta: Offset,
224
- source: CupertinoScrollSource,
225
- performScroll: (Offset) -> Offset
226
- ): Offset {
227
- // Calculate how much delta is available after being consumed by scrolling inside overscroll area
228
- val deltaLeftForPerformScroll = availableDelta(delta, source)
229
-
230
- // Then pass remaining delta to scroll closure
231
- val deltaConsumedByPerformScroll = performScroll(deltaLeftForPerformScroll)
232
-
233
- // Delta which is left after `performScroll` was invoked with availableDelta
234
- val unconsumedDelta = deltaLeftForPerformScroll - deltaConsumedByPerformScroll
235
-
236
- return when (source) {
237
- CupertinoScrollSource.DRAG -> {
238
- // [unconsumedDelta] is going into overscroll again in case a user drags and hits the
239
- // overscroll->content->overscroll or content->overscroll scenario within single frame
240
- overscrollOffset += unconsumedDelta
241
- lastFlingUnconsumedDelta = Offset.Zero
242
- delta - unconsumedDelta
243
- }
244
-
245
- CupertinoScrollSource.FLING -> {
246
- // If unconsumedDelta is not Zero, [CupertinoOverscrollEffect] will cancel fling and
247
- // start spring animation instead
248
- lastFlingUnconsumedDelta = unconsumedDelta
249
- delta - unconsumedDelta
250
- }
251
- }
252
- }
253
-
254
- override fun applyToScroll(
255
- delta: Offset,
256
- source: NestedScrollSource,
257
- performScroll: (Offset) -> Offset
258
- ): Offset {
259
- springAnimationScope?.cancel()
260
- springAnimationScope = null
261
-
262
- direction = direction.combinedWith(delta.toCupertinoOverscrollDirection())
263
-
264
- return source.toCupertinoScrollSource()?.let {
265
- applyToScroll(delta, it, performScroll)
266
- } ?: performScroll(delta)
267
- }
268
-
269
- override suspend fun applyToFling(
270
- velocity: Velocity,
271
- performFling: suspend (Velocity) -> Velocity
272
- ) {
273
- val availableFlingVelocity = playInitialSpringAnimationIfNeeded(velocity)
274
- val velocityConsumedByFling = performFling(availableFlingVelocity)
275
- val postFlingVelocity = availableFlingVelocity - velocityConsumedByFling
276
-
277
- val unconsumedDelta = lastFlingUnconsumedDelta.toFloat()
278
- if (unconsumedDelta == 0f && overscrollOffset == Offset.Zero) {
279
- return
280
- }
281
- applyPullToRefresh()
282
-
283
- playSpringAnimation(
284
- unconsumedDelta,
285
- postFlingVelocity.toFloat(),
286
- CupertinoSpringAnimationReason.POSSIBLE_SPRING_IN_THE_END
287
- )
288
- }
289
-
290
- private fun applyPullToRefresh() {
291
- val (isRefresh, refresh, threshHold, _, _) = pullRefreshState ?: return
292
- val overscrollY = overscrollOffset.y
293
- if (isRefresh.value || overscrollY < threshHold.value * density) return
294
- refresh.invoke()
295
- }
296
-
297
- private fun Offset.toCupertinoOverscrollDirection(): CupertinoOverscrollDirection {
298
- val hasXPart = abs(x) > 0f
299
- val hasYPart = abs(y) > 0f
300
-
301
- return if (hasXPart xor hasYPart) {
302
- if (hasXPart) {
303
- CupertinoOverscrollDirection.HORIZONTAL
304
- } else {
305
- // hasYPart != hasXPart and hasXPart is false
306
- CupertinoOverscrollDirection.VERTICAL
307
- }
308
- } else {
309
- // hasXPart and hasYPart are equal
310
- CupertinoOverscrollDirection.UNKNOWN
311
- }
312
- }
313
-
314
- private fun CupertinoOverscrollDirection.combinedWith(other: CupertinoOverscrollDirection): CupertinoOverscrollDirection =
315
- when (this) {
316
- CupertinoOverscrollDirection.UNKNOWN -> when (other) {
317
- CupertinoOverscrollDirection.UNKNOWN -> CupertinoOverscrollDirection.UNKNOWN
318
- CupertinoOverscrollDirection.VERTICAL -> CupertinoOverscrollDirection.VERTICAL
319
- CupertinoOverscrollDirection.HORIZONTAL -> CupertinoOverscrollDirection.HORIZONTAL
320
- }
321
-
322
- CupertinoOverscrollDirection.VERTICAL -> when (other) {
323
- CupertinoOverscrollDirection.UNKNOWN, CupertinoOverscrollDirection.VERTICAL -> CupertinoOverscrollDirection.VERTICAL
324
- CupertinoOverscrollDirection.HORIZONTAL -> CupertinoOverscrollDirection.HORIZONTAL
325
- }
326
-
327
- CupertinoOverscrollDirection.HORIZONTAL -> when (other) {
328
- CupertinoOverscrollDirection.UNKNOWN, CupertinoOverscrollDirection.HORIZONTAL -> CupertinoOverscrollDirection.HORIZONTAL
329
- CupertinoOverscrollDirection.VERTICAL -> CupertinoOverscrollDirection.VERTICAL
330
- }
331
- }
332
-
333
- private fun Velocity.toFloat(): Float =
334
- toOffset().toFloat()
335
-
336
- private fun Float.toVelocity(): Velocity =
337
- toOffset().toVelocity()
338
-
339
- private fun Offset.toFloat(): Float =
340
- when (direction) {
341
- CupertinoOverscrollDirection.UNKNOWN -> 0f
342
- CupertinoOverscrollDirection.VERTICAL -> y
343
- CupertinoOverscrollDirection.HORIZONTAL -> x
344
- }
345
-
346
- private fun Float.toOffset(): Offset =
347
- when (direction) {
348
- CupertinoOverscrollDirection.UNKNOWN -> Offset.Zero
349
- CupertinoOverscrollDirection.VERTICAL -> Offset(0f, this)
350
- CupertinoOverscrollDirection.HORIZONTAL -> Offset(this, 0f)
351
- }
352
-
353
- private suspend fun playInitialSpringAnimationIfNeeded(initialVelocity: Velocity): Velocity {
354
- val velocity = initialVelocity.toFloat()
355
- val overscroll = overscrollOffset.toFloat()
356
-
357
- return if ((velocity <= 0f && overscroll > 0f) || (velocity >= 0f && overscroll < 0f)) {
358
- playSpringAnimation(
359
- unconsumedDelta = 0f,
360
- velocity,
361
- CupertinoSpringAnimationReason.FLING_FROM_OVERSCROLL
362
- ).toVelocity()
363
- } else {
364
- initialVelocity
365
- }
366
- }
367
-
368
- private var springAnimationScope: CoroutineScope? = null
369
-
370
- private suspend fun playSpringAnimation(
371
- unconsumedDelta: Float,
372
- initialVelocity: Float,
373
- reason: CupertinoSpringAnimationReason
374
- ): Float {
375
- val initialValue = overscrollOffset.toFloat() + unconsumedDelta
376
- val initialSign = sign(initialValue)
377
- var currentVelocity = initialVelocity
378
-
379
- // All input values are divided by density so all internal calculations are performed as if
380
- // they operated on DPs. Callback value is then scaled back to raw pixels.
381
- val visibilityThreshold = 0.5f / density
382
-
383
- val spec = when (reason) {
384
- CupertinoSpringAnimationReason.FLING_FROM_OVERSCROLL -> {
385
- spring(
386
- stiffness = 300f,
387
- visibilityThreshold = visibilityThreshold
388
- )
389
- }
390
-
391
- CupertinoSpringAnimationReason.POSSIBLE_SPRING_IN_THE_END -> {
392
- spring(
393
- stiffness = 120f,
394
- visibilityThreshold = visibilityThreshold
395
- )
396
- }
397
- }
398
-
399
- springAnimationScope?.cancel()
400
- springAnimationScope = CoroutineScope(currentCoroutineContext())
401
- springAnimationScope?.run {
402
- AnimationState(
403
- Float.VectorConverter,
404
- initialValue / density,
405
- initialVelocity / density
406
- ).animateTo(
407
- targetValue = 0f,
408
- animationSpec = spec
409
- ) {
410
- overscrollOffset = pullRefreshState?.let { (refreshing, _, _, refreshOffset) ->
411
- if (!refreshing.value) return@let null
412
- value.coerceAtLeast(refreshOffset.value * density).toOffset()
413
- } ?: (value * density).toOffset()
414
- currentVelocity = velocity * density
415
-
416
- // If it was flung from overscroll, cancel animation and return velocity
417
- if (reason == CupertinoSpringAnimationReason.FLING_FROM_OVERSCROLL &&
418
- initialSign != 0f &&
419
- sign(value) != initialSign
420
- ) {
421
- this.cancelAnimation()
422
- }
423
- }
424
- springAnimationScope = null
425
- }
426
-
427
- if (currentCoroutineContext().isActive) {
428
- // The spring is critically damped, so in case spring-fling-spring sequence is slightly
429
- // offset and velocity is of the opposite sign, it will end up with no animation
430
- overscrollOffset = Offset.Zero
431
- }
432
-
433
- if (reason == CupertinoSpringAnimationReason.POSSIBLE_SPRING_IN_THE_END) {
434
- currentVelocity = 0f
435
- }
436
-
437
- return currentVelocity
438
- }
439
-
440
- private fun Offset.rubberBanded(): Offset {
441
- if (scrollSize.width == 0f || scrollSize.height == 0f) {
442
- return Offset.Zero
443
- }
444
-
445
- val dpOffset = this / density
446
- val dpSize = scrollSize / density
447
-
448
- return Offset(
449
- rubberBandedValue(dpOffset.x, dpSize.width),
450
- rubberBandedValue(dpOffset.y, dpSize.height)
451
- ) * density
452
- }
453
-
454
- /*
455
- * Maps raw delta offset [value] on an axis within scroll container with [dimension]
456
- * to actual visible offset
457
- */
458
- private fun rubberBandedValue(value: Float, dimension: Float) =
459
- sign(value) * (1f - (1f / (abs(value) * RUBBER_BAND_COEFFICIENT / dimension + 1f))) * dimension
460
-
461
- companion object Companion {
462
- private const val RUBBER_BAND_COEFFICIENT = 0.55f
463
- }
464
- }
465
-
466
- private class CupertinoOverscrollNode @OptIn(ExperimentalMaterialApi::class) constructor(
467
- val pullRefreshState: PullToRefreshCustomState?,
468
- val offset: Density.() -> IntOffset,
469
- val onNodeRemeasured: (IntSize) -> Unit,
470
- val onDraw: () -> Unit,
471
- val applyClip: Boolean
472
- ) : Modifier.Node(),
473
- LayoutModifierNode,
474
- LayoutAwareModifierNode,
475
- DrawModifierNode,
476
- PointerInputModifierNode {
477
- override fun onRemeasured(size: IntSize) = onNodeRemeasured(size)
478
-
479
- var pointersDown by mutableStateOf(0)
480
-
481
- override fun onPointerEvent(
482
- pointerEvent: PointerEvent,
483
- pass: PointerEventPass,
484
- bounds: IntSize
485
- ) {
486
- if (pass == PointerEventPass.Final) {
487
- if (pointerEvent.type == PointerEventType.Press) {
488
- pointersDown++
489
- } else if (pointerEvent.type == PointerEventType.Release) {
490
- pointersDown--
491
- // assert(pointersDown >= 0) { "pointersDown cannot be negative" }
492
- }
493
- }
494
- }
495
-
496
- override fun onCancelPointerInput() {
497
- pointersDown = 0
498
- }
499
-
500
- override fun ContentDrawScope.draw() {
501
- onDraw()
502
- if (applyClip) {
503
- val bounds = Rect(-offset().toOffset(), size)
504
- val rect = size.toRect().intersect(bounds)
505
- clipRect(
506
- left = rect.left,
507
- top = rect.top,
508
- right = rect.right,
509
- bottom = rect.bottom,
510
- ) { this@draw.drawContent() }
511
- } else {
512
- this@draw.drawContent()
513
- }
514
- }
515
-
516
- override fun MeasureScope.measure(
517
- measurable: Measurable,
518
- constraints: Constraints
519
- ): MeasureResult {
520
- val placeable = measurable.measure(constraints)
521
- return layout(placeable.width, placeable.height) {
522
- var position = offset()
523
-
524
- with(pullRefreshState) {
525
- this ?: return@with
526
- if (refreshingState.value) {
527
- position = position.copy(
528
- y = position.y.coerceAtLeast(refreshOffset.roundToPx())
529
- )
530
- }
531
- updatePercentage(position.y / refreshOffset.toPx())
532
- }
533
- placeable.placeWithLayer(position)
534
- }
535
- }
536
- }
537
-
538
- private fun Velocity.toOffset(): Offset =
539
- Offset(x, y)
540
-
541
- private fun Offset.toVelocity(): Velocity =
542
- Velocity(x, y)
@@ -1,23 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.foundation.background
4
- import androidx.compose.foundation.layout.Box
5
- import androidx.compose.foundation.layout.fillMaxWidth
6
- import androidx.compose.foundation.layout.height
7
- import androidx.compose.foundation.layout.padding
8
- import androidx.compose.runtime.Composable
9
- import androidx.compose.ui.Modifier
10
- import androidx.compose.ui.unit.dp
11
- import vn.momo.kits.const.AppTheme
12
- import vn.momo.kits.const.Spacing
13
-
14
- @Composable
15
- fun Divider() {
16
- Box(
17
- modifier = Modifier
18
- .fillMaxWidth()
19
- .height(1.dp)
20
- .background(color = AppTheme.current.colors.border.default)
21
- .padding(vertical = Spacing.XS)
22
- )
23
- }
@@ -1,76 +0,0 @@
1
- package vn.momo.kits.components
2
-
3
- import androidx.compose.foundation.border
4
- import androidx.compose.foundation.layout.Box
5
- import androidx.compose.foundation.layout.size
6
- import androidx.compose.runtime.Composable
7
- import androidx.compose.runtime.remember
8
- import androidx.compose.ui.Modifier
9
- import androidx.compose.ui.graphics.Color
10
- import androidx.compose.ui.graphics.ColorFilter
11
- import androidx.compose.ui.layout.ContentScale
12
- import androidx.compose.ui.semantics.contentDescription
13
- import androidx.compose.ui.semantics.semantics
14
- import androidx.compose.ui.unit.Dp
15
- import androidx.compose.ui.unit.dp
16
- import coil3.compose.AsyncImage
17
- import coil3.compose.LocalPlatformContext
18
- import coil3.request.ImageRequest
19
- import vn.momo.kits.application.IsShowBaseLineDebug
20
- import vn.momo.kits.const.AppTheme
21
- import vn.momo.kits.const.Colors
22
- import vn.momo.kits.modifier.conditional
23
- import vn.momo.kits.utils.Icons
24
- import vn.momo.kits.utils.noThemeIcons
25
-
26
- @Composable
27
- fun Icon(
28
- source: String,
29
- size: Dp = 24.dp,
30
- color: Color? = AppTheme.current.colors.text.default,
31
- modifier: Modifier = Modifier,
32
- ) {
33
- // decode image without downscaling it
34
- val context = LocalPlatformContext.current
35
-
36
- val iconUrl = remember(source) {
37
- if (source.contains("https")) {
38
- source
39
- } else {
40
- Icons[source] ?: ""
41
- }
42
- }
43
-
44
- val iconColor = remember(color) {
45
- if (noThemeIcons.contains(source)) null else color
46
- }
47
-
48
- val colorFilter = remember(iconColor) {
49
- iconColor?.let { ColorFilter.tint(it) }
50
- }
51
-
52
- val contentDesc = remember(iconUrl) { "img|$iconUrl" }
53
-
54
- Box(
55
- modifier = modifier
56
- .size(size)
57
- .conditional(IsShowBaseLineDebug) {
58
- border(1.dp, Colors.blue_03)
59
- }
60
- .semantics { contentDescription = contentDesc }
61
- ) {
62
- AsyncImage(
63
- modifier = Modifier.matchParentSize(),
64
- model = ImageRequest.Builder(context)
65
- .data(iconUrl)
66
- .size(
67
- coil3.size.Dimension.Undefined,
68
- coil3.size.Dimension.Undefined
69
- )
70
- .build(),
71
- contentDescription = null,
72
- contentScale = ContentScale.Fit,
73
- colorFilter = colorFilter,
74
- )
75
- }
76
- }