@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.
Files changed (215) hide show
  1. package/CLAUDE.md +1 -1
  2. package/compose/build.gradle.kts +2 -1
  3. package/compose/build.gradle.kts.backup +1 -0
  4. package/compose/compose.podspec +1 -1
  5. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +7 -0
  6. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +8 -10
  7. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +3 -0
  8. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +56 -0
  9. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +11 -9
  10. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +40 -55
  11. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +69 -26
  12. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +3 -1
  13. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +21 -0
  14. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +3 -6
  15. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +22 -0
  16. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +28 -21
  17. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +4 -0
  18. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +112 -115
  19. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +11 -6
  20. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +3 -4
  21. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +3 -1
  22. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +2 -1
  23. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +9 -0
  24. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +66 -0
  25. package/gradle/libs.versions.toml +2 -0
  26. package/gradle.properties +1 -1
  27. package/ios/Application/ApplicationEnvironment.swift +11 -1
  28. package/ios/Application/Components.swift +34 -44
  29. package/ios/Application/FloatingButton.swift +10 -9
  30. package/ios/Application/HeaderRight.swift +79 -45
  31. package/ios/Application/Navigation/BottomTab/BottomTab.swift +103 -0
  32. package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +215 -0
  33. package/ios/Application/Navigation/BottomTab/CurvedContainer.swift +65 -0
  34. package/ios/Application/Navigation/HeaderBackProps.swift +66 -0
  35. package/ios/Application/Navigation/HeaderTitle.swift +57 -0
  36. package/ios/Application/Navigation/HeaderUser.swift +209 -0
  37. package/ios/Application/Navigation/NavigationContainer.swift +176 -0
  38. package/ios/Application/Navigation/NavigationOptions.swift +109 -0
  39. package/ios/Application/Navigation/Navigator.swift +364 -0
  40. package/ios/Application/Navigation/Overplay/BottomSheet.swift +188 -0
  41. package/ios/Application/Navigation/Overplay/ModalScreen.swift +68 -0
  42. package/ios/Application/Navigation/Overplay/SnackBar.swift +144 -0
  43. package/ios/Application/Navigation/component/Header.swift +178 -0
  44. package/ios/Application/Navigation/component/HeaderBackground.swift +83 -0
  45. package/ios/Application/Navigation/component/HeaderColor.swift +65 -0
  46. package/ios/Application/Screen.swift +2 -1
  47. package/ios/Application/StackScreen.swift +453 -0
  48. package/ios/Avatar/Avatar.swift +193 -0
  49. package/ios/Badge/Badge.swift +11 -14
  50. package/ios/Badge/BadgeRibbon.swift +12 -21
  51. package/ios/BaselineView/BaselineView.swift +163 -0
  52. package/ios/Button/Button.swift +61 -22
  53. package/ios/Carousel/Carousel.swift +181 -0
  54. package/ios/Checkbox/Checkbox.swift +14 -13
  55. package/ios/Chip/Chip.swift +23 -9
  56. package/ios/Collapse/Collapse.swift +182 -0
  57. package/ios/Colors+Radius+Spacing/Colors.swift +12 -12
  58. package/ios/Colors+Radius+Spacing/Theme.swift +295 -0
  59. package/ios/DateTimePicker/DateTimePicker.swift +210 -0
  60. package/ios/DateTimePicker/DateTimePickerTypes.swift +55 -0
  61. package/ios/DateTimePicker/DateTimePickerUtils.swift +167 -0
  62. package/ios/DateTimePicker/WheelPicker.swift +161 -0
  63. package/ios/Divider/Divider.swift +16 -0
  64. package/ios/Extensions/Color++.swift +32 -0
  65. package/ios/Icon/Icon.swift +6 -1
  66. package/ios/IconButton/IconButton.swift +112 -0
  67. package/ios/Input/Input.swift +41 -25
  68. package/ios/Input/InputPhoneNumber.swift +20 -19
  69. package/ios/Input/InputSearch.swift +100 -47
  70. package/ios/Input/InputTextArea.swift +66 -40
  71. package/ios/InputDropDown/InputDropDown.swift +198 -0
  72. package/ios/InputMoney/InputMoney.swift +335 -0
  73. package/ios/InputOTP/InputOTP.swift +210 -0
  74. package/ios/Loader/Loader.swift +113 -0
  75. package/ios/MoMoUIKits.podspec +5 -0
  76. package/ios/Pagination/PaginationDot.swift +61 -0
  77. package/ios/Pagination/PaginationNumber.swift +35 -0
  78. package/ios/Pagination/PaginationScroll.swift +101 -0
  79. package/ios/Pagination/PaginationWhiteDot.swift +37 -0
  80. package/ios/Popup/PopupDisplay.swift +8 -16
  81. package/ios/Popup/PopupInput.swift +2 -8
  82. package/ios/Popup/PopupNotify.swift +219 -0
  83. package/ios/ProgressInfo/ProgressInfo.swift +294 -0
  84. package/ios/Radio/Radio.swift +70 -0
  85. package/ios/Rating/Rating.swift +82 -0
  86. package/ios/Resources/MoMoUIKitsColors.xcassets/AccentColor.colorset/Contents.json +11 -0
  87. package/ios/Resources/MoMoUIKitsColors.xcassets/Background.colorset/Contents.json +38 -0
  88. package/ios/Resources/MoMoUIKitsColors.xcassets/Border.colorset/Contents.json +38 -0
  89. package/ios/Resources/MoMoUIKitsColors.xcassets/Card.colorset/Contents.json +38 -0
  90. package/ios/Resources/MoMoUIKitsColors.xcassets/Contents.json +6 -0
  91. package/ios/Resources/MoMoUIKitsColors.xcassets/Error.colorset/Contents.json +38 -0
  92. package/ios/Resources/MoMoUIKitsColors.xcassets/Primary.colorset/Contents.json +38 -0
  93. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryDark.colorset/Contents.json +38 -0
  94. package/ios/Resources/MoMoUIKitsColors.xcassets/PrimaryLight.colorset/Contents.json +38 -0
  95. package/ios/Resources/MoMoUIKitsColors.xcassets/Secondary.colorset/Contents.json +38 -0
  96. package/ios/Resources/MoMoUIKitsColors.xcassets/Success.colorset/Contents.json +38 -0
  97. package/ios/Resources/MoMoUIKitsColors.xcassets/Text.colorset/Contents.json +38 -0
  98. package/ios/Resources/MoMoUIKitsColors.xcassets/TextSecondary.colorset/Contents.json +38 -0
  99. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/Contents.json +9 -0
  100. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-default.colorset/Contents.json +38 -0
  101. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-disable.colorset/Contents.json +38 -0
  102. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-pressed.colorset/Contents.json +38 -0
  103. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-selected.colorset/Contents.json +38 -0
  104. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-surface.colorset/Contents.json +38 -0
  105. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/background-tonal.colorset/Contents.json +38 -0
  106. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-default.colorset/Contents.json +38 -0
  107. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/border-disable.colorset/Contents.json +38 -0
  108. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/gradient.colorset/Contents.json +38 -0
  109. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/primary.colorset/Contents.json +38 -0
  110. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/secondary.colorset/Contents.json +38 -0
  111. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-container.colorset/Contents.json +38 -0
  112. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-primary.colorset/Contents.json +38 -0
  113. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/success-secondary.colorset/Contents.json +38 -0
  114. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-default.colorset/Contents.json +38 -0
  115. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-disable.colorset/Contents.json +38 -0
  116. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-hint.colorset/Contents.json +38 -0
  117. package/ios/Resources/MoMoUIKitsColors.xcassets/ThemeColors/text-secondary.colorset/Contents.json +38 -0
  118. package/ios/Resources/MoMoUIKitsColors.xcassets/Warning.colorset/Contents.json +38 -0
  119. package/ios/Skeleton/Skeleton.swift +99 -0
  120. package/ios/Slider/Slider.swift +237 -0
  121. package/ios/Stepper/Stepper.swift +220 -0
  122. package/ios/Steps/Steps.swift +451 -0
  123. package/ios/SuggestAction/SuggestAction.swift +97 -0
  124. package/ios/Swipeable/SwipeCell.swift +185 -0
  125. package/ios/Swipeable/SwipeCellModel.swift +21 -0
  126. package/ios/TabView/TabView.swift +530 -0
  127. package/ios/Tag/Tag.swift +98 -0
  128. package/ios/Title/Title.swift +269 -0
  129. package/ios/Tooltip/Tooltip.swift +482 -0
  130. package/ios/Typography/FontScaleStore.swift +19 -0
  131. package/ios/Typography/Text.swift +86 -17
  132. package/ios/Typography/Typography.swift +12 -14
  133. package/ios/Uploader/Uploader.swift +183 -0
  134. package/ios/native-kits.podspec +61 -8
  135. package/ios-demo/MoMoUIKitsDemo.podspec +20 -0
  136. package/ios-demo/README.md +120 -0
  137. package/ios-demo/Resources/dot_loading.json +558 -0
  138. package/ios-demo/Resources/icon.json +4052 -0
  139. package/ios-demo/Resources/lottie_circle_loader.json +1 -0
  140. package/ios-demo/Sources/MoMoUIKitsDemo/DemoScaffold.swift +48 -0
  141. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsBadgeDemoView.swift +25 -0
  142. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsButtonDemoView.swift +26 -0
  143. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsCheckboxDemoView.swift +19 -0
  144. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsChipDemoView.swift +33 -0
  145. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsInputDemoView.swift +48 -0
  146. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsPopupDemoView.swift +21 -0
  147. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsRadioDemoView.swift +17 -0
  148. package/ios-demo/Sources/MoMoUIKitsDemo/Demos/UIKitsTypographyDemoView.swift +28 -0
  149. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoContext.swift +31 -0
  150. package/ios-demo/Sources/MoMoUIKitsDemo/MoMoUIKitsDemoFactory.swift +24 -0
  151. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AnimatedHeaderDemo.swift +110 -0
  152. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/AvatarDemo.swift +93 -0
  153. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BadgeDemo.swift +269 -0
  154. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BaselineView.swift +117 -0
  155. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/BottomTabDemo.swift +89 -0
  156. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ButtonDemo.swift +100 -0
  157. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CarouselDemo.swift +126 -0
  158. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CheckboxDemo.swift +63 -0
  159. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ChipDemo.swift +20 -0
  160. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/CollapseDemo.swift +93 -0
  161. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +107 -0
  162. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DateTimePickerDemo.swift +124 -0
  163. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DividerDemo.swift +14 -0
  164. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/HeaderUserDemo.swift +49 -0
  165. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +278 -0
  166. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IconButtonDemo.swift +58 -0
  167. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ImageDemo.swift +78 -0
  168. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InformationDemo.swift +138 -0
  169. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDemo.swift +111 -0
  170. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputDropDownDemo.swift +136 -0
  171. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputMoneyDemo.swift +107 -0
  172. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputOTPDemo.swift +73 -0
  173. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputPhoneNumberDemo.swift +100 -0
  174. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputSearchDemo.swift +32 -0
  175. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/InputTextAreaDemo.swift +57 -0
  176. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/LoaderDemo.swift +70 -0
  177. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +227 -0
  178. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PaginationDemo.swift +72 -0
  179. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +175 -0
  180. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +121 -0
  181. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +76 -0
  182. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ProgressInfoDemo.swift +89 -0
  183. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RadioDemo.swift +32 -0
  184. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/RatingDemo.swift +56 -0
  185. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SkeletonDemo.swift +32 -0
  186. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SliderDemo.swift +150 -0
  187. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SnackBarDemo.swift +138 -0
  188. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepperDemo.swift +103 -0
  189. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/StepsDemo.swift +94 -0
  190. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SuggestActionDemo.swift +79 -0
  191. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwipeDemo.swift +152 -0
  192. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/SwitchDemo.swift +33 -0
  193. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TabViewDemo.swift +190 -0
  194. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TagDemo.swift +34 -0
  195. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ThemeDemo.swift +182 -0
  196. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TitleDemo.swift +109 -0
  197. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TooltipDemo.swift +187 -0
  198. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/TypographyDemo.swift +87 -0
  199. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/UploaderDemo.swift +131 -0
  200. package/ios-demo/Sources/MoMoUIKitsDemo/SwiftUIDemoBrowserView.swift +51 -0
  201. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoModels.swift +15 -0
  202. package/ios-demo/Sources/MoMoUIKitsDemo/UIKitsDemoRegistry.swift +73 -0
  203. package/package.json +1 -1
  204. package/publish.sh +50 -0
  205. package/scripts/gen-ios-color.mjs +136 -0
  206. package/example/ios/Example.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  207. package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  208. package/example/ios/Example.xcworkspace/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -5
  209. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
  210. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
  211. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImage.xcscheme +0 -58
  212. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SDWebImageSwiftUI.xcscheme +0 -58
  213. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/SkeletonUI.xcscheme +0 -58
  214. package/example/ios/Pods/Pods.xcodeproj/xcuserdata/huynhdung.xcuserdatad/xcschemes/xcschememanagement.plist +0 -46
  215. package/ios/Application/FontScaleStore.swift +0 -59
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`, `ScaleSizeMaxRate` (`application/`); `LocalNavigator`, `LocalMaxApi` (`navigation/`). Read with `X.current`.
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`.
@@ -40,7 +40,7 @@ kotlin {
40
40
  }
