react-native-firework-sdk 2.0.0 → 2.2.0-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.
Files changed (202) hide show
  1. package/FireworkVideoUI.xcframework/Info.plist +40 -0
  2. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/FireworkVideoUI +0 -0
  3. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Headers/FireworkVideoUI-Swift.h +280 -0
  4. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Headers/FireworkVideoUI.h +18 -0
  5. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Info.plist +0 -0
  6. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios.abi.json +1327 -0
  7. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios.private.swiftinterface +41 -0
  8. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  9. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios.swiftinterface +41 -0
  10. package/FireworkVideoUI.xcframework/ios-arm64/FireworkVideoUI.framework/Modules/module.modulemap +11 -0
  11. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/FireworkVideoUI +0 -0
  12. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Headers/FireworkVideoUI-Swift.h +556 -0
  13. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Headers/FireworkVideoUI.h +18 -0
  14. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Info.plist +0 -0
  15. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios-simulator.abi.json +1327 -0
  16. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +41 -0
  17. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  18. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/arm64-apple-ios-simulator.swiftinterface +41 -0
  19. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/x86_64-apple-ios-simulator.abi.json +1327 -0
  20. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +41 -0
  21. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  22. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/FireworkVideoUI.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +41 -0
  23. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/Modules/module.modulemap +11 -0
  24. package/FireworkVideoUI.xcframework/ios-arm64_x86_64-simulator/FireworkVideoUI.framework/_CodeSignature/CodeResources +245 -0
  25. package/README.md +1 -1
  26. package/android/build.gradle +5 -4
  27. package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/FWVideoFeed.kt +6 -0
  28. package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/StoryBlockFragment.kt +129 -0
  29. package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/StoryBlockFrameLayout.kt +90 -0
  30. package/android/src/main/java/com/fireworksdk/bridge/models/FWAdBadgeConfigModelDeserializer.kt +3 -3
  31. package/android/src/main/java/com/fireworksdk/bridge/models/FWEventName.kt +5 -1
  32. package/android/src/main/java/com/fireworksdk/bridge/models/FWFontInfoModelDeserializer.kt +1 -1
  33. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfiguration.kt +18 -5
  34. package/android/src/main/java/com/fireworksdk/bridge/models/FWProductInfoViewConfigurationDeserializer.kt +36 -8
  35. package/android/src/main/java/com/fireworksdk/bridge/models/FWSDKInitOptionsModelDeserializer.kt +3 -3
  36. package/android/src/main/java/com/fireworksdk/bridge/models/FWShoppingCtaResult.kt +17 -0
  37. package/android/src/main/java/com/fireworksdk/bridge/models/FWShoppingCtaResultDeserializer.kt +33 -0
  38. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedConfigModelDeserializer.kt +14 -12
  39. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModel.kt +1 -0
  40. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedPropsModelDeserializer.kt +11 -7
  41. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoFeedSource.kt +1 -0
  42. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlaybackDetails.kt +8 -8
  43. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModel.kt +1 -0
  44. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoPlayerConfigModelDeserializer.kt +19 -12
  45. package/android/src/main/java/com/fireworksdk/bridge/models/FWVideoShoppingProductDeserializer.kt +11 -11
  46. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWStoryBlockManager.kt +131 -45
  47. package/android/src/main/java/com/fireworksdk/bridge/reactnative/manager/FWVideoFeedManager.kt +11 -3
  48. package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWVideoShoppingInterface.kt +2 -2
  49. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWLiveStreamModule.kt +45 -4
  50. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWNavigatorModule.kt +9 -1
  51. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +83 -50
  52. package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FireworkSDKModule.kt +112 -36
  53. package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +16 -6
  54. package/android/src/main/java/com/fireworksdk/bridge/utils/FWConfigUtil.kt +26 -32
  55. package/android/src/main/java/com/fireworksdk/bridge/utils/FWGlobalDataUtil.kt +10 -0
  56. package/android/src/main/java/com/fireworksdk/bridge/utils/FWLanguageUtil.kt +48 -16
  57. package/android/src/main/res/layout/fw_bridge_story_block.xml +24 -0
  58. package/ios/Components/StoryBlock.swift +32 -2
  59. package/ios/Components/StoryBlockManager.m +33 -0
  60. package/ios/Components/StoryBlockManager.swift +4 -0
  61. package/ios/Components/VideoFeed.swift +16 -32
  62. package/ios/Components/VideoFeedManager.m +12 -6
  63. package/ios/Components/VideoFeedManager.swift +4 -0
  64. package/ios/Components/VideoPlayerConfiguration.swift +1 -0
  65. package/ios/FireworkSdk.xcodeproj/project.pbxproj +276 -212
  66. package/ios/FireworkVideoUI/FireworkVideoUI/FireworkVideoUI.docc/FireworkVideoUI.md +13 -0
  67. package/ios/FireworkVideoUI/FireworkVideoUI/FireworkVideoUI.h +18 -0
  68. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/AppLanguageManager.swift +147 -0
  69. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/Foundation/Bundle+AppLanguage.swift +58 -0
  70. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/Foundation/NumberFormatter+AppLanguage.swift +25 -0
  71. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/Foundation/URLSession+AppLanguage.swift +69 -0
  72. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/UIKit/UIImageView+AppLanguage.swift +91 -0
  73. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/UIKit/UILabel+AppLanguage.swift +98 -0
  74. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/UIKit/UITextField+AppLanguage.swift +97 -0
  75. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/UIKit/UITextView+AppLanguage.swift +97 -0
  76. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/UIKit/UIView+AppLanguage.swift +38 -0
  77. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/UIKit/UIViewController+AppLanguage.swift +46 -0
  78. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/Extensions/UIKit/UIWindow+AppLanguage.swift +26 -0
  79. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/AppLanguage/LanguageUtil.swift +43 -0
  80. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/LayoutFlip/Extensions/Foundation/NSObject+LayoutFlip.swift +42 -0
  81. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/LayoutFlip/Extensions/UIKit/CALayer+LayoutFlip.swift +160 -0
  82. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/LayoutFlip/Extensions/UIKit/UILabel+LayoutFlip.swift +35 -0
  83. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/LayoutFlip/Extensions/UIKit/UIView+LayoutFlip.swift +199 -0
  84. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/LayoutFlip/LayoutFlipManager.swift +59 -0
  85. package/ios/{Utils/DispatchQueue+FWOnce.swift → FireworkVideoUI/FireworkVideoUI/Sources/Utils/Extensions/Foundation/DispatchQueue+Once.swift} +5 -5
  86. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/Utils/Extensions/Foundation/String+Base64.swift +18 -0
  87. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/Utils/Extensions/UIKit/UIView+UIHierarchy.swift +46 -0
  88. package/ios/FireworkVideoUI/FireworkVideoUI/Sources/Utils/Swizzle.swift +37 -0
  89. package/ios/FireworkVideoUI/FireworkVideoUI.xcodeproj/project.pbxproj +766 -0
  90. package/ios/FireworkVideoUI/FireworkVideoUI.xcworkspace/contents.xcworkspacedata +10 -0
  91. package/ios/FireworkVideoUI/FireworkVideoUI.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +8 -0
  92. package/ios/FireworkVideoUI/FireworkVideoUITests/FireworkVideoUITests.swift +37 -0
  93. package/ios/FireworkVideoUI/Podfile +15 -0
  94. package/ios/FireworkVideoUI/Podfile.lock +16 -0
  95. package/ios/Models/NativeToRN/FireworkEventName.swift +7 -1
  96. package/ios/Models/NativeToRN/FireworkSDK+Json.swift +5 -1
  97. package/ios/Models/RNToNative/RCTConvert+Shopping.swift +21 -0
  98. package/ios/Models/RNToNative/RCTConvert+StoryBlock.swift +2 -1
  99. package/ios/Models/RNToNative/RCTConvert+VideoFeed.swift +29 -1
  100. package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +13 -101
  101. package/ios/Modules/FireworkSDKModule/FireworkSDKModule+EventTracking.swift +34 -16
  102. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.m +1 -0
  103. package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +48 -2
  104. package/ios/Modules/FireworkSDKModule/SDKInitOptions.swift +0 -1
  105. package/ios/Modules/LiveStream/LiveStreamModule.swift +1 -0
  106. package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +7 -2
  107. package/ios/Modules/Shopping/ShoppingCTAResult.swift +16 -0
  108. package/ios/Modules/Shopping/ShoppingModule.m +2 -1
  109. package/ios/Modules/Shopping/ShoppingModule.swift +92 -34
  110. package/ios/Support/MultiHostStreaming/FWMultiHostStreaming.podspec +22 -0
  111. package/ios/Support/MultiHostStreaming/Sources/MultiHostStreamingSDK.swift +17 -0
  112. package/ios/Utils/{UINavigationController+FWSwizzle.swift → Extensions/Swizzle/UINavigationController+FWSwizzle.swift} +9 -8
  113. package/ios/Utils/FWSwizzleLoader.m +6 -1
  114. package/ios/Utils/FWSwizzleLoader.swift +13 -0
  115. package/ios/react_native_firework_sdk.h +1 -0
  116. package/ios/scripts/react_native_firework_sdk_pods.rb +27 -0
  117. package/lib/commonjs/FireworkSDK.js +55 -15
  118. package/lib/commonjs/FireworkSDK.js.map +1 -1
  119. package/lib/commonjs/LiveStream.js +2 -2
  120. package/lib/commonjs/LiveStream.js.map +1 -1
  121. package/lib/commonjs/VideoShopping.js +21 -38
  122. package/lib/commonjs/VideoShopping.js.map +1 -1
  123. package/lib/commonjs/components/StoryBlock.js +193 -128
  124. package/lib/commonjs/components/StoryBlock.js.map +1 -1
  125. package/lib/commonjs/components/VideoFeed.js +17 -5
  126. package/lib/commonjs/components/VideoFeed.js.map +1 -1
  127. package/lib/commonjs/index.js.map +1 -1
  128. package/lib/commonjs/models/FWEventName.js +3 -0
  129. package/lib/commonjs/models/FWEventName.js.map +1 -1
  130. package/lib/commonjs/models/ShoppingCTAResult.js +2 -0
  131. package/lib/commonjs/models/VideoPlaybackEventName.js +3 -0
  132. package/lib/commonjs/models/VideoPlaybackEventName.js.map +1 -1
  133. package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -1
  134. package/lib/commonjs/modules/ShoppingModule.js.map +1 -1
  135. package/lib/module/FireworkSDK.js +54 -15
  136. package/lib/module/FireworkSDK.js.map +1 -1
  137. package/lib/module/LiveStream.js +2 -2
  138. package/lib/module/LiveStream.js.map +1 -1
  139. package/lib/module/VideoShopping.js +21 -40
  140. package/lib/module/VideoShopping.js.map +1 -1
  141. package/lib/module/components/StoryBlock.js +183 -133
  142. package/lib/module/components/StoryBlock.js.map +1 -1
  143. package/lib/module/components/VideoFeed.js +16 -5
  144. package/lib/module/components/VideoFeed.js.map +1 -1
  145. package/lib/module/index.js.map +1 -1
  146. package/lib/module/models/FWEventName.js +3 -0
  147. package/lib/module/models/FWEventName.js.map +1 -1
  148. package/lib/module/models/ShoppingCTAResult.js +2 -0
  149. package/lib/module/models/VideoPlaybackEventName.js +3 -0
  150. package/lib/module/models/VideoPlaybackEventName.js.map +1 -1
  151. package/lib/module/modules/FireworkSDKModule.js.map +1 -1
  152. package/lib/module/modules/ShoppingModule.js.map +1 -1
  153. package/lib/typescript/FireworkSDK.d.ts +15 -8
  154. package/lib/typescript/LiveStream.d.ts +2 -2
  155. package/lib/typescript/VideoShopping.d.ts +10 -12
  156. package/lib/typescript/components/StoryBlock.d.ts +25 -24
  157. package/lib/typescript/components/VideoFeed.d.ts +7 -0
  158. package/lib/typescript/index.d.ts +6 -6
  159. package/lib/typescript/models/FWEventName.d.ts +3 -0
  160. package/lib/typescript/models/FWEvents.d.ts +14 -1
  161. package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +12 -8
  162. package/lib/typescript/models/SDKInitOptions.d.ts +6 -1
  163. package/lib/typescript/models/ShoppingCTAResult.d.ts +11 -0
  164. package/lib/typescript/models/StoryBlockSource.d.ts +1 -1
  165. package/lib/typescript/models/VideoFeedSource.d.ts +1 -1
  166. package/lib/typescript/models/VideoPlaybackDetails.d.ts +16 -0
  167. package/lib/typescript/models/VideoPlaybackEventName.d.ts +13 -1
  168. package/lib/typescript/models/VideoPlayerConfiguration.d.ts +4 -0
  169. package/lib/typescript/modules/FireworkSDKModule.d.ts +1 -2
  170. package/lib/typescript/modules/ShoppingModule.d.ts +2 -1
  171. package/package.json +8 -3
  172. package/react-native-firework-sdk.podspec +31 -24
  173. package/src/FireworkSDK.ts +54 -15
  174. package/src/LiveStream.ts +2 -2
  175. package/src/VideoShopping.ts +41 -54
  176. package/src/components/StoryBlock.tsx +210 -98
  177. package/src/components/VideoFeed.tsx +23 -4
  178. package/src/index.ts +15 -9
  179. package/src/models/FWEventName.ts +3 -0
  180. package/src/models/FWEvents.ts +14 -1
  181. package/src/models/ProductInfoViewConfiguration.ts +13 -8
  182. package/src/models/SDKInitOptions.ts +6 -1
  183. package/src/models/ShoppingCTAResult.ts +11 -0
  184. package/src/models/StoryBlockSource.ts +2 -1
  185. package/src/models/VideoFeedSource.ts +2 -1
  186. package/src/models/VideoPlaybackDetails.ts +16 -0
  187. package/src/models/VideoPlaybackEventName.ts +13 -1
  188. package/src/models/VideoPlayerConfiguration.ts +4 -0
  189. package/src/modules/FireworkSDKModule.ts +1 -2
  190. package/src/modules/ShoppingModule.ts +5 -5
  191. package/android/src/main/java/com/fireworksdk/bridge/constants/FWCommandConstant.kt +0 -6
  192. package/ios/Utils/FWSwizzleUtil.swift +0 -29
  193. package/ios/Utils/UIView+ParentViewController.swift +0 -21
  194. package/lib/commonjs/models/AddToCartResult.js +0 -2
  195. package/lib/module/models/AddToCartResult.js +0 -2
  196. package/lib/typescript/models/AddToCartResult.d.ts +0 -10
  197. package/src/models/AddToCartResult.ts +0 -10
  198. /package/ios/Utils/{String+Color.swift → Extensions/String+Color.swift} +0 -0
  199. /package/ios/Utils/{UIView+Constraints.swift → Extensions/UIView+Constraints.swift} +0 -0
  200. /package/ios/Utils/{UIViewController+AttachChild.swift → Extensions/UIViewController+AttachChild.swift} +0 -0
  201. /package/lib/commonjs/models/{AddToCartResult.js.map → ShoppingCTAResult.js.map} +0 -0
  202. /package/lib/module/models/{AddToCartResult.js.map → ShoppingCTAResult.js.map} +0 -0
