@momo-kits/native-kits 0.163.1-beta.3-debug → 0.163.1-beta.5-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 +2 -1
- package/compose/build.gradle.kts.backup +1 -0
- 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 +8 -10
- 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/Button.kt +11 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +40 -55
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +69 -26
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +3 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +28 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +4 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +112 -115
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +11 -6
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +3 -4
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +3 -1
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +2 -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/libs.versions.toml +2 -0
- package/gradle.properties +1 -1
- package/ios/Application/ApplicationEnvironment.swift +11 -1
- 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 +86 -17
- package/ios/Typography/Typography.swift +12 -14
- 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/example/ios/Example.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -5
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImage.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImageSwiftUI.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SkeletonUI.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -46
- package/ios/Application/FontScaleStore.swift +0 -59
|
@@ -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
|
|
@@ -22,58 +22,65 @@ const val MAX_FONT_SCALE = 1.5f
|
|
|
22
22
|
const val MAX_DEVICE_SCALE = 5
|
|
23
23
|
|
|
24
24
|
@Composable
|
|
25
|
-
fun scaleSize(size: Float
|
|
26
|
-
val
|
|
27
|
-
|
|
28
|
-
val
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
val fontScale = fontScaleConfig.osFontScale ?: LocalDensity.current.fontScale
|
|
32
|
-
|
|
33
|
-
if (!useOSFontScale) {
|
|
34
|
-
return if (customRate > 1f) customRate * size else size
|
|
25
|
+
fun scaleSize(size: Float): Float {
|
|
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)
|
|
35
31
|
}
|
|
32
|
+
val scaleSizeMaxRate: Float = MAX_FONT_SCALE
|
|
33
|
+
val deviceWidth = getScreenDimensions().width
|
|
34
|
+
val deviceScale = deviceWidth / DEFAULT_SCREEN_SIZE
|
|
35
|
+
|
|
36
|
+
val density = LocalDensity.current
|
|
37
|
+
val fontScale = density.fontScale
|
|
36
38
|
|
|
37
39
|
var fontSizeScaleDevice = size
|
|
38
40
|
var fontSizeScaleOS = size
|
|
41
|
+
|
|
39
42
|
if (deviceScale > 1) {
|
|
40
43
|
fontSizeScaleDevice =
|
|
41
44
|
min(deviceScale * fontSizeScaleDevice, fontSizeScaleDevice + MAX_DEVICE_SCALE)
|
|
42
45
|
}
|
|
43
|
-
|
|
44
|
-
|
|
46
|
+
|
|
47
|
+
if (fontScale > 1) {
|
|
48
|
+
fontSizeScaleOS = min(fontScale * fontSizeScaleOS, fontSizeScaleOS * scaleSizeMaxRate)
|
|
45
49
|
}
|
|
46
50
|
|
|
47
|
-
return max(
|
|
51
|
+
return max(
|
|
52
|
+
fontSizeScaleDevice,
|
|
53
|
+
fontSizeScaleOS
|
|
54
|
+
)
|
|
48
55
|
}
|
|
49
56
|
|
|
50
57
|
@Composable
|
|
51
|
-
fun scaleSize(size: TextUnit
|
|
58
|
+
fun scaleSize(size: TextUnit): TextUnit {
|
|
52
59
|
if (!size.isSp) return size
|
|
53
60
|
|
|
54
61
|
val density = LocalDensity.current
|
|
55
62
|
|
|
56
|
-
val scaled = scaleSize(size.value
|
|
63
|
+
val scaled = scaleSize(size.value)
|
|
57
64
|
val spValue = scaled / density.fontScale
|
|
58
65
|
|
|
59
66
|
return TextUnit(value = spValue, type = TextUnitType.Sp)
|
|
60
67
|
}
|
|
61
68
|
|
|
62
69
|
@Composable
|
|
63
|
-
fun scaleSize(size: Dp
|
|
64
|
-
return scaleSize(size.value
|
|
70
|
+
fun scaleSize(size: Dp): Dp {
|
|
71
|
+
return scaleSize(size.value).dp
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
@Composable
|
|
68
|
-
fun scaleSize(textStyle: TextStyle
|
|
75
|
+
fun scaleSize(textStyle: TextStyle): TextStyle {
|
|
69
76
|
return textStyle.copy(
|
|
70
77
|
fontSize = if (textStyle.fontSize != TextUnit.Unspecified)
|
|
71
|
-
scaleSize(textStyle.fontSize
|
|
78
|
+
scaleSize(textStyle.fontSize)
|
|
72
79
|
else
|
|
73
80
|
TextUnit.Unspecified,
|
|
74
81
|
|
|
75
82
|
lineHeight = if (textStyle.lineHeight != TextUnit.Unspecified)
|
|
76
|
-
scaleSize(textStyle.lineHeight
|
|
83
|
+
scaleSize(textStyle.lineHeight)
|
|
77
84
|
else
|
|
78
85
|
TextUnit.Unspecified,
|
|
79
86
|
)
|
|
@@ -16,6 +16,10 @@ class Navigation(
|
|
|
16
16
|
val currentOptions: State<NavigationOptions> get() = _options
|
|
17
17
|
val options: NavigationOptions get() = _options.value
|
|
18
18
|
|
|
19
|
+
private val _isBottomTabRoot = mutableStateOf(false)
|
|
20
|
+
internal val isBottomTabRoot: Boolean get() = _isBottomTabRoot.value
|
|
21
|
+
internal fun markAsBottomTabRoot() { _isBottomTabRoot.value = true }
|
|
22
|
+
|
|
19
23
|
fun setOptions(
|
|
20
24
|
onBackHandler: (() -> Unit)? = null,
|
|
21
25
|
hiddenBack: Boolean? = null,
|
|
@@ -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
|
|
@@ -22,12 +40,12 @@ fun NavigationContainer(
|
|
|
22
40
|
initialScreen: @Composable () -> Unit,
|
|
23
41
|
options: NavigationOptions? = null,
|
|
24
42
|
initialTheme: Theme = defaultTheme,
|
|
25
|
-
|
|
26
|
-
maxApi: IMaxApi
|
|
43
|
+
miniAppContext: MiniAppContext? = null,
|
|
44
|
+
maxApi: IMaxApi? = null,
|
|
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) }
|
|
@@ -35,99 +53,101 @@ fun NavigationContainer(
|
|
|
35
53
|
val navigationBarHeight = getNavigationBarHeight()
|
|
36
54
|
|
|
37
55
|
val parentContext = LocalContext.current
|
|
38
|
-
val mergedContext = MiniAppContext.merge(parentContext,
|
|
56
|
+
val mergedContext = MiniAppContext.merge(parentContext, miniAppContext)
|
|
39
57
|
|
|
40
|
-
|
|
41
|
-
|
|
58
|
+
val theme = remember { mutableStateOf(initialTheme) }
|
|
59
|
+
val fallbackLocalize = remember { Localize() }
|
|
60
|
+
|
|
61
|
+
val resolvedLocalize = localize ?: fallbackLocalize
|
|
62
|
+
|
|
63
|
+
LaunchedEffect(maxApi, resolvedLocalize) {
|
|
42
64
|
val api = maxApi ?: return@LaunchedEffect
|
|
43
65
|
runCatching {
|
|
44
|
-
api.
|
|
45
|
-
|
|
46
|
-
|
|
66
|
+
api.getLanguage(callback = { data ->
|
|
67
|
+
if (parseLanguage(data) == Localize.EN) {
|
|
68
|
+
resolvedLocalize.changeLanguage(Localize.EN)
|
|
69
|
+
}
|
|
70
|
+
})
|
|
47
71
|
}
|
|
48
72
|
}
|
|
49
73
|
|
|
50
|
-
val theme = remember { mutableStateOf(initialTheme) }
|
|
51
|
-
|
|
52
|
-
val fallbackLocalize = remember { Localize() }
|
|
53
|
-
val resolvedLocalize = localize ?: fallbackLocalize
|
|
54
|
-
|
|
55
74
|
val screenId = rememberSaveable { registry.nextId() }
|
|
56
75
|
registry.bind(screenId, initialScreenName, initialScreen, options)
|
|
57
76
|
val startDestination = remember(screenId) { DynamicScreenRoute(screenId) }
|
|
58
77
|
|
|
59
|
-
|
|
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,34 +162,11 @@ 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
|
-
private
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
if (
|
|
153
|
-
@Suppress("UNCHECKED_CAST")
|
|
154
|
-
val data = (raw["response"] as? Map<String, Any?>)
|
|
155
|
-
?: (raw["data"] as? Map<String, Any?>)
|
|
156
|
-
?: raw
|
|
157
|
-
if (!data.containsKey("useOSFontScale") && !data.containsKey("userScaleRate")) return null
|
|
158
|
-
val useOS = when (val v = data["useOSFontScale"]) {
|
|
159
|
-
is Boolean -> v
|
|
160
|
-
is String -> v.equals("true", ignoreCase = true)
|
|
161
|
-
is Number -> v.toInt() != 0
|
|
162
|
-
else -> true
|
|
163
|
-
}
|
|
164
|
-
val rate = when (val v = data["userScaleRate"]) {
|
|
165
|
-
is Number -> v.toFloat()
|
|
166
|
-
is String -> v.toFloatOrNull()
|
|
167
|
-
else -> null
|
|
168
|
-
}
|
|
169
|
-
val osScale = when (val v = data["osFontScale"]) {
|
|
170
|
-
is Number -> v.toFloat()
|
|
171
|
-
is String -> v.toFloatOrNull()
|
|
172
|
-
else -> null
|
|
173
|
-
}
|
|
174
|
-
return FontScaleConfig(useOSFontScale = useOS, userScaleRate = rate, osFontScale = osScale)
|
|
167
|
+
private fun parseLanguage(raw: Map<String, Any?>?): String? {
|
|
168
|
+
val code = (raw?.get("response") as? String)?.trim()?.lowercase()
|
|
169
|
+
if (code.isNullOrEmpty()) return null
|
|
170
|
+
return if (code.startsWith(Localize.EN)) Localize.EN else Localize.VI
|
|
175
171
|
}
|
|
172
|
+
|
|
@@ -96,6 +96,8 @@ internal fun StackScreen(
|
|
|
96
96
|
val navigation = remember { Navigation(id = id, bottomTabIndex = bottomTabIndex, initOptions = navigationOptions, registry = screenRegistry) }
|
|
97
97
|
|
|
98
98
|
val options by navigation.currentOptions
|
|
99
|
+
val isBottomTabChild = bottomTabIndex != -1
|
|
100
|
+
val isBottomTabRoot = navigation.isBottomTabRoot
|
|
99
101
|
|
|
100
102
|
// Auto tracking state
|
|
101
103
|
val trackingState = remember {
|
|
@@ -193,7 +195,7 @@ internal fun StackScreen(
|
|
|
193
195
|
}
|
|
194
196
|
|
|
195
197
|
Column(Modifier.zIndex(2f).fillMaxSize()) {
|
|
196
|
-
MainContent(content = content)
|
|
198
|
+
MainContent(content = content, isBottomTab = isBottomTabRoot)
|
|
197
199
|
FooterContent()
|
|
198
200
|
}
|
|
199
201
|
|
|
@@ -201,7 +203,7 @@ internal fun StackScreen(
|
|
|
201
203
|
FloatingContent()
|
|
202
204
|
}
|
|
203
205
|
|
|
204
|
-
OverplayView(
|
|
206
|
+
OverplayView(isBottomTabChild = isBottomTabChild, id = id)
|
|
205
207
|
}
|
|
206
208
|
}
|
|
207
209
|
}
|
|
@@ -213,10 +215,11 @@ internal fun FloatingContent() {
|
|
|
213
215
|
val density = LocalDensity.current
|
|
214
216
|
val footerHeightPx = LocalFooterHeightPx.current
|
|
215
217
|
val scrollState = LocalScrollState.current
|
|
218
|
+
val navigationBar = AppNavigationBar.current
|
|
216
219
|
|
|
217
220
|
val fabProps = options.floatingButtonProps ?: return
|
|
218
221
|
val bottomPadding = fabProps.bottom
|
|
219
|
-
?: (Spacing.M + if (options.footerComponent != null) with(density) { footerHeightPx.intValue.toDp() } else
|
|
222
|
+
?: (Spacing.M + if (options.footerComponent != null) with(density) { footerHeightPx.intValue.toDp() } else navigationBar)
|
|
220
223
|
|
|
221
224
|
FloatingButton(
|
|
222
225
|
scrollPosition = fabProps.scrollState?.value ?: scrollState.value,
|
|
@@ -232,11 +235,12 @@ internal fun FloatingContent() {
|
|
|
232
235
|
}
|
|
233
236
|
|
|
234
237
|
@Composable
|
|
235
|
-
internal fun ColumnScope.MainContent(content: @Composable () -> Unit) {
|
|
238
|
+
internal fun ColumnScope.MainContent(content: @Composable () -> Unit, isBottomTab: Boolean) {
|
|
236
239
|
val options = LocalOptions.current
|
|
237
240
|
val inputSearchType = getInputSearchType(options)
|
|
238
241
|
val density = LocalDensity.current
|
|
239
242
|
val scrollState = LocalScrollState.current
|
|
243
|
+
val navigationBar = AppNavigationBar.current
|
|
240
244
|
|
|
241
245
|
Spacer(
|
|
242
246
|
Modifier.height(
|
|
@@ -260,6 +264,7 @@ internal fun ColumnScope.MainContent(content: @Composable () -> Unit) {
|
|
|
260
264
|
.conditional(options.scrollData.scrollable && options.scrollData.scrollState is ScrollState) {
|
|
261
265
|
verticalScroll(scrollState)
|
|
262
266
|
}
|
|
267
|
+
.padding(bottom = if (options.footerComponent != null || isBottomTab) 0.dp else navigationBar)
|
|
263
268
|
) {
|
|
264
269
|
ScreenContent(content = content)
|
|
265
270
|
}
|
|
@@ -303,12 +308,12 @@ internal fun keyboardSizeState(): State<Dp> {
|
|
|
303
308
|
}
|
|
304
309
|
|
|
305
310
|
@Composable
|
|
306
|
-
internal fun OverplayView(
|
|
311
|
+
internal fun OverplayView(isBottomTabChild: Boolean, id: Int) {
|
|
307
312
|
val overplayType = OverplayComponentRegistry.getOverplayType()
|
|
308
313
|
|
|
309
314
|
if (overplayType != null) {
|
|
310
315
|
Box(Modifier.zIndex(if (overplayType == OverplayComponentType.SNACK_BAR) 3f else 7f).fillMaxSize()) {
|
|
311
|
-
if (
|
|
316
|
+
if (isBottomTabChild) return@Box
|
|
312
317
|
if (OverplayComponentRegistry.currentRootId() != id) return@Box
|
|
313
318
|
OverplayComponentRegistry.OverlayComponent()
|
|
314
319
|
}
|
|
@@ -23,7 +23,6 @@ import vn.momo.kits.navigation.LocalNavigator
|
|
|
23
23
|
import vn.momo.kits.navigation.NavigationOptions
|
|
24
24
|
import vn.momo.kits.navigation.StackScreen
|
|
25
25
|
import vn.momo.kits.navigation.component.HeaderType
|
|
26
|
-
import vn.momo.kits.platform.getScreenHeight
|
|
27
26
|
|
|
28
27
|
private var bottomTabOptionItems : MutableList<NavigationOptions?> = mutableListOf()
|
|
29
28
|
internal fun setBottomTabOption(index: Int, options: NavigationOptions){
|
|
@@ -52,15 +51,15 @@ fun BottomTab(
|
|
|
52
51
|
|
|
53
52
|
|
|
54
53
|
LaunchedEffect(Unit){
|
|
54
|
+
navigation.markAsBottomTabRoot()
|
|
55
55
|
navigation.setOptions(
|
|
56
56
|
headerType = HeaderType.None
|
|
57
57
|
)
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
-
Box(modifier = Modifier.
|
|
60
|
+
Box(modifier = Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
|
|
61
61
|
Box(modifier = Modifier
|
|
62
62
|
.fillMaxSize()
|
|
63
|
-
.padding(bottom = BOTTOM_TAB_BAR_HEIGHT.dp + AppNavigationBar.current)
|
|
64
63
|
) {
|
|
65
64
|
NavHost(
|
|
66
65
|
navController = navController,
|
|
@@ -127,7 +126,7 @@ fun BottomTab(
|
|
|
127
126
|
onTabSelected = {
|
|
128
127
|
val currentRoute = navController.currentBackStackEntry?.destination?.route
|
|
129
128
|
val targetRoute = "option$it"
|
|
130
|
-
if (currentRoute != targetRoute){
|
|
129
|
+
if (currentRoute != targetRoute) {
|
|
131
130
|
navController.navigate(targetRoute)
|
|
132
131
|
}
|
|
133
132
|
}
|
|
@@ -23,12 +23,14 @@ import androidx.navigation.compose.currentBackStackEntryAsState
|
|
|
23
23
|
import vn.momo.kits.application.IsShowBaseLineDebug
|
|
24
24
|
import vn.momo.kits.components.*
|
|
25
25
|
import vn.momo.kits.const.*
|
|
26
|
+
import vn.momo.kits.modifier.InternalApi
|
|
26
27
|
import vn.momo.kits.modifier.conditional
|
|
27
28
|
import vn.momo.kits.modifier.noFeedbackClickable
|
|
28
29
|
import vn.momo.kits.platform.getScreenDimensions
|
|
29
30
|
|
|
30
31
|
internal val floatingButtonWidth = 75.dp
|
|
31
|
-
|
|
32
|
+
@InternalApi
|
|
33
|
+
const val BOTTOM_TAB_BAR_HEIGHT = 64
|
|
32
34
|
|
|
33
35
|
@Composable
|
|
34
36
|
internal fun BottomTabBar(
|
|
@@ -44,7 +44,8 @@ import vn.momo.kits.navigation.LocalOptions
|
|
|
44
44
|
import vn.momo.kits.navigation.LocalScrollState
|
|
45
45
|
import vn.momo.kits.navigation.getInputSearchType
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
@InternalApi
|
|
48
|
+
const val HEADER_HEIGHT = 52
|
|
48
49
|
internal enum class InputSearchType { None, Header, Animated }
|
|
49
50
|
enum class TitlePosition { LEFT, CENTER }
|
|
50
51
|
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
package vn.momo.kits.platform
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Composable
|
|
4
|
+
|
|
5
|
+
// Overrides LocalDensity.fontScale with the live OS Dynamic Type scale so text re-scales while a
|
|
6
|
+
// screen is visible. Wrapped inside the containers so every screen is covered, not just callers of
|
|
7
|
+
// the app-level wrappers.
|
|
8
|
+
@Composable
|
|
9
|
+
expect fun ProvideOsFontScale(content: @Composable () -> Unit)
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
package vn.momo.kits.platform
|
|
2
|
+
|
|
3
|
+
import androidx.compose.runtime.Composable
|
|
4
|
+
import androidx.compose.runtime.CompositionLocalProvider
|
|
5
|
+
import androidx.compose.runtime.DisposableEffect
|
|
6
|
+
import androidx.compose.runtime.mutableStateOf
|
|
7
|
+
import androidx.compose.runtime.remember
|
|
8
|
+
import androidx.compose.ui.platform.LocalDensity
|
|
9
|
+
import androidx.compose.ui.unit.Density
|
|
10
|
+
import kotlinx.cinterop.ExperimentalForeignApi
|
|
11
|
+
import kotlinx.cinterop.ObjCAction
|
|
12
|
+
import platform.Foundation.NSNotification
|
|
13
|
+
import platform.Foundation.NSNotificationCenter
|
|
14
|
+
import platform.Foundation.NSSelectorFromString
|
|
15
|
+
import platform.UIKit.UIContentSizeCategoryDidChangeNotification
|
|
16
|
+
import platform.UIKit.UIFont
|
|
17
|
+
import platform.UIKit.UIFontTextStyleBody
|
|
18
|
+
import platform.darwin.NSObject
|
|
19
|
+
|
|
20
|
+
// Compose MP iOS reads LocalDensity.fontScale once at ComposeUIViewController creation and does not
|
|
21
|
+
// recompose it when UIContentSizeCategory changes (Android tracks Configuration.fontScale live). We
|
|
22
|
+
// observe the notification and override LocalDensity.fontScale so scaleSize() recomposes live. The
|
|
23
|
+
// formula matches the SwiftUI kit (UIFont body point size / 17) so both iOS surfaces scale alike.
|
|
24
|
+
private const val DEFAULT_BODY_POINT_SIZE = 17.0
|
|
25
|
+
|
|
26
|
+
private fun currentOsFontScale(): Float =
|
|
27
|
+
(UIFont.preferredFontForTextStyle(UIFontTextStyleBody).pointSize / DEFAULT_BODY_POINT_SIZE).toFloat()
|
|
28
|
+
|
|
29
|
+
@OptIn(ExperimentalForeignApi::class)
|
|
30
|
+
@Composable
|
|
31
|
+
actual fun ProvideOsFontScale(content: @Composable () -> Unit) {
|
|
32
|
+
val osFontScale = remember { mutableStateOf(currentOsFontScale()) }
|
|
33
|
+
|
|
34
|
+
val listener = remember {
|
|
35
|
+
object : NSObject() {
|
|
36
|
+
@Suppress("unused")
|
|
37
|
+
@ObjCAction
|
|
38
|
+
fun contentSizeChanged(arg: NSNotification) {
|
|
39
|
+
osFontScale.value = currentOsFontScale()
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
DisposableEffect(Unit) {
|
|
45
|
+
NSNotificationCenter.defaultCenter.addObserver(
|
|
46
|
+
observer = listener,
|
|
47
|
+
selector = NSSelectorFromString(listener::contentSizeChanged.name + ":"),
|
|
48
|
+
name = UIContentSizeCategoryDidChangeNotification,
|
|
49
|
+
`object` = null,
|
|
50
|
+
)
|
|
51
|
+
onDispose {
|
|
52
|
+
NSNotificationCenter.defaultCenter.removeObserver(
|
|
53
|
+
observer = listener,
|
|
54
|
+
name = UIContentSizeCategoryDidChangeNotification,
|
|
55
|
+
`object` = null,
|
|
56
|
+
)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
val density = LocalDensity.current
|
|
61
|
+
CompositionLocalProvider(
|
|
62
|
+
LocalDensity provides Density(density.density, osFontScale.value),
|
|
63
|
+
) {
|
|
64
|
+
content()
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -21,6 +21,7 @@ maxapi = "0.1.1"
|
|
|
21
21
|
vanniktechMavenPublish = "0.34.0"
|
|
22
22
|
kits = "0.159.1-beta.7"
|
|
23
23
|
nativemaxapi = "0.0.6"
|
|
24
|
+
gif-image = "0.1.2"
|
|
24
25
|
|
|
25
26
|
[libraries]
|
|
26
27
|
ktor-client-core = { group = "io.ktor", name = "ktor-client-core", version.ref = "ktor-version" }
|
|
@@ -53,6 +54,7 @@ androidx-appcompat = { module = "androidx.appcompat:appcompat", version.ref = "a
|
|
|
53
54
|
androidx-activity-compose = { module = "androidx.activity:activity-compose", version.ref = "androidx-activity" }
|
|
54
55
|
material = { module = "com.google.android.material:material", version.ref = "material" }
|
|
55
56
|
|
|
57
|
+
gif-image = { module = "vn.momo.kits:gif-image", version.ref = "gif-image" }
|
|
56
58
|
[plugins]
|
|
57
59
|
jetbrains-kotlin-jvm = { id = "org.jetbrains.kotlin.jvm", version.ref = "kotlin" }
|
|
58
60
|
jetbrains-kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
|
package/gradle.properties
CHANGED
|
@@ -46,6 +46,16 @@ public class ApplicationEnvironment: ObservableObject {
|
|
|
46
46
|
self.applicationContext = applicationContext
|
|
47
47
|
self.composeApi = composeApi
|
|
48
48
|
self.config = config
|
|
49
|
-
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private struct ApplicationEnvironmentKey: EnvironmentKey {
|
|
53
|
+
static let defaultValue = ApplicationEnvironment()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
public extension EnvironmentValues {
|
|
57
|
+
var applicationEnvironment: ApplicationEnvironment {
|
|
58
|
+
get { self[ApplicationEnvironmentKey.self] }
|
|
59
|
+
set { self[ApplicationEnvironmentKey.self] = newValue }
|
|
50
60
|
}
|
|
51
61
|
}
|