41
41
 
42
42
  cocoapods {
43
- version = "0.163.1-beta.3-debug"
43
+ version = "0.163.1-beta.5-debug"
44
44
  summary = "IOS Shared module"
45
45
  homepage = "https://momo.vn"
46
46
  ios.deploymentTarget = "15.0"
@@ -77,6 +77,7 @@ kotlin {
77
77
  implementation(libs.kotlinx.datetime)
78
78
  api(libs.native.max.api)
79
79
  implementation(libs.compottie)
80
+ implementation(libs.gif.image)
80
81
  }
81
82
  androidMain.dependencies {
82
83
  implementation(libs.ktor.client.okhttp)
@@ -77,6 +77,7 @@ kotlin {
77
77
  implementation(libs.kotlinx.datetime)
78
78
  api(libs.native.max.api)
79
79
  implementation(libs.compottie)
80
+ implementation(libs.gif.image)
80
81
  }
81
82
  androidMain.dependencies {
82
83
  implementation(libs.ktor.client.okhttp)
@@ -1,6 +1,6 @@
1
1
  Pod::Spec.new do |spec|
2
2
  spec.name = 'compose'
3
- spec.version = '0.163.1-beta.1'
3
+ spec.version = '0.163.1-beta.5-debug'
4
4
  spec.homepage = 'https://momo.vn'
5
5
  spec.source = { :http=> ''}
6
6
  spec.authors = ''
@@ -0,0 +1,7 @@
1
+ package vn.momo.kits.platform
2
+
3
+ import androidx.compose.runtime.Composable
4
+
5
+ // Android's LocalDensity.fontScale already tracks Configuration.fontScale live.
6
+ @Composable
7
+ actual fun ProvideOsFontScale(content: @Composable () -> Unit) = content()
@@ -28,7 +28,9 @@ data class MiniAppContext(
28
28
  val providerId: String = "",
29
29
  val permissions: List<Map<String, Any>>? = emptyList(),
30
30
  val features: FeatureFlags? = null,
31
- val fontScaleConfig: FontScaleConfig? = null,
31
+ val scaleSizeMaxRate: Float? = null,
32
+ val userScaleRate: Float? = null,
33
+ val useOSScaleRate: Boolean? = null,
32
34
  ) {
33
35
  companion object {
34
36
 
@@ -60,7 +62,9 @@ data class MiniAppContext(
60
62
  providerId = parent.providerId.ifBlank { child.providerId },
61
63
  permissions = if (!parent.permissions.isNullOrEmpty()) parent.permissions else child.permissions,
62
64
  features = mergeFeatureFlags(parent.features, child.features),
63
- fontScaleConfig = parent.fontScaleConfig ?: child.fontScaleConfig,
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,11 +102,5 @@ val LocalComponentInformation = staticCompositionLocalOf<ComponentInformation?>
98
102
  null
99
103
  }
100
104
 
101
- @Immutable
102
- data class FontScaleConfig(
103
- val useOSFontScale: Boolean = true,
104
- val userScaleRate: Float? = null,
105
- val osFontScale: Float? = null,
106
- )
107
-
108
- val LocalFontScaleConfig = staticCompositionLocalOf { FontScaleConfig() }
105
+ @Deprecated("Max font scale is fixed at MAX_FONT_SCALE (1.5); this CompositionLocal is no longer read.")
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
+ }
@@ -95,11 +95,13 @@ private fun getStyle(size: Size): TextStyle {
95
95
  return styleCache[size] ?: Typography.actionDefaultBold
96
96
  }
97
97
 
98
- private fun getIconSize(size: Size): Dp = iconSizeCache[size] ?: 24.dp
98
+ @InternalApi
99
+ fun getIconSize(size: Size): Dp = iconSizeCache[size] ?: 24.dp
99
100
  private fun getIconSpace(size: Size): Dp = iconSpaceCache[size] ?: Spacing.S
100
101
 
102
+ @InternalApi
101
103
  @Composable
102
- internal fun getTextColor(loading: Boolean, type: ButtonType): Color {
104
+ fun getTextColor(loading: Boolean, type: ButtonType): Color {
103
105
  val theme = AppTheme.current
104
106
 
105
107
  return remember(type, theme, loading) {
@@ -140,7 +142,6 @@ fun RenderIcon(
140
142
  useTintColor: Boolean = true,
141
143
  icon: String = "",
142
144
  forceLoading: Boolean = false,
143
- bgColor: Color? = null,
144
145
  textColor: Color? = null,
145
146
  ) {
146
147
  val iconSize = remember(size) { getIconSize(size) }
@@ -156,9 +157,10 @@ fun RenderIcon(
156
157
  Box(modifier) {
157
158
  LottieAnimation(
158
159
  modifier = Modifier.size(iconSize),
159
- bgColor = bgColor,
160
+ bgColor = null,
160
161
  tintColor = color,
161
- path = "files/lottie_circle_loader"
162
+ path = "files/lottie_circle_loader",
163
+ useCompose = true
162
164
  )
163
165
  }
164
166
  } else if (icon.isNotEmpty()) {
@@ -183,8 +185,9 @@ private fun shouldLoadingOnLeft(iconLeft: String, iconRight: String): Boolean {
183
185
  }
184
186
  }
185
187
 
188
+ @InternalApi
186
189
  @Composable
187
- internal fun getTypeStyle(
190
+ fun getTypeStyle(
188
191
  type: ButtonType,
189
192
  color: Color? = AppTheme.current.colors.primary,
190
193
  size: Size,
@@ -219,8 +222,9 @@ internal fun getTypeStyle(
219
222
  }
220
223
  }
221
224
 
225
+ @InternalApi
222
226
  @Composable
223
- internal fun getButtonBackgroundColor(
227
+ fun getButtonBackgroundColor(
224
228
  loading: Boolean,
225
229
  type: ButtonType
226
230
  ): Color {
@@ -336,7 +340,6 @@ fun Button(
336
340
  useTintColor = useTintColor,
337
341
  icon = iconLeft,
338
342
  forceLoading = loading && loadingOnLeft,
339
- bgColor = bgColor,
340
343
  textColor = textColor
341
344
  )
342
345
  RenderTitle(size, title, textColor = textColor)
@@ -346,7 +349,6 @@ fun Button(
346
349
  useTintColor = useTintColor,
347
350
  icon = iconRight,
348
351
  forceLoading = loading && !loadingOnLeft,
349
- bgColor = bgColor,
350
352
  textColor = textColor
351
353
  )
352
354
  }
@@ -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
@@ -12,6 +13,7 @@ import androidx.compose.ui.Alignment
12
13
  import androidx.compose.ui.Modifier
13
14
  import androidx.compose.ui.draw.clip
14
15
  import androidx.compose.ui.graphics.Color
16
+ import androidx.compose.ui.graphics.Shape
15
17
  import androidx.compose.ui.unit.Dp
16
18
  import androidx.compose.ui.unit.dp
17
19
  import vn.momo.kits.application.IsShowBaseLineDebug
@@ -21,69 +23,58 @@ import vn.momo.kits.const.Radius
21
23
  import vn.momo.kits.modifier.conditional
22
24
 
23
25
  data class IconSpecs(
24
- val width: Dp,
25
- val height: Dp,
26
- val radius: Dp,
27
- val size: Dp
26
+ val box: Dp,
27
+ val icon: Dp,
28
28
  )
29
29
 
30
30
  enum class IconSize(val value: IconSpecs) {
31
- LARGE(
32
- IconSpecs(
33
- height = 48.dp,
34
- radius = Radius.XL,
35
- width = 48.dp,
36
- size = 48.dp
37
- )
38
- ),
39
- SMALL(
40
- IconSpecs(
41
- height = 40.dp,
42
- radius = Radius.XL,
43
- width = 40.dp,
44
- size = 40.dp
45
- )
46
- )
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)),
47
34
  }
48
35
 
49
- // Pre-computed shape to avoid repeated creation
50
- private val iconButtonShape = RoundedCornerShape(Radius.XL)
36
+ enum class IconShape {
37
+ CIRCLE,
38
+ SQUARE,
39
+ }
51
40
 
52
- // Cache for icon sizes to avoid repeated calculations
53
- private val iconSizeMap = mapOf(
54
- IconSize.SMALL to 16.dp,
55
- IconSize.LARGE to 24.dp
56
- )
41
+ // Square keeps an 8dp rounded corner; circle is fully rounded regardless of size.
42
+ private val squareShape = RoundedCornerShape(Radius.S)
43
+
44
+ private fun IconShape.toShape(): Shape = when (this) {
45
+ IconShape.CIRCLE -> CircleShape
46
+ IconShape.SQUARE -> squareShape
47
+ }
57
48
 
58
49
  @Composable
59
- internal fun getIconStyle(type: ButtonType, color: Color? = null): Modifier {
50
+ internal fun getIconStyle(type: ButtonType, shape: Shape, color: Color? = null): Modifier {
60
51
  val theme = AppTheme.current
61
52
 
62
- return remember(type, color, theme) {
53
+ return remember(type, shape, color, theme) {
63
54
  when (type) {
64
55
  ButtonType.DISABLED -> Modifier
65
- .background(theme.colors.background.disable, iconButtonShape)
66
- .border(0.dp, Color.Unspecified, iconButtonShape)
56
+ .background(theme.colors.background.disable, shape)
57
+ .border(0.dp, Color.Unspecified, shape)
67
58
 
68
59
  ButtonType.PRIMARY -> Modifier
69
- .background(theme.colors.primary, iconButtonShape)
70
- .border(0.dp, Color.Unspecified, iconButtonShape)
60
+ .background(theme.colors.primary, shape)
61
+ .border(0.dp, Color.Unspecified, shape)
71
62
 
72
63
  ButtonType.SECONDARY -> Modifier
73
- .background(theme.colors.background.surface, iconButtonShape)
74
- .border(1.dp, theme.colors.border.default, iconButtonShape)
64
+ .background(theme.colors.background.surface, shape)
65
+ .border(1.dp, theme.colors.border.default, shape)
75
66
 
76
67
  ButtonType.OUTLINE -> Modifier
77
- .background(theme.colors.background.surface, iconButtonShape)
78
- .border(1.dp, color ?: theme.colors.primary, iconButtonShape)
68
+ .background(theme.colors.background.surface, shape)
69
+ .border(1.dp, color ?: theme.colors.primary, shape)
79
70
 
80
71
  ButtonType.TONAL -> Modifier
81
- .background(theme.colors.background.tonal, iconButtonShape)
82
- .border(0.dp, Color.Unspecified, iconButtonShape)
72
+ .background(theme.colors.background.tonal, shape)
73
+ .border(0.dp, Color.Unspecified, shape)
83
74
 
84
75
  ButtonType.DANGER -> Modifier
85
- .background(theme.colors.error.primary, iconButtonShape)
86
- .border(0.dp, Color.Unspecified, iconButtonShape)
76
+ .background(theme.colors.error.primary, shape)
77
+ .border(0.dp, Color.Unspecified, shape)
87
78
 
88
79
  ButtonType.TEXT -> Modifier
89
80
  }
@@ -103,38 +94,32 @@ fun IconButton(
103
94
  onClick: () -> Unit,
104
95
  type: ButtonType = ButtonType.PRIMARY,
105
96
  size: IconSize = IconSize.SMALL,
97
+ shape: IconShape = IconShape.CIRCLE,
106
98
  icon: String = "",
107
99
  ) {
108
- // Memoize icon size calculation
109
- val iconSize = remember(size) {
110
- iconSizeMap[size] ?: 16.dp
111
- }
100
+ val specs = size.value
112
101
 
113
- // Memoize enabled state
114
102
  val isEnabled = remember(type) {
115
103
  type != ButtonType.DISABLED
116
104
  }
117
105
 
118
- // Memoize radius for clipping
119
- val radius = remember(size) {
120
- size.value.radius
121
- }
106
+ val boxShape = remember(shape) { shape.toShape() }
122
107
 
123
108
  Box(
124
109
  modifier = Modifier
125
- .size(size.value.size)
126
- .then(getIconStyle(type))
110
+ .size(specs.box)
111
+ .then(getIconStyle(type, boxShape))
127
112
  .conditional(IsShowBaseLineDebug) {
128
113
  border(1.dp, Colors.blue_03)
129
114
  }
130
- .clip(RoundedCornerShape(radius))
115
+ .clip(boxShape)
131
116
  .clickable(enabled = isEnabled, onClick = onClick),
132
117
  contentAlignment = Alignment.Center
133
118
  ) {
134
119
  Icon(
135
120
  source = icon,
136
121
  color = getIconColor(type),
137
- size = iconSize,
122
+ size = specs.icon,
138
123
  )
139
124
  }
140
- }
125
+ }
@@ -1,7 +1,9 @@
1
1
  package vn.momo.kits.components
2
2
 
3
3
  import androidx.compose.foundation.border
4
+ import androidx.compose.foundation.layout.Box
4
5
  import androidx.compose.foundation.layout.BoxWithConstraints
6
+ import androidx.compose.foundation.layout.fillMaxSize
5
7
  import androidx.compose.runtime.Composable
6
8
  import androidx.compose.runtime.getValue
7
9
  import androidx.compose.runtime.mutableStateOf
@@ -17,10 +19,12 @@ import androidx.compose.ui.semantics.contentDescription
17
19
  import androidx.compose.ui.semantics.semantics
18
20
  import androidx.compose.ui.platform.LocalDensity
19
21
  import androidx.compose.ui.unit.dp
20
- import coil3.compose.AsyncImage
22
+ import coil3.compose.AsyncImage as CoilAsyncImage
21
23
  import vn.momo.kits.application.IsShowBaseLineDebug
22
24
  import vn.momo.kits.const.AppTheme
23
25
  import vn.momo.kits.const.Colors
26
+ import vn.momo.kits.gifimage.GifImage
27
+ import vn.momo.kits.gifimage.GifImageState
24
28
  import vn.momo.kits.modifier.conditional
25
29
 
26
30
  data class Options(
@@ -73,6 +77,19 @@ private fun getHostFromUrl(url: String): String? {
73
77
  }
74
78
  }
75
79
 
80
+ private fun isGifUrl(url: String): Boolean {
81
+ val path = url.substringBefore('#').substringBefore('?')
82
+ return path.endsWith(".gif", ignoreCase = true)
83
+ }
84
+
85
+ private fun GifImageState.toImageState(): ImageState {
86
+ return when (this) {
87
+ GifImageState.Success -> ImageState.Success
88
+ GifImageState.Error -> ImageState.Error
89
+ GifImageState.Loading -> ImageState.Loading
90
+ }
91
+ }
92
+
76
93
  // Optimized query parameter appending
77
94
  private fun appendSizeQueryParam(url: String, value: String): String {
78
95
  val fragmentIndex = url.indexOf('#')
@@ -95,12 +112,12 @@ fun Image(
95
112
  modifier: Modifier = Modifier,
96
113
  options: Options? = null,
97
114
  loading: Boolean = true,
115
+ onStateChanged: (ImageState) -> Unit = {},
98
116
  ) {
99
117
  val imageOptions = remember(options) {
100
118
  options ?: Options()
101
119
  }
102
120
 
103
- var imageState by remember { mutableStateOf(ImageState.Loading) }
104
121
  val density = LocalDensity.current
105
122
 
106
123
  BoxWithConstraints(
@@ -121,34 +138,46 @@ fun Image(
121
138
  processedUrl
122
139
  }
123
140
  }
124
- else -> source
141
+ else -> source.toString()
125
142
  }
126
143
  }
127
144
 
128
- AsyncImage(
129
- modifier = Modifier.matchParentSize(),
130
- model = urlToLoad,
131
- contentDescription = null,
132
- contentScale = imageOptions.contentScale,
133
- alignment = imageOptions.alignment,
134
- colorFilter = imageOptions.colorFilter,
135
- alpha = imageOptions.alpha,
136
- onLoading = { imageState = ImageState.Loading },
137
- onSuccess = { imageState = ImageState.Success },
138
- onError = { imageState = ImageState.Error },
139
- )
145
+ var imageState by remember(urlToLoad) { mutableStateOf(ImageState.Loading) }
146
+ fun updateImageState(state: ImageState) {
147
+ imageState = state
148
+ onStateChanged(state)
149
+ }
150
+
151
+ if (isGifUrl(urlToLoad)) {
152
+ GifImage(
153
+ modifier = Modifier.matchParentSize(),
154
+ url = urlToLoad,
155
+ contentDescription = null,
156
+ contentScale = imageOptions.contentScale,
157
+ alignment = imageOptions.alignment,
158
+ colorFilter = imageOptions.colorFilter,
159
+ alpha = imageOptions.alpha,
160
+ onStateChanged = { updateImageState(it.toImageState()) },
161
+ )
162
+ } else {
163
+ CoilAsyncImage(
164
+ modifier = Modifier.matchParentSize(),
165
+ model = urlToLoad,
166
+ contentDescription = null,
167
+ contentScale = imageOptions.contentScale,
168
+ alignment = imageOptions.alignment,
169
+ colorFilter = imageOptions.colorFilter,
170
+ alpha = imageOptions.alpha,
171
+ onLoading = { updateImageState(ImageState.Loading) },
172
+ onSuccess = { updateImageState(ImageState.Success) },
173
+ onError = { updateImageState(ImageState.Error) },
174
+ )
175
+ }
140
176
 
141
177
  when (imageState) {
142
- ImageState.Loading -> if (loading) Skeleton()
143
- ImageState.Error -> {
144
- val theme = AppTheme.current
145
- Icon(
146
- source = "media_fail",
147
- color = theme.colors.text.disable,
148
- modifier = Modifier.align(Alignment.Center)
149
- )
150
- }
151
178
  ImageState.Success -> {}
179
+ ImageState.Error -> ImageError()
180
+ ImageState.Loading -> if (loading) Skeleton()
152
181
  }
153
182
  }
154
183
  }
@@ -156,7 +185,7 @@ fun Image(
156
185
  // Extracted URL processing logic for better performance
157
186
  private fun processImageUrl(url: String, maxWidth: androidx.compose.ui.unit.Dp, density: androidx.compose.ui.unit.Density): String {
158
187
  val host = getHostFromUrl(url)
159
- return if (host != null && supportedDomains.contains(host)) {
188
+ return if (!isGifUrl(url) && host != null && supportedDomains.contains(host)) {
160
189
  val widthPx = with(density) { maxWidth.roundToPx() }
161
190
  val pixelRatio = density.density
162
191
  val pixelFitForWidth = widthPx * pixelRatio
@@ -167,6 +196,20 @@ private fun processImageUrl(url: String, maxWidth: androidx.compose.ui.unit.Dp,
167
196
  }
168
197
  }
169
198
 
199
+ @Composable
200
+ private fun ImageError() {
201
+ val theme = AppTheme.current
202
+ Box(
203
+ modifier = Modifier.fillMaxSize(),
204
+ contentAlignment = Alignment.Center
205
+ ) {
206
+ Icon(
207
+ source = "media_fail",
208
+ color = theme.colors.text.disable,
209
+ )
210
+ }
211
+ }
212
+
170
213
  @Composable
171
214
  fun Image(
172
215
  source: Painter,
@@ -185,4 +228,4 @@ fun Image(
185
228
  colorFilter = colorFilter,
186
229
  alpha = alpha,
187
230
  )
188
- }
231
+ }
@@ -21,9 +21,11 @@ import androidx.compose.ui.unit.sp
21
21
  import androidx.compose.ui.zIndex
22
22
  import vn.momo.kits.application.IsShowBaseLineDebug
23
23
  import vn.momo.kits.const.*
24
+ import vn.momo.kits.modifier.InternalApi
24
25
  import vn.momo.kits.modifier.conditional
25
26
 
26
- internal const val MAX_LENGTH = 300
27
+ @InternalApi
28
+ const val MAX_LENGTH = 300
27
29
  internal val DEFAULT_HEIGHT = 104.dp
28
30
 
29
31
  @Composable
@@ -0,0 +1,21 @@
1
+ package vn.momo.kits.components
2
+
3
+ import androidx.compose.runtime.Composable
4
+ import androidx.compose.runtime.CompositionLocalProvider
5
+ import vn.momo.kits.application.ScaleSizeMaxRate
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
+ )
11
+ @Composable
12
+ fun ScaleSizeScope(
13
+ scaleSizeMaxRate: Float? = null,
14
+ content: @Composable () -> Unit
15
+ ) {
16
+ CompositionLocalProvider(
17
+ ScaleSizeMaxRate provides scaleSizeMaxRate,
18
+ ) {
19
+ content()
20
+ }
21
+ }
@@ -36,7 +36,6 @@ fun Text(
36
36
  softWrap: Boolean = true,
37
37
  accessibilityId: String? = null,
38
38
  inlineContent: Map<String, InlineTextContent> = mapOf(),
39
- userScaleRate: Float? = null,
40
39
  ) {
41
40
  Text(
42
41
  text = AnnotatedString(text),
@@ -53,8 +52,7 @@ fun Text(
53
52
  letterSpacing = letterSpacing,
54
53
  softWrap = softWrap,
55
54
  accessibilityId = accessibilityId,
56
- inlineContent = inlineContent,
57
- userScaleRate = userScaleRate
55
+ inlineContent = inlineContent
58
56
  )
59
57
  }
60
58
 
@@ -76,14 +74,13 @@ fun Text(
76
74
  softWrap: Boolean = true,
77
75
  accessibilityId: String? = null,
78
76
  inlineContent: Map<String, InlineTextContent> = mapOf(),
79
- userScaleRate: Float? = null,
80
77
  ) {
81
78
  // Cache theme access to avoid repeated lookups
82
79
  val theme = AppTheme.current
83
80
 
84
81
  // Call @Composable functions directly in composable context
85
- val scaledFontSize = scaleSize(style.fontSize, userScaleRate)
86
- val scaledLineHeight = scaleSize(style.lineHeight, userScaleRate)
82
+ val scaledFontSize = scaleSize(style.fontSize)
83
+ val scaledLineHeight = scaleSize(style.lineHeight)
87
84
  val fontFamilyResult = getFontFamily(fontFamily ?: theme.font, style.fontWeight)
88
85
 
89
86
  // Now memoize the results
@@ -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
+ }