@@ -0,0 +1,97 @@
1
+ //
2
+ // UITextView+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/23.
5
+ //
6
+
7
+ import UIKit
8
+
9
+ extension UITextView {
10
+ private struct AssociatedKeys {
11
+ static var hasCalculatedTextAlignment = "hasCalculatedTextAlignmentKey"
12
+ }
13
+
14
+ private var hasCalculatedTextAlignment: Bool {
15
+ get {
16
+ let result = objc_getAssociatedObject(self, &AssociatedKeys.hasCalculatedTextAlignment) as? Bool
17
+ return result ?? false
18
+ }
19
+
20
+ set {
21
+ objc_setAssociatedObject(
22
+ self,
23
+ &AssociatedKeys.hasCalculatedTextAlignment,
24
+ newValue,
25
+ .OBJC_ASSOCIATION_RETAIN_NONATOMIC
26
+ )
27
+ }
28
+ }
29
+
30
+ static func swizzleTextViewMethodsForAppLanguage() {
31
+ Swizzle.swizzleSelector(cls: self,
32
+ originalSelector: #selector(setter: UITextView.textAlignment),
33
+ customSelector: #selector(UITextView.fw_setTextViewTextAlignment(_:)))
34
+ Swizzle.swizzleSelector(cls: self,
35
+ originalSelector: #selector(UITextView.didMoveToWindow),
36
+ customSelector: #selector(UITextView.fw_textViewDidMoveToWindow))
37
+ Swizzle.swizzleSelector(cls: self,
38
+ originalSelector: #selector(UITextView.removeFromSuperview),
39
+ customSelector: #selector(UITextView.fw_textViewRemoveFromSuperview))
40
+ }
41
+
42
+ @objc func fw_setTextViewTextAlignment(_ textAlignment: NSTextAlignment) {
43
+ addReloadClosure(key: "alignment") { [weak self] in
44
+ guard let self = self else {
45
+ return
46
+ }
47
+
48
+ self.fw_setTextViewTextAlignment(self.calculatedTextAlignment(textAlignment))
49
+ }
50
+ }
51
+
52
+ @objc func fw_textViewDidMoveToWindow() {
53
+ fw_textViewDidMoveToWindow()
54
+ if shouldCalculateTextAlignment(),
55
+ !self.hasCalculatedTextAlignment,
56
+ self.isIOSSDKView {
57
+ self.textAlignment = self.textAlignment
58
+ }
59
+ }
60
+
61
+ @objc func fw_textViewRemoveFromSuperview() {
62
+ fw_textViewRemoveFromSuperview()
63
+ self.hasCalculatedTextAlignment = false
64
+ }
65
+
66
+ private func calculatedTextAlignment(_ textAlignment: NSTextAlignment) -> NSTextAlignment {
67
+ if shouldCalculateTextAlignment(),
68
+ let layoutDirection = AppLanguageManager.shared.appLanguageLayoutDirection {
69
+ self.hasCalculatedTextAlignment = true
70
+ if layoutDirection == .rtl {
71
+ if textAlignment == .center {
72
+ return textAlignment
73
+ } else if textAlignment == .right {
74
+ return .left
75
+ } else {
76
+ return .right
77
+ }
78
+ } else if layoutDirection == .ltr {
79
+ return .left
80
+ }
81
+ } else {
82
+ return textAlignment
83
+ }
84
+ return textAlignment
85
+ }
86
+
87
+ private func shouldCalculateTextAlignment() -> Bool {
88
+ if AppLanguageManager.shared.shouldHorizontalFlip,
89
+ self.isIOSSDKView,
90
+ let layoutDirection = AppLanguageManager.shared.appLanguageLayoutDirection,
91
+ layoutDirection != .unsupported {
92
+ return true
93
+ }
94
+
95
+ return false
96
+ }
97
+ }
@@ -0,0 +1,38 @@
1
+ //
2
+ // UIView+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/3/11.
5
+ //
6
+
7
+ import UIKit
8
+ import FireworkVideo
9
+
10
+ extension UIView {
11
+ static func swizzleViewMethodsForAppLanguage() {
12
+ Swizzle.swizzleSelector(
13
+ cls: self,
14
+ originalSelector: #selector(UIView.init(frame:)),
15
+ customSelector: #selector(UIView.fw_init(frame:))
16
+ )
17
+ Swizzle.swizzleSelector(
18
+ cls: self,
19
+ originalSelector: #selector(UIView.awakeFromNib),
20
+ customSelector: #selector(UIView.fw_viewAwakeFromNib)
21
+ )
22
+ }
23
+
24
+ @objc func fw_init(frame: CGRect) -> UIView {
25
+ let view = self.fw_init(frame: frame)
26
+ if view is FireworkPlayerView {
27
+ view.viewType = .normal
28
+ }
29
+ return view
30
+ }
31
+
32
+ @objc func fw_viewAwakeFromNib() {
33
+ self.fw_viewAwakeFromNib()
34
+ if self is FireworkPlayerView, AppLanguageManager.shared.shouldHorizontalFlip {
35
+ self.viewType = .normal
36
+ }
37
+ }
38
+ }
@@ -0,0 +1,46 @@
1
+ //
2
+ // UIViewController+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/21.
5
+ //
6
+
7
+ import UIKit
8
+ import FireworkVideo
9
+
10
+ extension UIViewController {
11
+ static func swizzleViewControllerMethodsForAppLanguage() {
12
+ Swizzle.swizzleSelector(
13
+ cls: self,
14
+ originalSelector: #selector(UIViewController.present(_:animated:completion:)),
15
+ customSelector: #selector(UIViewController.fw_present(_:animated:completion:))
16
+ )
17
+
18
+ Swizzle.swizzleSelector(
19
+ cls: self,
20
+ originalSelector: #selector(UIViewController.viewDidLoad),
21
+ customSelector: #selector(UIViewController.fw_viewDidLoad)
22
+ )
23
+ }
24
+
25
+ @objc func fw_present(
26
+ _ viewControllerToPresent: UIViewController,
27
+ animated flag: Bool,
28
+ completion: (() -> Void)? = nil
29
+ ) {
30
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
31
+ let viewControllerToPresentBundle = Bundle(for: type(of: viewControllerToPresent))
32
+ if AppLanguageManager.shared.shouldHorizontalFlip,
33
+ viewControllerToPresentBundle == iOSSDKBundle {
34
+ viewControllerToPresent.view.viewType = .flip
35
+ }
36
+ fw_present(viewControllerToPresent, animated: flag, completion: completion)
37
+ }
38
+
39
+ @objc func fw_viewDidLoad() {
40
+ fw_viewDidLoad()
41
+ if self is StoryBlockViewController
42
+ || self is VideoFeedViewController {
43
+ self.view.viewType = .flip
44
+ }
45
+ }
46
+ }
@@ -0,0 +1,26 @@
1
+ //
2
+ // UIWindow+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/24.
5
+ //
6
+
7
+ import UIKit
8
+ import FireworkVideo
9
+
10
+ extension UIWindow {
11
+ static func swizzleWindowMethodsForAppLanguage() {
12
+ Swizzle.swizzleSelector(cls: self,
13
+ originalSelector: #selector(setter: UIWindow.rootViewController),
14
+ customSelector: #selector(UIWindow.fw_setRootViewController(_:)))
15
+ }
16
+
17
+ @objc func fw_setRootViewController(_ rootViewController: UIViewController?) {
18
+ fw_setRootViewController(rootViewController)
19
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
20
+ if AppLanguageManager.shared.shouldHorizontalFlip,
21
+ let viewController = rootViewController,
22
+ Bundle(for: type(of: viewController)) == iOSSDKBundle {
23
+ viewController.view.viewType = .flip
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,43 @@
1
+ //
2
+ // LanguageUtil.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/9.
5
+ //
6
+
7
+ import Foundation
8
+
9
+ class LanguageUtil {
10
+ static func getLanguageCode(_ language: String) -> String? {
11
+ guard language.count > 0 else {
12
+ return nil
13
+ }
14
+
15
+ var languageCode = ""
16
+ #if compiler(>=5.7)
17
+ if #available(iOS 16, *) {
18
+ languageCode = Locale(identifier: language).language.languageCode?.identifier ?? ""
19
+ } else {
20
+ languageCode = Locale(identifier: language).languageCode ?? ""
21
+ }
22
+ #else
23
+ languageCode = Locale(identifier: language).languageCode ?? ""
24
+ #endif
25
+ return languageCode.lowercased()
26
+ }
27
+
28
+ static func isValidLanguage(_ language: String?) -> Bool {
29
+ guard let language = language else {
30
+ return false
31
+ }
32
+
33
+ guard language.count > 0 else {
34
+ return false
35
+ }
36
+
37
+ let languageWithUnderline = language.replacingOccurrences(of: "-", with: "_")
38
+
39
+ let availableIdentifiers = Locale.availableIdentifiers
40
+
41
+ return availableIdentifiers.contains(language) || availableIdentifiers.contains(languageWithUnderline)
42
+ }
43
+ }
@@ -0,0 +1,42 @@
1
+ //
2
+ // NSObject+LayoutFlip.swift
3
+ //
4
+ // Created by linjie jiang on 4/25/23.
5
+ //
6
+
7
+ import Foundation
8
+
9
+ typealias ReloadClosure = () -> Void
10
+
11
+ extension NSObject {
12
+ private struct AssociatedKeys {
13
+ static var reloadClosures = "reloadBlocks"
14
+ }
15
+
16
+ private var reloadClosures: [String: ReloadClosure] {
17
+ get {
18
+ let result = objc_getAssociatedObject(self, &AssociatedKeys.reloadClosures) as? [String: ReloadClosure]
19
+ return result ?? [:]
20
+ }
21
+
22
+ set {
23
+ objc_setAssociatedObject(
24
+ self,
25
+ &AssociatedKeys.reloadClosures,
26
+ newValue,
27
+ .OBJC_ASSOCIATION_RETAIN_NONATOMIC
28
+ )
29
+ }
30
+ }
31
+
32
+ func performReload() {
33
+ for (_, closure) in reloadClosures {
34
+ closure()
35
+ }
36
+ }
37
+
38
+ func addReloadClosure(key: String, reloadClosure: @escaping ReloadClosure) {
39
+ reloadClosures[key] = reloadClosure
40
+ reloadClosure()
41
+ }
42
+ }
@@ -0,0 +1,160 @@
1
+ //
2
+ // CALayer+LayoutFlip.swift
3
+ //
4
+ // Created by linjie jiang on 4/25/23.
5
+ //
6
+
7
+ import UIKit
8
+
9
+ private var gHasEnabledHorizontalFlip = false
10
+
11
+ extension CALayer {
12
+ private struct AssociatedKeys {
13
+ static var basicTransform = "basicTransform"
14
+ static var isRenderStartLayer = "isRenderStartLayer"
15
+ static var affineTransform = "affineTransform"
16
+ }
17
+
18
+ static func swizzleLayerMethodsForLayoutFlip() {
19
+ Swizzle.swizzleSelector(
20
+ cls: self,
21
+ originalSelector: #selector(CALayer.setAffineTransform(_:)),
22
+ customSelector: #selector(CALayer.fw_setAffineTransform(_:)))
23
+ Swizzle.swizzleSelector(
24
+ cls: self,
25
+ originalSelector: #selector(CALayer.affineTransform),
26
+ customSelector: #selector(CALayer.fw_affineTransform))
27
+ Swizzle.swizzleSelector(
28
+ cls: self,
29
+ originalSelector: #selector(CALayer.add(_:forKey:)),
30
+ customSelector: #selector(CALayer.fw_add(_:forKey:)))
31
+ Swizzle.swizzleSelector(
32
+ cls: self,
33
+ originalSelector: #selector(CALayer.render(in:)),
34
+ customSelector: #selector(CALayer.fw_render(in:)))
35
+ }
36
+
37
+ var basicTransform: CGAffineTransform {
38
+ get {
39
+ let result = objc_getAssociatedObject(self, &AssociatedKeys.basicTransform) as? NSValue
40
+
41
+ return result?.cgAffineTransformValue ?? CGAffineTransformIdentity
42
+ }
43
+
44
+ set {
45
+ if objc_getAssociatedObject(self, &AssociatedKeys.basicTransform) == nil,
46
+ CGAffineTransformIsIdentity(newValue) {
47
+ return
48
+ }
49
+
50
+ objc_setAssociatedObject(
51
+ self,
52
+ &AssociatedKeys.basicTransform,
53
+ NSValue(cgAffineTransform: newValue),
54
+ .OBJC_ASSOCIATION_RETAIN_NONATOMIC
55
+ )
56
+ self.setAffineTransform(self.affineTransform())
57
+ }
58
+ }
59
+
60
+ var isRenderStartLayer: Bool {
61
+ get {
62
+ let result = objc_getAssociatedObject(self, &AssociatedKeys.isRenderStartLayer) as? Bool
63
+ return result ?? false
64
+ }
65
+
66
+ set {
67
+ objc_setAssociatedObject(
68
+ self,
69
+ &AssociatedKeys.basicTransform,
70
+ newValue,
71
+ .OBJC_ASSOCIATION_RETAIN_NONATOMIC
72
+ )
73
+ }
74
+ }
75
+
76
+ @objc func fw_setAffineTransform(_ affineTransform: CGAffineTransform) {
77
+ if !gHasEnabledHorizontalFlip && LayoutFlipManager.shared.enableHorizontalFlip {
78
+ gHasEnabledHorizontalFlip = true
79
+ }
80
+
81
+ if gHasEnabledHorizontalFlip {
82
+ objc_setAssociatedObject(
83
+ self,
84
+ &AssociatedKeys.affineTransform,
85
+ NSValue(cgAffineTransform: affineTransform),
86
+ .OBJC_ASSOCIATION_RETAIN_NONATOMIC
87
+ )
88
+ fw_setAffineTransform(CGAffineTransformConcat(basicTransform, affineTransform))
89
+ } else {
90
+ fw_setAffineTransform(affineTransform)
91
+ }
92
+ }
93
+
94
+ @objc func fw_affineTransform() -> CGAffineTransform {
95
+ if !gHasEnabledHorizontalFlip && LayoutFlipManager.shared.enableHorizontalFlip {
96
+ gHasEnabledHorizontalFlip = true
97
+ }
98
+
99
+ if gHasEnabledHorizontalFlip {
100
+ if let value = objc_getAssociatedObject(self, &AssociatedKeys.affineTransform) as? NSValue {
101
+ return value.cgAffineTransformValue
102
+ }
103
+ return fw_affineTransform()
104
+ } else {
105
+ return fw_affineTransform()
106
+ }
107
+ }
108
+
109
+ @objc func fw_add(_ anim: CAAnimation, forKey key: String?) {
110
+ if let basicAnim = anim as? CABasicAnimation,
111
+ let keyPath = basicAnim.keyPath,
112
+ keyPath.starts(with: "transform.scale"),
113
+ self.basicTransform.a == -1,
114
+ let fromValue = basicAnim.fromValue as? Double,
115
+ let toValue = basicAnim.toValue as? Double {
116
+ basicAnim.fromValue = fromValue * -1
117
+ basicAnim.toValue = toValue * -1
118
+ }
119
+
120
+ fw_add(anim, forKey: key)
121
+ }
122
+
123
+ @objc func fw_render(in ctx: CGContext) {
124
+ if !gHasEnabledHorizontalFlip && LayoutFlipManager.shared.enableHorizontalFlip {
125
+ gHasEnabledHorizontalFlip = true
126
+ }
127
+
128
+ if gHasEnabledHorizontalFlip {
129
+ var isRenderStartLayer = true
130
+ var allSuperLayerTransform = basicTransform
131
+ var layer = self
132
+ while let superlayer = layer.superlayer {
133
+ layer = superlayer
134
+ if layer.isRenderStartLayer {
135
+ isRenderStartLayer = false
136
+ break
137
+ }
138
+ allSuperLayerTransform = CGAffineTransformConcat(layer.basicTransform, allSuperLayerTransform)
139
+ }
140
+
141
+ if isRenderStartLayer {
142
+ self.isRenderStartLayer = true
143
+ if allSuperLayerTransform.a == -1 {
144
+ ctx.saveGState()
145
+ ctx.concatenate(CGAffineTransformMakeScale(-1, 1))
146
+ ctx.translateBy(x: -self.bounds.size.width, y: 0)
147
+ }
148
+ }
149
+ fw_render(in: ctx)
150
+ if isRenderStartLayer {
151
+ self.isRenderStartLayer = false
152
+ if allSuperLayerTransform.a == -1 {
153
+ ctx.restoreGState()
154
+ }
155
+ }
156
+ } else {
157
+ fw_render(in: ctx)
158
+ }
159
+ }
160
+ }
@@ -0,0 +1,35 @@
1
+ //
2
+ // UILabel+LayoutFlip.swift
3
+ //
4
+ // Created by linjie jiang on 4/25/23.
5
+ //
6
+
7
+ import UIKit
8
+
9
+ private let gNoUseClasses: [String] = [
10
+ "VUlUZXh0RmllbGRMYWJlbA==".decodeBase64String() // UITextFieldLabel
11
+ ]
12
+ private let gSuperviewNoUseClasses: [String] = [
13
+ "VUlEYXRlUGlja2VyQ29udGVudFZpZXc=".decodeBase64String() // UIDatePickerContentView
14
+ ]
15
+
16
+ extension UILabel {
17
+ func shouldUseCalculatedTextAlignment() -> Bool {
18
+ for className in gNoUseClasses {
19
+ if let cls = NSClassFromString(className),
20
+ self.isKind(of: cls) {
21
+ return false
22
+ }
23
+ }
24
+
25
+ for className in gSuperviewNoUseClasses {
26
+ if let cls = NSClassFromString(className),
27
+ let superview = superview,
28
+ superview.isKind(of: cls) {
29
+ return false
30
+ }
31
+ }
32
+
33
+ return true
34
+ }
35
+ }
@@ -0,0 +1,199 @@
1
+ //
2
+ // UIView+LayoutFlip.swift
3
+ //
4
+ // Created by linjie jiang on 4/25/23.
5
+ //
6
+
7
+ import UIKit
8
+ import WebKit
9
+
10
+ private let gNoFlipClasses: [Any] = [
11
+ UILabel.self,
12
+ UITextView.self,
13
+ UITextField.self,
14
+ WKWebView.self,
15
+ UIImageView.self,
16
+ UISearchBar.self,
17
+ "PUPhotosSectionHeaderContentView",
18
+ "UITableViewIndex",
19
+ "UIWebView",
20
+ "X1VJUmVtb3RlVmlldw==".decodeBase64String(), // _UIRemoteView
21
+ "VUlBdXRvY29ycmVjdFRleHRWaWV3".decodeBase64String() // UIAutocorrectTextView
22
+ ]
23
+
24
+ enum LayoutFlipViewType: Int {
25
+ case auto
26
+ case inherit
27
+ case normal
28
+ case flip
29
+ case normalWithAllDescendants
30
+ case flipWithAllDescendants
31
+ }
32
+
33
+ extension UIView {
34
+ private struct AssociatedKeys {
35
+ static var viewType = "viewType"
36
+ static var calculatedViewType = "calculatedViewType"
37
+ static var lastType = "lastType"
38
+ }
39
+
40
+ static func swizzleViewMethodsForLayoutFlip() {
41
+ Swizzle.swizzleSelector(
42
+ cls: self,
43
+ originalSelector: #selector(UIView.didMoveToSuperview),
44
+ customSelector: #selector(UIView.fw_didMoveToSuperview))
45
+ Swizzle.swizzleSelector(
46
+ cls: self,
47
+ originalSelector: #selector(UIView.didMoveToWindow),
48
+ customSelector: #selector(UIView.fw_didMoveToWindow))
49
+ Swizzle.swizzleSelector(
50
+ cls: self,
51
+ originalSelector: #selector(UIView.snapshotView(afterScreenUpdates:)),
52
+ customSelector: #selector(UIView.fw_snapshotView(afterScreenUpdates:)))
53
+ }
54
+
55
+ var viewType: LayoutFlipViewType {
56
+ get {
57
+ let rawValue = objc_getAssociatedObject(self, &AssociatedKeys.viewType) as? Int ?? 0
58
+ let type = LayoutFlipViewType(rawValue: rawValue) ?? .auto
59
+
60
+ return type
61
+ }
62
+
63
+ set {
64
+ if viewType == newValue {
65
+ return
66
+ }
67
+
68
+ objc_setAssociatedObject(
69
+ self,
70
+ &AssociatedKeys.viewType,
71
+ newValue.rawValue,
72
+ .OBJC_ASSOCIATION_RETAIN_NONATOMIC
73
+ )
74
+ renewLayerTransformForceRecursively(false)
75
+ }
76
+ }
77
+
78
+ private(set) var calculatedViewType: LayoutFlipViewType {
79
+ get {
80
+ let rawValue = objc_getAssociatedObject(self, &AssociatedKeys.calculatedViewType) as? Int ?? 0
81
+ var type = LayoutFlipViewType(rawValue: rawValue) ?? .auto
82
+ if type == .auto {
83
+ if self.window != nil {
84
+ updateCalculatedViewType()
85
+ let newRawValue = objc_getAssociatedObject(self, &AssociatedKeys.calculatedViewType) as? Int ?? 0
86
+ type = LayoutFlipViewType(rawValue: newRawValue) ?? .auto
87
+ } else {
88
+ type = .normal
89
+ }
90
+ }
91
+
92
+ return type
93
+ }
94
+
95
+ set {
96
+ objc_setAssociatedObject(
97
+ self,
98
+ &AssociatedKeys.calculatedViewType,
99
+ newValue.rawValue,
100
+ .OBJC_ASSOCIATION_RETAIN_NONATOMIC
101
+ )
102
+ }
103
+ }
104
+
105
+ private var lastType: LayoutFlipViewType {
106
+ get {
107
+ let rawValue = objc_getAssociatedObject(self, &AssociatedKeys.lastType) as? Int ?? 0
108
+ let type = LayoutFlipViewType(rawValue: rawValue) ?? .auto
109
+
110
+ return type
111
+ }
112
+
113
+ set {
114
+ objc_setAssociatedObject(
115
+ self,
116
+ &AssociatedKeys.lastType,
117
+ newValue.rawValue,
118
+ .OBJC_ASSOCIATION_RETAIN_NONATOMIC
119
+ )
120
+ }
121
+ }
122
+
123
+ @objc func fw_didMoveToSuperview() {
124
+ fw_didMoveToSuperview()
125
+ renewLayerTransformForceRecursively(false)
126
+ }
127
+
128
+ @objc func fw_didMoveToWindow() {
129
+ fw_didMoveToWindow()
130
+ renewLayerTransformForceRecursively(false)
131
+ LayoutFlipManager.shared.registerUIElement(self)
132
+ }
133
+
134
+ @objc func fw_snapshotView(afterScreenUpdates afterUpdates: Bool) -> UIView? {
135
+ let view = fw_snapshotView(afterScreenUpdates: afterUpdates)
136
+ view?.viewType = calculatedViewType
137
+ return view
138
+ }
139
+
140
+ func renewLayerTransformForceRecursively(_ forceRecursively: Bool) {
141
+ updateCalculatedViewType()
142
+ let updatedViewType = calculatedViewType
143
+ let superViewCalculatedViewType = superview?.calculatedViewType ?? .auto
144
+ let shouldFlipCurrentView = updatedViewType == .flip || updatedViewType == .flipWithAllDescendants
145
+ let shouldFlipSuperview = superViewCalculatedViewType == .flip
146
+ || superViewCalculatedViewType == .flipWithAllDescendants
147
+
148
+ let shouldSetFlipTransform = shouldFlipSuperview != shouldFlipCurrentView
149
+
150
+ if shouldSetFlipTransform && LayoutFlipManager.shared.enableHorizontalFlip {
151
+ layer.basicTransform = CGAffineTransformMakeScale(-1, 1)
152
+ } else {
153
+ layer.basicTransform = CGAffineTransformIdentity
154
+ }
155
+
156
+ if updatedViewType != lastType || forceRecursively {
157
+ for subView in subviews {
158
+ subView.renewLayerTransformForceRecursively(forceRecursively)
159
+ }
160
+ }
161
+
162
+ lastType = updatedViewType
163
+ }
164
+
165
+ private func automaticViewType() -> LayoutFlipViewType {
166
+ if self is UIWindow {
167
+ return .normal
168
+ }
169
+
170
+ for element in gNoFlipClasses {
171
+ if let cls = element as? AnyClass,
172
+ self.isKind(of: cls) {
173
+ return .normal
174
+
175
+ } else if let className = element as? String,
176
+ let cls = NSClassFromString(className),
177
+ self.isKind(of: cls) {
178
+ return .normal
179
+ }
180
+ }
181
+
182
+ return superview != nil ? .inherit : .normal
183
+ }
184
+
185
+ private func updateCalculatedViewType() {
186
+ var resultCalculatedViewType = viewType
187
+ if resultCalculatedViewType == .auto {
188
+ resultCalculatedViewType = automaticViewType()
189
+ }
190
+ let superViewCalculatedViewType = superview?.calculatedViewType ?? .auto
191
+ if superViewCalculatedViewType == .flipWithAllDescendants
192
+ || superViewCalculatedViewType == .normalWithAllDescendants
193
+ || resultCalculatedViewType == .inherit {
194
+ calculatedViewType = superViewCalculatedViewType
195
+ } else {
196
+ calculatedViewType = resultCalculatedViewType
197
+ }
198
+ }
199
+ }