@momo-kits/native-kits 0.162.2-beta.23-debug → 0.162.2-beta.24-debug
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +1 -1
- package/compose/build.gradle.kts +1 -1
- package/compose/compose.podspec +1 -1
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +5 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +20 -62
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +4 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +8 -2
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +93 -75
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +25 -7
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +11 -0
- package/ios/Application/Components.swift +34 -44
- package/ios/Application/FloatingButton.swift +10 -9
- package/ios/Application/HeaderRight.swift +79 -45
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +103 -0
- package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
- package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
- package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
- package/ios/Application/Navigation/HeaderTitle.swift +57 -0
- package/ios/Application/Navigation/HeaderUser.swift +209 -0
- package/ios/Application/Navigation/NavigationContainer.swift +176 -0
- package/ios/Application/Navigation/NavigationOptions.swift +109 -0
- package/ios/Application/Navigation/Navigator.swift +364 -0
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +188 -0
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +68 -0
- package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
- package/ios/Application/Navigation/component/Header.swift +178 -0
- package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
- package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
- package/ios/Application/Screen.swift +2 -1
- package/ios/Application/StackScreen.swift +453 -0
- package/ios/Avatar/Avatar.swift +193 -0
- package/ios/Badge/Badge.swift +11 -14
- package/ios/Badge/BadgeRibbon.swift +12 -21
- package/ios/BaselineView/BaselineView.swift +163 -0
- package/ios/Button/Button.swift +61 -22
- package/ios/Carousel/Carousel.swift +181 -0
- package/ios/Checkbox/Checkbox.swift +14 -13
- package/ios/Chip/Chip.swift +23 -9
- package/ios/Collapse/Collapse.swift +182 -0
- package/ios/Colors+Radius+Spacing/Colors.swift +12 -12
- package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
- package/ios/DateTimePicker/DateTimePicker.swift +210 -0
- package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
- package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
- package/ios/DateTimePicker/WheelPicker.swift +161 -0
- package/ios/Divider/Divider.swift +16 -0
- package/ios/Extensions/Color++.swift +32 -0
- package/ios/Icon/Icon.swift +6 -1
- package/ios/IconButton/IconButton.swift +112 -0
- package/ios/Input/Input.swift +41 -25
- package/ios/Input/InputPhoneNumber.swift +20 -19
- package/ios/Input/InputSearch.swift +100 -47
- package/ios/Input/InputTextArea.swift +66 -40
- package/ios/InputDropDown/InputDropDown.swift +198 -0
- package/ios/InputMoney/InputMoney.swift +335 -0
- package/ios/InputOTP/InputOTP.swift +210 -0
- package/ios/Loader/Loader.swift +113 -0
- package/ios/MoMoUIKits.podspec +5 -0
- package/ios/Pagination/PaginationDot.swift +61 -0
- package/ios/Pagination/PaginationNumber.swift +35 -0
- package/ios/Pagination/PaginationScroll.swift +101 -0
- package/ios/Pagination/PaginationWhiteDot.swift +37 -0
- package/ios/Popup/PopupDisplay.swift +8 -16
- package/ios/Popup/PopupInput.swift +2 -8
- package/ios/Popup/PopupNotify.swift +219 -0
- package/ios/ProgressInfo/ProgressInfo.swift +294 -0
- package/ios/Radio/Radio.swift +70 -0
- package/ios/Rating/Rating.swift +82 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
- package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
- package/ios/Skeleton/Skeleton.swift +99 -0
- package/ios/Slider/Slider.swift +237 -0
- package/ios/Stepper/Stepper.swift +220 -0
- package/ios/Steps/Steps.swift +451 -0
- package/ios/SuggestAction/SuggestAction.swift +97 -0
- package/ios/Swipeable/SwipeCell.swift +185 -0
- package/ios/Swipeable/SwipeCellModel.swift +21 -0
- package/ios/TabView/TabView.swift +530 -0
- package/ios/Tag/Tag.swift +98 -0
- package/ios/Title/Title.swift +269 -0
- package/ios/Tooltip/Tooltip.swift +482 -0
- package/ios/Typography/FontScaleStore.swift +19 -0
- package/ios/Typography/Text.swift +79 -5
- package/ios/Typography/Typography.swift +3 -0
- package/ios/Uploader/Uploader.swift +183 -0
- package/ios/native-kits.podspec +61 -8
- package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
- package/ios-demo/README.md +120 -0
- package/ios-demo/Resources/dot_loading.json +558 -0
- package/ios-demo/Resources/icon.json +4052 -0
- package/ios-demo/Resources/lottie_circle_loader.json +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +269 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +126 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +63 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +20 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +93 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +124 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +14 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +278 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +58 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +78 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +138 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +111 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +136 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +107 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +73 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +100 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +57 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +70 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +227 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +72 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +121 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +76 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +89 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +56 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +32 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +150 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +138 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +103 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +94 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +79 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +152 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +33 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +190 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +34 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +182 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +109 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +187 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +131 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +51 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
- package/package.json +1 -1
- package/publish.sh +50 -0
- package/scripts/gen-ios-color.mjs +136 -0
- package/local.properties +0 -8
package/CLAUDE.md
CHANGED
|
@@ -40,7 +40,7 @@ Publishing is automated (`publish.sh` + GitLab CI on `[ci build]` / `main`). Do
|
|
|
40
40
|
## Architecture essentials
|
|
41
41
|
|
|
42
42
|
- **Entry point:** wrap content in `NavigationContainer(...)` from `navigation/`. It builds the `Navigator`, takes a host-supplied `Localize` (falls back to an empty one), and provides the CompositionLocals below. **Do not use** `ApplicationContainer` (`application/NavigationContainer.kt`) — deprecated and does **not** wire `LocalLocalize` / `LocalNavigator` / `LocalMaxApi`.
|
|
43
|
-
- **Configuration flows via CompositionLocals**, not params. Public ones: `AppTheme`, `AppStatusBar`, `AppNavigationBar` (`const/Theme.kt`); `ApplicationContext`, `AppConfig`, `AppLanguage`, `LocalLocalize
|
|
43
|
+
- **Configuration flows via CompositionLocals**, not params. Public ones: `AppTheme`, `AppStatusBar`, `AppNavigationBar` (`const/Theme.kt`); `ApplicationContext`, `AppConfig`, `AppLanguage`, `LocalLocalize` (`application/`); `LocalNavigator`, `LocalMaxApi` (`navigation/`). Read with `X.current`.
|
|
44
44
|
- **Platform code** goes through `expect`/`actual` in `platform/` — never reference Android/iOS APIs from `commonMain` directly.
|
|
45
45
|
- **Native bridge:** `IMaxApi` (`vn.momo.maxapi`, exposed as `LocalMaxApi`) is the host-app bridge (dismiss, tracking, device info, language).
|
|
46
46
|
- Navigation uses a runtime `DynamicScreenRegistry`; overlays (modal/bottom-sheet/snackbar) go through `Navigator` + `OverplayComponentRegistry`.
|
package/compose/build.gradle.kts
CHANGED
package/compose/compose.podspec
CHANGED
|
@@ -29,6 +29,8 @@ data class MiniAppContext(
|
|
|
29
29
|
val permissions: List<Map<String, Any>>? = emptyList(),
|
|
30
30
|
val features: FeatureFlags? = null,
|
|
31
31
|
val scaleSizeMaxRate: Float? = null,
|
|
32
|
+
val userScaleRate: Float? = null,
|
|
33
|
+
val useOSScaleRate: Boolean? = null,
|
|
32
34
|
) {
|
|
33
35
|
companion object {
|
|
34
36
|
|
|
@@ -61,6 +63,8 @@ data class MiniAppContext(
|
|
|
61
63
|
permissions = if (!parent.permissions.isNullOrEmpty()) parent.permissions else child.permissions,
|
|
62
64
|
features = mergeFeatureFlags(parent.features, child.features),
|
|
63
65
|
scaleSizeMaxRate = parent.scaleSizeMaxRate ?: child.scaleSizeMaxRate,
|
|
66
|
+
userScaleRate = parent.userScaleRate ?: child.userScaleRate,
|
|
67
|
+
useOSScaleRate = parent.useOSScaleRate ?: child.useOSScaleRate,
|
|
64
68
|
)
|
|
65
69
|
}
|
|
66
70
|
|
|
@@ -98,4 +102,5 @@ val LocalComponentInformation = staticCompositionLocalOf<ComponentInformation?>
|
|
|
98
102
|
null
|
|
99
103
|
}
|
|
100
104
|
|
|
105
|
+
@Deprecated("Max font scale is fixed at MAX_FONT_SCALE (1.5); this CompositionLocal is no longer read.")
|
|
101
106
|
val ScaleSizeMaxRate = staticCompositionLocalOf<Float?> { null }
|
|
@@ -7,6 +7,7 @@ import androidx.compose.ui.Modifier
|
|
|
7
7
|
import androidx.compose.ui.unit.Dp
|
|
8
8
|
import vn.momo.kits.const.*
|
|
9
9
|
import vn.momo.kits.modifier.DeprecatedModifier
|
|
10
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
10
11
|
import vn.momo.kits.platform.getStatusBarHeight
|
|
11
12
|
|
|
12
13
|
@Deprecated("Use IMaxApi instead", ReplaceWith("IMaxApi"))
|
|
@@ -93,6 +94,7 @@ fun ApplicationContainer(
|
|
|
93
94
|
|
|
94
95
|
val appStatusBarHeight = statusBarHeight ?: getStatusBarHeight()
|
|
95
96
|
|
|
97
|
+
ProvideOsFontScale {
|
|
96
98
|
CompositionLocalProvider(
|
|
97
99
|
AppTheme provides appTheme,
|
|
98
100
|
PlatformApi provides composeApi,
|
|
@@ -103,5 +105,6 @@ fun ApplicationContainer(
|
|
|
103
105
|
content()
|
|
104
106
|
}
|
|
105
107
|
}
|
|
108
|
+
}
|
|
106
109
|
|
|
107
110
|
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
package vn.momo.kits.application
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Composable
|
|
4
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
5
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
6
|
+
import androidx.compose.runtime.remember
|
|
7
|
+
import vn.momo.kits.const.AppTheme
|
|
8
|
+
import vn.momo.kits.const.Theme
|
|
9
|
+
import vn.momo.kits.navigation.LocalMaxApi
|
|
10
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
11
|
+
import vn.momo.maxapi.IMaxApi
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
@Composable
|
|
15
|
+
fun WidgetContainer(
|
|
16
|
+
theme: Theme? = null,
|
|
17
|
+
miniAppContext: MiniAppContext? = null,
|
|
18
|
+
maxApi: IMaxApi? = null,
|
|
19
|
+
localize: Localize? = null,
|
|
20
|
+
content: @Composable () -> Unit,
|
|
21
|
+
) {
|
|
22
|
+
val parentContext = LocalContext.current
|
|
23
|
+
val mergedContext = remember(parentContext, miniAppContext) {
|
|
24
|
+
MiniAppContext.merge(parentContext, miniAppContext)
|
|
25
|
+
}
|
|
26
|
+
val resolvedTheme = theme ?: AppTheme.current
|
|
27
|
+
val resolvedLocalize = localize ?: LocalLocalize.current
|
|
28
|
+
val resolvedMaxApi = maxApi ?: LocalMaxApi.current
|
|
29
|
+
|
|
30
|
+
LaunchedEffect(resolvedMaxApi, localize) {
|
|
31
|
+
val api = resolvedMaxApi ?: return@LaunchedEffect
|
|
32
|
+
val target = localize ?: return@LaunchedEffect
|
|
33
|
+
runCatching {
|
|
34
|
+
api.getLanguage(callback = { data ->
|
|
35
|
+
if (parseLanguage(data) == Localize.EN) target.changeLanguage(Localize.EN)
|
|
36
|
+
})
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
ProvideOsFontScale {
|
|
41
|
+
CompositionLocalProvider(
|
|
42
|
+
AppTheme provides resolvedTheme,
|
|
43
|
+
LocalContext provides mergedContext,
|
|
44
|
+
LocalLocalize provides resolvedLocalize,
|
|
45
|
+
LocalMaxApi provides resolvedMaxApi,
|
|
46
|
+
) {
|
|
47
|
+
content()
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private fun parseLanguage(raw: Map<String, Any?>?): String? {
|
|
53
|
+
val code = (raw?.get("response") as? String)?.trim()?.lowercase()
|
|
54
|
+
if (code.isNullOrEmpty()) return null
|
|
55
|
+
return if (code.startsWith(Localize.EN)) Localize.EN else Localize.VI
|
|
56
|
+
}
|
|
@@ -5,6 +5,7 @@ import androidx.compose.foundation.border
|
|
|
5
5
|
import androidx.compose.foundation.clickable
|
|
6
6
|
import androidx.compose.foundation.layout.Box
|
|
7
7
|
import androidx.compose.foundation.layout.size
|
|
8
|
+
import androidx.compose.foundation.shape.CircleShape
|
|
8
9
|
import androidx.compose.foundation.shape.RoundedCornerShape
|
|
9
10
|
import androidx.compose.runtime.Composable
|
|
10
11
|
import androidx.compose.runtime.remember
|
|
@@ -19,65 +20,32 @@ import vn.momo.kits.application.IsShowBaseLineDebug
|
|
|
19
20
|
import vn.momo.kits.const.AppTheme
|
|
20
21
|
import vn.momo.kits.const.Colors
|
|
21
22
|
import vn.momo.kits.const.Radius
|
|
22
|
-
import vn.momo.kits.const.Spacing
|
|
23
23
|
import vn.momo.kits.modifier.conditional
|
|
24
24
|
|
|
25
25
|
data class IconSpecs(
|
|
26
|
-
val
|
|
27
|
-
val
|
|
28
|
-
val radius: Dp,
|
|
29
|
-
val size: Dp
|
|
26
|
+
val box: Dp,
|
|
27
|
+
val icon: Dp,
|
|
30
28
|
)
|
|
31
29
|
|
|
32
30
|
enum class IconSize(val value: IconSpecs) {
|
|
33
|
-
LARGE(
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
radius = Radius.XL,
|
|
37
|
-
width = 48.dp,
|
|
38
|
-
size = 48.dp
|
|
39
|
-
)
|
|
40
|
-
),
|
|
41
|
-
SMALL(
|
|
42
|
-
IconSpecs(
|
|
43
|
-
height = 40.dp,
|
|
44
|
-
radius = Radius.XL,
|
|
45
|
-
width = 40.dp,
|
|
46
|
-
size = 40.dp
|
|
47
|
-
)
|
|
48
|
-
)
|
|
31
|
+
LARGE(IconSpecs(box = 48.dp, icon = 24.dp)),
|
|
32
|
+
MEDIUM(IconSpecs(box = 36.dp, icon = 16.dp)),
|
|
33
|
+
SMALL(IconSpecs(box = 28.dp, icon = 16.dp)),
|
|
49
34
|
}
|
|
50
35
|
|
|
51
|
-
enum class
|
|
36
|
+
enum class IconShape {
|
|
52
37
|
CIRCLE,
|
|
53
38
|
SQUARE,
|
|
54
|
-
RECTANGLE
|
|
55
39
|
}
|
|
56
40
|
|
|
57
|
-
//
|
|
58
|
-
|
|
59
|
-
val width: Dp,
|
|
60
|
-
val height: Dp,
|
|
61
|
-
val radius: Dp
|
|
62
|
-
)
|
|
41
|
+
// Square keeps an 8dp rounded corner; circle is fully rounded regardless of size.
|
|
42
|
+
private val squareShape = RoundedCornerShape(Radius.S)
|
|
63
43
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
val base = size.value.height
|
|
68
|
-
return when (shape) {
|
|
69
|
-
IconButtonShape.CIRCLE -> IconButtonGeometry(base, base, size.value.radius)
|
|
70
|
-
IconButtonShape.SQUARE -> IconButtonGeometry(base, base, Radius.S)
|
|
71
|
-
IconButtonShape.RECTANGLE -> IconButtonGeometry(base + Spacing.S, base, Radius.S)
|
|
72
|
-
}
|
|
44
|
+
private fun IconShape.toShape(): Shape = when (this) {
|
|
45
|
+
IconShape.CIRCLE -> CircleShape
|
|
46
|
+
IconShape.SQUARE -> squareShape
|
|
73
47
|
}
|
|
74
48
|
|
|
75
|
-
// Cache for icon sizes to avoid repeated calculations
|
|
76
|
-
private val iconSizeMap = mapOf(
|
|
77
|
-
IconSize.SMALL to 16.dp,
|
|
78
|
-
IconSize.LARGE to 24.dp
|
|
79
|
-
)
|
|
80
|
-
|
|
81
49
|
@Composable
|
|
82
50
|
internal fun getIconStyle(type: ButtonType, shape: Shape, color: Color? = null): Modifier {
|
|
83
51
|
val theme = AppTheme.current
|
|
@@ -126,42 +94,32 @@ fun IconButton(
|
|
|
126
94
|
onClick: () -> Unit,
|
|
127
95
|
type: ButtonType = ButtonType.PRIMARY,
|
|
128
96
|
size: IconSize = IconSize.SMALL,
|
|
129
|
-
shape:
|
|
97
|
+
shape: IconShape = IconShape.CIRCLE,
|
|
130
98
|
icon: String = "",
|
|
131
99
|
) {
|
|
132
|
-
|
|
133
|
-
val iconSize = remember(size) {
|
|
134
|
-
iconSizeMap[size] ?: 16.dp
|
|
135
|
-
}
|
|
100
|
+
val specs = size.value
|
|
136
101
|
|
|
137
|
-
// Memoize enabled state
|
|
138
102
|
val isEnabled = remember(type) {
|
|
139
103
|
type != ButtonType.DISABLED
|
|
140
104
|
}
|
|
141
105
|
|
|
142
|
-
|
|
143
|
-
val geometry = remember(size, shape) {
|
|
144
|
-
resolveIconButtonGeometry(size, shape)
|
|
145
|
-
}
|
|
146
|
-
val cornerShape = remember(geometry.radius) {
|
|
147
|
-
RoundedCornerShape(geometry.radius)
|
|
148
|
-
}
|
|
106
|
+
val boxShape = remember(shape) { shape.toShape() }
|
|
149
107
|
|
|
150
108
|
Box(
|
|
151
109
|
modifier = Modifier
|
|
152
|
-
.size(
|
|
153
|
-
.then(getIconStyle(type,
|
|
110
|
+
.size(specs.box)
|
|
111
|
+
.then(getIconStyle(type, boxShape))
|
|
154
112
|
.conditional(IsShowBaseLineDebug) {
|
|
155
113
|
border(1.dp, Colors.blue_03)
|
|
156
114
|
}
|
|
157
|
-
.clip(
|
|
115
|
+
.clip(boxShape)
|
|
158
116
|
.clickable(enabled = isEnabled, onClick = onClick),
|
|
159
117
|
contentAlignment = Alignment.Center
|
|
160
118
|
) {
|
|
161
119
|
Icon(
|
|
162
120
|
source = icon,
|
|
163
121
|
color = getIconColor(type),
|
|
164
|
-
size =
|
|
122
|
+
size = specs.icon,
|
|
165
123
|
)
|
|
166
124
|
}
|
|
167
|
-
}
|
|
125
|
+
}
|
|
@@ -4,6 +4,10 @@ import androidx.compose.runtime.Composable
|
|
|
4
4
|
import androidx.compose.runtime.CompositionLocalProvider
|
|
5
5
|
import vn.momo.kits.application.ScaleSizeMaxRate
|
|
6
6
|
|
|
7
|
+
@Deprecated(
|
|
8
|
+
"Max font scale is fixed at MAX_FONT_SCALE (1.5); this override is no longer applied. Remove the wrapper.",
|
|
9
|
+
ReplaceWith("content()"),
|
|
10
|
+
)
|
|
7
11
|
@Composable
|
|
8
12
|
fun ScaleSizeScope(
|
|
9
13
|
scaleSizeMaxRate: Float? = null,
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package vn.momo.kits.const
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.getValue
|
|
4
|
+
import androidx.compose.runtime.mutableStateOf
|
|
5
|
+
import androidx.compose.runtime.setValue
|
|
6
|
+
|
|
7
|
+
// App-wide font-scale holder. The kit is sandboxed and can't read the host cache directly, so the
|
|
8
|
+
// host (which sees both core and this kit) seeds this once at startup and pushes runtime updates into
|
|
9
|
+
// it. scaleSize() reads it as the fallback, so every screen — including direct NavigationContainer
|
|
10
|
+
// screens with no host-pushed MiniAppContext — scales with no per-render prop and no async flicker.
|
|
11
|
+
// Backed by snapshot state: writes recompose text automatically.
|
|
12
|
+
object KitFontScale {
|
|
13
|
+
var userScaleRate by mutableStateOf(1f)
|
|
14
|
+
private set
|
|
15
|
+
var useOSScaleRate by mutableStateOf(true)
|
|
16
|
+
private set
|
|
17
|
+
|
|
18
|
+
fun update(userScaleRate: Float, useOSScaleRate: Boolean) {
|
|
19
|
+
this.userScaleRate = userScaleRate
|
|
20
|
+
this.useOSScaleRate = useOSScaleRate
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -11,7 +11,7 @@ import androidx.compose.ui.unit.*
|
|
|
11
11
|
import org.jetbrains.compose.resources.Font
|
|
12
12
|
import org.jetbrains.compose.resources.FontResource
|
|
13
13
|
import org.jetbrains.compose.resources.InternalResourceApi
|
|
14
|
-
import vn.momo.kits.application.
|
|
14
|
+
import vn.momo.kits.application.LocalContext
|
|
15
15
|
import vn.momo.kits.platform.getScreenDimensions
|
|
16
16
|
import vn.momo.uikits.resources.*
|
|
17
17
|
import kotlin.math.max
|
|
@@ -23,7 +23,13 @@ const val MAX_DEVICE_SCALE = 5
|
|
|
23
23
|
|
|
24
24
|
@Composable
|
|
25
25
|
fun scaleSize(size: Float): Float {
|
|
26
|
-
val
|
|
26
|
+
val context = LocalContext.current
|
|
27
|
+
// Host-pushed context wins; otherwise fall back to the app-wide KitFontScale holder.
|
|
28
|
+
val useOsScale = context?.useOSScaleRate ?: KitFontScale.useOSScaleRate
|
|
29
|
+
if (!useOsScale) {
|
|
30
|
+
return size * (context?.userScaleRate ?: KitFontScale.userScaleRate)
|
|
31
|
+
}
|
|
32
|
+
val scaleSizeMaxRate: Float = MAX_FONT_SCALE
|
|
27
33
|
val deviceWidth = getScreenDimensions().width
|
|
28
34
|
val deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
|
|
29
35
|
|
|
@@ -85,7 +85,9 @@ data class NavigationOptions(
|
|
|
85
85
|
val footerComponent: @Composable (() -> Unit)? = null,
|
|
86
86
|
val floatingButtonProps: FloatingButtonProps? = null,
|
|
87
87
|
val keyboardOptions: KeyboardOptions = KeyboardOptions()
|
|
88
|
-
)
|
|
88
|
+
) {
|
|
89
|
+
internal fun hasFooter() : Boolean = footerComponent != null
|
|
90
|
+
}
|
|
89
91
|
|
|
90
92
|
data class KeyboardOptions(
|
|
91
93
|
val keyboardShouldPersistTaps: Boolean = false,
|
|
@@ -1,17 +1,35 @@
|
|
|
1
1
|
package vn.momo.kits.navigation
|
|
2
2
|
|
|
3
|
-
import androidx.compose.animation.*
|
|
4
3
|
import androidx.compose.animation.core.tween
|
|
5
|
-
import androidx.compose.
|
|
4
|
+
import androidx.compose.animation.fadeIn
|
|
5
|
+
import androidx.compose.animation.slideInHorizontally
|
|
6
|
+
import androidx.compose.animation.slideInVertically
|
|
7
|
+
import androidx.compose.animation.slideOutHorizontally
|
|
8
|
+
import androidx.compose.animation.slideOutVertically
|
|
9
|
+
import androidx.compose.runtime.Composable
|
|
10
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
11
|
+
import androidx.compose.runtime.DisposableEffect
|
|
12
|
+
import androidx.compose.runtime.LaunchedEffect
|
|
13
|
+
import androidx.compose.runtime.mutableStateOf
|
|
14
|
+
import androidx.compose.runtime.remember
|
|
6
15
|
import androidx.compose.runtime.saveable.rememberSaveable
|
|
16
|
+
import androidx.compose.runtime.staticCompositionLocalOf
|
|
7
17
|
import androidx.compose.ui.unit.Dp
|
|
8
18
|
import androidx.navigation.compose.NavHost
|
|
9
19
|
import androidx.navigation.compose.composable
|
|
10
20
|
import androidx.navigation.compose.rememberNavController
|
|
11
21
|
import androidx.navigation.toRoute
|
|
12
|
-
import vn.momo.kits.application
|
|
13
|
-
import vn.momo.kits.
|
|
22
|
+
import vn.momo.kits.application.LocalContext
|
|
23
|
+
import vn.momo.kits.application.LocalLocalize
|
|
24
|
+
import vn.momo.kits.application.Localize
|
|
25
|
+
import vn.momo.kits.application.MiniAppContext
|
|
26
|
+
import vn.momo.kits.const.AppNavigationBar
|
|
27
|
+
import vn.momo.kits.const.AppStatusBar
|
|
28
|
+
import vn.momo.kits.const.AppTheme
|
|
29
|
+
import vn.momo.kits.const.Theme
|
|
30
|
+
import vn.momo.kits.const.defaultTheme
|
|
14
31
|
import vn.momo.kits.platform.ProvideNavigationEventDispatcherOwner
|
|
32
|
+
import vn.momo.kits.platform.ProvideOsFontScale
|
|
15
33
|
import vn.momo.kits.utils.getAppStatusBarHeight
|
|
16
34
|
import vn.momo.kits.utils.getNavigationBarHeight
|
|
17
35
|
import vn.momo.maxapi.IMaxApi
|
|
@@ -27,7 +45,7 @@ fun NavigationContainer(
|
|
|
27
45
|
setNavigator: ((Navigator) -> Unit)? = null,
|
|
28
46
|
statusBarHeight: Dp? = null,
|
|
29
47
|
localize: Localize? = null,
|
|
30
|
-
){
|
|
48
|
+
) {
|
|
31
49
|
val navController = rememberNavController()
|
|
32
50
|
val registry = remember { DynamicScreenRegistry() }
|
|
33
51
|
val navigator = remember { Navigator(navController = navController, maxApi = maxApi, registry = registry) }
|
|
@@ -57,77 +75,79 @@ fun NavigationContainer(
|
|
|
57
75
|
registry.bind(screenId, initialScreenName, initialScreen, options)
|
|
58
76
|
val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
|
|
59
77
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
ProvideOsFontScale {
|
|
79
|
+
ProvideNavigationEventDispatcherOwner {
|
|
80
|
+
CompositionLocalProvider(
|
|
81
|
+
LocalNavigator provides navigator,
|
|
82
|
+
LocalDynamicScreenRegistry provides registry,
|
|
83
|
+
LocalMaxApi provides maxApi,
|
|
84
|
+
AppTheme provides theme.value,
|
|
85
|
+
AppStatusBar provides statusBarHeight,
|
|
86
|
+
AppNavigationBar provides navigationBarHeight,
|
|
87
|
+
LocalContext provides mergedContext,
|
|
88
|
+
LocalLocalize provides resolvedLocalize,
|
|
70
89
|
) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
NavHost(navController, startDestination = startDestination) {
|
|
76
|
-
composable<DynamicScreenRoute>(
|
|
77
|
-
enterTransition = {
|
|
78
|
-
slideInHorizontally(
|
|
79
|
-
animationSpec = tween(300),
|
|
80
|
-
initialOffsetX = { it }
|
|
81
|
-
)
|
|
82
|
-
},
|
|
83
|
-
exitTransition = null,
|
|
84
|
-
popEnterTransition = { fadeIn(animationSpec = tween(0)) },
|
|
85
|
-
popExitTransition = {
|
|
86
|
-
slideOutHorizontally(
|
|
87
|
-
animationSpec = tween(300),
|
|
88
|
-
targetOffsetX = { it }
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
) { backStackEntry ->
|
|
92
|
-
val route = backStackEntry.toRoute<DynamicScreenRoute>()
|
|
93
|
-
val screen = registry.getScreen(route.id)
|
|
94
|
-
|
|
95
|
-
if (screen != null) {
|
|
96
|
-
StackScreen(
|
|
97
|
-
id = route.id,
|
|
98
|
-
name = screen.name,
|
|
99
|
-
content = screen.content,
|
|
100
|
-
navigationOptions = screen.options
|
|
101
|
-
)
|
|
102
|
-
}
|
|
90
|
+
LaunchedEffect(Unit) {
|
|
91
|
+
setNavigator?.invoke(navigator)
|
|
103
92
|
}
|
|
104
93
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
94
|
+
NavHost(navController, startDestination = startDestination) {
|
|
95
|
+
composable<DynamicScreenRoute>(
|
|
96
|
+
enterTransition = {
|
|
97
|
+
slideInHorizontally(
|
|
98
|
+
animationSpec = tween(300),
|
|
99
|
+
initialOffsetX = { it }
|
|
100
|
+
)
|
|
101
|
+
},
|
|
102
|
+
exitTransition = null,
|
|
103
|
+
popEnterTransition = { fadeIn(animationSpec = tween(0)) },
|
|
104
|
+
popExitTransition = {
|
|
105
|
+
slideOutHorizontally(
|
|
106
|
+
animationSpec = tween(300),
|
|
107
|
+
targetOffsetX = { it }
|
|
108
|
+
)
|
|
109
|
+
}
|
|
110
|
+
) { backStackEntry ->
|
|
111
|
+
val route = backStackEntry.toRoute<DynamicScreenRoute>()
|
|
112
|
+
val screen = registry.getScreen(route.id)
|
|
113
|
+
|
|
114
|
+
if (screen != null) {
|
|
115
|
+
StackScreen(
|
|
116
|
+
id = route.id,
|
|
117
|
+
name = screen.name,
|
|
118
|
+
content = screen.content,
|
|
119
|
+
navigationOptions = screen.options
|
|
120
|
+
)
|
|
121
|
+
}
|
|
119
122
|
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
123
|
+
|
|
124
|
+
composable<DynamicDialogRoute>(
|
|
125
|
+
enterTransition = {
|
|
126
|
+
slideInVertically(
|
|
127
|
+
animationSpec = tween(300),
|
|
128
|
+
initialOffsetY = { it }
|
|
129
|
+
)
|
|
130
|
+
},
|
|
131
|
+
exitTransition = null,
|
|
132
|
+
popEnterTransition = { fadeIn(animationSpec = tween(0)) },
|
|
133
|
+
popExitTransition = {
|
|
134
|
+
slideOutVertically(
|
|
135
|
+
animationSpec = tween(300),
|
|
136
|
+
targetOffsetY = { it }
|
|
137
|
+
)
|
|
138
|
+
}
|
|
139
|
+
) { backStackEntry ->
|
|
140
|
+
val route = backStackEntry.toRoute<DynamicDialogRoute>()
|
|
141
|
+
val screen = registry.getScreen(route.id)
|
|
142
|
+
|
|
143
|
+
if (screen != null) {
|
|
144
|
+
StackScreen(
|
|
145
|
+
id = route.id,
|
|
146
|
+
name = screen.name,
|
|
147
|
+
content = screen.content,
|
|
148
|
+
navigationOptions = screen.options
|
|
149
|
+
)
|
|
150
|
+
}
|
|
131
151
|
}
|
|
132
152
|
}
|
|
133
153
|
}
|
|
@@ -142,9 +162,7 @@ fun NavigationContainer(
|
|
|
142
162
|
}
|
|
143
163
|
}
|
|
144
164
|
|
|
145
|
-
val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> {
|
|
146
|
-
error("No MaxApi provided")
|
|
147
|
-
}
|
|
165
|
+
val LocalMaxApi = staticCompositionLocalOf<IMaxApi?> { null }
|
|
148
166
|
|
|
149
167
|
private fun parseLanguage(raw: Map<String, Any?>?): String? {
|
|
150
168
|
val code = (raw?.get("response") as? String)?.trim()?.lowercase()
|
|
@@ -56,6 +56,7 @@ import vn.momo.kits.const.Colors
|
|
|
56
56
|
import vn.momo.kits.const.Spacing
|
|
57
57
|
import vn.momo.kits.modifier.conditional
|
|
58
58
|
import vn.momo.kits.modifier.hideKeyboardOnTap
|
|
59
|
+
import vn.momo.kits.navigation.bottomtab.BOTTOM_TAB_BAR_HEIGHT
|
|
59
60
|
import vn.momo.kits.navigation.component.FABPosition
|
|
60
61
|
import vn.momo.kits.navigation.component.FloatingButton
|
|
61
62
|
import vn.momo.kits.navigation.component.HEADER_HEIGHT
|
|
@@ -77,6 +78,13 @@ import kotlin.time.ExperimentalTime
|
|
|
77
78
|
internal val LocalFooterHeightPx = staticCompositionLocalOf { mutableIntStateOf(0) }
|
|
78
79
|
internal val LocalHeaderRightWidthPx = staticCompositionLocalOf { mutableIntStateOf(0) }
|
|
79
80
|
|
|
81
|
+
@Composable
|
|
82
|
+
private fun bottomTabBarInset(): Dp {
|
|
83
|
+
if (LocalNavigation.current.bottomTabIndex == -1) return 0.dp
|
|
84
|
+
val keyboard = keyboardSizeState().value
|
|
85
|
+
return (BOTTOM_TAB_BAR_HEIGHT.dp + Spacing.S - keyboard).coerceAtLeast(0.dp)
|
|
86
|
+
}
|
|
87
|
+
|
|
80
88
|
@OptIn(ExperimentalMaterialApi::class, ExperimentalTime::class)
|
|
81
89
|
@Composable
|
|
82
90
|
internal fun StackScreen(
|
|
@@ -195,12 +203,12 @@ internal fun StackScreen(
|
|
|
195
203
|
}
|
|
196
204
|
|
|
197
205
|
Column(Modifier.zIndex(2f).fillMaxSize()) {
|
|
198
|
-
MainContent(content = content,
|
|
206
|
+
MainContent(content = content, isBottomTabRoot = isBottomTabRoot, isBottomTabChild = isBottomTabChild)
|
|
199
207
|
FooterContent()
|
|
200
208
|
}
|
|
201
209
|
|
|
202
210
|
Box(Modifier.zIndex(6f)) {
|
|
203
|
-
FloatingContent()
|
|
211
|
+
FloatingContent(isBottomTabChild = isBottomTabChild)
|
|
204
212
|
}
|
|
205
213
|
|
|
206
214
|
OverplayView(isBottomTabChild = isBottomTabChild, id = id)
|
|
@@ -210,7 +218,7 @@ internal fun StackScreen(
|
|
|
210
218
|
|
|
211
219
|
@Suppress("FrequentlyChangingValue")
|
|
212
220
|
@Composable
|
|
213
|
-
internal fun FloatingContent() {
|
|
221
|
+
internal fun FloatingContent(isBottomTabChild: Boolean) {
|
|
214
222
|
val options = LocalOptions.current
|
|
215
223
|
val density = LocalDensity.current
|
|
216
224
|
val footerHeightPx = LocalFooterHeightPx.current
|
|
@@ -219,7 +227,11 @@ internal fun FloatingContent() {
|
|
|
219
227
|
|
|
220
228
|
val fabProps = options.floatingButtonProps ?: return
|
|
221
229
|
val bottomPadding = fabProps.bottom
|
|
222
|
-
?: (Spacing.M +
|
|
230
|
+
?: (Spacing.M + when {
|
|
231
|
+
options.hasFooter() -> with(density) { footerHeightPx.intValue.toDp() }
|
|
232
|
+
isBottomTabChild -> bottomTabBarInset() + (navigationBar - keyboardSizeState().value).coerceAtLeast(0.dp)
|
|
233
|
+
else -> navigationBar
|
|
234
|
+
})
|
|
223
235
|
|
|
224
236
|
FloatingButton(
|
|
225
237
|
scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
|
|
@@ -235,7 +247,7 @@ internal fun FloatingContent() {
|
|
|
235
247
|
}
|
|
236
248
|
|
|
237
249
|
@Composable
|
|
238
|
-
internal fun ColumnScope.MainContent(content: @Composable () -> Unit,
|
|
250
|
+
internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTabRoot: Boolean, isBottomTabChild: Boolean) {
|
|
239
251
|
val options = LocalOptions.current
|
|
240
252
|
val inputSearchType = getInputSearchType(options)
|
|
241
253
|
val density = LocalDensity.current
|
|
@@ -264,7 +276,13 @@ internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTa
|
|
|
264
276
|
.conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
|
|
265
277
|
verticalScroll(scrollState)
|
|
266
278
|
}
|
|
267
|
-
.padding(
|
|
279
|
+
.padding(
|
|
280
|
+
bottom = when {
|
|
281
|
+
options.hasFooter() || isBottomTabRoot -> 0.dp
|
|
282
|
+
isBottomTabChild -> bottomTabBarInset() + (navigationBar - keyboardSizeState().value).coerceAtLeast(0.dp)
|
|
283
|
+
else -> navigationBar
|
|
284
|
+
}
|
|
285
|
+
)
|
|
268
286
|
) {
|
|
269
287
|
ScreenContent(content = content)
|
|
270
288
|
}
|
|
@@ -294,7 +312,7 @@ internal fun ScreenContent(content: @Composable () -> Unit) {
|
|
|
294
312
|
@Composable
|
|
295
313
|
internal fun FooterContent() {
|
|
296
314
|
val options = LocalOptions.current
|
|
297
|
-
if (options.
|
|
315
|
+
if (options.hasFooter()) {
|
|
298
316
|
val keyboardSize = keyboardSizeState()
|
|
299
317
|
val bottomPadding = (AppNavigationBar.current - keyboardSize.value).coerceAtLeast(0.dp)
|
|
300
318
|
Footer(footerComponent = options.footerComponent, bottomPadding = bottomPadding)
|
|
@@ -18,6 +18,7 @@ import androidx.navigation.compose.rememberNavController
|
|
|
18
18
|
import vn.momo.kits.const.AppNavigationBar
|
|
19
19
|
import vn.momo.kits.const.AppTheme
|
|
20
20
|
import vn.momo.kits.const.Spacing
|
|
21
|
+
import vn.momo.kits.navigation.KeyboardOptions
|
|
21
22
|
import vn.momo.kits.navigation.LocalNavigation
|
|
22
23
|
import vn.momo.kits.navigation.LocalNavigator
|
|
23
24
|
import vn.momo.kits.navigation.NavigationOptions
|
|
@@ -53,7 +54,8 @@ fun BottomTab(
|
|
|
53
54
|
LaunchedEffect(Unit){
|
|
54
55
|
navigation.markAsBottomTabRoot()
|
|
55
56
|
navigation.setOptions(
|
|
56
|
-
headerType = HeaderType.None
|
|
57
|
+
headerType = HeaderType.None,
|
|
58
|
+
keyboardOptions = KeyboardOptions(useAvoidKeyboard = false)
|
|
57
59
|
)
|
|
58
60
|
}
|
|
59
61
|
|