react-native-firework-sdk 1.7.1 → 1.9.0-beta.3

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 (139) hide show
  1. package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/FWVideoFeed.kt +0 -1
  2. package/android/src/main/java/com/fireworksdk/bridge/models/FWEventName.kt +1 -0
  3. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWVideoShoppingInterface.kt +1 -0
  4. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +11 -1
  5. package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +9 -0
  6. package/android/src/main/java/com/fireworksdk/bridge/utils/FWLanguageUtil.kt +0 -2
  7. package/android/src/main/java/com/fireworksdk/bridge/utils/FWVideoPlayerUtils.kt +1 -0
  8. package/ios/Components/StoryBlock.swift +6 -9
  9. package/ios/Components/StoryBlockManager.swift +4 -0
  10. package/ios/Components/VideoFeed.swift +14 -15
  11. package/ios/Components/VideoFeedConfiguration.swift +2 -0
  12. package/ios/Components/VideoFeedManager.m +2 -0
  13. package/ios/Components/VideoFeedManager.swift +4 -0
  14. package/ios/Components/VideoPlayerConfiguration.swift +1 -0
  15. package/ios/FireworkSdk-Bridging-Header.h +6 -0
  16. package/ios/FireworkSdk.xcodeproj/project.pbxproj +374 -200
  17. package/ios/Models/Common/FontInfo.swift +57 -0
  18. package/ios/Models/NativeToRN/FireworkEventName.swift +1 -0
  19. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.m +2 -0
  20. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +271 -107
  21. package/ios/Modules/FireworkSDKModule/FireworkSDKModule+EventTracking.swift +0 -2
  22. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.m +1 -0
  23. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +43 -12
  24. package/ios/Modules/LiveStream/LiveStreamModule.swift +5 -3
  25. package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +7 -2
  26. package/ios/Modules/Shopping/ShoppingModule.m +1 -1
  27. package/ios/Modules/Shopping/ShoppingModule.swift +72 -63
  28. package/ios/Utils/AppLanguage/Bundle+FWSwizzle.swift +58 -0
  29. package/ios/Utils/AppLanguage/FWAppLanguageManager.swift +118 -0
  30. package/ios/Utils/AppLanguage/FWLanguageUtil.swift +39 -0
  31. package/ios/Utils/AppLanguage/NumberFormatter+FWSwizzle.swift +25 -0
  32. package/ios/Utils/AppLanguage/UIImageView+FWSwizzle.swift +91 -0
  33. package/ios/Utils/AppLanguage/UILabel+FWSwizzle.swift +98 -0
  34. package/ios/Utils/AppLanguage/UITextField+FWSwizzle.swift +97 -0
  35. package/ios/Utils/AppLanguage/UITextView+FWSwizzle.swift +97 -0
  36. package/ios/Utils/AppLanguage/UIView+FWSwizzle.swift +38 -0
  37. package/ios/Utils/AppLanguage/UIViewController+FWSwizzle.swift +32 -0
  38. package/ios/Utils/AppLanguage/UIWindow+FWSwizzle.swift +26 -0
  39. package/ios/Utils/AppLanguage/URLSession+FWSwizzle.swift +69 -0
  40. package/ios/Utils/{DispatchQueue+FWOnce.swift → Extensions/DispatchQueue+FWOnce.swift} +3 -3
  41. package/ios/Utils/{UINavigationController+FWSwizzle.swift → Extensions/Swizzle/UINavigationController+FWSwizzle.swift} +6 -8
  42. package/ios/Utils/Extensions/UIView+FWUIHierarchy.swift +47 -0
  43. package/ios/Utils/FWRTL/Classes/Manager/FWRTLManager.h +25 -0
  44. package/ios/Utils/FWRTL/Classes/Manager/FWRTLManager.m +75 -0
  45. package/ios/Utils/FWRTL/Classes/UICategories/CALayer+FWRTL.h +21 -0
  46. package/ios/Utils/FWRTL/Classes/UICategories/CALayer+FWRTL.m +124 -0
  47. package/ios/Utils/FWRTL/Classes/UICategories/FWRTLRemoteViewControllerAdaptor.h +11 -0
  48. package/ios/Utils/FWRTL/Classes/UICategories/FWRTLRemoteViewControllerAdaptor.m +86 -0
  49. package/ios/Utils/FWRTL/Classes/UICategories/FWRTLWhiteListManager.h +16 -0
  50. package/ios/Utils/FWRTL/Classes/UICategories/FWRTLWhiteListManager.m +55 -0
  51. package/ios/Utils/FWRTL/Classes/UICategories/UILabel+FWRTL.h +18 -0
  52. package/ios/Utils/FWRTL/Classes/UICategories/UILabel+FWRTL.m +39 -0
  53. package/ios/Utils/FWRTL/Classes/UICategories/UIView+FWRTL.h +54 -0
  54. package/ios/Utils/FWRTL/Classes/UICategories/UIView+FWRTL.m +141 -0
  55. package/ios/Utils/FWRTL/Classes/UICategories/UIWindow+FWRTL.h +16 -0
  56. package/ios/Utils/FWRTL/Classes/UICategories/UIWindow+FWRTL.m +20 -0
  57. package/ios/Utils/FWRTL/Classes/Utils/FWRTLDefinitions.h +52 -0
  58. package/ios/Utils/FWRTL/Classes/Utils/NSObject+FWRTLReloadBlock.h +19 -0
  59. package/ios/Utils/FWRTL/Classes/Utils/NSObject+FWRTLReloadBlock.m +49 -0
  60. package/ios/Utils/FWRTL/Classes/Utils/NSString+FWRTL.h +21 -0
  61. package/ios/Utils/FWRTL/Classes/Utils/NSString+FWRTL.m +38 -0
  62. package/ios/Utils/FWRTL/Classes/Utils/UIImage+FWRTL.h +18 -0
  63. package/ios/Utils/FWRTL/Classes/Utils/UIImage+FWRTL.m +43 -0
  64. package/ios/Utils/FWSwizzleLoader.m +1 -2
  65. package/ios/Utils/FWSwizzleLoader.swift +13 -0
  66. package/ios/Utils/FWSwizzleUtil.swift +17 -9
  67. package/ios/react_native_firework_sdk.h +1 -0
  68. package/ios/scripts/firework_sdk_pods.rb +3 -0
  69. package/lib/commonjs/FWNavigator.js +32 -1
  70. package/lib/commonjs/FWNavigator.js.map +1 -1
  71. package/lib/commonjs/FireworkSDK.js +26 -12
  72. package/lib/commonjs/FireworkSDK.js.map +1 -1
  73. package/lib/commonjs/VideoShopping.js +64 -9
  74. package/lib/commonjs/VideoShopping.js.map +1 -1
  75. package/lib/commonjs/components/VideoFeed.js +26 -5
  76. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  77. package/lib/commonjs/index.js +6 -0
  78. package/lib/commonjs/index.js.map +1 -1
  79. package/lib/commonjs/models/FWEventName.js +2 -0
  80. package/lib/commonjs/models/FWEventName.js.map +1 -1
  81. package/lib/commonjs/models/IOSFontInfo.js +2 -0
  82. package/lib/commonjs/models/IOSFontInfo.js.map +1 -0
  83. package/lib/commonjs/modules/FWNavigatorModule.js.map +1 -1
  84. package/lib/commonjs/modules/ShoppingModule.js.map +1 -1
  85. package/lib/module/FWNavigator.js +31 -1
  86. package/lib/module/FWNavigator.js.map +1 -1
  87. package/lib/module/FireworkSDK.js +27 -11
  88. package/lib/module/FireworkSDK.js.map +1 -1
  89. package/lib/module/VideoShopping.js +63 -9
  90. package/lib/module/VideoShopping.js.map +1 -1
  91. package/lib/module/components/VideoFeed.js +21 -5
  92. package/lib/module/components/VideoFeed.js.map +1 -1
  93. package/lib/module/index.js +1 -1
  94. package/lib/module/index.js.map +1 -1
  95. package/lib/module/models/FWEventName.js +2 -0
  96. package/lib/module/models/FWEventName.js.map +1 -1
  97. package/lib/module/models/IOSFontInfo.js +2 -0
  98. package/lib/module/models/IOSFontInfo.js.map +1 -0
  99. package/lib/module/modules/FWNavigatorModule.js.map +1 -1
  100. package/lib/module/modules/ShoppingModule.js.map +1 -1
  101. package/lib/typescript/FWNavigator.d.ts +17 -2
  102. package/lib/typescript/FireworkSDK.d.ts +9 -5
  103. package/lib/typescript/LiveStream.d.ts +2 -2
  104. package/lib/typescript/VideoShopping.d.ts +33 -11
  105. package/lib/typescript/components/VideoFeed.d.ts +5 -1
  106. package/lib/typescript/index.d.ts +8 -4
  107. package/lib/typescript/models/AdBadgeConfiguration.d.ts +1 -1
  108. package/lib/typescript/models/FWEventName.d.ts +3 -1
  109. package/lib/typescript/models/FWEvents.d.ts +5 -0
  110. package/lib/typescript/models/IOSFontInfo.d.ts +19 -0
  111. package/lib/typescript/models/NewNativeContainerProps.d.ts +1 -1
  112. package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +23 -0
  113. package/lib/typescript/models/StoryBlockSource.d.ts +1 -1
  114. package/lib/typescript/models/VideoFeedConfiguration.d.ts +20 -2
  115. package/lib/typescript/models/VideoFeedSource.d.ts +1 -1
  116. package/lib/typescript/models/VideoPlayerConfiguration.d.ts +20 -4
  117. package/lib/typescript/modules/FWNavigatorModule.d.ts +2 -0
  118. package/lib/typescript/modules/ShoppingModule.d.ts +2 -1
  119. package/package.json +7 -4
  120. package/react-native-firework-sdk.podspec +15 -18
  121. package/src/{FWNavigator.tsx → FWNavigator.ts} +30 -2
  122. package/src/FireworkSDK.ts +24 -13
  123. package/src/VideoShopping.ts +86 -20
  124. package/src/components/VideoFeed.tsx +24 -2
  125. package/src/{index.tsx → index.ts} +24 -1
  126. package/src/models/FWEventName.ts +2 -0
  127. package/src/models/FWEvents.ts +6 -0
  128. package/src/models/IOSFontInfo.ts +29 -0
  129. package/src/models/ProductInfoViewConfiguration.ts +25 -0
  130. package/src/models/VideoFeedConfiguration.ts +20 -1
  131. package/src/models/VideoPlayerConfiguration.ts +17 -0
  132. package/src/modules/FWNavigatorModule.ts +2 -0
  133. package/src/modules/ShoppingModule.ts +2 -4
  134. package/ios/Utils/FWPiPManager.swift +0 -24
  135. package/ios/Utils/UIButton+FWSwizzle.swift +0 -33
  136. package/ios/Utils/UIView+ParentViewController.swift +0 -21
  137. /package/ios/Utils/{String+Color.swift → Extensions/String+Color.swift} +0 -0
  138. /package/ios/Utils/{UIView+Constraints.swift → Extensions/UIView+Constraints.swift} +0 -0
  139. /package/ios/Utils/{UIViewController+AttachChild.swift → Extensions/UIViewController+AttachChild.swift} +0 -0
