@momo-kits/native-kits 0.167.1-duo.2-debug → 0.167.1-duo.20

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 (266) hide show
  1. package/CLAUDE.md +36 -8
  2. package/README.md +2 -2
  3. package/ios/Application/ApplicationEnvironment.swift +17 -0
  4. package/ios/Application/MaxApi.swift +12 -3
  5. package/ios/Avatar/Avatar.swift +4 -3
  6. package/ios/Badge/Badge.swift +6 -4
  7. package/ios/Badge/BadgeDot.swift +1 -1
  8. package/ios/Badge/BadgeRibbon.swift +0 -1
  9. package/ios/Button/Button.swift +15 -12
  10. package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +64 -18
  11. package/ios/Carousel/Carousel.swift +29 -12
  12. package/ios/Checkbox/Checkbox.swift +7 -3
  13. package/ios/Chip/Chip.swift +5 -4
  14. package/ios/Collapse/Collapse.swift +70 -19
  15. package/ios/Colors+Radius+Spacing/Colors.swift +10 -1
  16. package/ios/Colors+Radius+Spacing/Radius.swift +6 -0
  17. package/ios/DateTimePicker/DateTimePicker.swift +54 -20
  18. package/ios/DateTimePicker/WheelPicker.swift +103 -105
  19. package/ios/Divider/Divider.swift +37 -4
  20. package/ios/Extensions/Color++.swift +38 -9
  21. package/ios/Extensions/OptionalEnvironmentObject.swift +12 -0
  22. package/ios/Extensions/SkeletonUICompat.swift +11 -0
  23. package/ios/Icon/Icon.swift +21 -23
  24. package/ios/Icon/Icons.swift +1329 -0
  25. package/ios/IconButton/IconButton.swift +15 -7
  26. package/ios/Image/Image.swift +7 -23
  27. package/ios/Information/Information.swift +27 -9
  28. package/ios/Input/ErrorView.swift +2 -2
  29. package/ios/Input/Input.swift +160 -147
  30. package/ios/Input/InputPhoneNumber.swift +12 -9
  31. package/ios/Input/InputSearch.swift +102 -75
  32. package/ios/Input/InputTextArea.swift +128 -145
  33. package/ios/InputDropDown/InputDropDown.swift +10 -7
  34. package/ios/InputMoney/InputMoney.swift +33 -11
  35. package/ios/InputOTP/InputOTP.swift +22 -12
  36. package/ios/Layout/Card.swift +50 -0
  37. package/ios/Layout/GridContext.swift +187 -3
  38. package/ios/Layout/Item.swift +5 -4
  39. package/ios/Layout/ScreenLayout.swift +380 -0
  40. package/ios/Layout/Section.swift +4 -100
  41. package/ios/Loader/Loader.swift +5 -9
  42. package/ios/Lottie/LottieView.swift +14 -2
  43. package/ios/{Application/Navigation/Overplay → Navigation}/BottomSheet.swift +128 -9
  44. package/ios/Navigation/BottomTab/BottomTab.swift +185 -0
  45. package/ios/{Application/Navigation → Navigation}/BottomTab/BottomTabBar.swift +15 -7
  46. package/ios/Navigation/BottomTab/DuoBarCompression.swift +105 -0
  47. package/ios/Navigation/BottomTab/DuoTabBar.swift +304 -0
  48. package/ios/{Application → Navigation/Component}/FloatingButton.swift +14 -3
  49. package/ios/Navigation/Component/Header.swift +531 -0
  50. package/ios/Navigation/Component/HeaderBackground.swift +133 -0
  51. package/ios/Navigation/Component/HeaderJourney.swift +73 -0
  52. package/ios/Navigation/Component/HeaderLocation.swift +48 -0
  53. package/ios/Navigation/Component/HeaderRight.swift +377 -0
  54. package/ios/Navigation/Component/HeaderTitle.swift +36 -0
  55. package/ios/{Application/Navigation → Navigation/Component}/HeaderUser.swift +21 -24
  56. package/ios/Navigation/Component/SideBar.swift +183 -0
  57. package/ios/{Application/Navigation/Overplay → Navigation/Component}/SnackBar.swift +5 -6
  58. package/ios/Navigation/HostBackGestureBridge.swift +78 -0
  59. package/ios/{Application/Navigation/Overplay → Navigation}/ModalScreen.swift +5 -2
  60. package/ios/Navigation/Navigation.swift +204 -0
  61. package/ios/Navigation/NavigationContainer.swift +194 -0
  62. package/ios/{Application/Navigation → Navigation}/Navigator.swift +177 -91
  63. package/ios/Navigation/StackScreen.swift +820 -0
  64. package/ios/Navigation/StackTransition.swift +400 -0
  65. package/ios/Navigation/SwipeBackHaptic.swift +33 -0
  66. package/ios/{Application/Navigation → Navigation}/Tracking/ScreenTracker.swift +12 -5
  67. package/ios/OTPKeyboard/OTPKeyboard.swift +8 -11
  68. package/ios/Pagination/PaginationScroll.swift +2 -2
  69. package/ios/Popup/PopupDisplay.swift +72 -136
  70. package/ios/Popup/PopupInput.swift +10 -13
  71. package/ios/Popup/PopupLayout.swift +140 -0
  72. package/ios/Popup/PopupNotify.swift +56 -73
  73. package/ios/Popup/PopupPromotion.swift +31 -47
  74. package/ios/PopupView/FullscreenPopup.swift +13 -19
  75. package/ios/PopupView/PopupView.swift +1 -1
  76. package/ios/PopupView/Utils++.swift +0 -8
  77. package/ios/ProgressInfo/ProgressInfo.swift +4 -2
  78. package/ios/Radio/Radio.swift +2 -1
  79. package/ios/Rating/Rating.swift +9 -1
  80. package/ios/Resources/dot_loading.json +558 -0
  81. package/ios/Resources/lottie_circle_loader.json +1 -0
  82. package/ios/ScrollIndicator/ScrollIndicator.swift +11 -10
  83. package/ios/Skeleton/Skeleton.swift +22 -27
  84. package/ios/Slider/Slider.swift +16 -18
  85. package/ios/Stepper/Stepper.swift +6 -1
  86. package/ios/Steps/Steps.swift +8 -6
  87. package/ios/SuggestAction/SuggestAction.swift +5 -0
  88. package/ios/Swipeable/SwipeCell.swift +10 -6
  89. package/ios/Switch/Switch.swift +22 -20
  90. package/ios/TabView/TabView.swift +102 -21
  91. package/ios/Tag/Tag.swift +15 -4
  92. package/ios/Template/Logo/Logo.swift +2 -1
  93. package/ios/Template/TrustBanner/TrustBanner.swift +106 -54
  94. package/ios/Title/Title.swift +6 -17
  95. package/ios/Tooltip/Tooltip.swift +29 -14
  96. package/ios/Typography/Text.swift +61 -19
  97. package/ios/Uploader/Uploader.swift +3 -1
  98. package/ios/native-kits.podspec +2 -1
  99. package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
  100. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/ContentView.swift +1 -1
  101. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DuoTabDemo.swift +80 -0
  102. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +1 -0
  103. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IPhoneDuoDemo.swift +173 -0
  104. package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/NavigationDemo.swift +77 -1
  105. package/package.json +1 -1
  106. package/scripts/gen-ios-icons.mjs +36 -0
  107. package/build.gradle.kts +0 -11
  108. package/compose/build.gradle.kts +0 -190
  109. package/compose/build.gradle.kts.backup +0 -190
  110. package/compose/compose.podspec +0 -47
  111. package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +0 -19
  112. package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
  113. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +0 -12
  114. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +0 -7
  115. package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -151
  116. package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
  117. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -124
  118. package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
  119. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
  120. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
  121. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
  122. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
  123. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
  124. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
  125. package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
  126. package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -831
  127. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +0 -269
  128. package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
  129. package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
  130. package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +0 -56
  131. package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
  132. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
  133. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -82
  134. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
  135. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -338
  136. package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -175
  137. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -356
  138. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -113
  139. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -89
  140. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -128
  141. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -209
  142. package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -542
  143. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -49
  144. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
  145. package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -125
  146. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -231
  147. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -189
  148. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -475
  149. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -114
  150. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -266
  151. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -240
  152. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -223
  153. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -264
  154. package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -185
  155. package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -343
  156. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
  157. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
  158. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
  159. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -84
  160. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
  161. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -334
  162. package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -98
  163. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -310
  164. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -59
  165. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
  166. package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -21
  167. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -90
  168. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -323
  169. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -220
  170. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -473
  171. package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -122
  172. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -199
  173. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -91
  174. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -552
  175. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -88
  176. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -125
  177. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -207
  178. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -498
  179. package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -176
  180. package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -182
  181. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -193
  182. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
  183. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -234
  184. package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -188
  185. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -325
  186. package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +0 -16
  187. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +0 -18
  188. package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
  189. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
  190. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
  191. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -188
  192. package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -297
  193. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -54
  194. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -50
  195. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/ScreenLayout.kt +0 -157
  196. package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -41
  197. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -52
  198. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -66
  199. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
  200. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -104
  201. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -48
  202. package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
  203. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -299
  204. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +0 -58
  205. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -129
  206. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -106
  207. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -205
  208. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -393
  209. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
  210. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -622
  211. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +0 -148
  212. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +0 -35
  213. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -175
  214. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -232
  215. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
  216. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -169
  217. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -381
  218. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -83
  219. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +0 -105
  220. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +0 -74
  221. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -347
  222. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -37
  223. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -363
  224. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SideBar.kt +0 -169
  225. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -132
  226. package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -127
  227. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +0 -12
  228. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -91
  229. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +0 -9
  230. package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -71
  231. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
  232. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -55
  233. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
  234. package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -118
  235. package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +0 -40
  236. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +0 -45
  237. package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -32
  238. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +0 -38
  239. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +0 -66
  240. package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -213
  241. package/gradle/libs.versions.toml +0 -69
  242. package/gradle/wrapper/gradle-wrapper.jar +0 -0
  243. package/gradle/wrapper/gradle-wrapper.properties +0 -8
  244. package/gradle.properties +0 -26
  245. package/gradlew +0 -252
  246. package/gradlew.bat +0 -94
  247. package/ios/Application/Components.swift +0 -270
  248. package/ios/Application/ComposeApi.swift +0 -22
  249. package/ios/Application/HeaderRight.swift +0 -306
  250. package/ios/Application/Navigation/BottomTab/BottomTab.swift +0 -104
  251. package/ios/Application/Navigation/HeaderBackProps.swift +0 -66
  252. package/ios/Application/Navigation/HeaderTitle.swift +0 -57
  253. package/ios/Application/Navigation/NavigationContainer.swift +0 -213
  254. package/ios/Application/Navigation/NavigationOptions.swift +0 -109
  255. package/ios/Application/Navigation/NavigatorManager.swift +0 -22
  256. package/ios/Application/Navigation/component/Header.swift +0 -178
  257. package/ios/Application/Navigation/component/HeaderBackground.swift +0 -83
  258. package/ios/Application/Navigation/component/HeaderColor.swift +0 -65
  259. package/ios/Application/Navigation/component/HeaderRightWidthKey.swift +0 -11
  260. package/ios/Application/Navigation/component/NavigationFooter.swift +0 -90
  261. package/ios/Application/Navigation/component/NavigationHeaderRight.swift +0 -196
  262. package/ios/Application/Screen.swift +0 -250
  263. package/ios/Application/StackScreen.swift +0 -492
  264. package/ios-demo/README.md +0 -120
  265. package/settings.gradle.kts +0 -64
  266. /package/ios/{Application/Navigation → Navigation}/BottomTab/CurvedContainer.swift +0 -0
