@momo-kits/native-kits 0.113.3-webview.2 → 0.114.1-beta.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.
@@ -10,9 +10,9 @@ public struct SwipeCellModifier: ViewModifier {
10
10
  var trailingSideGroup: [SwipeCellActionItem] = []
11
11
  @Binding var currentUserInteractionCellID: String?
12
12
  var settings: SwipeCellSettings = .init()
13
-
13
+
14
14
  @State private var offsetX: CGFloat = 0
15
-
15
+
16
16
  let generator = UINotificationFeedbackGenerator()
17
17
  @State private var hapticFeedbackOccurred: Bool = false
18
18
  @State private var openSideLock: SwipeGroupSide?
@@ -22,15 +22,23 @@ public struct SwipeCellModifier: ViewModifier {
22
22
  if self.leadingSideGroup.isEmpty == false && self.offsetX != 0 {
23
23
  self.swipeToRevealArea(swipeItemGroup: self.leadingSideGroup, side: .leading)
24
24
  }
25
-
25
+
26
26
  if self.trailingSideGroup.isEmpty == false && self.offsetX != 0 {
27
27
  self.swipeToRevealArea(swipeItemGroup: self.trailingSideGroup, side: .trailing)
28
28
  }
29
-
29
+
30
30
  content
31
31
  .offset(x: self.offsetX)
32
- .gesture(DragGesture(minimumDistance: 30, coordinateSpace: .local).onChanged(self.dragOnChanged(value:)).onEnded(dragOnEnded(value:)))
33
-
32
+ .simultaneousGesture(
33
+ DragGesture(minimumDistance: 30, coordinateSpace: .local)
34
+ .onChanged { value in
35
+ self.dragOnChanged(value: value)
36
+ }
37
+ .onEnded { value in
38
+ self.dragOnEnded(value: value)
39
+ }
40
+ )
41
+
34
42
  }.frame(width: cellWidth)
35
43
  .edgesIgnoringSafeArea(.horizontal)
36
44
  .clipped()
@@ -43,7 +51,7 @@ public struct SwipeCellModifier: ViewModifier {
43
51
  }
44
52
  }
45
53
  }
46
-
54
+
47
55
  internal func swipeToRevealArea(swipeItemGroup: [SwipeCellActionItem], side: SwipeGroupSide)->some View {
48
56
  HStack {
49
57
  if side == .trailing {
@@ -63,17 +71,17 @@ public struct SwipeCellModifier: ViewModifier {
63
71
  }
64
72
  }
65
73
  }.opacity(self.swipeRevealAreaOpacity(side: side))
66
-
74
+
67
75
  if side == .leading {
68
76
  Spacer()
69
77
  }
70
78
  }
71
79
  }