@@ -0,0 +1,57 @@
1
+ //
2
+ // FontInfo.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/27.
5
+ //
6
+
7
+ import UIKit
8
+
9
+ @objc
10
+ public class FontInfo: NSObject, Codable {
11
+ var fontName: String?
12
+ var systemFontStyle: SystemFontStyle?
13
+ var systemFontWeight: SystemFontWeight?
14
+
15
+ public enum SystemFontStyle: String, Codable {
16
+ case normal, italic
17
+ }
18
+
19
+ public enum SystemFontWeight: String, Codable {
20
+ case ultraLight, thin, light, regular, medium, semibold, bold, heavy, black
21
+
22
+ func getFontWeight() -> UIFont.Weight {
23
+ switch self {
24
+ case .ultraLight:
25
+ return .ultraLight
26
+ case .thin:
27
+ return .thin
28
+ case .light:
29
+ return .light
30
+ case .regular:
31
+ return .regular
32
+ case .medium:
33
+ return .medium
34
+ case .semibold:
35
+ return .semibold
36
+ case .bold:
37
+ return .bold
38
+ case .heavy:
39
+ return .heavy
40
+ case .black:
41
+ return .black
42
+ }
43
+ }
44
+ }
45
+
46
+ public func getFont(_ fontSize: Double) -> UIFont {
47
+ if let fontName = fontName, let font = UIFont(name: fontName, size: fontSize) {
48
+ return font
49
+ } else if let fontStyle = systemFontStyle, fontStyle == .italic {
50
+ return UIFont.italicSystemFont(ofSize: fontSize)
51
+ } else if let systemFontWeight = systemFontWeight?.getFontWeight() {
52
+ return UIFont.systemFont(ofSize: fontSize, weight: systemFontWeight)
53
+ } else {
54
+ return UIFont.systemFont(ofSize: fontSize)
55
+ }
56
+ }
57
+ }
@@ -15,6 +15,7 @@ enum FWEventName: String, CaseIterable {
15
15
  case videoFeedClick = "fw:video-feed-click"
16
16
  case shareBaseURLUpdated = "fw:share-base-url-updated" // emitted in JS side
17
17
  case adBadgeConfigurationUpdated = "fw:ad-badge-configuration-updated" // emitted in JS side
18
+ case appLanguageUpdated = "fw:app-language-updated" // emitted in JS side
18
19
  case logMessage = "fw:log-message"
19
20
  }