@@ -1,4 +1,3 @@
1
- import SDWebImageSwiftUI
2
1
  import SwiftUI
3
2
 
4
3
  // MARK: - PopupButtonDirection
@@ -16,45 +15,13 @@ public enum PopupButtonType {
16
15
  case button
17
16
  }
18
17
 
19
- extension View {
20
- func measureLineHeights(font: Font,
21
- oneLine: Binding<CGFloat>,
22
- twoLines: Binding<CGFloat>) -> some View {
23
- overlay(
24
- VStack(spacing: 0) {
25
- Text("A")
26
- .font(font)
27
- .ignoreBoldTextSetting()
28
- .lineLimit(1)
29
- .fixedSize()
30
- .background(
31
- GeometryReader { g in
32
- Color.clear.onAppear { oneLine.wrappedValue = g.size.height }
33
- }
34
- )
35
- .hidden()
36
-
37
- Text("A\nA")
38
- .font(font)
39
- .ignoreBoldTextSetting()
40
- .lineLimit(2)
41
- .fixedSize(horizontal: false, vertical: true)
42
- .background(
43
- GeometryReader { g in
44
- Color.clear.onAppear { twoLines.wrappedValue = g.size.height }
45
- }
46
- )
47
- .hidden()
48
- }
49
- .frame(width: 0, height: 0)
50
- )
51
- }
52
- }
53
-
54
18
  // MARK: - PopupDisplay
