@momo-kits/native-kits 0.167.1-beta.9-debug → 0.167.1-duo-search.1
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 +36 -0
- package/ios/Application/ApplicationEnvironment.swift +6 -0
- package/ios/Application/Components.swift +1 -3
- package/ios/Application/HeaderRight.swift +32 -14
- package/ios/Application/Layout/ScreenLayout.swift +312 -0
- package/ios/Application/Navigation/BottomTab/BottomTab.swift +67 -10
- package/ios/Application/Navigation/BottomTab/BottomTabBar.swift +5 -2
- package/ios/Application/Navigation/BottomTab/DuoBarCompression.swift +105 -0
- package/ios/Application/Navigation/BottomTab/DuoTabBar.swift +304 -0
- package/ios/Application/Navigation/HeaderUser.swift +4 -4
- package/ios/Application/Navigation/NavigationContainer.swift +48 -42
- package/ios/Application/Navigation/Navigator.swift +122 -29
- package/ios/Application/Navigation/NavigatorManager.swift +13 -6
- package/ios/Application/Navigation/Overplay/BottomSheet.swift +41 -4
- package/ios/Application/Navigation/Overplay/ModalScreen.swift +7 -0
- package/ios/Application/Navigation/component/DuoScrollGradient.swift +54 -0
- package/ios/Application/Navigation/component/Header.swift +11 -6
- package/ios/Application/Navigation/component/HeaderBackground.swift +3 -2
- package/ios/Application/Navigation/component/NavigationFooter.swift +1 -1
- package/ios/Application/Navigation/component/NavigationHeaderRight.swift +93 -9
- package/ios/Application/Navigation/component/SideBar.swift +155 -0
- package/ios/Application/StackScreen.swift +175 -18
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +59 -5
- package/ios/Colors+Radius+Spacing/Colors.swift +1 -1
- package/ios/Extensions/Color++.swift +20 -9
- package/ios/Extensions/OptionalEnvironmentObject.swift +12 -0
- package/ios/Icon/Icon.swift +14 -22
- package/ios/Icon/Icons.swift +1329 -0
- package/ios/Image/Image.swift +16 -5
- package/ios/Lottie/LottieView.swift +4 -2
- package/ios/Popup/PopupDisplay.swift +84 -67
- package/ios/Popup/PopupLayout.swift +45 -0
- package/ios/Popup/PopupNotify.swift +44 -26
- package/ios/Popup/PopupPromotion.swift +18 -6
- package/ios/Resources/dot_loading.json +558 -0
- package/ios/Resources/lottie_circle_loader.json +1 -0
- package/ios/Template/TrustBanner/TrustBanner.swift +69 -31
- package/ios/Typography/FontScale.swift +3 -3
- package/ios/native-kits.podspec +1 -1
- package/ios-demo/MoMoUIKitsDemo.podspec +1 -1
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/DuoTabDemo.swift +80 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/Home.swift +2 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/IPhoneDuoDemo.swift +173 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupDisplayDemo.swift +1 -0
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupNotifyDemo.swift +2 -2
- package/ios-demo/Sources/MoMoUIKitsDemo/SampleDemos/PopupPromotionDemo.swift +2 -0
- package/package.json +1 -1
- package/scripts/gen-ios-icons.mjs +36 -0
- package/build.gradle.kts +0 -11
- package/compose/build.gradle.kts +0 -190
- package/compose/build.gradle.kts.backup +0 -190
- package/compose/compose.podspec +0 -47
- package/compose/src/androidMain/kotlin/vn/momo/kits/const/HostFont.android.kt +0 -19
- package/compose/src/androidMain/kotlin/vn/momo/kits/navigation/ScrollToTop.android.kt +0 -6
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/BackGesture.android.kt +0 -12
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/OsFontScale.android.kt +0 -7
- package/compose/src/androidMain/kotlin/vn/momo/kits/platform/Platform.android.kt +0 -151
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/AnimationSearchInput.kt +0 -52
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Context.kt +0 -124
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/FloatingButton.kt +0 -183
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Header.kt +0 -207
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderAnimated.kt +0 -39
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderBackground.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderDefault.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderExtended.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderRight.kt +0 -293
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/HeaderTitle.kt +0 -33
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/LiteScreen.kt +0 -831
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Localize.kt +0 -269
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +0 -110
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +0 -378
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/WidgetContainer.kt +0 -56
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/useHeaderSearchAnimation.kt +0 -69
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Avatar.kt +0 -157
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +0 -82
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +0 -32
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeRibbon.kt +0 -338
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BaselineView.kt +0 -175
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +0 -356
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Carousel.kt +0 -113
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +0 -89
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Chip.kt +0 -128
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Collapse.kt +0 -209
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CupertinoOverscroll.kt +0 -542
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +0 -49
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +0 -76
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +0 -125
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +0 -231
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Information.kt +0 -189
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +0 -475
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputDropDown.kt +0 -114
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +0 -266
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputOTP.kt +0 -240
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputPhoneNumber.kt +0 -223
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +0 -264
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +0 -185
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/LazyColumnWithBouncing.kt +0 -343
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Loader.kt +0 -108
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationDot.kt +0 -56
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationNumber.kt +0 -41
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationScroll.kt +0 -84
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PaginationWhiteDot.kt +0 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +0 -328
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupPromotion.kt +0 -97
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ProgressInfo.kt +0 -310
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +0 -59
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Rating.kt +0 -87
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/ScaleSizeScope.kt +0 -21
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +0 -90
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Slider.kt +0 -323
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Stepper.kt +0 -220
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Steps.kt +0 -473
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/SuggestAction.kt +0 -122
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Swipe.kt +0 -199
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +0 -91
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TabView.kt +0 -552
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +0 -88
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +0 -125
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Title.kt +0 -207
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tooltip.kt +0 -498
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/TrustBanner.kt +0 -176
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Uploader.kt +0 -182
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePicker.kt +0 -193
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerTypes.kt +0 -29
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/DateTimePickerUtils.kt +0 -234
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/datetimepicker/WheelPicker.kt +0 -188
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +0 -325
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/HostFont.kt +0 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitDesignSystem.kt +0 -14
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/KitFontScale.kt +0 -22
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +0 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +0 -16
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +0 -221
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +0 -270
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +0 -52
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +0 -38
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +0 -39
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/AutomationId.kt +0 -52
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Clickable.kt +0 -66
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Conditional.kt +0 -11
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/DeprecatedModifier.kt +0 -104
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +0 -48
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Size.kt +0 -51
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/BottomSheet.kt +0 -299
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/HostBackGestureBridge.kt +0 -58
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ModalScreen.kt +0 -129
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigation.kt +0 -106
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/NavigationContainer.kt +0 -201
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/Navigator.kt +0 -393
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/ScrollToTop.kt +0 -8
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackScreen.kt +0 -595
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/StackTransition.kt +0 -148
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/SwipeBackHaptic.kt +0 -35
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTab.kt +0 -175
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/BottomTabBar.kt +0 -225
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/bottomtab/CurvedContainer.kt +0 -86
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/FloatingButton.kt +0 -169
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/Header.kt +0 -358
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderBackground.kt +0 -83
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderJourney.kt +0 -106
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderLocation.kt +0 -75
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderRight.kt +0 -309
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderTitle.kt +0 -40
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/HeaderUser.kt +0 -364
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/component/SnackBar.kt +0 -132
- package/compose/src/commonMain/kotlin/vn/momo/kits/navigation/tracking/ScreenTracker.kt +0 -127
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/BackGesture.kt +0 -12
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/ComposeLottieAnimation.kt +0 -91
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/OsFontScale.kt +0 -9
- package/compose/src/commonMain/kotlin/vn/momo/kits/platform/Platform.kt +0 -71
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +0 -1329
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Resources.kt +0 -55
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Tracking.kt +0 -15
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +0 -105
- package/compose/src/iosMain/kotlin/vn/momo/kits/const/HostFont.ios.kt +0 -40
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/HostBackGesture.ios.kt +0 -45
- package/compose/src/iosMain/kotlin/vn/momo/kits/navigation/ScrollToTop.ios.kt +0 -32
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/BackGesture.ios.kt +0 -38
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/OsFontScale.ios.kt +0 -66
- package/compose/src/iosMain/kotlin/vn/momo/kits/platform/Platform.ios.kt +0 -213
- package/gradle/libs.versions.toml +0 -69
- package/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/gradle/wrapper/gradle-wrapper.properties +0 -8
- package/gradle.properties +0 -26
- package/gradlew +0 -252
- package/gradlew.bat +0 -94
- package/ios-demo/README.md +0 -120
- package/local.properties +0 -8
- package/settings.gradle.kts +0 -64
package/ios/Image/Image.swift
CHANGED
|
@@ -41,11 +41,7 @@ public struct ImageView: View {
|
|
|
41
41
|
.placeholder {
|
|
42
42
|
VStack(alignment: .center, content: {
|
|
43
43
|
if error {
|
|
44
|
-
|
|
45
|
-
.resizable()
|
|
46
|
-
.renderingMode(.template)
|
|
47
|
-
.foregroundColor(theme.colors.text.disable)
|
|
48
|
-
.frame(width: 24, height: 24)
|
|
44
|
+
ImageErrorIcon(color: theme.colors.text.disable)
|
|
49
45
|
} else if placeholder != nil {
|
|
50
46
|
placeholder
|
|
51
47
|
}
|
|
@@ -74,6 +70,21 @@ public struct ImageView: View {
|
|
|
74
70
|
var url: String
|
|
75
71
|
}
|
|
76
72
|
|
|
73
|
+
// A bare WebImage on purpose: going through `Icon` nests another `ImageView`, whose own
|
|
74
|
+
// failure would render this placeholder again, without end while offline.
|
|
75
|
+
private struct ImageErrorIcon: View {
|
|
76
|
+
let color: Color
|
|
77
|
+
|
|
78
|
+
var body: some View {
|
|
79
|
+
WebImage(url: URL(string: iconSources["media_fail"] ?? ""))
|
|
80
|
+
.resizable()
|
|
81
|
+
.renderingMode(.template)
|
|
82
|
+
.scaledToFit()
|
|
83
|
+
.foregroundColor(color)
|
|
84
|
+
.frame(width: 24, height: 24)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
77
88
|
private struct ColorMultiplyModifier: ViewModifier {
|
|
78
89
|
let color: Color?
|
|
79
90
|
|
|
@@ -36,7 +36,8 @@ struct LottieView: UIViewRepresentable {
|
|
|
36
36
|
animationView.animation = cachedAnimation
|
|
37
37
|
setupAnimationView(animationView, view)
|
|
38
38
|
} else {
|
|
39
|
-
|
|
39
|
+
guard let animationURL = URL(string: url) else { return view }
|
|
40
|
+
LottieAnimation.loadedFrom(url: animationURL, closure: { animation in
|
|
40
41
|
if let animation = animation {
|
|
41
42
|
Self.animationCache.setObject(animation, forKey: url as NSString)
|
|
42
43
|
animationView.animation = animation
|
|
@@ -49,7 +50,8 @@ struct LottieView: UIViewRepresentable {
|
|
|
49
50
|
if let cachedAnimation = Self.animationCache.object(forKey: name as NSString) {
|
|
50
51
|
animationView.animation = cachedAnimation
|
|
51
52
|
setupAnimationView(animationView, view)
|
|
52
|
-
} else if let animation = LottieAnimation.named(name)
|
|
53
|
+
} else if let animation = LottieAnimation.named(name, bundle: MoMoUIKitsResources.bundle)
|
|
54
|
+
?? LottieAnimation.named(name) {
|
|
53
55
|
Self.animationCache.setObject(animation, forKey: name as NSString)
|
|
54
56
|
animationView.animation = animation
|
|
55
57
|
setupAnimationView(animationView, view)
|
|
@@ -55,6 +55,7 @@ extension View {
|
|
|
55
55
|
|
|
56
56
|
public struct PopupDisplay: View {
|
|
57
57
|
@Environment(\.localize) private var localize
|
|
58
|
+
@Environment(\.screenLayout) private var layout
|
|
58
59
|
|
|
59
60
|
// MARK: Lifecycle
|
|
60
61
|
|
|
@@ -91,6 +92,7 @@ public struct PopupDisplay: View {
|
|
|
91
92
|
|
|
92
93
|
@State private var textHeight: CGFloat = .zero
|
|
93
94
|
@State private var isScrollable = false
|
|
95
|
+
@State private var actionsHeight: CGFloat = 0
|
|
94
96
|
|
|
95
97
|
public var body: some View {
|
|
96
98
|
var shouldUseColumn: Bool {
|
|
@@ -114,88 +116,103 @@ public struct PopupDisplay: View {
|
|
|
114
116
|
}
|
|
115
117
|
|
|
116
118
|
VStack(spacing: 0) {
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
.
|
|
121
|
-
|
|
122
|
-
.
|
|
119
|
+
// scrolls when iPhone Duo landscape is too short; actions stay visible
|
|
120
|
+
PopupScrollBody(maxHeight: layout.popupMaxHeight.map { $0 - actionsHeight }) {
|
|
121
|
+
VStack(spacing: 0) {
|
|
122
|
+
if(!url.isEmpty) {
|
|
123
|
+
WebImage(url: URL(string: url), isAnimating: .constant(true))
|
|
124
|
+
.resizable()
|
|
125
|
+
.placeholder {
|
|
126
|
+
Rectangle()
|
|
127
|
+
.fill(Color.gray.opacity(0.3))
|
|
128
|
+
.aspectRatio(1.777, contentMode: .fit)
|
|
129
|
+
.frame(maxWidth: .infinity, maxHeight: 184)
|
|
130
|
+
}
|
|
123
131
|
.aspectRatio(1.777, contentMode: .fit)
|
|
124
|
-
.frame(maxWidth: .infinity,
|
|
132
|
+
.frame(maxWidth: .infinity, alignment: .center)
|
|
133
|
+
.clipShape(RoundedCorner(radius: 15, corners: [.topLeft, .topRight]))
|
|
134
|
+
.clipped()
|
|
125
135
|
}
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
MomoText(title, typography: .headerDefaultBold)
|
|
133
|
-
.padding(.top, 24)
|
|
134
|
-
.padding(.bottom, 8)
|
|
135
|
-
.lineLimit(2)
|
|
136
|
-
.accessibility(identifier: "title_popup_permission")
|
|
136
|
+
VStack(alignment: .leading, spacing: 0) {
|
|
137
|
+
MomoText(title, typography: .headerDefaultBold)
|
|
138
|
+
.padding(.top, 24)
|
|
139
|
+
.padding(.bottom, 8)
|
|
140
|
+
.lineLimit(2)
|
|
141
|
+
.accessibility(identifier: "title_popup_permission")
|
|
137
142
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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
|
|
143
|
+
Group {
|
|
144
|
+
if isScrollable {
|
|
145
|
+
ScrollView(showsIndicators: false) {
|
|
146
|
+
MomoText(description, typography: .bodyDefaultRegular)
|
|
147
|
+
.multilineTextAlignment(.leading)
|
|
148
|
+
.background(GeometryReader { geo in
|
|
149
|
+
Color.clear.onAppear { textHeight = geo.size.height }
|
|
150
|
+
})
|
|
151
|
+
.measureLineHeights(font: .body_default_regular,
|
|
152
|
+
oneLine: $oneLineH,
|
|
153
|
+
twoLines: $twoLineH)
|
|
154
|
+
.accessibility(identifier: "description_popup_permission")
|
|
161
155
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
156
|
+
// Cap the visible height to ~8.5 lines
|
|
157
|
+
.frame(height: min(maxHeight8_5, textHeight))
|
|
158
|
+
} else {
|
|
159
|
+
MomoText(description, typography: .bodyDefaultRegular)
|
|
160
|
+
.multilineTextAlignment(.leading)
|
|
161
|
+
.background(GeometryReader { geo in
|
|
162
|
+
Color.clear.onAppear {
|
|
163
|
+
textHeight = geo.size.height
|
|
164
|
+
// Trigger scroll at ~8.5 lines
|
|
165
|
+
isScrollable = textHeight > maxHeight8_5
|
|
166
|
+
}
|
|
167
|
+
})
|
|
168
|
+
.measureLineHeights(font: .body_default_regular,
|
|
169
|
+
oneLine: $oneLineH,
|
|
170
|
+
twoLines: $twoLineH)
|
|
171
|
+
.accessibility(identifier: "description_popup_permission")
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
174
|
.padding(.bottom, 8)
|
|
175
|
+
|
|
176
|
+
if(!errorCode.isEmpty) {
|
|
177
|
+
MomoText(localize.translate("errorCode") + errorCode, typography: .descriptionXsRegular, color: Colors.black12)
|
|
178
|
+
.lineLimit(1)
|
|
179
|
+
.padding(.bottom, 8)
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
.frame(maxWidth: .infinity, alignment: .leading)
|
|
183
|
+
.padding(.horizontal, 24)
|
|
184
|
+
.padding(.bottom, 16)
|
|
175
185
|
}
|
|
176
186
|
}
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
ColumnButtons
|
|
186
|
-
}
|
|
187
|
-
} else {
|
|
188
|
-
if buttonType == .text {
|
|
189
|
-
RowTextButtons
|
|
187
|
+
|
|
188
|
+
Group {
|
|
189
|
+
if shouldUseColumn {
|
|
190
|
+
if buttonType == .text {
|
|
191
|
+
ColumnTextButtons
|
|
192
|
+
} else {
|
|
193
|
+
ColumnButtons
|
|
194
|
+
}
|
|
190
195
|
} else {
|
|
191
|
-
|
|
196
|
+
if buttonType == .text {
|
|
197
|
+
RowTextButtons
|
|
198
|
+
} else {
|
|
199
|
+
RowButtons
|
|
200
|
+
}
|
|
192
201
|
}
|
|
193
202
|
}
|
|
203
|
+
.background(
|
|
204
|
+
GeometryReader { proxy in
|
|
205
|
+
Color.clear
|
|
206
|
+
.onAppear { actionsHeight = proxy.size.height }
|
|
207
|
+
.onChange(of: proxy.size.height) { actionsHeight = $0 }
|
|
208
|
+
}
|
|
209
|
+
)
|
|
194
210
|
}
|
|
195
211
|
.fixedSize(horizontal: false, vertical: true)
|
|
196
212
|
}
|
|
197
213
|
}
|
|
198
214
|
.background(Color.white.cornerRadius(15))
|
|
215
|
+
.frame(maxWidth: layout.popupMaxWidth)
|
|
199
216
|
.padding(.horizontal, 12)
|
|
200
217
|
.accessibilityElement(children: .ignore)
|
|
201
218
|
.accessibility(identifier: "popup_notify")
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
|
|
3
|
+
// Width of a system alert on the iPhone Duo inner display, in both orientations (RN Popup/utils.ts).
|
|
4
|
+
private let duoPopupMaxWidth: CGFloat = 440
|
|
5
|
+
|
|
6
|
+
extension ScreenLayout {
|
|
7
|
+
var isDuoDevice: Bool { isIPhoneDuoDevice(windowSize: CGSize(width: width, height: height)) }
|
|
8
|
+
|
|
9
|
+
/// Card width cap; other devices keep the full window width minus the popup's own padding.
|
|
10
|
+
var popupMaxWidth: CGFloat {
|
|
11
|
+
isDuoDevice ? min(width - Spacing.XL * 2, duoPopupMaxWidth) : .infinity
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/// Room left for a popup on iPhone Duo, where landscape is too short for it; nil elsewhere.
|
|
15
|
+
var popupMaxHeight: CGFloat? {
|
|
16
|
+
guard isDuoDevice else { return nil }
|
|
17
|
+
return height - duoTopInset - insets.bottom - Spacing.XL * 2
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/// Scrolls `content` once it is taller than `maxHeight`; otherwise sizes to it.
|
|
22
|
+
struct PopupScrollBody<Content: View>: View {
|
|
23
|
+
let maxHeight: CGFloat?
|
|
24
|
+
@ViewBuilder let content: () -> Content
|
|
25
|
+
|
|
26
|
+
@State private var contentHeight: CGFloat = 0
|
|
27
|
+
|
|
28
|
+
var body: some View {
|
|
29
|
+
if let maxHeight {
|
|
30
|
+
ScrollView(.vertical, showsIndicators: false) {
|
|
31
|
+
content()
|
|
32
|
+
.background(
|
|
33
|
+
GeometryReader { proxy in
|
|
34
|
+
Color.clear
|
|
35
|
+
.onAppear { contentHeight = proxy.size.height }
|
|
36
|
+
.onChange(of: proxy.size.height) { contentHeight = $0 }
|
|
37
|
+
}
|
|
38
|
+
)
|
|
39
|
+
}
|
|
40
|
+
.frame(height: min(contentHeight, max(maxHeight, 0)))
|
|
41
|
+
} else {
|
|
42
|
+
content()
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -40,10 +40,12 @@ public struct PopupNotifyProps {
|
|
|
40
40
|
public struct PopupNotify: View {
|
|
41
41
|
@Environment(\.localize) private var localize
|
|
42
42
|
@Environment(\.momoFontScale) private var fontScale
|
|
43
|
+
@Environment(\.screenLayout) private var layout
|
|
43
44
|
|
|
44
45
|
public let props: PopupNotifyProps
|
|
45
46
|
|
|
46
47
|
@State private var descriptionHeight: CGFloat = 0
|
|
48
|
+
@State private var actionsHeight: CGFloat = 0
|
|
47
49
|
|
|
48
50
|
private var errorCodePrefix: String {
|
|
49
51
|
localize.translate("errorCode")
|
|
@@ -71,51 +73,67 @@ public struct PopupNotify: View {
|
|
|
71
73
|
public var body: some View {
|
|
72
74
|
ZStack(alignment: .topTrailing) {
|
|
73
75
|
VStack(spacing: 0) {
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
typography: .headerDefaultBold,
|
|
82
|
-
maxLines: 2,
|
|
83
|
-
accessibilityId: "title_popup_permission"
|
|
84
|
-
)
|
|
85
|
-
.padding(.bottom, Spacing.S)
|
|
86
|
-
|
|
87
|
-
descriptionContent
|
|
88
|
-
|
|
89
|
-
if !props.error.isEmpty {
|
|
90
|
-
MomoText(
|
|
91
|
-
errorCodePrefix + props.error,
|
|
92
|
-
typography: .descriptionXsRegular,
|
|
93
|
-
color: Colors.black12,
|
|
94
|
-
maxLines: 1
|
|
95
|
-
)
|
|
96
|
-
.padding(.top, Spacing.S)
|
|
76
|
+
// scrolls when iPhone Duo landscape is too short; actions stay visible
|
|
77
|
+
PopupScrollBody(maxHeight: layout.popupMaxHeight.map { $0 - actionsHeight }) {
|
|
78
|
+
VStack(spacing: 0) {
|
|
79
|
+
if !props.image.isEmpty {
|
|
80
|
+
popupImage
|
|
81
|
+
}
|
|
82
|
+
textContent
|
|
97
83
|
}
|
|
98
84
|
}
|
|
99
|
-
.frame(maxWidth: .infinity, alignment: .leading)
|
|
100
|
-
.padding(Spacing.XL)
|
|
101
85
|
|
|
102
86
|
actionButtons
|
|
103
87
|
.padding(.horizontal, Spacing.XL)
|
|
104
88
|
.padding(.bottom, Spacing.XL)
|
|
89
|
+
.background(
|
|
90
|
+
GeometryReader { proxy in
|
|
91
|
+
Color.clear
|
|
92
|
+
.onAppear { actionsHeight = proxy.size.height }
|
|
93
|
+
.onChange(of: proxy.size.height) { actionsHeight = $0 }
|
|
94
|
+
}
|
|
95
|
+
)
|
|
105
96
|
}
|
|
106
97
|
.background(Colors.black01)
|
|
107
98
|
.clipShape(RoundedRectangle(cornerRadius: Radius.L))
|
|
108
99
|
|
|
109
100
|
if props.isShowCloseIcon {
|
|
110
101
|
closeButton
|
|
111
|
-
.offset(x:
|
|
102
|
+
.offset(x: 11, y: -11)
|
|
112
103
|
}
|
|
113
104
|
}
|
|
105
|
+
.frame(maxWidth: layout.popupMaxWidth)
|
|
114
106
|
.padding(.horizontal, Spacing.M)
|
|
115
107
|
.accessibilityElement(children: .ignore)
|
|
116
108
|
.accessibilityIdentifier("popup_notify")
|
|
117
109
|
}
|
|
118
110
|
|
|
111
|
+
private var textContent: some View {
|
|
112
|
+
VStack(alignment: .leading, spacing: 0) {
|
|
113
|
+
MomoText(
|
|
114
|
+
props.title,
|
|
115
|
+
typography: .headerDefaultBold,
|
|
116
|
+
maxLines: 2,
|
|
117
|
+
accessibilityId: "title_popup_permission"
|
|
118
|
+
)
|
|
119
|
+
.padding(.bottom, Spacing.S)
|
|
120
|
+
|
|
121
|
+
descriptionContent
|
|
122
|
+
|
|
123
|
+
if !props.error.isEmpty {
|
|
124
|
+
MomoText(
|
|
125
|
+
errorCodePrefix + props.error,
|
|
126
|
+
typography: .descriptionXsRegular,
|
|
127
|
+
color: Colors.black12,
|
|
128
|
+
maxLines: 1
|
|
129
|
+
)
|
|
130
|
+
.padding(.top, Spacing.S)
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
.frame(maxWidth: .infinity, alignment: .leading)
|
|
134
|
+
.padding(Spacing.XL)
|
|
135
|
+
}
|
|
136
|
+
|
|
119
137
|
private var popupImage: some View {
|
|
120
138
|
WebImage(url: URL(string: props.image), isAnimating: .constant(true))
|
|
121
139
|
.resizable()
|
|
@@ -3,6 +3,7 @@ import SDWebImageSwiftUI
|
|
|
3
3
|
|
|
4
4
|
public struct PopupPromotion: View {
|
|
5
5
|
@Environment(\.appTheme) private var theme
|
|
6
|
+
@Environment(\.screenLayout) private var layout
|
|
6
7
|
|
|
7
8
|
var imageUrl: String
|
|
8
9
|
var onIconClose: (() -> Void)?
|
|
@@ -19,22 +20,33 @@ public struct PopupPromotion: View {
|
|
|
19
20
|
self.onAction = onAction
|
|
20
21
|
}
|
|
21
22
|
|
|
23
|
+
private static let aspectRatio: CGFloat = 0.72
|
|
24
|
+
// close button row under the image: stack spacing + padded 40pt button
|
|
25
|
+
private static let closeRowHeight: CGFloat = 8 + 40 + Spacing.S * 2
|
|
26
|
+
|
|
27
|
+
// fit the portrait image by height when iPhone Duo leaves too little room
|
|
28
|
+
private var imageWidth: CGFloat {
|
|
29
|
+
let width = min(layout.width - Spacing.XL * 2, layout.popupMaxWidth)
|
|
30
|
+
guard let maxHeight = layout.popupMaxHeight else { return width }
|
|
31
|
+
return min(width, (maxHeight - Self.closeRowHeight) * Self.aspectRatio)
|
|
32
|
+
}
|
|
33
|
+
|
|
22
34
|
public var body: some View {
|
|
23
35
|
VStack(spacing: 8) {
|
|
24
36
|
if(imageUrl.isEmpty) {
|
|
25
|
-
Icon(source: "media_fail", size:
|
|
37
|
+
Icon(source: "media_fail", size: imageWidth)
|
|
26
38
|
}
|
|
27
39
|
else {
|
|
28
|
-
WebImage(url: URL(string: imageUrl)
|
|
40
|
+
WebImage(url: URL(string: imageUrl))
|
|
29
41
|
.resizable()
|
|
30
42
|
.placeholder {
|
|
31
43
|
Color.gray
|
|
32
|
-
.aspectRatio(
|
|
33
|
-
.frame(maxWidth:
|
|
44
|
+
.aspectRatio(Self.aspectRatio, contentMode: .fit)
|
|
45
|
+
.frame(maxWidth: imageWidth)
|
|
34
46
|
.clipped()
|
|
35
47
|
}
|
|
36
|
-
.aspectRatio(
|
|
37
|
-
.frame(maxWidth:
|
|
48
|
+
.aspectRatio(Self.aspectRatio, contentMode: .fit)
|
|
49
|
+
.frame(maxWidth: imageWidth, alignment: .center)
|
|
38
50
|
.clipped()
|
|
39
51
|
.onTapGesture {
|
|
40
52
|
onAction?()
|