20
21
 
@@ -14,5 +14,7 @@
14
14
  RCT_EXTERN_METHOD(pushNativeContainer:(NSDictionary *)props resolver:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
15
15
  RCT_EXTERN_METHOD(popNativeContainer:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
16
16
  RCT_EXTERN_METHOD(canPopNativeContainer:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
17
+ RCT_EXTERN_METHOD(startFloatingPlayer:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
18
+ RCT_EXTERN_METHOD(stopFloatingPlayer:(RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
17
19
 
18
20
  @end
@@ -7,6 +7,19 @@
7
7
 
8
8
  import FireworkVideo
9
9
 
10
+ private let FWExitButtonImageNames: [String] = [
11
+ "closeX",
12
+ "down-arrow-light",
13
+ ]
14
+
15
+ private struct PlayerInfo {
16
+ enum PlayerMode: Int {
17
+ case fullscreen, floating
18
+ }
19
+ var playerVC: PlayerViewController
20
+ var mode: PlayerMode
21
+ }
22
+
10
23
  @objc(FWNavigatorModule)
11
24
  class FWNavigatorModule: RCTEventEmitter, FWNavigator {
12
25
  override func supportedEvents() -> [String]! {
@@ -17,6 +30,10 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
17
30
  return true
18
31
  }
19
32
 
33
+ override var methodQueue: DispatchQueue {
34
+ return DispatchQueue.main
35
+ }
36
+
20
37
  // swiftlint:disable function_body_length
21
38
 
22
39
  @objc(pushNativeContainer:resolver:rejecter:)
@@ -34,139 +51,120 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
34
51
  ])
35
52
  #endif
36
53
 
37
- DispatchQueue.main.async {
38
- guard let props = props as? [String: Any] else {
39
- resolver(false)
40
- return
41
- }
54
+ guard let props = props as? [String: Any] else {
55
+ resolver(false)
56
+ return
57
+ }
42
58
 
43
- guard let appComponentName = gAppComponentName, appComponentName.count > 0 else {
44
- resolver(false)
45
- return
46
- }
59
+ guard let appComponentName = gAppComponentName, appComponentName.count > 0 else {
60
+ resolver(false)
61
+ return
62
+ }
47
63
 
48
- guard let presentedVC = RCTPresentedViewController() else {
49
- resolver(false)
50
- return
51
- }
64
+ guard let presentedVC = RCTPresentedViewController() else {
65
+ resolver(false)
66
+ return
67
+ }
52
68
 
53
- #if DEBUG
54
- self.sendEvent(
55
- withName: FWEventName.logMessage.rawValue,
56
- body: [
57
- "message":
58
- "[iOS] Before creating containerViewController \(formatter.string(from: Date()))"
59
- ])
60
- #endif
69
+ #if DEBUG
70
+ self.sendEvent(
71
+ withName: FWEventName.logMessage.rawValue,
72
+ body: [
73
+ "message":
74
+ "[iOS] Before creating containerViewController \(formatter.string(from: Date()))"
75
+ ])
76
+ #endif
61
77
 
62
- let containerViewController = FWNavigatorContainerViewController()
78
+ let containerViewController = FWNavigatorContainerViewController()
63
79
 
64
- #if DEBUG
65
- self.sendEvent(
66
- withName: FWEventName.logMessage.rawValue,
67
- body: [
68
- "message":
69
- "[iOS] After creating containerViewController \(formatter.string(from: Date()))"
70
- ])
71
- #endif
80
+ #if DEBUG
81
+ self.sendEvent(
82
+ withName: FWEventName.logMessage.rawValue,
83
+ body: [
84
+ "message":
85
+ "[iOS] After creating containerViewController \(formatter.string(from: Date()))"
86
+ ])
87
+ #endif
72
88
 
73
- containerViewController.moduleName = appComponentName
74
- containerViewController.properties = props
75
- containerViewController.modalPresentationStyle = .fullScreen
76
- if presentedVC.modalPresentationStyle == .custom,
77
- let presentingVC = presentedVC.presentingViewController,
78
- presentingVC is FireworkVideo.PlayerViewController
79
- {
80
- containerViewController.modalPresentationStyle = .overFullScreen
81
- }
89
+ containerViewController.moduleName = appComponentName
90
+ containerViewController.properties = props
91
+ containerViewController.modalPresentationStyle = .fullScreen
92
+ if presentedVC.modalPresentationStyle == .custom,
93
+ let presentingVC = presentedVC.presentingViewController,
94
+ presentingVC is FireworkVideo.PlayerViewController
95
+ {
96
+ containerViewController.modalPresentationStyle = .overFullScreen
97
+ }
98
+
99
+ #if DEBUG
100
+ self.sendEvent(
101
+ withName: FWEventName.logMessage.rawValue,
102
+ body: [
103
+ "message":
104
+ "[iOS] Present containerViewController \(formatter.string(from: Date()))"
105
+ ])
106
+ #endif
82
107
 
108
+ presentedVC.present(containerViewController, animated: true) {
83
109
  #if DEBUG
84
110
  self.sendEvent(
85
111
  withName: FWEventName.logMessage.rawValue,
86
112
  body: [
87
113
  "message":
88
- "[iOS] Present containerViewController \(formatter.string(from: Date()))"
114
+ "[iOS] Finish presenting containerViewController \(formatter.string(from: Date()))"
89
115
  ])
90
116
  #endif
91
117
 
92
- presentedVC.present(containerViewController, animated: true) {
93
- #if DEBUG
94
- self.sendEvent(
95
- withName: FWEventName.logMessage.rawValue,
96
- body: [
97
- "message":
98
- "[iOS] Finish presenting containerViewController \(formatter.string(from: Date()))"
99
- ])
100
- #endif
101
-
102
- resolver(true)
103
- }
118
+ resolver(true)
104
119
  }
105
120
  }
106
121
 
107
- func getCloseButton(view: UIView) -> UIButton? {
108
- if let button = view as? UIButton, let targetImage = button.image(for: .normal) {
109
- let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
110
- if targetImage.isEqual(UIImage(named: "closeX", in: iOSSDKBundle, compatibleWith: nil))
111
- || targetImage.isEqual(UIImage(named: "down-arrow-light", in: iOSSDKBundle, compatibleWith: nil)) {
112
- return button
113
- }
114
- }
115
-
116
- for subview in view.subviews {
117
- if let result = getCloseButton(view: subview) {
118
- return result
119
- }
120
- }
121
-
122
- return nil
123
- }
124
-
125
122
  // swiftlint:enable function_body_length
126
123
 
127
124
  @objc(popNativeContainer:rejecter:)
128
125
  func popNativeContainer(
129
126
  _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
130
127
  ) {
131
- DispatchQueue.main.async {
132
- if let navigatorContainerVC = RCTPresentedViewController()
133
- as? FWNavigatorContainerViewController,
134
- navigatorContainerVC.presentingViewController != nil {
135
- navigatorContainerVC.dismiss(animated: true) {
136
- resolver(true)
137
- }
138
- } else if let cartViewController = gCartViewController {
139
- cartViewController.navigationController?.popViewController(animated: true)
140
- gCartViewController = nil
128
+ if let navigatorContainerVC = RCTPresentedViewController()
129
+ as? FWNavigatorContainerViewController,
130
+ navigatorContainerVC.presentingViewController != nil {
131
+ navigatorContainerVC.dismiss(animated: true) {
141
132
  resolver(true)
142
- } else if let presentedVC = RCTPresentedViewController(),
143
- let presentingVC = presentedVC.presentingViewController,
144
- presentingVC.presentingViewController == RCTKeyWindow()?.rootViewController {
145
- presentedVC.dismiss(animated: false) {
146
- DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.1) {
147
- if let closeButton = self.getCloseButton(view: presentingVC.view) {
148
- closeButton.sendActions(for: .touchUpInside)
133
+ }
134
+ } else if let cartViewController = gCartViewController {
135
+ cartViewController.navigationController?.popViewController(animated: true)
136
+ gCartViewController = nil
137
+ resolver(true)
138
+ } else if let presentedVC = RCTPresentedViewController(),
139
+ FWNavigatorModule.isIOSSDKViewController(presentedVC),
140
+ let presentingVC = presentedVC.presentingViewController,
141
+ presentingVC.presentingViewController == RCTKeyWindow()?.rootViewController,
142
+ FWNavigatorModule.isIOSSDKViewController(presentingVC) {
143
+ presentedVC.dismiss(animated: false) {
144
+ DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.1) {
145
+ if let closeButton = FWNavigatorModule.getExitButton(view: presentingVC.view) {
146
+ closeButton.sendActions(for: .touchUpInside)
147
+ resolver(true)
148
+ } else {
149
+ presentingVC.dismiss(animated: true) {
149
150
  resolver(true)
150
- } else {
151
- presentingVC.dismiss(animated: true) {
152
- resolver(true)
153
- }
154
151
  }
155
152
  }
156
153
  }
157
- } else if let rootVC = RCTKeyWindow()?.rootViewController,
158
- let presentedVC = rootVC.presentedViewController {
159
- if let closeButton = self.getCloseButton(view: presentedVC.view) {
160
- closeButton.sendActions(for: .touchUpInside)
154
+ }
155
+ } else if let rootVC = RCTKeyWindow()?.rootViewController,
156
+ let presentedVC = rootVC.presentedViewController,
157
+ FWNavigatorModule.isIOSSDKViewController(presentedVC) {
158
+ if let closeButton = FWNavigatorModule.getExitButton(view: presentedVC.view) {
159
+ closeButton.sendActions(for: .touchUpInside)
160
+ resolver(true)
161
+ } else {
162
+ presentedVC.dismiss(animated: true) {
161
163
  resolver(true)
162
- } else {
163
- presentedVC.dismiss(animated: true) {
164
- resolver(true)
165
- }
166
164
  }
167
- } else {
168
- resolver(false)
169
165
  }
166
+ } else {
167
+ resolver(false)
170
168
  }
171
169
  }
172
170
 
@@ -174,15 +172,181 @@ class FWNavigatorModule: RCTEventEmitter, FWNavigator {
174
172
  func canPopNativeContainer(
175
173
  _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
176
174
  ) {
177
- DispatchQueue.main.async {
178
- if let presentedVC = RCTPresentedViewController(),
179
- presentedVC.presentingViewController != nil {
180
- resolver(true)
181
- } else if gCartViewController != nil {
175
+ if let presentedVC = RCTPresentedViewController(),
176
+ presentedVC.presentingViewController != nil {
177
+ resolver(true)
178
+ } else if gCartViewController != nil {
179
+ resolver(true)
180
+ } else {
181
+ resolver(false)
182
+ }
183
+ }
184
+
185
+ @objc(startFloatingPlayer:rejecter:)
186
+ func startFloatingPlayer(
187
+ _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
188
+ ) {
189
+ guard let playerInfo = FWNavigatorModule.getPlayerInfo() else {
190
+ resolver(false)
191
+ return
192
+ }
193
+
194
+ if playerInfo.mode == .fullscreen {
195
+ do {
196
+ try playerInfo.playerVC.startPictureInPicture()
182
197
  resolver(true)
183
- } else {
198
+ } catch {
184
199
  resolver(false)
185
200
  }
201
+ } else {
202
+ // current player is already in floating mode.
203
+ resolver(false)
204
+ }
205
+ }
206
+
207
+ @objc(stopFloatingPlayer:rejecter:)
208
+ func stopFloatingPlayer(
209
+ _ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
210
+ ) {
211
+ let result = FWNavigatorModule.stopFloatingPlayer()
212
+ resolver(result)
213
+ }
214
+ }
215
+
216
+ extension FWNavigatorModule {
217
+ private static func getExitButton(view: UIView) -> UIButton? {
218
+ if let button = view as? UIButton, let image = button.image(for: .normal) {
219
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
220
+ for imageName in FWExitButtonImageNames {
221
+ let targetImage = UIImage(named: imageName, in: iOSSDKBundle, compatibleWith: nil)
222
+ if image.isEqual(targetImage) {
223
+ return button
224
+ }
225
+
226
+ if let cgImage = image.cgImage,
227
+ let targetCgImage = targetImage?.cgImage,
228
+ cgImage == targetCgImage {
229
+ return button
230
+ }
231
+
232
+ if let ciImage = image.ciImage,
233
+ let targetCiImage = targetImage?.ciImage,
234
+ ciImage == targetCiImage {
235
+ return button
236
+ }
237
+ }
238
+ }
239
+
240
+ for subview in view.subviews {
241
+ if let result = getExitButton(view: subview) {
242
+ return result
243
+ }
244
+ }
245
+
246
+ return nil
247
+ }
248
+
249
+ private static func getWindowList() -> [UIWindow] {
250
+ var windowList: [UIWindow] = []
251
+ if #available(iOS 13.0, *) {
252
+ for scene in UIApplication.shared.connectedScenes {
253
+ if let currentSene = scene as? UIWindowScene {
254
+ for window in currentSene.windows {
255
+ windowList.append(window)
256
+ }
257
+ }
258
+ }
259
+ } else {
260
+ for window in UIApplication.shared.windows {
261
+ windowList.append(window)
262
+ }
263
+ }
264
+
265
+ return windowList
266
+ }
267
+
268
+ private static func getFurthestAncestorController(_ controller: UIViewController) -> UIViewController {
269
+ guard let parentVC = controller.parent else {
270
+ return controller
271
+ }
272
+
273
+ return getFurthestAncestorController(parentVC)
274
+ }
275
+
276
+ private static func getPlayerViewController(_ viewController: UIViewController) -> PlayerViewController? {
277
+ if let playerVC = viewController as? PlayerViewController {
278
+ return playerVC
279
+ }
280
+
281
+ for childVC in viewController.children {
282
+ if let playerVC = getPlayerViewController(childVC) {
283
+ return playerVC
284
+ }
285
+ }
286
+
287
+ return nil
288
+ }
289
+
290
+ private static func getPlayerInfo() -> PlayerInfo? {
291
+ let windowList: [UIWindow] = getWindowList()
292
+
293
+ if let floatingPlayerWindow = windowList.first(where: { window in
294
+ NSStringFromClass(type(of: window)) == "FireworkVideo.FloatingPlayerController"
295
+ }) {
296
+ if let rootVC = floatingPlayerWindow.rootViewController,
297
+ let playerVC = getPlayerViewController(rootVC) {
298
+ return PlayerInfo(playerVC: playerVC, mode: .floating)
299
+ }
300
+ return nil
301
+ }
302
+
303
+ if let keyWindow = windowList.first(where: { window in
304
+ return window.isKeyWindow
305
+ }) {
306
+ if let rootVC = keyWindow.rootViewController,
307
+ let presentedVC = rootVC.presentedViewController {
308
+ let furthestAncestorController = getFurthestAncestorController(presentedVC)
309
+ if let playerVC = getPlayerViewController(furthestAncestorController) {
310
+ return PlayerInfo(playerVC: playerVC, mode: .fullscreen)
311
+ }
312
+ }
313
+
314
+ return nil
315
+ }
316
+
317
+ return nil
318
+ }
319
+
320
+ private static func isIOSSDKViewController(_ controller: UIViewController?) -> Bool {
321
+ guard let controller = controller else {
322
+ return false
323
+ }
324
+
325
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
326
+ if Bundle(for: type(of: controller)) == iOSSDKBundle {
327
+ return true
328
+ }
329
+
330
+ return isIOSSDKViewController(controller.parent)
331
+ }
332
+ }
333
+
334
+ extension FWNavigatorModule {
335
+ static func stopFloatingPlayer() -> Bool {
336
+ guard let playerInfo = self.getPlayerInfo() else {
337
+ return false
338
+ }
339
+
340
+ if playerInfo.mode == .floating {
341
+ do {
342
+ try playerInfo.playerVC.stopPictureInPicture()
343
+ return true
344
+ } catch {
345
+ return false
346
+ }
347
+ } else {
348
+ // current player is in fullscreen player
349
+ return false
186
350
  }
187
351
  }
188
352
  }
@@ -127,7 +127,5 @@ extension FireworkSDKModule: FireworkVideoFeedDelegate {
127
127
 
128
128
  sendEvent(
129
129
  withName: FWEventName.videoFeedClick.rawValue, body: ["info": eventDetails.jsObject])
130
-
131
- FWPiPManager.shared.removeAllPiPControllers()
132
130
  }
133
131
  }
@@ -19,5 +19,6 @@ RCT_EXTERN_METHOD(setVideoPlaybackEventEnabled:(BOOL)enabled)
19
19
  RCT_EXTERN_METHOD(setAdBadgeConfiguration:(NSDictionary *)config resolver: (RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
20
20
  RCT_EXTERN_METHOD(setAppComponentName:(NSString *)name resolver: (RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
21
21
  RCT_EXTERN_METHOD(trackPurchase:(NSDictionary *)parameters)
22
+ RCT_EXTERN_METHOD(changeAppLanguage:(NSString *)language resolver: (RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
22
23
 
23
24
  @end
@@ -30,11 +30,27 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
30
30
  return true
31
31
  }
32
32
 
33
+ override var methodQueue: DispatchQueue {
34
+ return DispatchQueue.main
35
+ }
36
+
33
37
  @objc(initializeSDK:)
34
38
  func initializeSDK(_ userId: String? = nil) {
35
39
  #if DEBUG
36
40
  let formatter = DateFormatter()
37
41
  formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
42
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
43
+
44
+ let messageForLocalizations = """
45
+ [iOS] localizations information \(formatter.string(from: Date()))
46
+ AppleLanguages: \((UserDefaults.standard.object(forKey: "AppleLanguages") as? [String]) ?? [])
47
+ Bundle.main.localizations \(Bundle.main.localizations)
48
+ Bundle.main.preferredLocalizations \(Bundle.main.preferredLocalizations)
49
+ iOSSDKBundle.localizations \(iOSSDKBundle.localizations)
50
+ iOSSDKBundle.preferredLocalizations \(iOSSDKBundle.preferredLocalizations)
51
+ """
52
+ print("[react-native-firework-sdk] [swift] \(messageForLocalizations)")
53
+ sendEvent(withName: FWEventName.logMessage.rawValue, body: ["message": messageForLocalizations])
38
54
 
39
55
  let message = "[iOS] Call initializeSDK \(formatter.string(from: Date()))"
40
56
  print("[react-native-firework-sdk] [swift] \(message)")
@@ -42,12 +58,10 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
42
58
  sendEvent(withName: FWEventName.logMessage.rawValue, body: ["message": message])
43
59
  #endif
44
60
 
45
- DispatchQueue.main.async {
46
- FireworkVideoSDK.initializeSDK(delegate: self, userID: userId)
47
- FireworkVideoSDK.ctaDelegate = self
48
- FireworkVideoSDK.eventTracking.videoPlaybackDelegate = self
49
- FireworkVideoSDK.eventTracking.feedDelegate = self
50
- }
61
+ FireworkVideoSDK.initializeSDK(delegate: self, userID: userId)
62
+ FireworkVideoSDK.ctaDelegate = self
63
+ FireworkVideoSDK.eventTracking.videoPlaybackDelegate = self
64
+ FireworkVideoSDK.eventTracking.feedDelegate = self
51
65
  }
52
66
 
53
67
  @objc(openVideoPlayer:config:)
@@ -67,14 +81,12 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
67
81
  feedContentConfig.adBadge = adBadge
68
82
  }
69
83
 
70
- DispatchQueue.main.async {
71
- guard let presentedVC = RCTPresentedViewController() else {
72
- return
73
- }
84
+ guard let presentedVC = RCTPresentedViewController() else {
85
+ return
86
+ }
74
87
 
75
- VideoFeedViewController.openVideoPlayer(with: urlString, feedContentConfig, presentedVC) { _ in
88
+ VideoFeedViewController.openVideoPlayer(with: urlString, feedContentConfig, presentedVC) { _ in
76
89
 
77
- }
78
90
  }
79
91
  }
80
92
 
@@ -147,6 +159,25 @@ class FireworkSDKModule: RCTEventEmitter, FireworkVideoSDKDelegate {
147
159
  )
148
160
  }
149
161
 
162
+ @objc(changeAppLanguage:resolver:rejecter:)
163
+ func changeAppLanguage(
164
+ _ language: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock
165
+ ) {
166
+ #if DEBUG
167
+ let formatter = DateFormatter()
168
+ formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
169
+ let message = "[iOS] Call changeAppLanguage: \(language) \(formatter.string(from: Date()))"
170
+ sendEvent(withName: FWEventName.logMessage.rawValue, body: ["message": message])
171
+ #endif
172
+
173
+ DispatchQueue.main.async {
174
+ let result = FWAppLanguageManager.shared.changeAppLanguage(language)
175
+ resolver(result)
176
+
177
+ FWRTLManager.sharedInstance().enableHorizontalFlip = FWAppLanguageManager.shared.shouldHorizontalFlip
178
+ }
179
+ }
180
+
150
181
  // MARK: - FireworkVideoSDKDelegate
151
182
  func fireworkVideoDidLoadSuccessfully() {
152
183
  #if DEBUG
@@ -19,11 +19,13 @@ class LiveStreamModule: RCTEventEmitter, FireworkLiveStreamEventDelegate {
19
19
  return true
20
20
  }
21
21
 
22
+ override var methodQueue: DispatchQueue {
23
+ return DispatchQueue.main
24
+ }
25
+
22
26
  @objc
23
27
  func initialize() {
24
- DispatchQueue.main.async {
25
- FireworkVideoSDK.eventTracking.liveStreamEventDelegate = self
26
- }
28
+ FireworkVideoSDK.eventTracking.liveStreamEventDelegate = self
27
29
  }
28
30
  func fireworkLiveStreamUserDidJoin(_ liveStream: LiveStreamEventDetails) {
29
31
  sendEvent(
@@ -8,12 +8,17 @@
8
8
  import Foundation
9
9
 
10
10
  struct ProductInfoViewConfiguration: Codable {
11
- var addToCartButton: ButtonConfiguration?
11
+ var addToCartButton: AddToCartButtonConfiguration?
12
+ var linkButton: LinkButtonConfiguration?
12
13
 
13
- struct ButtonConfiguration: Codable {
14
+ struct AddToCartButtonConfiguration: Codable {
14
15
  var backgroundColor: String?
15
16
  var textColor: String?
16
17
  var fontSize: Double?
18
+ var iOSFontInfo: FontInfo?
17
19
  }
18
20
 
21
+ struct LinkButtonConfiguration: Codable {
22
+ var isHidden: Bool?
23
+ }
19
24
  }
@@ -13,10 +13,10 @@ _RCT_EXTERN_REMAP_METHOD(init, initialize, NO)
13
13
  RCT_EXTERN_METHOD(setCartIconVisible:(BOOL)visible)
14
14
  RCT_EXTERN_METHOD(setCartItemCount:(int)itemCounts)
15
15
  RCT_EXTERN_METHOD(updateVideoProducts:(NSArray *)products cbId:(nonnull NSNumber *)cbId)
16
- RCT_EXTERN_METHOD(updateProductViewConfig:(NSDictionary *)config cbId:(nonnull NSNumber *)cbId)
17
16
  RCT_EXTERN_METHOD(updateAddToCartStatus:(NSString *)res tips:(nullable NSString *)tips cbId:(nonnull NSNumber *)cbId)
18
17
  RCT_EXTERN_METHOD(jumpToCartPage:(nonnull NSNumber *)cbId props:(NSDictionary *)props)
19
18
  RCT_EXTERN_METHOD(setCustomClickCartIconEnabled:(BOOL)enabled resolver: (RCTPromiseResolveBlock)resolver rejecter:(RCTPromiseRejectBlock)rejecter)
19
+ RCT_EXTERN_METHOD(setProductInfoViewConfiguration:(NSDictionary *)config)
20
20
  RCT_EXTERN_METHOD(clearCallbackId:(nonnull NSNumber *)cbId eventName:(nonnull NSString *)name)
21
21
 
22
22
  @end