55
19
 
56
20
  public struct PopupDisplay: View {
21
+ @Environment(\.appTheme) private var theme
57
22
  @Environment(\.localize) private var localize
23
+ @Environment(\.momoFontScale) private var fontScale
24
+ @Environment(\.screenLayout) private var layout
58
25
 
59
26
  // MARK: Lifecycle
60
27
 
@@ -75,109 +42,53 @@ public struct PopupDisplay: View {
75
42
  }
76
43
 
77
44
  // MARK: Public
78
-
45
+
79
46
  @State private var oneLineH: CGFloat = 0
80
47
  @State private var twoLineH: CGFloat = 0
48
+ @State private var textHeight: CGFloat = .zero
49
+ @State private var actionsHeight: CGFloat = 0
81
50
 
82
- private var fallbackLH: CGFloat { UIFont.preferredFont(forTextStyle: .body).lineHeight }
83
- private var perLine: CGFloat { max(twoLineH - oneLineH, oneLineH > 0 ? oneLineH : fallbackLH) }
84
-
85
- private func heightForLines(lines: CGFloat) -> CGFloat {
86
- guard oneLineH > 0 && twoLineH > 0 else { return ceil(fallbackLH * lines) }
87
- return ceil(oneLineH + max(0, lines - 1) * (twoLineH - oneLineH))
51
+ // ~8.5 lines as laid out; nominal line height until measured
52
+ private var maxHeight8_5: CGFloat {
53
+ popupLinesHeight(8.5, oneLine: oneLineH, twoLines: twoLineH)
54
+ ?? fontScale(TypographyStyle.bodyDefaultRegular.lineHeight) * 8.5
88
55
  }
89
- private var maxHeight8_5: CGFloat { heightForLines(lines: 8.5) }
90
56
 
57
+ private var shouldUseColumn: Bool {
58
+ // UTF-16 length, as PopupNotify counts it
59
+ buttonDirection == .column || (buttonDirection == .auto && (closeButtonTitle.utf16.count > 12 || actionButtonTitle.utf16.count > 12))
60
+ }
91
61
 
92
- @State private var textHeight: CGFloat = .zero
93
- @State private var isScrollable = false
94
-
95
62
  public var body: some View {
96
- var shouldUseColumn: Bool {
97
- buttonDirection == .column || (buttonDirection == .auto && (closeButtonTitle.count > 12 || actionButtonTitle.count > 12))
98
- }
99
-
100
- VStack(spacing: 12) {
101
- ZStack(alignment: .topTrailing) {
102
- if(isShowCloseIcon) {
103
- SwiftUI.Button(action: onClose) {
104
- Image(systemName: "xmark.circle.fill")
105
- .resizable()
106
- .frame(width: 22, height: 22)
107
- .overlay(RoundedRectangle(cornerRadius: Radius.L).stroke(Colors.black01, lineWidth: 2))
108
- }.foregroundColor(Colors.black20)
109
- .background(Colors.black01.cornerRadius(15))
110
- .padding(.trailing, -11)
111
- .padding(.top, -11)
112
- .zIndex(1)
113
- .accessibility(identifier: "ic_popup_close")
114
- }
115
-
116
- VStack(spacing: 0) {
117
- if(!url.isEmpty) {
118
- WebImage(url: URL(string: url), isAnimating: .constant(true))
119
- .resizable()
120
- .placeholder {
121
- Rectangle()
122
- .fill(Color.gray.opacity(0.3))
123
- .aspectRatio(1.777, contentMode: .fit)
124
- .frame(maxWidth: .infinity, maxHeight: 184)
125
- }
126
- .aspectRatio(1.777, contentMode: .fit)
127
- .frame(maxWidth: .infinity, alignment: .center)
128
- .clipShape(RoundedCorner(radius: 15, corners: [.topLeft, .topRight]))
129
- .clipped()
130
- }
131
- VStack(alignment: .leading, spacing: 0) {
132
- MomoText(title, typography: .headerDefaultBold)
133
- .padding(.top, 24)
134
- .padding(.bottom, 8)
135
- .lineLimit(2)
136
- .accessibility(identifier: "title_popup_permission")
137
-
138
- Group {
139
- if isScrollable {
140
- ScrollView(showsIndicators: false) {
141
- MomoText(description, typography: .bodyDefaultRegular)
142
- .multilineTextAlignment(.leading)
143
- .background(GeometryReader { geo in
144
- Color.clear.onAppear { textHeight = geo.size.height }
145
- })
146
- .measureLineHeights(font: .body_default_regular,
147
- oneLine: $oneLineH,
148
- twoLines: $twoLineH)
149
- .accessibility(identifier: "description_popup_permission")
150
- }
151
- // Cap the visible height to ~8.5 lines
152
- .frame(height: min(maxHeight8_5, textHeight))
153
- } else {
154
- MomoText(description, typography: .bodyDefaultRegular)
155
- .multilineTextAlignment(.leading)
156
- .background(GeometryReader { geo in
157
- Color.clear.onAppear {
158
- textHeight = geo.size.height
159
- // Trigger scroll at ~8.5 lines
160
- isScrollable = textHeight > maxHeight8_5
161
- }
162
- })
163
- .measureLineHeights(font: .body_default_regular,
164
- oneLine: $oneLineH,
165
- twoLines: $twoLineH)
166
- .accessibility(identifier: "description_popup_permission")
167
- }
63
+ ZStack(alignment: .topTrailing) {
64
+ VStack(spacing: 0) {
65
+ // scrolls when iPhone Duo landscape is too short; actions stay visible
66
+ PopupScrollBody(maxHeight: layout.popupMaxHeight.map { $0 - actionsHeight }) {
67
+ VStack(spacing: 0) {
68
+ if !url.isEmpty {
69
+ PopupHeaderImage(url: url)
168
70
  }
169
- .padding(.bottom, 8)
170
-
171
- if(!errorCode.isEmpty) {
172
- MomoText(localize.translate("errorCode") + errorCode, typography: .descriptionXsRegular, color: Colors.black12)
173
- .lineLimit(1)
71
+ VStack(alignment: .leading, spacing: 0) {
72
+ MomoText(title, typography: .headerDefaultBold, maxLines: 2, accessibilityId: "title_popup_permission")
73
+ .padding(.top, 24)
174
74
  .padding(.bottom, 8)
75
+
76
+ descriptionContent
77
+ .padding(.bottom, 8)
78
+
79
+ if !errorCode.isEmpty {
80
+ MomoText(localize.translate("errorCode") + errorCode, typography: .descriptionXsRegular, color: theme.colors.text.hint, maxLines: 1)
81
+ .padding(.bottom, 8)
82
+ }
175
83
  }
84
+ .frame(maxWidth: .infinity, alignment: .leading)
85
+ .padding(.horizontal, 24)
86
+ .padding(.bottom, 16)
87
+ .measureLineHeights(typography: .bodyDefaultRegular, oneLine: $oneLineH, twoLines: $twoLineH)
176
88
  }
177
- .frame(maxWidth: .infinity, alignment: .leading)
178
- .padding(.horizontal, 24)
179
- .padding(.bottom, 16)
180
-
89
+ }
90
+
91
+ Group {
181
92
  if shouldUseColumn {
182
93
  if buttonType == .text {
183
94
  ColumnTextButtons
@@ -192,14 +103,39 @@ public struct PopupDisplay: View {
192
103
  }
193
104
  }
194
105
  }
195
- .fixedSize(horizontal: false, vertical: true)
106
+ .popupReadHeight($actionsHeight)
107
+ }
108
+ .fixedSize(horizontal: false, vertical: true)
109
+ .background(theme.colors.background.surface)
110
+ .clipShape(RoundedRectangle(cornerRadius: Radius.L))
111
+
112
+ if isShowCloseIcon {
113
+ PopupCloseButton(action: onClose)
114
+ .offset(x: 11, y: -11)
115
+ }
116
+ }
117
+ .frame(maxWidth: layout.popupMaxWidth)
118
+ .padding(.horizontal, 12)
119
+ .accessibilityElement(children: .contain)
120
+ .accessibilityIdentifier("popup_notify")
121
+ }
122
+
123
+ @ViewBuilder
124
+ private var descriptionContent: some View {
125
+ if textHeight > maxHeight8_5 {
126
+ ScrollView(showsIndicators: false) {
127
+ descriptionText
196
128
  }
129
+ .frame(height: maxHeight8_5)
130
+ } else {
131
+ descriptionText
197
132
  }
198
- .background(Color.white.cornerRadius(15))
199
- .frame(maxWidth: popupMaxWidth - 24)
200
- .padding(.horizontal, 12)
201
- .accessibilityElement(children: .ignore)
202
- .accessibility(identifier: "popup_notify")
133
+ }
134
+
135
+ private var descriptionText: some View {
136
+ MomoText(description, typography: .bodyDefaultRegular, accessibilityId: "description_popup_permission")
137
+ .frame(maxWidth: .infinity, alignment: .leading)
138
+ .popupReadHeight($textHeight)
203
139
  }
204
140
 
205
141
  // MARK: Internal
@@ -249,7 +185,7 @@ public struct PopupDisplay: View {
249
185
  }
250
186
 
251
187
  var RowButtons: some View {
252
- HStack {
188
+ HStack(spacing: Spacing.S) {
253
189
  if(!closeButtonTitle.isEmpty) {
254
190
  Button(title: closeButtonTitle, action: onPressCloseButton, type: .text, size: .medium).accessibility(identifier: "btn_popup_cancel")
255
191
  }
@@ -262,7 +198,7 @@ public struct PopupDisplay: View {
262
198
  }
263
199
 
264
200
  var ColumnButtons: some View {
265
- VStack(alignment: .trailing) {
201
+ VStack(alignment: .trailing, spacing: Spacing.S) {
266
202
  Button(
267
203
  title: actionButtonTitle,
268
204
  action: onPressAction,
@@ -1,7 +1,9 @@
1
- import SDWebImageSwiftUI
2
1
  import SwiftUI
3
2
 
4
3
  public struct PopupInput: View {
4
+ @Environment(\.appTheme) private var theme
5
+ @Environment(\.screenLayout) private var layout
6
+
5
7
  // MARK: Lifecycle
6
8
 
7
9
  public init(isPresented: Binding<Bool>, title: String = "", description: String = "", numberOfButtons: Int = 1, actionButtonTitle: String = "", closeButtonTitle: String = "", onPressAction: @escaping () -> Void = {}, onPressCloseButton: @escaping () -> Void = {}, onClose: @escaping () -> Void = {}, inputPlaceholder: String = "", inputValue: Binding<String> = Binding.constant(""), onTextChange: ((String) -> Void)? = nil) {
@@ -24,22 +26,13 @@ public struct PopupInput: View {
24
26
  public var body: some View {
25
27
  VStack(spacing: 12) {
26
28
  ZStack(alignment: .topTrailing) {
27
- SwiftUI.Button(action: onPressClose) {
28
- Image(systemName: "xmark.circle.fill")
29
- .resizable()
30
- .frame(width: 16, height: 16)
31
- }.foregroundColor(Colors.black20)
32
- .background(Colors.black01.cornerRadius(8))
33
- .offset(x: 6, y: -6)
34
- .zIndex(1)
35
-
36
29
  VStack {
37
30
  VStack(alignment: .leading) {
38
- MomoText(title, typography: .headerDefaultBold, color: .black)
31
+ MomoText(title, typography: .headerDefaultBold)
39
32
  .padding(.top, 12)
40
33
  .padding(.bottom, 24)
41
34
 
42
- MomoText(description, typography: .bodyDefaultRegular, color: .black)
35
+ MomoText(description, typography: .bodyDefaultRegular)
43
36
  .opacity(0.6)
44
37
  .multilineTextAlignment(.leading)
45
38
  .padding(.bottom, 20)
@@ -61,11 +54,15 @@ public struct PopupInput: View {
61
54
  }
62
55
 
63
56
  }.clipped()
57
+
58
+ PopupCloseButton(action: onPressClose)
59
+ .offset(x: 11, y: -11)
64
60
  }
65
61
  }
66
- .background(Color.white.cornerRadius(8))
62
+ .background(theme.colors.background.surface.cornerRadius(8))
67
63
  .shadow(color: .black.opacity(0.08), radius: 2, x: 0, y: 0)
68
64
  .shadow(color: .black.opacity(0.16), radius: 24, x: 0, y: 0)
65
+ .frame(maxWidth: layout.popupMaxWidth)
69
66
  .padding(.horizontal, 40)
70
67
  }
71
68
 
@@ -0,0 +1,140 @@
1
+ import SDWebImageSwiftUI
2
+ import SwiftUI
3
+
4
+ // Width of a system alert on the iPhone Duo inner display, in both orientations (RN Popup/utils.ts).
5
+ private let duoPopupMaxWidth: CGFloat = 440
6
+
7
+ extension ScreenLayout {
8
+ var isDuoDevice: Bool { isIPhoneDuoDevice(windowSize: CGSize(width: width, height: height)) }
9
+
10
+ /// Card width cap (Compose `popupMaxWidth`); unbounded off iPhone Duo, where the popup's own padding sets the width.
11
+ var popupMaxWidth: CGFloat {
12
+ isDuoDevice ? duoPopupMaxWidth : .infinity
13
+ }
14
+
15
+ /// Room left for a popup on iPhone Duo, where landscape is too short for it; nil elsewhere.
16
+ var popupMaxHeight: CGFloat? {
17
+ guard isDuoDevice else { return nil }
18
+ return height - duoTopInset - insets.bottom - Spacing.XL * 2
19
+ }
20
+ }
21
+
22
+ /// Scrolls `content` once it is taller than `maxHeight`; otherwise sizes to it.
23
+ struct PopupScrollBody<Content: View>: View {
24
+ let maxHeight: CGFloat?
25
+ @ViewBuilder let content: () -> Content
26
+
27
+ @State private var contentHeight: CGFloat = 0
28
+
29
+ var body: some View {
30
+ if let maxHeight {
31
+ ScrollView(.vertical, showsIndicators: false) {
32
+ content()
33
+ .background(
34
+ GeometryReader { proxy in
35
+ Color.clear
36
+ .onAppear { contentHeight = proxy.size.height }
37
+ .onChange(of: proxy.size.height) { contentHeight = $0 }
38
+ }
39
+ )
40
+ }
41
+ .frame(height: min(contentHeight, max(maxHeight, 0)))
42
+ } else {
43
+ content()
44
+ }
45
+ }
46
+ }
47
+
48
+ /// Height of `lines` (may be fractional) lines measured by `measureLineHeights`; nil until measured.
49
+ func popupLinesHeight(_ lines: CGFloat, oneLine: CGFloat, twoLines: CGFloat) -> CGFloat? {
50
+ guard oneLine > 0, twoLines > oneLine else { return nil }
51
+ return oneLine + (lines - 1) * (twoLines - oneLine)
52
+ }
53
+
54
+ extension View {
55
+ /// Measures one and two lines of `typography` as MomoText lays them out, its line spacing included.
56
+ func measureLineHeights(typography: TypographyStyle,
57
+ oneLine: Binding<CGFloat>,
58
+ twoLines: Binding<CGFloat>) -> some View {
59
+ overlay(
60
+ VStack(spacing: 0) {
61
+ MomoText("A", typography: typography)
62
+ .fixedSize()
63
+ .popupReadHeight(oneLine)
64
+ MomoText("A\nA", typography: typography)
65
+ .fixedSize()
66
+ .popupReadHeight(twoLines)
67
+ }
68
+ .frame(width: 0, height: 0)
69
+ .hidden()
70
+ .accessibilityHidden(true)
71
+ )
72
+ }
73
+
74
+ func popupReadHeight(_ height: Binding<CGFloat>) -> some View {
75
+ background(
76
+ GeometryReader { proxy in
77
+ Color.clear
78
+ .onAppear { height.wrappedValue = proxy.size.height }
79
+ .onChange(of: proxy.size.height) { height.wrappedValue = $0 }
80
+ }
81
+ )
82
+ }
83
+ }
84
+
85
+ /// 22pt round close button shared by the popups (Compose `PopupNotify` / `PopupPromotion`).
86
+ struct PopupCloseButton: View {
87
+ @Environment(\.appTheme) private var theme
88
+ var tapSize: CGFloat = 22
89
+ let action: () -> Void
90
+
91
+ var body: some View {
92
+ SwiftUI.Button(action: action) {
93
+ Circle()
94
+ .fill(theme.colors.text.default)
95
+ .overlay(Circle().strokeBorder(theme.colors.background.surface, lineWidth: 2))
96
+ .overlay(Icon(source: "navigation_close", size: 16, color: theme.colors.background.surface))
97
+ .frame(width: 22, height: 22)
98
+ .frame(width: tapSize, height: tapSize)
99
+ .contentShape(Rectangle())
100
+ }
101
+ .accessibilityIdentifier("ic_popup_close")
102
+ }
103
+ }
104
+
105
+ /// Compose `Image` states: skeleton while loading, `media_fail` once loading fails.
106
+ struct PopupImagePlaceholder: View {
107
+ @Environment(\.appTheme) private var theme
108
+ let failed: Bool
109
+
110
+ var body: some View {
111
+ if failed {
112
+ Icon(source: "media_fail", color: theme.colors.text.disable)
113
+ .frame(maxWidth: .infinity, maxHeight: .infinity)
114
+ } else {
115
+ Skeleton()
116
+ }
117
+ }
118
+ }
119
+
120
+ /// 16:9 header image, cropped like Compose `Image` (ContentScale.Crop).
121
+ struct PopupHeaderImage: View {
122
+ let url: String
123
+
124
+ @State private var failed = false
125
+
126
+ var body: some View {
127
+ Color.clear
128
+ .aspectRatio(1.777, contentMode: .fit)
129
+ .frame(maxWidth: .infinity)
130
+ .overlay(
131
+ WebImage(url: URL(string: url), isAnimating: .constant(true))
132
+ .onSuccess { _, _, _ in failed = false }
133
+ .onFailure { _ in failed = true }
134
+ .resizable()
135
+ .placeholder { PopupImagePlaceholder(failed: failed || URL(string: url) == nil) }
136
+ .scaledToFill()
137
+ )
138
+ .clipped()
139
+ }
140
+ }
@@ -1,12 +1,15 @@
1
- import SDWebImageSwiftUI
2
1
  import SwiftUI
3
2
 
4
3
  public typealias PopupActionDirection = PopupButtonDirection
5
4
 
6
- // Portrait width in landscape too, so aspect-ratio images don't push popups past the screen height.
7
- var popupMaxWidth: CGFloat {
8
- let size = UIScreen.main.bounds.size
9
- return min(size.width, size.height)
5
+ public struct PopupAction {
6
+ public let title: String
7
+ public let onPress: (() -> Void)?
8
+
9
+ public init(title: String, onPress: (() -> Void)? = nil) {
10
+ self.title = title
11
+ self.onPress = onPress
12
+ }
10
13
  }
11
14
 
12
15
  public struct PopupNotifyProps {
@@ -44,19 +47,26 @@ public struct PopupNotifyProps {
44
47
  }
45
48
 
46
49
  public struct PopupNotify: View {
50
+ @Environment(\.appTheme) private var theme
47
51
  @Environment(\.localize) private var localize
48
52
  @Environment(\.momoFontScale) private var fontScale
53
+ @Environment(\.screenLayout) private var layout
49
54
 
50
55
  public let props: PopupNotifyProps
51
56
 
52
57
  @State private var descriptionHeight: CGFloat = 0
58
+ @State private var actionsHeight: CGFloat = 0
59
+ @State private var oneLineHeight: CGFloat = 0
60
+ @State private var twoLinesHeight: CGFloat = 0
53
61
 
54
62
  private var errorCodePrefix: String {
55
63
  localize.translate("errorCode")
56
64
  }
57
65
 
66
+ // ~8.5 lines as laid out (Compose measures the real lines); nominal line height until measured
58
67
  private var maxDescriptionHeight: CGFloat {
59
- fontScale(TypographyStyle.bodyDefaultRegular.lineHeight) * 8.5
68
+ popupLinesHeight(8.5, oneLine: oneLineHeight, twoLines: twoLinesHeight)
69
+ ?? fontScale(TypographyStyle.bodyDefaultRegular.lineHeight) * 8.5
60
70
  }
61
71
 
62
72
  private var shouldUseColumnButtons: Bool {
@@ -66,7 +76,9 @@ public struct PopupNotify: View {
66
76
  case .row:
67
77
  return false
68
78
  case .auto:
69
- return (props.secondary?.title.count ?? 0) > 12 || (props.primary?.title.count ?? 0) > 12
79
+ // UTF-16 length, as Kotlin and JS count it
80
+ guard let secondary = props.secondary else { return false }
81
+ return secondary.title.utf16.count > 12 || (props.primary?.title.utf16.count ?? 0) > 12
70
82
  }
71
83
  }
72
84
 
@@ -77,64 +89,60 @@ public struct PopupNotify: View {
77
89
  public var body: some View {
78
90
  ZStack(alignment: .topTrailing) {
79
91
  VStack(spacing: 0) {
80
- if !props.image.isEmpty {
81
- popupImage
82
- }
83
-
84
- VStack(alignment: .leading, spacing: 0) {
85
- MomoText(
86
- props.title,
87
- typography: .headerDefaultBold,
88
- maxLines: 2,
89
- accessibilityId: "title_popup_permission"
90
- )
91
- .padding(.bottom, Spacing.S)
92
-
93
- descriptionContent
94
-
95
- if !props.error.isEmpty {
96
- MomoText(
97
- errorCodePrefix + props.error,
98
- typography: .descriptionXsRegular,
99
- color: Colors.black12,
100
- maxLines: 1
101
- )
102
- .padding(.top, Spacing.S)
92
+ // scrolls when iPhone Duo landscape is too short; actions stay visible
93
+ PopupScrollBody(maxHeight: layout.popupMaxHeight.map { $0 - actionsHeight }) {
94
+ VStack(spacing: 0) {
95
+ if !props.image.isEmpty {
96
+ PopupHeaderImage(url: props.image)
97
+ }
98
+ textContent
103
99
  }
104
100
  }
105
- .frame(maxWidth: .infinity, alignment: .leading)
106
- .padding(Spacing.XL)
107
101
 
108
102
  actionButtons
109
103
  .padding(.horizontal, Spacing.XL)
110
104
  .padding(.bottom, Spacing.XL)
105
+ .popupReadHeight($actionsHeight)
111
106
  }
112
- .background(Colors.black01)
107
+ .background(theme.colors.background.surface)
113
108
  .clipShape(RoundedRectangle(cornerRadius: Radius.L))
114
109
 
115
110
  if props.isShowCloseIcon {
116
- closeButton
111
+ PopupCloseButton(action: props.onIconClose)
117
112
  .offset(x: 11, y: -11)
118
113
  }
119
114
  }
120
- .frame(maxWidth: popupMaxWidth - Spacing.M * 2)
115
+ .frame(maxWidth: layout.popupMaxWidth)
121
116
  .padding(.horizontal, Spacing.M)
122
- .accessibilityElement(children: .ignore)
117
+ .accessibilityElement(children: .contain)
123
118
  .accessibilityIdentifier("popup_notify")
124
119
  }
125
120
 
126
- private var popupImage: some View {
127
- WebImage(url: URL(string: props.image), isAnimating: .constant(true))
128
- .resizable()
129
- .placeholder {
130
- Rectangle()
131
- .fill(Colors.black03)
132
- .aspectRatio(1.777, contentMode: .fit)
133
- .frame(maxWidth: .infinity)
121
+ private var textContent: some View {
122
+ VStack(alignment: .leading, spacing: 0) {
123
+ MomoText(
124
+ props.title,
125
+ typography: .headerDefaultBold,
126
+ maxLines: 2,
127
+ accessibilityId: "title_popup_permission"
128
+ )
129
+ .padding(.bottom, Spacing.S)
130
+
131
+ descriptionContent
132
+
133
+ if !props.error.isEmpty {
134
+ MomoText(
135
+ errorCodePrefix + props.error,
136
+ typography: .descriptionXsRegular,
137
+ color: theme.colors.text.hint,
138
+ maxLines: 1
139
+ )
140
+ .padding(.top, Spacing.S)
134
141
  }
135
- .aspectRatio(1.777, contentMode: .fit)
136
- .frame(maxWidth: .infinity)
137
- .clipShape(RoundedCorner(radius: Radius.L, corners: [.topLeft, .topRight]))
142
+ }
143
+ .frame(maxWidth: .infinity, alignment: .leading)
144
+ .padding(Spacing.XL)
145
+ .measureLineHeights(typography: .bodyDefaultRegular, oneLine: $oneLineHeight, twoLines: $twoLinesHeight)
138
146
  }
139
147
 
140
148
  @ViewBuilder
@@ -156,15 +164,7 @@ public struct PopupNotify: View {
156
164
  accessibilityId: "description_popup_permission"
157
165
  )
158
166
  .frame(maxWidth: .infinity, alignment: .leading)
159
- .background(
160
- GeometryReader { proxy in
161
- Color.clear
162
- .onAppear { descriptionHeight = proxy.size.height }
163
- .onChange(of: props.description) { _ in
164
- descriptionHeight = proxy.size.height
165
- }
166
- }
167
- )
167
+ .popupReadHeight($descriptionHeight)
168
168
  }
169
169
 
170
170
  @ViewBuilder
@@ -206,21 +206,4 @@ public struct PopupNotify: View {
206
206
  )
207
207
  .accessibilityIdentifier("btn_popup_cancel")
208
208
  }
209
-
210
- private var closeButton: some View {
211
- SwiftUI.Button(action: props.onIconClose) {
212
- ZStack {
213
- Circle()
214
- .fill(Colors.black17)
215
- .overlay(
216
- Circle()
217
- .stroke(Colors.black01, lineWidth: 2)
218
- )
219
- .frame(width: 22, height: 22)
220
-
221
- Icon(source: "navigation_close", size: 16, color: Colors.black01)
222
- }
223
- }
224
- .accessibilityIdentifier("ic_popup_close")
225
- }
226
209
  }