@momo-kits/native-kits 0.0.1-beta.4 → 0.89.1-2
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/README.md +1 -0
- package/android/.gradle/8.0/checksums/checksums.lock +0 -0
- package/android/.gradle/8.0/dependencies-accessors/dependencies-accessors.lock +0 -0
- package/android/.gradle/8.0/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.0/gc.properties +0 -0
- package/android/.gradle/config.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/.idea/gradle.xml +12 -0
- package/android/.idea/migrations.xml +10 -0
- package/android/.idea/misc.xml +10 -0
- package/android/.idea/vcs.xml +6 -0
- package/android/.idea/workspace.xml +50 -0
- package/android/build.gradle +35 -69
- package/android/local.properties +8 -0
- package/android/proguard-rules.pro +21 -0
- package/android/src/main/AndroidManifest.xml +2 -2
- package/android/src/main/java/com/momoplatform/nativekits/foundations/Button.kt +16 -0
- package/android/src/main/java/com/momoplatform/nativekits/libs/Logo.kt +63 -0
- package/android/src/main/java/com/momoplatform/nativekits/libs/TrustBanner.kt +246 -0
- package/android/src/main/res/drawable/ic_launcher_background.xml +170 -0
- package/android/src/main/res/drawable-v24/ic_launcher_foreground.xml +30 -0
- package/android/src/main/res/mipmap-anydpi-v26/ic_launcher.xml +6 -0
- package/android/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml +6 -0
- package/android/src/main/res/mipmap-hdpi/ic_launcher.webp +0 -0
- package/android/src/main/res/mipmap-hdpi/ic_launcher_round.webp +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_launcher.webp +0 -0
- package/android/src/main/res/mipmap-mdpi/ic_launcher_round.webp +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_launcher.webp +0 -0
- package/android/src/main/res/mipmap-xhdpi/ic_launcher_round.webp +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_launcher.webp +0 -0
- package/android/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_launcher.webp +0 -0
- package/android/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp +0 -0
- package/android/src/main/res/values/colors.xml +10 -0
- package/android/src/main/res/values/strings.xml +3 -0
- package/android/src/main/res/values/themes.xml +3 -0
- package/android/src/main/res/values-night/themes.xml +3 -0
- package/android/src/main/res/xml/backup_rules.xml +13 -0
- package/android/src/main/res/xml/data_extraction_rules.xml +19 -0
- package/build.gradle.kts +18 -0
- package/compose/build.gradle.kts +82 -0
- package/compose/src/androidMain/AndroidManifest.xml +2 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/utils/Platform.kt +3 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/utils/SetMaskFilter.kt +8 -0
- package/compose/src/androidMain/kotlin/vn/momo/kits/utils/Utils.android.kt +14 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Components.kt +194 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/NavigationContainer.kt +197 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/application/Screen.kt +133 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Badge.kt +62 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/BadgeDot.kt +27 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Button.kt +288 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/CheckBox.kt +80 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Divider.kt +23 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Icon.kt +42 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/IconButton.kt +126 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Image.kt +51 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Input.kt +299 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputMoney.kt +246 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputSearch.kt +223 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/InputTextArea.kt +244 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PopupNotify.kt +281 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/PromotionPopup.kt +72 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Radio.kt +65 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Skeleton.kt +64 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Switch.kt +63 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Tag.kt +73 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/components/Text.kt +42 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Colors.kt +150 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Radius.kt +12 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Spacing.kt +13 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Theme.kt +173 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/const/Typography.kt +242 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Card.kt +2 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Item.kt +2 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/layout/Section.kt +2 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/modifier/Shadow.kt +50 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Icons.kt +1321 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Platform.kt +3 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/SetMaskFilter.kt +5 -0
- package/compose/src/commonMain/kotlin/vn/momo/kits/utils/Utils.kt +97 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/utils/Platform.kt +3 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/utils/SetMaskFilter.kt +9 -0
- package/compose/src/iosMain/kotlin/vn/momo/kits/utils/Utils.ios.kt +18 -0
- package/gradle.properties +19 -0
- package/gradlew +240 -0
- package/gradlew.bat +91 -0
- package/ios/Button/Button.swift +9 -2
- package/ios/CalculatorKeyboard/CalculatorKeyboard.swift +126 -0
- package/ios/Checkbox/Checkbox.swift +38 -0
- package/ios/{Colors+Spacing → Colors+Radius+Spacing}/Colors.swift +21 -19
- package/ios/Colors+Radius+Spacing/Radius.swift +22 -0
- package/ios/Image/Image.swift +60 -0
- package/ios/Input/Input.swift +88 -37
- package/ios/OTPKeyboard/KeyboardButton.swift +12 -4
- package/ios/OTPKeyboard/OTPKeyboard.swift +1 -1
- package/ios/Popup/PopupDisplay.swift +169 -0
- package/ios/Popup/PopupInput.swift +96 -0
- package/ios/Popup/PopupPromotion.swift +52 -0
- package/ios/PopupView/FullscreenPopup.swift +251 -0
- package/ios/{Popup → PopupView}/Modifiers.swift +6 -20
- package/ios/{Popup → PopupView}/PopupView.swift +38 -146
- package/ios/PopupView/Utils++.swift +281 -0
- package/ios/ScrollIndicator/ScrollIndicator.swift +79 -0
- package/ios/Switch/Switch.swift +44 -0
- package/ios/Template/Logo/Logo.swift +75 -0
- package/ios/Template/TrustBanner/TrustBanner.swift +189 -0
- package/ios/native-kits.podspec +2 -0
- package/local.properties +8 -0
- package/package.json +6 -6
- package/publish.sh +1 -10
- package/settings.gradle.kts +41 -0
- package/android/gradle.properties +0 -5
- package/android/src/main/java/com/momoplatform/nativekits/NativeKitsPackage.kt +0 -17
- package/android/src/main/java/com/momoplatform/nativekits/NativeKitsViewManager.kt +0 -20
- package/example/ios/Example/Assets.xcassets/AppIcon.appiconset/Contents.json +0 -63
- package/example/ios/Example/Assets.xcassets/Background.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/Border.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/Card.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/Contents.json +0 -6
- package/example/ios/Example/Assets.xcassets/Error.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/Primary.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/PrimaryDark.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/PrimaryLight.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/Secondary.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/Success.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/Text.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/TextSecondary.colorset/Contents.json +0 -38
- package/example/ios/Example/Assets.xcassets/Warning.colorset/Contents.json +0 -38
- package/example/ios/Example/ComponentDetail.swift +0 -35
- package/example/ios/Example/ComponentItem.swift +0 -24
- package/example/ios/Example/ComponentModel.swift +0 -33
- package/example/ios/Example/ContentView.swift +0 -53
- package/example/ios/Example/Example.entitlements +0 -10
- package/example/ios/Example/Foundation/ButtonDemo.swift +0 -80
- package/example/ios/Example/Foundation/Popup/ActionSheets.swift +0 -136
- package/example/ios/Example/Foundation/Popup/Floats.swift +0 -127
- package/example/ios/Example/Foundation/Popup/Popups.swift +0 -101
- package/example/ios/Example/Foundation/PopupDemo.swift +0 -366
- package/example/ios/Example/Foundation/TextInputDemo.swift +0 -31
- package/example/ios/Example/Foundation/TypographyDemo.swift +0 -53
- package/example/ios/Example/Foundation.swift +0 -26
- package/example/ios/Example/Info.plist +0 -18
- package/example/ios/Example/Library/SwipeableDemo.swift +0 -105
- package/example/ios/Example/Library.swift +0 -26
- package/example/ios/Example/Main.swift +0 -11
- package/example/ios/Example/Overview.swift +0 -20
- package/example/ios/Example/Preview Content/Preview Assets.xcassets/Contents.json +0 -6
- package/example/ios/Example/Resource/SFProText-Black.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Bold.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Heavy.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Light.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Medium.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Regular.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Semibold.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Thin.ttf +0 -0
- package/example/ios/Example/Resource/SFProText-Ultralight.ttf +0 -0
- package/example/ios/Example/Resource/foundation.json +0 -33
- package/example/ios/Example/Resource/library.json +0 -8
- package/example/ios/Example/Utils.swift +0 -30
- package/example/ios/Example/ViewModifier/DarkViewModifier.swift +0 -22
- package/example/ios/Example.xcodeproj/project.pbxproj +0 -570
- package/example/ios/Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
- package/example/ios/Example.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/example/ios/Example.xcodeproj/project.xcworkspace/xcuserdata/wem.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
- package/example/ios/Example.xcworkspace/contents.xcworkspacedata +0 -10
- package/example/ios/Example.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
- package/example/ios/Example.xcworkspace/xcuserdata/wem.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/example/ios/Example.xcworkspace/xcuserdata/wem.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +0 -6
- package/example/ios/Podfile +0 -6
- package/example/ios/Podfile.lock +0 -16
- package/example/ios/Pods/Local Podspecs/MoMoUIKits.podspec.json +0 -29
- package/example/ios/Pods/Manifest.lock +0 -16
- package/example/ios/Pods/Pods.xcodeproj/project.pbxproj +0 -661
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/MoMoUIKits.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/Pods-Example.xcscheme +0 -58
- package/example/ios/Pods/Pods.xcodeproj/xcuserdata/wem.xcuserdatad/xcschemes/xcschememanagement.plist +0 -25
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-dummy.m +0 -5
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-prefix.pch +0 -12
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits-umbrella.h +0 -16
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.debug.xcconfig +0 -12
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.modulemap +0 -6
- package/example/ios/Pods/Target Support Files/MoMoUIKits/MoMoUIKits.release.xcconfig +0 -12
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-acknowledgements.markdown +0 -3
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-acknowledgements.plist +0 -29
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-dummy.m +0 -5
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example-umbrella.h +0 -16
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.debug.xcconfig +0 -14
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.modulemap +0 -6
- package/example/ios/Pods/Target Support Files/Pods-Example/Pods-Example.release.xcconfig +0 -14
- package/ios/Colors+Spacing/Radius.swift +0 -11
- package/ios/Popup/Utils++.swift +0 -163
- /package/ios/{Colors+Spacing → Colors+Radius+Spacing}/Spacing.swift +0 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
import SwiftUI
|
|
2
|
+
import Combine
|
|
3
|
+
|
|
4
|
+
final class DispatchWorkHolder {
|
|
5
|
+
var work: DispatchWorkItem?
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
final class ClassReference<T> {
|
|
9
|
+
var value: T
|
|
10
|
+
|
|
11
|
+
init(_ value: T) {
|
|
12
|
+
self.value = value
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
public extension View {
|
|
17
|
+
|
|
18
|
+
@ViewBuilder
|
|
19
|
+
func valueChanged<T: Equatable>(value: T, onChange: @escaping (T) -> Void) -> some View {
|
|
20
|
+
if #available(iOS 14.0, tvOS 14.0, macOS 11.0, watchOS 7.0, *) {
|
|
21
|
+
self.onChange(of: value, perform: onChange)
|
|
22
|
+
} else {
|
|
23
|
+
self.onReceive(Just(value)) { value in
|
|
24
|
+
onChange(value)
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public extension View {
|
|
31
|
+
@ViewBuilder
|
|
32
|
+
func applyIf<T: View>(_ condition: Bool, apply: (Self) -> T) -> some View {
|
|
33
|
+
if condition {
|
|
34
|
+
apply(self)
|
|
35
|
+
} else {
|
|
36
|
+
self
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@ViewBuilder
|
|
41
|
+
func addTapIf(if condition: Bool, onTap: @escaping ()->()) -> some View {
|
|
42
|
+
if condition {
|
|
43
|
+
self.simultaneousGesture(
|
|
44
|
+
TapGesture().onEnded {
|
|
45
|
+
onTap()
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
} else {
|
|
49
|
+
self
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
struct FrameGetter: ViewModifier {
|
|
55
|
+
|
|
56
|
+
@Binding var frame: CGRect
|
|
57
|
+
|
|
58
|
+
func body(content: Content) -> some View {
|
|
59
|
+
content
|
|
60
|
+
.background(
|
|
61
|
+
GeometryReader { proxy -> AnyView in
|
|
62
|
+
DispatchQueue.main.async {
|
|
63
|
+
let rect = proxy.frame(in: .global)
|
|
64
|
+
// This avoids an infinite layout loop
|
|
65
|
+
if rect.integral != self.frame.integral {
|
|
66
|
+
self.frame = rect
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return AnyView(EmptyView())
|
|
70
|
+
}
|
|
71
|
+
)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
extension View {
|
|
76
|
+
public func frameGetter(_ frame: Binding<CGRect>) -> some View {
|
|
77
|
+
modifier(FrameGetter(frame: frame))
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
struct AnimationCompletionObserverModifier<Value>: AnimatableModifier where Value: VectorArithmetic, Value: Comparable {
|
|
82
|
+
|
|
83
|
+
/// While animating, SwiftUI changes the old input value to the new target value using this property. This value is set to the old value until the animation completes.
|
|
84
|
+
var animatableData: Value {
|
|
85
|
+
didSet {
|
|
86
|
+
notifyCompletionIfFinished()
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/// The target value for which we're observing. This value is directly set once the animation starts. During animation, `animatableData` will hold the oldValue and is only updated to the target value once the animation completes.
|
|
91
|
+
private var targetValue: Value
|
|
92
|
+
|
|
93
|
+
/// The completion callback which is called once the animation completes.
|
|
94
|
+
private var completion: () -> Void
|
|
95
|
+
|
|
96
|
+
init(observedValue: Value, completion: @escaping () -> Void) {
|
|
97
|
+
self.completion = completion
|
|
98
|
+
self.animatableData = observedValue
|
|
99
|
+
targetValue = observedValue
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// Verifies whether the current animation is finished and calls the completion callback if true.
|
|
103
|
+
private func notifyCompletionIfFinished() {
|
|
104
|
+
guard animatableData == targetValue else { return }
|
|
105
|
+
|
|
106
|
+
/// Dispatching is needed to take the next runloop for the completion callback.
|
|
107
|
+
/// This prevents errors like "Modifying state during view update, this will cause undefined behavior."
|
|
108
|
+
DispatchQueue.main.async {
|
|
109
|
+
self.completion()
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
func body(content: Content) -> some View {
|
|
114
|
+
/// We're not really modifying the view so we can directly return the original input value.
|
|
115
|
+
return content
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
struct AnimatableModifierDouble: AnimatableModifier {
|
|
120
|
+
|
|
121
|
+
var targetValue: Double
|
|
122
|
+
static var done = false
|
|
123
|
+
|
|
124
|
+
// SwiftUI gradually varies it from old value to the new value
|
|
125
|
+
var animatableData: Double {
|
|
126
|
+
didSet {
|
|
127
|
+
checkIfFinished()
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
var completion: () -> ()
|
|
131
|
+
|
|
132
|
+
// Re-created every time the control argument changes
|
|
133
|
+
init(bindedValue: Double, completion: @escaping () -> ()) {
|
|
134
|
+
self.completion = completion
|
|
135
|
+
|
|
136
|
+
// Set animatableData to the new value. But SwiftUI again directly
|
|
137
|
+
// and gradually varies the value while the body
|
|
138
|
+
// is being called to animate. Following line serves the purpose of
|
|
139
|
+
// associating the extenal argument with the animatableData.
|
|
140
|
+
self.animatableData = bindedValue
|
|
141
|
+
targetValue = bindedValue
|
|
142
|
+
AnimatableModifierDouble.done = false
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
func checkIfFinished() -> () {
|
|
146
|
+
if AnimatableModifierDouble.done { return }
|
|
147
|
+
let delta = 0.1
|
|
148
|
+
if animatableData > targetValue - delta &&
|
|
149
|
+
animatableData < targetValue + delta {
|
|
150
|
+
//print("check", animatableData, targetValue)
|
|
151
|
+
AnimatableModifierDouble.done = true
|
|
152
|
+
DispatchQueue.main.async {
|
|
153
|
+
self.completion()
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
func body(content: Content) -> some View {
|
|
159
|
+
content
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
extension View {
|
|
164
|
+
|
|
165
|
+
func onAnimationCompleted(for value: Double, completion: @escaping () -> Void) -> some View {
|
|
166
|
+
modifier(AnimatableModifierDouble(bindedValue: value, completion: completion))
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
extension UIApplication {
|
|
171
|
+
var keyWindow: UIWindow? {
|
|
172
|
+
connectedScenes
|
|
173
|
+
.compactMap {
|
|
174
|
+
$0 as? UIWindowScene
|
|
175
|
+
}
|
|
176
|
+
.flatMap {
|
|
177
|
+
$0.windows
|
|
178
|
+
}
|
|
179
|
+
.first {
|
|
180
|
+
$0.isKeyWindow
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private struct SafeAreaInsetsKey: EnvironmentKey {
|
|
186
|
+
static var defaultValue: EdgeInsets {
|
|
187
|
+
UIApplication.shared.keyWindow?.safeAreaInsets.swiftUiInsets ?? EdgeInsets()
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
extension EnvironmentValues {
|
|
192
|
+
var safeAreaInsets: EdgeInsets {
|
|
193
|
+
self[SafeAreaInsetsKey.self]
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private extension UIEdgeInsets {
|
|
198
|
+
var swiftUiInsets: EdgeInsets {
|
|
199
|
+
EdgeInsets(top: top, leading: left, bottom: bottom, trailing: right)
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
extension View {
|
|
204
|
+
|
|
205
|
+
func transparentNonAnimatingFullScreenCover<Content: View>(isPresented: Binding<Bool>, content: @escaping () -> Content) -> some View {
|
|
206
|
+
modifier(TransparentNonAnimatableFullScreenModifier(isPresented: isPresented, fullScreenContent: content))
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private struct TransparentNonAnimatableFullScreenModifier<FullScreenContent: View>: ViewModifier {
|
|
211
|
+
|
|
212
|
+
@Binding var isPresented: Bool
|
|
213
|
+
let fullScreenContent: () -> (FullScreenContent)
|
|
214
|
+
|
|
215
|
+
func body(content: Content) -> some View {
|
|
216
|
+
if #available(iOS 14.0, *) {
|
|
217
|
+
content
|
|
218
|
+
.valueChanged(value: isPresented, onChange: { isPresented in
|
|
219
|
+
UIView.setAnimationsEnabled(false)
|
|
220
|
+
})
|
|
221
|
+
.fullScreenCover(isPresented: $isPresented, content: {
|
|
222
|
+
ZStack {
|
|
223
|
+
fullScreenContent()
|
|
224
|
+
}
|
|
225
|
+
.background(FullScreenCoverBackgroundRemovalView())
|
|
226
|
+
.onAppear {
|
|
227
|
+
if !UIView.areAnimationsEnabled {
|
|
228
|
+
UIView.setAnimationsEnabled(true)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
.onDisappear {
|
|
232
|
+
if !UIView.areAnimationsEnabled {
|
|
233
|
+
UIView.setAnimationsEnabled(true)
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
} else {
|
|
238
|
+
content
|
|
239
|
+
.valueChanged(value: isPresented, onChange: { isPresented in
|
|
240
|
+
UIView.setAnimationsEnabled(false)
|
|
241
|
+
})
|
|
242
|
+
.sheet(isPresented: $isPresented, content: {
|
|
243
|
+
ZStack {
|
|
244
|
+
fullScreenContent()
|
|
245
|
+
}
|
|
246
|
+
.background(FullScreenCoverBackgroundRemovalView())
|
|
247
|
+
.onAppear {
|
|
248
|
+
if !UIView.areAnimationsEnabled {
|
|
249
|
+
UIView.setAnimationsEnabled(true)
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
.onDisappear {
|
|
253
|
+
if !UIView.areAnimationsEnabled {
|
|
254
|
+
UIView.setAnimationsEnabled(true)
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
})
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
private struct FullScreenCoverBackgroundRemovalView: UIViewRepresentable {
|
|
264
|
+
|
|
265
|
+
private class BackgroundRemovalView: UIView {
|
|
266
|
+
|
|
267
|
+
override func didMoveToWindow() {
|
|
268
|
+
super.didMoveToWindow()
|
|
269
|
+
|
|
270
|
+
superview?.superview?.backgroundColor = .clear
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
func makeUIView(context: Context) -> UIView {
|
|
276
|
+
return BackgroundRemovalView()
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
func updateUIView(_ uiView: UIView, context: Context) {}
|
|
280
|
+
|
|
281
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import SwiftUI
|
|
3
|
+
|
|
4
|
+
public struct ScrollViewWithScrollBar<Content: View>: View {
|
|
5
|
+
let INDICATOR_HEIGHT: CGFloat = 4
|
|
6
|
+
@State var position = CGPoint(x: 0, y: 2) //2 is INDICATOR_HEIGHT/2
|
|
7
|
+
@State var contentSize: CGFloat = 0
|
|
8
|
+
@State var scrollViewWidth: CGFloat = 0
|
|
9
|
+
var indicatorWidth: CGFloat
|
|
10
|
+
var indicatorContainerWidth: CGFloat
|
|
11
|
+
var indicatorColor: Color
|
|
12
|
+
var indicatorContainerColor: Color
|
|
13
|
+
@ViewBuilder var content: () -> Content
|
|
14
|
+
|
|
15
|
+
public init(indicatorWidth: CGFloat = 12, indicatorContainerWidth: CGFloat = 36,indicatorColor: Color = Colors.primary, indicatorContainerColor: Color = Colors.black06,@ViewBuilder content: @escaping () -> Content) {
|
|
16
|
+
self.indicatorWidth = indicatorWidth
|
|
17
|
+
self.indicatorContainerWidth = indicatorContainerWidth
|
|
18
|
+
self.content = content
|
|
19
|
+
self.indicatorColor = indicatorColor
|
|
20
|
+
self.indicatorContainerColor = indicatorContainerColor
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// MARK: Public
|
|
24
|
+
|
|
25
|
+
public var body: some View {
|
|
26
|
+
return VStack {
|
|
27
|
+
ScrollView(.horizontal, showsIndicators: false) {
|
|
28
|
+
HStack {
|
|
29
|
+
content()
|
|
30
|
+
}.background(GeometryReader {
|
|
31
|
+
proxy in
|
|
32
|
+
Color.clear.onAppear {
|
|
33
|
+
self.contentSize = proxy.size.width
|
|
34
|
+
self.position = CGPoint(x: indicatorWidth / 2, y: INDICATOR_HEIGHT / 2)
|
|
35
|
+
}
|
|
36
|
+
Color.clear.preference(key: ViewOffsetKey.self,
|
|
37
|
+
value: -proxy.frame(in: .named("scroll")).origin.x)
|
|
38
|
+
|
|
39
|
+
})
|
|
40
|
+
.onPreferenceChange(ViewOffsetKey.self) {
|
|
41
|
+
let newPosition = $0 * ((indicatorContainerWidth - indicatorWidth) / (contentSize - scrollViewWidth)) + indicatorWidth / 2
|
|
42
|
+
if (newPosition > indicatorWidth / 2 && newPosition < indicatorContainerWidth - indicatorWidth / 2 + 1)
|
|
43
|
+
{
|
|
44
|
+
self.position = CGPoint(x: newPosition, y: INDICATOR_HEIGHT / 2)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}.background(GeometryReader {
|
|
48
|
+
proxy in
|
|
49
|
+
Color.clear.onAppear {
|
|
50
|
+
self.scrollViewWidth = proxy.size.width
|
|
51
|
+
}
|
|
52
|
+
}).coordinateSpace(name: "scroll")
|
|
53
|
+
|
|
54
|
+
HStack {
|
|
55
|
+
HStack {}.frame(width: indicatorWidth, height: INDICATOR_HEIGHT)
|
|
56
|
+
.background(indicatorColor)
|
|
57
|
+
.cornerRadius(Radius.S)
|
|
58
|
+
.position(position)
|
|
59
|
+
}.frame(width: indicatorContainerWidth, height: INDICATOR_HEIGHT, alignment: .leading)
|
|
60
|
+
.background(indicatorContainerColor).cornerRadius(Radius.S)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// MARK: - ViewOffsetKey
|
|
70
|
+
|
|
71
|
+
struct ViewOffsetKey: PreferenceKey {
|
|
72
|
+
typealias Value = CGFloat
|
|
73
|
+
|
|
74
|
+
static var defaultValue = CGFloat.zero
|
|
75
|
+
|
|
76
|
+
static func reduce(value: inout Value, nextValue: () -> Value) {
|
|
77
|
+
value += nextValue()
|
|
78
|
+
}
|
|
79
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import SwiftUI
|
|
3
|
+
|
|
4
|
+
public struct Switch: View{
|
|
5
|
+
@Binding var value: Bool
|
|
6
|
+
var disabled: Bool
|
|
7
|
+
var onChange: ((Bool)->Void)?
|
|
8
|
+
|
|
9
|
+
public init(_ value: Binding<Bool>,disabled: Bool = false, onChange: ((Bool)->Void)? = nil){
|
|
10
|
+
self._value = value
|
|
11
|
+
self.disabled = disabled
|
|
12
|
+
self.onChange = onChange
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
public var body: some View {
|
|
17
|
+
SwiftUI.Button(action: {
|
|
18
|
+
withAnimation{
|
|
19
|
+
value.toggle()
|
|
20
|
+
onChange?(value)
|
|
21
|
+
}
|
|
22
|
+
}){
|
|
23
|
+
HStack{
|
|
24
|
+
HStack {
|
|
25
|
+
}
|
|
26
|
+
.frame(width: 6, height: 6)
|
|
27
|
+
.background(value ? Colors.pink03 : Colors.black07)
|
|
28
|
+
.clipShape(Circle())
|
|
29
|
+
.opacity(disabled ? 0.4 : 1)
|
|
30
|
+
}
|
|
31
|
+
.frame(width: 14, height: 14)
|
|
32
|
+
.background(Colors.black01)
|
|
33
|
+
.clipShape(Circle())
|
|
34
|
+
.padding(.leading,5)
|
|
35
|
+
.padding(.trailing,5)
|
|
36
|
+
|
|
37
|
+
}
|
|
38
|
+
.disabled(disabled)
|
|
39
|
+
.frame(width: 40, height: 24, alignment: value == true ? .trailing : .leading)
|
|
40
|
+
.background(value ? Colors.pink03 : Colors.black07)
|
|
41
|
+
.clipShape(Capsule())
|
|
42
|
+
.opacity(disabled ? 0.4 : 1)
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import SwiftUI
|
|
3
|
+
|
|
4
|
+
public struct LogoView: View {
|
|
5
|
+
var type: String
|
|
6
|
+
var useShadow: Bool
|
|
7
|
+
var useBorder: Bool
|
|
8
|
+
var useBackground : Bool
|
|
9
|
+
var backgroundColor: Color
|
|
10
|
+
var shadowColor : Color
|
|
11
|
+
var borderColor : Color
|
|
12
|
+
var source: String
|
|
13
|
+
var radius: CGFloat
|
|
14
|
+
|
|
15
|
+
public init(source: String = "",
|
|
16
|
+
type: String = "image",
|
|
17
|
+
useBackground : Bool = true,
|
|
18
|
+
useShadow: Bool = true,
|
|
19
|
+
useBorder : Bool = true,
|
|
20
|
+
backgroundColor: Color = Colors.black01,
|
|
21
|
+
shadowColor : Color = Color(hex: "d9d9d9"),
|
|
22
|
+
borderColor : Color = Color(hex: "e2e2e2")){
|
|
23
|
+
self.type = type
|
|
24
|
+
self.useShadow = useShadow
|
|
25
|
+
self.useBorder = useBorder
|
|
26
|
+
self.useBackground = useBackground
|
|
27
|
+
self.backgroundColor = backgroundColor
|
|
28
|
+
self.borderColor = borderColor
|
|
29
|
+
self.source = source
|
|
30
|
+
self.shadowColor = shadowColor
|
|
31
|
+
self.radius = type == "image" ? 7 : 0
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
public var body: some View {
|
|
36
|
+
return ImageView(source)
|
|
37
|
+
.scaledToFit()
|
|
38
|
+
.frame(width: 28, height: 28)
|
|
39
|
+
.cornerRadius(radius)
|
|
40
|
+
.containerBorder(type, useBorder, borderColor)
|
|
41
|
+
.containerBackground(type, useBackground, backgroundColor)
|
|
42
|
+
.containerShadow(useShadow, shadowColor)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
private extension View {
|
|
48
|
+
func containerBorder (_ type: String, _ useBorder: Bool, _ borderColor: Color) -> some View {
|
|
49
|
+
Group {
|
|
50
|
+
if (useBorder && type != "icon") {
|
|
51
|
+
self.overlay(RoundedRectangle(cornerRadius: 8).stroke(borderColor, lineWidth: 1))
|
|
52
|
+
} else {
|
|
53
|
+
self
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
func containerBackground (_ type: String, _ useBackground: Bool, _ backgroundColor: Color) -> some View {
|
|
58
|
+
Group {
|
|
59
|
+
if (useBackground && type != "icon") {
|
|
60
|
+
self.background(backgroundColor)
|
|
61
|
+
} else {
|
|
62
|
+
self
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
func containerShadow (_ useShadow: Bool, _ shadowColor: Color) -> some View {
|
|
67
|
+
Group {
|
|
68
|
+
if useShadow {
|
|
69
|
+
self.shadow(color: shadowColor, radius: 2, x: 0, y: 2)
|
|
70
|
+
} else {
|
|
71
|
+
self
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
//
|
|
2
|
+
// TrustBanner.swift
|
|
3
|
+
// MoMoUIKits
|
|
4
|
+
//
|
|
5
|
+
// Created by Nguyễn Hoàng Sơn on 14/12/2023.
|
|
6
|
+
//
|
|
7
|
+
|
|
8
|
+
import Foundation
|
|
9
|
+
import SwiftUI
|
|
10
|
+
import SDWebImageSwiftUI
|
|
11
|
+
|
|
12
|
+
let jsonUrl = "https://static.momocdn.net/app/json/component-kits/design_system.json"
|
|
13
|
+
|
|
14
|
+
struct TrustBannerData: Decodable {
|
|
15
|
+
let trustBanner: TrustBanner
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
struct TrustBanner: Decodable {
|
|
19
|
+
let content: Dictionary<String, String>
|
|
20
|
+
let pciImage: String
|
|
21
|
+
let sslImage: String
|
|
22
|
+
let urlConfig: String
|
|
23
|
+
let featureCode: String
|
|
24
|
+
let icons: [String]
|
|
25
|
+
let momoImage: String
|
|
26
|
+
|
|
27
|
+
enum CodingKeys: String, CodingKey {
|
|
28
|
+
case content, pciImage, sslImage, icons, momoImage
|
|
29
|
+
case urlConfig = "url_config"
|
|
30
|
+
case featureCode = "feature_code"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
let defaultBanner = TrustBanner(
|
|
35
|
+
content: ["vi": "Bảo mật thông tin & An toàn tài sản của bạn là ưu tiên hàng đầu của MoMo.",
|
|
36
|
+
"en": "Your data security and money safety are MoMo's top priorities."],
|
|
37
|
+
pciImage: "https://static.momocdn.net/app/img/kits/trustBanner/pci.png",
|
|
38
|
+
sslImage: "https://static.momocdn.net/app/img/kits/trustBanner/ssl.png",
|
|
39
|
+
urlConfig: "https://momo.vn/an-toan-bao-mat",
|
|
40
|
+
featureCode: "login_and_security",
|
|
41
|
+
icons: [
|
|
42
|
+
"https://static.momocdn.net/app/img/kits/trustBanner/ic_viettinbank.png",
|
|
43
|
+
"https://static.momocdn.net/app/img/kits/trustBanner/ic_agribank.png",
|
|
44
|
+
"https://static.momocdn.net/app/img/kits/trustBanner/ic_vietcombank.png",
|
|
45
|
+
"https://static.momocdn.net/app/img/kits/trustBanner/ic_bidv.png"
|
|
46
|
+
],
|
|
47
|
+
momoImage: "https://static.momocdn.net/app/img/kits/trustBanner/ic_momo_secu.png"
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
let defaultData = TrustBannerData(trustBanner: defaultBanner)
|
|
51
|
+
|
|
52
|
+
class TrustBannerViewModel: ObservableObject {
|
|
53
|
+
@Published var trustBanner: TrustBannerData?
|
|
54
|
+
|
|
55
|
+
init() {
|
|
56
|
+
fetchData(from: jsonUrl)
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
func fetchData(from urlString: String) {
|
|
60
|
+
guard let url = URL(string: urlString) else { return }
|
|
61
|
+
|
|
62
|
+
URLSession.shared.dataTask(with: url) { [weak self] data, response, error in
|
|
63
|
+
guard let self = self else { return }
|
|
64
|
+
|
|
65
|
+
if let error = error {
|
|
66
|
+
print("Data fetching error: \(error)")
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
guard let data = data else {
|
|
71
|
+
print("No data received")
|
|
72
|
+
return
|
|
73
|
+
}
|
|
74
|
+
do {
|
|
75
|
+
let decodedData = try JSONDecoder().decode(TrustBannerData.self, from: data)
|
|
76
|
+
DispatchQueue.main.async {
|
|
77
|
+
self.trustBanner = decodedData
|
|
78
|
+
}
|
|
79
|
+
} catch {
|
|
80
|
+
print("Decoding error: \(error)")
|
|
81
|
+
}
|
|
82
|
+
}.resume()
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
public struct TrustBannerView: View {
|
|
87
|
+
var serviceName: String? = ""
|
|
88
|
+
var screenName: String? = ""
|
|
89
|
+
var onPress: ((_ params: NSDictionary) -> Void)?
|
|
90
|
+
var trackEvent: ((_ eventName: String, _ params: NSDictionary) -> Void)?
|
|
91
|
+
var language: String?
|
|
92
|
+
|
|
93
|
+
@ObservedObject private var viewModel = TrustBannerViewModel()
|
|
94
|
+
|
|
95
|
+
public init(serviceName: String?,
|
|
96
|
+
screenName: String?,
|
|
97
|
+
onPress: ((_ params: NSDictionary) -> Void)?,
|
|
98
|
+
trackEvent: ((_ eventName: String,_ params: NSDictionary) -> Void)?, language: String? = "vi") {
|
|
99
|
+
if let trackEvent = trackEvent {
|
|
100
|
+
trackEvent("service_component_displayed", ["service_name": serviceName ?? "", "screen_name": screenName ?? "", "component_name": "logo_trust"])
|
|
101
|
+
}
|
|
102
|
+
self.onPress = onPress
|
|
103
|
+
self.trackEvent = trackEvent
|
|
104
|
+
self.screenName = screenName
|
|
105
|
+
self.serviceName = serviceName
|
|
106
|
+
self.language = language
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
public var body: some View {
|
|
110
|
+
if let trustBanner = viewModel.trustBanner {
|
|
111
|
+
TrustBannerContentView(trustBanner: trustBanner.trustBanner, onPress: onPress, trackEvent: trackEvent, serviceName: serviceName, screenName: screenName, language: language)
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
struct TrustBannerContentView: View {
|
|
117
|
+
var trustBanner: TrustBanner
|
|
118
|
+
var onPress: ((_ params: NSDictionary) -> Void)?
|
|
119
|
+
var trackEvent: ((_ eventName: String, _ params: NSDictionary) -> Void)?
|
|
120
|
+
var serviceName: String?
|
|
121
|
+
var screenName: String?
|
|
122
|
+
var language: String?
|
|
123
|
+
|
|
124
|
+
var body: some View {
|
|
125
|
+
GeometryReader { geo in
|
|
126
|
+
HStack(alignment: .center, spacing: 8) {
|
|
127
|
+
WebImage(url: URL(string: trustBanner.momoImage))
|
|
128
|
+
.resizable()
|
|
129
|
+
.scaledToFit()
|
|
130
|
+
.frame(width: 64, height: 64)
|
|
131
|
+
VStack(alignment: .leading, spacing: 8){
|
|
132
|
+
Text(trustBanner.content[language ?? "vi"] ?? "")
|
|
133
|
+
.foregroundColor(Color(hex: 0xFF484848))
|
|
134
|
+
.lineLimit(2)
|
|
135
|
+
.font(.system(size: 12, weight: Font.Weight.regular))
|
|
136
|
+
.frame(width: geo.size.width - 24 - 64 - 8, height: 40,alignment: .leading)
|
|
137
|
+
HStack{
|
|
138
|
+
HStack{
|
|
139
|
+
WebImage(url: URL(string: trustBanner.pciImage))
|
|
140
|
+
.resizable()
|
|
141
|
+
.scaledToFit()
|
|
142
|
+
.frame(width: 52, height: 20)
|
|
143
|
+
WebImage(url: URL(string: trustBanner.sslImage))
|
|
144
|
+
.resizable()
|
|
145
|
+
.scaledToFit()
|
|
146
|
+
.frame(width: 52, height: 20)
|
|
147
|
+
}
|
|
148
|
+
Spacer()
|
|
149
|
+
HStack(spacing: -6){
|
|
150
|
+
ForEach(trustBanner.icons, id: \.self) { iconURL in
|
|
151
|
+
WebImage(url: URL(string: iconURL))
|
|
152
|
+
.resizable()
|
|
153
|
+
.scaledToFit()
|
|
154
|
+
.frame(width:24, height: 24)
|
|
155
|
+
.background(Color.white)
|
|
156
|
+
.cornerRadius(12)
|
|
157
|
+
.overlay(
|
|
158
|
+
Circle().stroke(Color(hex: 0xFFE8E8E8), lineWidth: 1)
|
|
159
|
+
)
|
|
160
|
+
}
|
|
161
|
+
Text("36+")
|
|
162
|
+
.font(.system(size: 10, weight: Font.Weight.regular))
|
|
163
|
+
.frame(width: 24, height: 24, alignment: .center)
|
|
164
|
+
.foregroundColor(Color(hex: 0xFFEB2F96))
|
|
165
|
+
.background(Color(hex: 0xFFFDEAF4))
|
|
166
|
+
.cornerRadius(12)
|
|
167
|
+
.overlay(
|
|
168
|
+
Circle()
|
|
169
|
+
.stroke(Color(hex: 0xFFE8E8E8), lineWidth: 1)
|
|
170
|
+
)
|
|
171
|
+
}.frame(width: 96, height: 24)
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
.frame(width: geo.size.width - 24)
|
|
176
|
+
.padding(EdgeInsets(top: 12, leading: 12, bottom: 12, trailing: 12))
|
|
177
|
+
.background(Color(hex: 0xFFF2F8FF))
|
|
178
|
+
.cornerRadius(12)
|
|
179
|
+
.onTapGesture {
|
|
180
|
+
if let trackEvent = trackEvent {
|
|
181
|
+
trackEvent("service_component_clicked", ["service_name": self.serviceName ?? "", "screen_name": self.screenName ?? "", "component_name": "logo_trust", "url_config": trustBanner.urlConfig])
|
|
182
|
+
}
|
|
183
|
+
if let onPress = onPress {
|
|
184
|
+
onPress(["service_name": self.serviceName ?? "", "screen_name": self.screenName ?? "", "component_name": "logo_trust", "url_config": trustBanner.urlConfig, "feature_code": trustBanner.featureCode])
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
package/ios/native-kits.podspec
CHANGED
package/local.properties
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
## This file must *NOT* be checked into Version Control Systems,
|
|
2
|
+
# as it contains information specific to your local configuration.
|
|
3
|
+
#
|
|
4
|
+
# Location of the SDK. This is only used by Gradle.
|
|
5
|
+
# For customization when using a Version Control System, please read the
|
|
6
|
+
# header note.
|
|
7
|
+
#Mon Mar 04 18:29:01 ICT 2024
|
|
8
|
+
sdk.dir=/Users/wem/Library/Android/sdk
|