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,13 @@
1
+ # ``FireworkVideoUI``
2
+
3
+ <!--@START_MENU_TOKEN@-->Summary<!--@END_MENU_TOKEN@-->
4
+
5
+ ## Overview
6
+
7
+ <!--@START_MENU_TOKEN@-->Text<!--@END_MENU_TOKEN@-->
8
+
9
+ ## Topics
10
+
11
+ ### <!--@START_MENU_TOKEN@-->Group<!--@END_MENU_TOKEN@-->
12
+
13
+ - <!--@START_MENU_TOKEN@-->``Symbol``<!--@END_MENU_TOKEN@-->
@@ -0,0 +1,18 @@
1
+ //
2
+ // FireworkVideoUI.h
3
+ // FireworkVideoUI
4
+ //
5
+ // Created by linjie jiang on 4/25/23.
6
+ //
7
+
8
+ #import <Foundation/Foundation.h>
9
+
10
+ //! Project version number for FireworkVideoUI.
11
+ FOUNDATION_EXPORT double FireworkVideoUIVersionNumber;
12
+
13
+ //! Project version string for FireworkVideoUI.
14
+ FOUNDATION_EXPORT const unsigned char FireworkVideoUIVersionString[];
15
+
16
+ // In this header, you should import all the public headers of your framework using statements like #import <FireworkVideoUI/PublicHeader.h>
17
+
18
+
@@ -0,0 +1,147 @@
1
+ //
2
+ // AppLanguageManager.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/7.
5
+ //
6
+
7
+ import UIKit
8
+
9
+ private let appLanguageStorageKey = "firework_sdk_app_language_storage_key"
10
+
11
+ enum AppLanguageLayoutDirection: Int {
12
+ case ltr, rtl, unsupported
13
+ }
14
+
15
+ /// The manager of supporting app language
16
+ public class AppLanguageManager {
17
+ public struct NotificationName {
18
+ /// The notification name for language change
19
+ public static let AppLanguageChanged = Notification.Name(
20
+ rawValue: "firework.notification.name.appLanguageChanged"
21
+ )
22
+ }
23
+
24
+ public static let shared = AppLanguageManager()
25
+
26
+ var systemLanguage: String?
27
+ private var systemLanguageCode: String? {
28
+ guard let language = systemLanguage else {
29
+ return nil
30
+ }
31
+
32
+ return LanguageUtil.getLanguageCode(language)
33
+ }
34
+
35
+ /// Get current app language.
36
+ public private(set) var appLanguage: String? {
37
+ didSet {
38
+ if appLanguage != nil {
39
+ AppLanguageManager.swizzelMethods()
40
+ LayoutFlipManager.shared.enableHorizontalFlip = shouldHorizontalFlip
41
+ }
42
+
43
+ if appLanguage != oldValue {
44
+ NotificationCenter.default.post(name: NotificationName.AppLanguageChanged, object: nil)
45
+ }
46
+ }
47
+ }
48
+
49
+ var appLanguageCode: String? {
50
+ guard let language = appLanguage else {
51
+ return nil
52
+ }
53
+
54
+ return LanguageUtil.getLanguageCode(language)
55
+ }
56
+
57
+ var appLanguageLayoutDirection: AppLanguageLayoutDirection? {
58
+ guard let languageCode = appLanguageCode else {
59
+ return nil
60
+ }
61
+ let direction = Locale.characterDirection(forLanguage: languageCode)
62
+ switch direction {
63
+ case .leftToRight:
64
+ return .ltr
65
+ case .rightToLeft:
66
+ return .rtl
67
+ default:
68
+ return .unsupported
69
+ }
70
+ }
71
+
72
+ var shouldHorizontalFlip: Bool {
73
+ guard let appLanguageCode = appLanguageCode else {
74
+ return false
75
+ }
76
+
77
+ guard let systemLanguageCode = systemLanguageCode else {
78
+ return false
79
+ }
80
+
81
+ let appLanguageDirection = Locale.characterDirection(forLanguage: appLanguageCode)
82
+ let systemLanguageDirection = Locale.characterDirection(forLanguage: systemLanguageCode)
83
+
84
+ if appLanguageDirection == .leftToRight, systemLanguageDirection == .rightToLeft {
85
+ return true
86
+ }
87
+
88
+ if appLanguageDirection == .rightToLeft, systemLanguageDirection == .leftToRight {
89
+ return true
90
+ }
91
+
92
+ return false
93
+ }
94
+
95
+ private static func swizzelMethods() {
96
+ DispatchQueue.once {
97
+ UIViewController.swizzleViewControllerMethodsForAppLanguage()
98
+ Bundle.swizzleBundleMethodsForAppLanguage()
99
+ URLSession.swizzleURLSessionMethodsForAppLanguage()
100
+ NumberFormatter.swizzleNumberFormatterMethodsForAppLanguage()
101
+ UIImageView.swizzleImageViewMethodsForAppLanguage()
102
+ UILabel.swizzleLabelMethodsForAppLanguage()
103
+ UITextField.swizzleTextFieldMethodsForAppLanguage()
104
+ UITextView.swizzleTextViewMethodsForAppLanguage()
105
+ UIWindow.swizzleWindowMethodsForAppLanguage()
106
+ UIView.swizzleViewMethodsForAppLanguage()
107
+ }
108
+
109
+ LayoutFlipManager.swizzelMethods()
110
+ }
111
+
112
+ private init() {
113
+ initializeManager()
114
+ }
115
+
116
+ private func initializeManager() {
117
+ self.systemLanguage = Locale.preferredLanguages.first
118
+ let cachedAppLanguage = UserDefaults.standard.object(forKey: appLanguageStorageKey) as? String
119
+ if LanguageUtil.isValidLanguage(cachedAppLanguage) {
120
+ self.appLanguage = cachedAppLanguage
121
+ }
122
+ }
123
+
124
+ /// Change app language
125
+ ///
126
+ /// - Parameters:
127
+ /// - language: app language. We will use system langauge when language is nil.
128
+ /// - Returns: The result of changing app language.
129
+ @discardableResult
130
+ public func changeAppLanguage(_ language: String?) -> Bool {
131
+ guard let language = language, language.count > 0 else {
132
+ appLanguage = nil
133
+ UserDefaults.standard.removeObject(forKey: appLanguageStorageKey)
134
+ UserDefaults.standard.synchronize()
135
+ return true
136
+ }
137
+
138
+ if LanguageUtil.isValidLanguage(language) {
139
+ appLanguage = language
140
+ UserDefaults.standard.set(language, forKey: appLanguageStorageKey)
141
+ UserDefaults.standard.synchronize()
142
+ return true
143
+ } else {
144
+ return false
145
+ }
146
+ }
147
+ }
@@ -0,0 +1,58 @@
1
+ //
2
+ // Bundle+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/7.
5
+ //
6
+
7
+ import Foundation
8
+ import FireworkVideo
9
+
10
+ extension Bundle {
11
+ static func swizzleBundleMethodsForAppLanguage() {
12
+ Swizzle.swizzleSelector(
13
+ cls: self,
14
+ originalSelector: #selector(Bundle.localizedString(forKey:value:table:)),
15
+ customSelector: #selector(Bundle.fw_localizedString(forKey:value:table:)))
16
+ }
17
+
18
+ @objc func fw_localizedString(
19
+ forKey key: String,
20
+ value: String?,
21
+ table tableName: String?
22
+ ) -> String {
23
+ if let language = AppLanguageManager.shared.appLanguage,
24
+ let languageCode = AppLanguageManager.shared.appLanguageCode,
25
+ Bundle(for: FireworkVideoSDK.self) == self {
26
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
27
+
28
+ var languageBundlePath: String?
29
+ let defaultLanguageBundlePath = iOSSDKBundle.path(forResource: "Base", ofType: "lproj")
30
+ if languageCode == "en" {
31
+ languageBundlePath = defaultLanguageBundlePath
32
+ } else if let path = iOSSDKBundle.path(forResource: language, ofType: "lproj") {
33
+ languageBundlePath = path
34
+ } else if let path = iOSSDKBundle.path(forResource: languageCode, ofType: "lproj") {
35
+ languageBundlePath = path
36
+ } else {
37
+ let targeLanguageList = iOSSDKBundle.localizations.filter { item in
38
+ return item != "Base" && item != "en"
39
+ }
40
+ if let targeLanguage = targeLanguageList.first(where: { item in
41
+ let targeLanguageCode = LanguageUtil.getLanguageCode(item)
42
+ return languageCode == targeLanguageCode
43
+ }) {
44
+ languageBundlePath = iOSSDKBundle.path(forResource: targeLanguage, ofType: "lproj")
45
+ }
46
+ }
47
+
48
+ if let resultLanguageBundlePath = languageBundlePath ?? defaultLanguageBundlePath,
49
+ let resultLanguageBundle = Bundle(path: resultLanguageBundlePath) {
50
+ return resultLanguageBundle.fw_localizedString(forKey: key, value: value, table: tableName)
51
+ } else {
52
+ return self.fw_localizedString(forKey: key, value: value, table: tableName)
53
+ }
54
+ } else {
55
+ return self.fw_localizedString(forKey: key, value: value, table: tableName)
56
+ }
57
+ }
58
+ }
@@ -0,0 +1,25 @@
1
+ //
2
+ // NumberFormatter+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/20.
5
+ //
6
+
7
+ import Foundation
8
+
9
+ extension NumberFormatter {
10
+ static func swizzleNumberFormatterMethodsForAppLanguage() {
11
+ Swizzle.swizzleSelector(
12
+ cls: self,
13
+ originalSelector: #selector(NumberFormatter.string(from:)),
14
+ customSelector: #selector(NumberFormatter.fw_string(from:)))
15
+ }
16
+
17
+ @objc func fw_string(from number: NSNumber) -> String? {
18
+ if let language = AppLanguageManager.shared.appLanguage,
19
+ self.numberStyle == .currency {
20
+ self.locale = Locale(identifier: language)
21
+ }
22
+
23
+ return fw_string(from: number)
24
+ }
25
+ }
@@ -0,0 +1,69 @@
1
+ //
2
+ // URLSession+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/20.
5
+ //
6
+
7
+ import Foundation
8
+
9
+ private var FWHostList: [String] = [
10
+ "api.firework.tv",
11
+ "p2.fwpixel.com"
12
+ ]
13
+
14
+ extension URLSession {
15
+ static func swizzleURLSessionMethodsForAppLanguage() {
16
+ // swiftlint:disable:next line_length
17
+ let orginalSelector1 = #selector(URLSession.dataTask(with:completionHandler:) as (URLSession) -> (URLRequest, @escaping (Data?, URLResponse?, Error?) -> Void) -> URLSessionDataTask)
18
+ let customSelector1 = #selector(URLSession.fw_dataTask(with:completionHandler:))
19
+ Swizzle.swizzleSelector(
20
+ cls: self,
21
+ originalSelector: orginalSelector1,
22
+ customSelector: customSelector1)
23
+ // swiftlint:disable:next line_length
24
+ let orginalSelector2 = #selector(URLSession.dataTask(with:) as (URLSession) -> (URLRequest) -> URLSessionDataTask)
25
+ let customSelector2 = #selector(URLSession.fw_dataTask(with:))
26
+ Swizzle.swizzleSelector(
27
+ cls: self,
28
+ originalSelector: orginalSelector2,
29
+ customSelector: customSelector2)
30
+ }
31
+
32
+ @objc func fw_dataTask(
33
+ with request: URLRequest,
34
+ completionHandler: @escaping @Sendable (Data?, URLResponse?, Error?) -> Void
35
+ ) -> URLSessionDataTask {
36
+ return fw_dataTask(with: swizzleRequest(request), completionHandler: completionHandler)
37
+ }
38
+
39
+ @objc func fw_dataTask(with request: URLRequest) -> URLSessionDataTask {
40
+ return fw_dataTask(with: swizzleRequest(request))
41
+ }
42
+
43
+ private func swizzleRequest(_ request: URLRequest) -> URLRequest {
44
+ var host = ""
45
+ #if compiler(>=5.7)
46
+ if #available(iOS 16, *) {
47
+ host = request.url?.host() ?? ""
48
+ } else {
49
+ host = request.url?.host ?? ""
50
+ }
51
+ #else
52
+ host = request.url?.host ?? ""
53
+ #endif
54
+
55
+ if let language = AppLanguageManager.shared.appLanguage,
56
+ let languageCode = AppLanguageManager.shared.appLanguageCode,
57
+ FWHostList.contains(host) {
58
+ var mutableRequest = request
59
+ if language != languageCode {
60
+ mutableRequest.setValue("\(language),\(languageCode);q=0.9", forHTTPHeaderField: "Accept-Language")
61
+ } else {
62
+ mutableRequest.setValue("\(language);q=0.9", forHTTPHeaderField: "Accept-Language")
63
+ }
64
+ return mutableRequest
65
+ }
66
+
67
+ return request
68
+ }
69
+ }
@@ -0,0 +1,91 @@
1
+ //
2
+ // UIImageView+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/22.
5
+ //
6
+
7
+ import UIKit
8
+ import FireworkVideo
9
+
10
+ private let FWImageNamesWithDirections: [String] = [
11
+ "shopping-cart",
12
+ "left-arrow",
13
+ "right-arrow",
14
+ "speaker-unmute",
15
+ "speaker-mute"
16
+ ]
17
+
18
+ extension UIImageView {
19
+ static func swizzleImageViewMethodsForAppLanguage() {
20
+ Swizzle.swizzleSelector(
21
+ cls: self,
22
+ originalSelector: #selector(UIImageView.didMoveToWindow),
23
+ customSelector: #selector(UIImageView.fw_imageViewDidMoveToWindow))
24
+ Swizzle.swizzleSelector(
25
+ cls: self,
26
+ originalSelector: #selector(setter: UIImageView.image),
27
+ customSelector: #selector(UIImageView.fw_setImage(_:))
28
+ )
29
+ Swizzle.swizzleSelector(
30
+ cls: self,
31
+ originalSelector: #selector(UIImageView.awakeFromNib),
32
+ customSelector: #selector(UIImageView.fw_imageViewAwakeFromNib)
33
+ )
34
+ }
35
+
36
+ @objc func fw_imageViewDidMoveToWindow() {
37
+ fw_imageViewDidMoveToWindow()
38
+ updateViewType(self.image)
39
+ }
40
+
41
+ @objc func fw_setImage(_ image: UIImage?) {
42
+ fw_setImage(image)
43
+ updateViewType(image)
44
+ }
45
+
46
+ @objc func fw_imageViewAwakeFromNib() {
47
+ self.fw_imageViewAwakeFromNib()
48
+ updateViewType(self.image)
49
+ }
50
+
51
+ private func updateViewType(_ image: UIImage?) {
52
+ self.viewType = shouldFlipImage(image) ? .flip : .auto
53
+ }
54
+
55
+ private func shouldFlipImage(_ image: UIImage?) -> Bool {
56
+ guard let image = image else {
57
+ return false
58
+ }
59
+
60
+ if AppLanguageManager.shared.shouldHorizontalFlip, self.isIOSSDKView {
61
+ let iOSSDKBundle = Bundle(for: FireworkVideoSDK.self)
62
+
63
+ for imageName in FWImageNamesWithDirections {
64
+ let targetImage = UIImage(named: imageName, in: iOSSDKBundle, compatibleWith: nil)
65
+ if image.isEqual(targetImage) {
66
+ return true
67
+ }
68
+
69
+ if let cgImage = image.cgImage,
70
+ let targetCgImage = targetImage?.cgImage,
71
+ cgImage == targetCgImage {
72
+ return true
73
+ }
74
+
75
+ if let ciImage = image.ciImage,
76
+ let targetCiImage = targetImage?.ciImage,
77
+ ciImage == targetCiImage {
78
+ return true
79
+ }
80
+ }
81
+ }
82
+
83
+ if AppLanguageManager.shared.shouldHorizontalFlip,
84
+ image.flipsForRightToLeftLayoutDirection == true,
85
+ self.isIOSSDKView {
86
+ return true
87
+ }
88
+
89
+ return false
90
+ }
91
+ }
@@ -0,0 +1,98 @@
1
+ //
2
+ // UILabel+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/22.
5
+ //
6
+
7
+ import UIKit
8
+
9
+ extension UILabel {
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 swizzleLabelMethodsForAppLanguage() {
31
+ Swizzle.swizzleSelector(cls: self,
32
+ originalSelector: #selector(setter: UILabel.textAlignment),
33
+ customSelector: #selector(UILabel.fw_setLabelTextAlignment(_:)))
34
+ Swizzle.swizzleSelector(cls: self,
35
+ originalSelector: #selector(UILabel.didMoveToWindow),
36
+ customSelector: #selector(UILabel.fw_labelDidMoveToWindow))
37
+ Swizzle.swizzleSelector(cls: self,
38
+ originalSelector: #selector(UILabel.removeFromSuperview),
39
+ customSelector: #selector(UILabel.fw_labelRemoveFromSuperview))
40
+ }
41
+
42
+ @objc func fw_setLabelTextAlignment(_ textAlignment: NSTextAlignment) {
43
+ addReloadClosure(key: "alignment") { [weak self] in
44
+ guard let self = self else {
45
+ return
46
+ }
47
+
48
+ self.fw_setLabelTextAlignment(self.calculatedTextAlignment(textAlignment))
49
+ }
50
+ }
51
+
52
+ @objc func fw_labelDidMoveToWindow() {
53
+ fw_labelDidMoveToWindow()
54
+ if shouldCalculateTextAlignment(),
55
+ !self.hasCalculatedTextAlignment,
56
+ self.isIOSSDKView {
57
+ self.textAlignment = self.textAlignment
58
+ }
59
+ }
60
+
61
+ @objc func fw_labelRemoveFromSuperview() {
62
+ fw_labelRemoveFromSuperview()
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
+ shouldUseCalculatedTextAlignment() {
93
+ return true
94
+ }
95
+
96
+ return false
97
+ }
98
+ }
@@ -0,0 +1,97 @@
1
+ //
2
+ // UITextField+AppLanguage.swift
3
+ //
4
+ // Created by linjie jiang on 2023/2/23.
5
+ //
6
+
7
+ import UIKit
8
+
9
+ extension UITextField {
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 swizzleTextFieldMethodsForAppLanguage() {
31
+ Swizzle.swizzleSelector(cls: self,
32
+ originalSelector: #selector(setter: UITextField.textAlignment),
33
+ customSelector: #selector(UITextField.fw_setTextFieldTextAlignment(_:)))
34
+ Swizzle.swizzleSelector(cls: self,
35
+ originalSelector: #selector(UITextField.didMoveToWindow),
36
+ customSelector: #selector(UITextField.fw_textFieldDidMoveToWindow))
37
+ Swizzle.swizzleSelector(cls: self,
38
+ originalSelector: #selector(UITextField.removeFromSuperview),
39
+ customSelector: #selector(UITextField.fw_textFieldRemoveFromSuperview))
40
+ }
41
+
42
+ @objc func fw_setTextFieldTextAlignment(_ textAlignment: NSTextAlignment) {
43
+ addReloadClosure(key: "alignment") { [weak self] in
44
+ guard let self = self else {
45
+ return
46
+ }
47
+
48
+ self.fw_setTextFieldTextAlignment(self.calculatedTextAlignment(textAlignment))
49
+ }
50
+ }
51
+
52
+ @objc func fw_textFieldDidMoveToWindow() {
53
+ fw_textFieldDidMoveToWindow()
54
+ if shouldCalculateTextAlignment(),
55
+ !self.hasCalculatedTextAlignment,
56
+ self.isIOSSDKView {
57
+ self.textAlignment = self.textAlignment
58
+ }
59
+ }
60
+
61
+ @objc func fw_textFieldRemoveFromSuperview() {
62
+ fw_textFieldRemoveFromSuperview()
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
+ }