72
-
80
+
73
81
  internal func buttonContentView(item: SwipeCellActionItem, group: [SwipeCellActionItem], side: SwipeGroupSide)->some View {
74
82
  ZStack {
75
83
  item.backgroundColor
76
-
84
+
77
85
  HStack {
78
86
  if self.warnSwipeOutCondition(side: side, hasSwipeOut: item.swipeOutAction) && item.swipeOutButtonView != nil {
79
87
  item.swipeOutButtonView!()
@@ -81,28 +89,28 @@ public struct SwipeCellModifier: ViewModifier {
81
89
  item.buttonView()
82
90
  }
83
91
  }
84
-
92
+
85
93
  }.frame(width: self.itemButtonWidth(item: item, itemGroup: group, side: side))
86
94
  }
87
-
95
+
88
96
  internal func menuWidth(side: SwipeGroupSide)->CGFloat {
89
97
  switch side {
90
98
  case .leading:
91
99
  return self.leadingSideGroup.map { $0.buttonWidth }.reduce(0, +)
92
-
100
+
93
101
  case .trailing:
94
102
  return self.trailingSideGroup.map { $0.buttonWidth }.reduce(0, +)
95
103
  }
96
104
  }
97
-
105
+
98
106
  // MARK: drag gesture
99
-
107
+
100
108
  internal func dragOnChanged(value: DragGesture.Value) {
101
109
  let horizontalTranslation = value.translation.width
102
110
  if self.nonDraggableCondition(horizontalTranslation: horizontalTranslation) {
103
111
  return
104
112
  }
105
-
113
+
106
114
  if self.openSideLock != nil {
107
115
  // if one side is open, we need to add the menu width!
108
116
  let menuWidth = self.openSideLock == .leading ? self.menuWidth(side: .leading) : self.menuWidth(side: .trailing)
@@ -110,9 +118,9 @@ public struct SwipeCellModifier: ViewModifier {
110
118
  self.triggerHapticFeedbackIfNeeded(horizontalTranslation: horizontalTranslation)
111
119
  return
112
120
  }
113
-
121
+
114
122
  self.triggerHapticFeedbackIfNeeded(horizontalTranslation: horizontalTranslation)
115
-
123
+
116
124
  if horizontalTranslation > 8 || horizontalTranslation < -8 { // makes sure the swipe cell doesn't open too easily
117
125
  self.currentUserInteractionCellID = self.id
118
126
  self.offsetX = horizontalTranslation
@@ -120,11 +128,11 @@ public struct SwipeCellModifier: ViewModifier {
120
128
  self.offsetX = 0
121
129
  }
122
130
  }
123
-
131
+
124
132
  internal func nonDraggableCondition(horizontalTranslation: CGFloat)->Bool {
125
133
  return self.offsetX == 0 && (self.leadingSideGroup.isEmpty && horizontalTranslation > 0 || self.trailingSideGroup.isEmpty && horizontalTranslation < 0)
126
134
  }
127
-
135
+
128
136
  internal func dragOnEnded(value: DragGesture.Value) {
129
137
  let swipeOutTriggerValue = self.cellWidth * self.settings.swipeOutTriggerRatio
130
138
 
@@ -139,7 +147,7 @@ public struct SwipeCellModifier: ViewModifier {
139
147
  } else {
140
148
  self.lockSideMenu(side: .leading)
141
149
  }
142
-
150
+
143
151
  } else {
144
152
  // leading group emtpy
145
153
  self.setOffsetX(value: 0)
@@ -160,7 +168,7 @@ public struct SwipeCellModifier: ViewModifier {
160
168
  }
161
169
  }
162
170
  }
163
-
171
+
164
172
  internal func triggerHapticFeedbackIfNeeded(horizontalTranslation: CGFloat) {
165
173
  let side: SwipeGroupSide = horizontalTranslation > 0 ? .leading : .trailing
166
174
  let group = side == .leading ? self.leadingSideGroup : self.trailingSideGroup
@@ -170,7 +178,7 @@ public struct SwipeCellModifier: ViewModifier {
170
178
  self.hapticFeedbackOccurred = true
171
179
  }
172
180
  }
173
-
181
+
174
182
  internal func swipeOutItemWithHapticFeedback(group: [SwipeCellActionItem])->SwipeCellActionItem? {
175
183
  if let item = group.filter({ $0.swipeOutAction == true }).first {
176
184
  if item.swipeOutHapticFeedbackType != nil {
@@ -179,7 +187,7 @@ public struct SwipeCellModifier: ViewModifier {
179
187
  }
180
188
  return nil
181
189
  }
182
-
190
+
183
191
  internal func swipeOutAction(item: SwipeCellActionItem, sideFactor: CGFloat) {
184
192
  if item.swipeOutIsDestructive {
185
193
  let swipeOutWidth = cellWidth + 10
@@ -188,12 +196,12 @@ public struct SwipeCellModifier: ViewModifier {
188
196
  } else {
189
197
  self.setOffsetX(value: 0) // open side lock set in function!
190
198
  }
191
-
199
+
192
200
  DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
193
201
  item.actionCallback()
194
202
  }
195
203
  }
196
-
204
+
197
205
  internal func lockSideMenu(side: SwipeGroupSide) {
198
206
  self.setOffsetX(value: side.sideFactor * self.menuWidth(side: side))
199
207
  self.openSideLock = side
@@ -214,7 +222,7 @@ public struct SwipeCellModifier: ViewModifier {
214
222
  let dynamicButtonWidth = self.dynamicButtonWidth(item: item, itemCount: itemGroup.count, side: side)
215
223
  let triggerValue = self.cellWidth * settings.swipeOutTriggerRatio
216
224
  let swipeOutActionCondition = side == .leading ? self.offsetX > triggerValue : self.offsetX < -triggerValue
217
-
225
+
218
226
  if item.swipeOutAction && swipeOutActionCondition {
219
227
  return self.offsetX.magnitude + settings.addWidthMargin
220
228
  } else if swipeOutActionCondition && item.swipeOutAction == false && itemGroup.contains(where: { $0.swipeOutAction == true }) {
@@ -223,12 +231,12 @@ public struct SwipeCellModifier: ViewModifier {
223
231
  return dynamicButtonWidth
224
232
  }
225
233
  }
226
-
234
+
227
235
  internal func dynamicButtonWidth(item: SwipeCellActionItem, itemCount: Int, side: SwipeGroupSide)->CGFloat {
228
236
  let menuWidth = self.menuWidth(side: side)
229
237
  return (self.offsetX.magnitude + settings.addWidthMargin) * (item.buttonWidth / menuWidth)
230
238
  }
231
-
239
+
232
240
  internal func warnSwipeOutCondition(side: SwipeGroupSide, hasSwipeOut: Bool)->Bool {
233
241
  if hasSwipeOut == false {
234
242
  return false
@@ -236,11 +244,11 @@ public struct SwipeCellModifier: ViewModifier {
236
244
  let triggerValue = self.cellWidth * settings.swipeOutTriggerRatio
237
245
  return (side == .trailing && self.offsetX < -triggerValue) || (side == .leading && self.offsetX > triggerValue)
238
246
  }
239
-
247
+
240
248
  internal func swipeRevealAreaOpacity(side: SwipeGroupSide)->Double {
241
249
  switch side {
242
250
  case .leading:
243
-
251
+
244
252
  return self.offsetX > 5 ? 1 : 0
245
253
  case .trailing:
246
254
  return self.offsetX < -5 ? 1 : 0
@@ -11,179 +11,110 @@ import SDWebImageSwiftUI
11
11
 
12
12
  let jsonUrl = "https://static.momocdn.net/app/json/component-kits/design_system.json"
13
13
 
14
- struct TrustBannerData: Decodable {
15
- let trustBanner: TrustBanner
16
- }
17
-
18
- struct TrustBanner: Decodable {
19
- let content: Dictionary<String, String>
14
+ public struct TrustBannerData: Decodable {
15
+ let content: [String: String]
16
+ let subContent: [String: String]
20
17
  let pciImage: String
21
18
  let sslImage: String
22
19
  let urlConfig: String
23
- let featureCode: String
24
20
  let icons: [String]
25
21
  let momoImage: String
26
-
22
+
27
23
  enum CodingKeys: String, CodingKey {
28
- case content, pciImage, sslImage, icons, momoImage
24
+ case content
25
+ case subContent
26
+ case pciImage
27
+ case sslImage
28
+ case icons
29
+ case momoImage
29
30
  case urlConfig = "url_config"
30
- case featureCode = "feature_code"
31
31
  }
32
32
  }
33
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."],
34
+ let defaultBanner = TrustBannerData(
35
+ content: ["vi": "An toàn tài sản & Bảo mật thông tin của bạn là ưu tiên hàng đầu của MoMo.",
36
+ "en": "Ensuring financial security and data privacy is MoMo's highest priority."],
37
+ subContent: [
38
+ "vi": "Tìm hiểu thêm",
39
+ "en": "Learn more"
40
+ ],
37
41
  pciImage: "https://static.momocdn.net/app/img/kits/trustBanner/pci.png",
38
42
  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",
43
+ urlConfig: "login_and_security",
41
44
  icons: [
42
45
  "https://static.momocdn.net/app/img/kits/trustBanner/ic_viettinbank.png",
43
46
  "https://static.momocdn.net/app/img/kits/trustBanner/ic_agribank.png",
44
47
  "https://static.momocdn.net/app/img/kits/trustBanner/ic_vietcombank.png",
45
48
  "https://static.momocdn.net/app/img/kits/trustBanner/ic_bidv.png"
46
49
  ],
47
- momoImage: "https://static.momocdn.net/app/img/kits/trustBanner/ic_momo_secu.png"
50
+ momoImage: "https://static.momocdn.net/app/img/kits/trustBanner/ic_secu.png"
48
51
  )
49
52
 
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
- }
53
+ public struct TrustBanner: View {
54
+ @EnvironmentObject var applicationEnvironment: ApplicationEnvironment
55
+
56
+ var onPress: ((String)->Void)?
57
+
58
+ public init(onPress: ((String)->Void)?) {
102
59
  self.onPress = onPress
103
- self.trackEvent = trackEvent
104
- self.screenName = screenName
105
- self.serviceName = serviceName
106
- self.language = language
107
60
  }
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)
61
+
62
+ var language: String? = "vi"
63
+
64
+ func onPressSecurity() {
65
+ if (onPress != nil) {
66
+ onPress!(applicationEnvironment.config?.trustBanner?.urlConfig ?? defaultBanner.urlConfig)
112
67
  }
113
68
  }
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
69
 
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)
70
+
71
+ public var body: some View {
72
+ HStack(alignment: .center, spacing: 8) {
73
+ WebImage(url: URL(string: applicationEnvironment.config?.trustBanner?.momoImage ?? defaultBanner.momoImage))
74
+ .resizable()
75
+ .scaledToFit()
76
+ .frame(width: 64, height: 64)
77
+ VStack(alignment: .leading){
78
+ Text(applicationEnvironment.config?.trustBanner?.content[language ?? "vi"] as? String ?? defaultBanner.content[language ?? "vi"])
79
+ .foregroundColor(Color(hex: "484848"))
80
+ .lineLimit(2)
81
+ .font(.system(size: 13, weight: Font.Weight.regular))
82
+ .lineSpacing(3)
83
+ .padding(.bottom, 8)
84
+ HStack {
85
+ HStack(spacing: 0) {
86
+ Text(applicationEnvironment.config?.trustBanner?.subContent[language ?? "vi"] as? String ?? defaultBanner.subContent[language ?? "vi"])
87
+ .foregroundColor(Colors.pink03)
88
+ .font(.system(size: 13, weight: .bold))
89
+ .padding(.trailing, 4)
90
+
91
+ Icon(source: "arrow_chevron_right_small", color: Colors.pink03)
92
+ }.onTapGesture {
93
+ onPressSecurity()
94
+ }
95
+
96
+ Spacer()
137
97
  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)
98
+ WebImage(url: URL(string: applicationEnvironment.config?.trustBanner?.pciImage ?? defaultBanner.pciImage))
99
+ .resizable()
100
+ .scaledToFit()
101
+ .frame(width: 24, height: 20)
102
+ WebImage(url: URL(string: applicationEnvironment.config?.trustBanner?.sslImage ?? defaultBanner.sslImage))
103
+ .resizable()
104
+ .scaledToFit()
105
+ .frame(width: 52, height: 20)
172
106
  }
173
107
  }
108
+
174
109
  }
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
- }
110
+
111
+ }
112
+ .padding(.all, 12)
113
+ .background(Color(hex: "F2F8FF"))
114
+ .cornerRadius(12)
115
+ .onTapGesture {
116
+ onPressSecurity()
187
117
  }
118
+ .frame(maxWidth: UIScreen.main.bounds.size.width)
188
119
  }
189
120
  }
package/local.properties CHANGED
@@ -4,5 +4,5 @@
4
4
  # Location of the SDK. This is only used by Gradle.
5
5
  # For customization when using a Version Control System, please read the
6
6
  # header note.
7
- #Sun Mar 02 11:30:14 ICT 2025
8
- sdk.dir=/Users/nguyenhoangson/Library/Android/sdk
7
+ #Tue Apr 23 16:40:15 ICT 2024
8
+ sdk.dir=/Users/hung.dao1/Library/Android/sdk
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@momo-kits/native-kits",
3
- "version": "0.113.3-webview.2",
3
+ "version": "0.114.1-beta.1",
4
4
  "private": false,
5
5
  "dependencies": {},
6
6
  "devDependencies": {},