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.
- package/android/src/main/java/com/fireworksdk/bridge/components/videofeed/FWVideoFeed.kt +0 -1
- package/android/src/main/java/com/fireworksdk/bridge/models/FWEventName.kt +1 -0
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/models/FWVideoShoppingInterface.kt +1 -0
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/module/FWVideoShoppingModule.kt +11 -1
- package/android/src/main/java/com/fireworksdk/bridge/reactnative/utils/FWEventUtils.kt +9 -0
- package/android/src/main/java/com/fireworksdk/bridge/utils/FWLanguageUtil.kt +0 -2
- package/android/src/main/java/com/fireworksdk/bridge/utils/FWVideoPlayerUtils.kt +1 -0
- package/ios/Components/StoryBlock.swift +6 -9
- package/ios/Components/StoryBlockManager.swift +4 -0
- package/ios/Components/VideoFeed.swift +14 -15
- package/ios/Components/VideoFeedConfiguration.swift +2 -0
- package/ios/Components/VideoFeedManager.m +2 -0
- package/ios/Components/VideoFeedManager.swift +4 -0
- package/ios/Components/VideoPlayerConfiguration.swift +1 -0
- package/ios/FireworkSdk-Bridging-Header.h +6 -0
- package/ios/FireworkSdk.xcodeproj/project.pbxproj +374 -200
- package/ios/Models/Common/FontInfo.swift +57 -0
- package/ios/Models/NativeToRN/FireworkEventName.swift +1 -0
- package/ios/Modules/FWNavigatorModule/FWNavigatorModule.m +2 -0
- package/ios/Modules/FWNavigatorModule/FWNavigatorModule.swift +271 -107
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule+EventTracking.swift +0 -2
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.m +1 -0
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +43 -12
- package/ios/Modules/LiveStream/LiveStreamModule.swift +5 -3
- package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +7 -2
- package/ios/Modules/Shopping/ShoppingModule.m +1 -1
- package/ios/Modules/Shopping/ShoppingModule.swift +72 -63
- package/ios/Utils/AppLanguage/Bundle+FWSwizzle.swift +58 -0
- package/ios/Utils/AppLanguage/FWAppLanguageManager.swift +118 -0
- package/ios/Utils/AppLanguage/FWLanguageUtil.swift +39 -0
- package/ios/Utils/AppLanguage/NumberFormatter+FWSwizzle.swift +25 -0
- package/ios/Utils/AppLanguage/UIImageView+FWSwizzle.swift +91 -0
- package/ios/Utils/AppLanguage/UILabel+FWSwizzle.swift +98 -0
- package/ios/Utils/AppLanguage/UITextField+FWSwizzle.swift +97 -0
- package/ios/Utils/AppLanguage/UITextView+FWSwizzle.swift +97 -0
- package/ios/Utils/AppLanguage/UIView+FWSwizzle.swift +38 -0
- package/ios/Utils/AppLanguage/UIViewController+FWSwizzle.swift +32 -0
- package/ios/Utils/AppLanguage/UIWindow+FWSwizzle.swift +26 -0
- package/ios/Utils/AppLanguage/URLSession+FWSwizzle.swift +69 -0
- package/ios/Utils/{DispatchQueue+FWOnce.swift → Extensions/DispatchQueue+FWOnce.swift} +3 -3
- package/ios/Utils/{UINavigationController+FWSwizzle.swift → Extensions/Swizzle/UINavigationController+FWSwizzle.swift} +6 -8
- package/ios/Utils/Extensions/UIView+FWUIHierarchy.swift +47 -0
- package/ios/Utils/FWRTL/Classes/Manager/FWRTLManager.h +25 -0
- package/ios/Utils/FWRTL/Classes/Manager/FWRTLManager.m +75 -0
- package/ios/Utils/FWRTL/Classes/UICategories/CALayer+FWRTL.h +21 -0
- package/ios/Utils/FWRTL/Classes/UICategories/CALayer+FWRTL.m +124 -0
- package/ios/Utils/FWRTL/Classes/UICategories/FWRTLRemoteViewControllerAdaptor.h +11 -0
- package/ios/Utils/FWRTL/Classes/UICategories/FWRTLRemoteViewControllerAdaptor.m +86 -0
- package/ios/Utils/FWRTL/Classes/UICategories/FWRTLWhiteListManager.h +16 -0
- package/ios/Utils/FWRTL/Classes/UICategories/FWRTLWhiteListManager.m +55 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UILabel+FWRTL.h +18 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UILabel+FWRTL.m +39 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UIView+FWRTL.h +54 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UIView+FWRTL.m +141 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UIWindow+FWRTL.h +16 -0
- package/ios/Utils/FWRTL/Classes/UICategories/UIWindow+FWRTL.m +20 -0
- package/ios/Utils/FWRTL/Classes/Utils/FWRTLDefinitions.h +52 -0
- package/ios/Utils/FWRTL/Classes/Utils/NSObject+FWRTLReloadBlock.h +19 -0
- package/ios/Utils/FWRTL/Classes/Utils/NSObject+FWRTLReloadBlock.m +49 -0
- package/ios/Utils/FWRTL/Classes/Utils/NSString+FWRTL.h +21 -0
- package/ios/Utils/FWRTL/Classes/Utils/NSString+FWRTL.m +38 -0
- package/ios/Utils/FWRTL/Classes/Utils/UIImage+FWRTL.h +18 -0
- package/ios/Utils/FWRTL/Classes/Utils/UIImage+FWRTL.m +43 -0
- package/ios/Utils/FWSwizzleLoader.m +1 -2
- package/ios/Utils/FWSwizzleLoader.swift +13 -0
- package/ios/Utils/FWSwizzleUtil.swift +17 -9
- package/ios/react_native_firework_sdk.h +1 -0
- package/ios/scripts/firework_sdk_pods.rb +3 -0
- package/lib/commonjs/FWNavigator.js +32 -1
- package/lib/commonjs/FWNavigator.js.map +1 -1
- package/lib/commonjs/FireworkSDK.js +26 -12
- package/lib/commonjs/FireworkSDK.js.map +1 -1
- package/lib/commonjs/VideoShopping.js +64 -9
- package/lib/commonjs/VideoShopping.js.map +1 -1
- package/lib/commonjs/components/VideoFeed.js +26 -5
- package/lib/commonjs/components/VideoFeed.js.map +1 -1
- package/lib/commonjs/index.js +6 -0
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/models/FWEventName.js +2 -0
- package/lib/commonjs/models/FWEventName.js.map +1 -1
- package/lib/commonjs/models/IOSFontInfo.js +2 -0
- package/lib/commonjs/models/IOSFontInfo.js.map +1 -0
- package/lib/commonjs/modules/FWNavigatorModule.js.map +1 -1
- package/lib/commonjs/modules/ShoppingModule.js.map +1 -1
- package/lib/module/FWNavigator.js +31 -1
- package/lib/module/FWNavigator.js.map +1 -1
- package/lib/module/FireworkSDK.js +27 -11
- package/lib/module/FireworkSDK.js.map +1 -1
- package/lib/module/VideoShopping.js +63 -9
- package/lib/module/VideoShopping.js.map +1 -1
- package/lib/module/components/VideoFeed.js +21 -5
- package/lib/module/components/VideoFeed.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/models/FWEventName.js +2 -0
- package/lib/module/models/FWEventName.js.map +1 -1
- package/lib/module/models/IOSFontInfo.js +2 -0
- package/lib/module/models/IOSFontInfo.js.map +1 -0
- package/lib/module/modules/FWNavigatorModule.js.map +1 -1
- package/lib/module/modules/ShoppingModule.js.map +1 -1
- package/lib/typescript/FWNavigator.d.ts +17 -2
- package/lib/typescript/FireworkSDK.d.ts +9 -5
- package/lib/typescript/LiveStream.d.ts +2 -2
- package/lib/typescript/VideoShopping.d.ts +33 -11
- package/lib/typescript/components/VideoFeed.d.ts +5 -1
- package/lib/typescript/index.d.ts +8 -4
- package/lib/typescript/models/AdBadgeConfiguration.d.ts +1 -1
- package/lib/typescript/models/FWEventName.d.ts +3 -1
- package/lib/typescript/models/FWEvents.d.ts +5 -0
- package/lib/typescript/models/IOSFontInfo.d.ts +19 -0
- package/lib/typescript/models/NewNativeContainerProps.d.ts +1 -1
- package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +23 -0
- package/lib/typescript/models/StoryBlockSource.d.ts +1 -1
- package/lib/typescript/models/VideoFeedConfiguration.d.ts +20 -2
- package/lib/typescript/models/VideoFeedSource.d.ts +1 -1
- package/lib/typescript/models/VideoPlayerConfiguration.d.ts +20 -4
- package/lib/typescript/modules/FWNavigatorModule.d.ts +2 -0
- package/lib/typescript/modules/ShoppingModule.d.ts +2 -1
- package/package.json +7 -4
- package/react-native-firework-sdk.podspec +15 -18
- package/src/{FWNavigator.tsx → FWNavigator.ts} +30 -2
- package/src/FireworkSDK.ts +24 -13
- package/src/VideoShopping.ts +86 -20
- package/src/components/VideoFeed.tsx +24 -2
- package/src/{index.tsx → index.ts} +24 -1
- package/src/models/FWEventName.ts +2 -0
- package/src/models/FWEvents.ts +6 -0
- package/src/models/IOSFontInfo.ts +29 -0
- package/src/models/ProductInfoViewConfiguration.ts +25 -0
- package/src/models/VideoFeedConfiguration.ts +20 -1
- package/src/models/VideoPlayerConfiguration.ts +17 -0
- package/src/modules/FWNavigatorModule.ts +2 -0
- package/src/modules/ShoppingModule.ts +2 -4
- package/ios/Utils/FWPiPManager.swift +0 -24
- package/ios/Utils/UIButton+FWSwizzle.swift +0 -33
- package/ios/Utils/UIView+ParentViewController.swift +0 -21
- /package/ios/Utils/{String+Color.swift → Extensions/String+Color.swift} +0 -0
- /package/ios/Utils/{UIView+Constraints.swift → Extensions/UIView+Constraints.swift} +0 -0
- /package/ios/Utils/{UIViewController+AttachChild.swift → Extensions/UIViewController+AttachChild.swift} +0 -0
|
@@ -21,6 +21,7 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate, CartViewCo
|
|
|
21
21
|
private var cartIconVisible = true
|
|
22
22
|
private var itemCounts = 0
|
|
23
23
|
private var customClickCartIconEnabled = false
|
|
24
|
+
private var productInfoViewConfiguration: ProductInfoViewConfiguration?
|
|
24
25
|
|
|
25
26
|
override func supportedEvents() -> [String]! {
|
|
26
27
|
ShoppingEventName.allCases.map { $0.rawValue }
|
|
@@ -30,6 +31,10 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate, CartViewCo
|
|
|
30
31
|
return true
|
|
31
32
|
}
|
|
32
33
|
|
|
34
|
+
override var methodQueue: DispatchQueue {
|
|
35
|
+
return DispatchQueue.main
|
|
36
|
+
}
|
|
37
|
+
|
|
33
38
|
private static func generateCallbackId() -> Int {
|
|
34
39
|
struct CBIdIncreasingFactor {
|
|
35
40
|
static var callbackId = 0
|
|
@@ -41,15 +46,18 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate, CartViewCo
|
|
|
41
46
|
|
|
42
47
|
@objc
|
|
43
48
|
func initialize() {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
FireworkVideoSDK.shopping.cartViewControllerProvider = self
|
|
47
|
-
}
|
|
49
|
+
FireworkVideoSDK.shopping.shoppingDelegate = self
|
|
50
|
+
FireworkVideoSDK.shopping.cartViewControllerProvider = self
|
|
48
51
|
}
|
|
49
52
|
|
|
50
53
|
@objc
|
|
51
54
|
func setCartIconVisible(_ visible: Bool) {
|
|
52
55
|
cartIconVisible = visible
|
|
56
|
+
guard let rProductInfoViewConfigurator = productInfoViewConfigurator else {
|
|
57
|
+
return
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
rProductInfoViewConfigurator.1.shoppingCartIconConfiguration.isHidden = !visible
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
@objc
|
|
@@ -59,13 +67,8 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate, CartViewCo
|
|
|
59
67
|
guard let rProductInfoViewConfigurator = productInfoViewConfigurator else {
|
|
60
68
|
return
|
|
61
69
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
.shoppingCartIconConfiguration
|
|
65
|
-
shoppingCartIconConfiguration.indicator.isHidden = itemCounts == 0
|
|
66
|
-
rProductInfoViewConfigurator.1.shoppingCartIconConfiguration =
|
|
67
|
-
shoppingCartIconConfiguration
|
|
68
|
-
}
|
|
70
|
+
|
|
71
|
+
rProductInfoViewConfigurator.1.shoppingCartIconConfiguration.indicator.isHidden = itemCounts == 0
|
|
69
72
|
}
|
|
70
73
|
|
|
71
74
|
@objc
|
|
@@ -119,33 +122,11 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate, CartViewCo
|
|
|
119
122
|
])
|
|
120
123
|
#endif
|
|
121
124
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
product
|
|
126
|
-
|
|
127
|
-
})
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
@objc
|
|
133
|
-
func updateProductViewConfig(_ config: [String: Any]?, cbId: NSNumber) {
|
|
134
|
-
let config = RCTConvert.buildProductInfoViewConfiguration(config)
|
|
135
|
-
guard let rConfig = config, let rProductInfoViewConfigurator = productInfoViewConfigurator,
|
|
136
|
-
rProductInfoViewConfigurator.0 == Int(truncating: cbId)
|
|
137
|
-
else {
|
|
138
|
-
return
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
DispatchQueue.main.async {
|
|
142
|
-
// The configuration of CartIcon'visible determined by global cartIconVisible
|
|
143
|
-
rProductInfoViewConfigurator.1.shoppingCartIconConfiguration.isHidden = !self
|
|
144
|
-
.cartIconVisible
|
|
145
|
-
// The configuration of CartIcon'indicator'visible determined by global itemCounts
|
|
146
|
-
rProductInfoViewConfigurator.1.shoppingCartIconConfiguration.indicator.isHidden =
|
|
147
|
-
self.itemCounts == 0
|
|
148
|
-
ShoppingModule.hydrateProductViewConfig(rConfig, rProductInfoViewConfigurator.1)
|
|
125
|
+
for product in rProducts {
|
|
126
|
+
productHydrating.hydrateProduct(
|
|
127
|
+
product.productId, { build in
|
|
128
|
+
return ShoppingModule.hydrateProduct(product, build)
|
|
129
|
+
})
|
|
149
130
|
}
|
|
150
131
|
}
|
|
151
132
|
|
|
@@ -157,27 +138,23 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate, CartViewCo
|
|
|
157
138
|
|
|
158
139
|
addToCartHandlerMap.removeValue(forKey: Int(truncating: cbId))
|
|
159
140
|
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
handler(.feedbackOnly(.failure(message: tips ?? "failure")))
|
|
165
|
-
}
|
|
141
|
+
if res == "success" {
|
|
142
|
+
handler(.feedbackOnly(.success(message: tips ?? "success")))
|
|
143
|
+
} else {
|
|
144
|
+
handler(.feedbackOnly(.failure(message: tips ?? "failure")))
|
|
166
145
|
}
|
|
167
146
|
}
|
|
168
147
|
|
|
169
148
|
@objc
|
|
170
149
|
func jumpToCartPage(_ cbId: NSNumber, props: NSDictionary) {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
NotificationCenter.default.post(noti)
|
|
180
|
-
}
|
|
150
|
+
let properties: [String: Any] = (props as? [String: Any]) ?? [:]
|
|
151
|
+
let noti = Notification(
|
|
152
|
+
name: Notification.Name(rawValue: "showCustomCartView"), object: nil,
|
|
153
|
+
userInfo: [
|
|
154
|
+
"cbId": Int(truncating: cbId),
|
|
155
|
+
"properties": properties
|
|
156
|
+
])
|
|
157
|
+
NotificationCenter.default.post(noti)
|
|
181
158
|
}
|
|
182
159
|
|
|
183
160
|
@objc
|
|
@@ -189,6 +166,22 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate, CartViewCo
|
|
|
189
166
|
resolver([:])
|
|
190
167
|
}
|
|
191
168
|
|
|
169
|
+
@objc
|
|
170
|
+
func setProductInfoViewConfiguration(_ config: [String: Any]?) {
|
|
171
|
+
let config = RCTConvert.buildProductInfoViewConfiguration(config)
|
|
172
|
+
guard let rConfig = config else {
|
|
173
|
+
return
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
productInfoViewConfiguration = rConfig
|
|
177
|
+
|
|
178
|
+
guard let rProductInfoViewConfigurator = productInfoViewConfigurator else {
|
|
179
|
+
return
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
ShoppingModule.hydrateProductViewConfig(rConfig, rProductInfoViewConfigurator.1)
|
|
183
|
+
}
|
|
184
|
+
|
|
192
185
|
@objc
|
|
193
186
|
func clearCallbackId(_ cbId: NSNumber, eventName: String) {
|
|
194
187
|
if eventName == ShoppingEventName.updateProductDetails.rawValue {
|
|
@@ -207,6 +200,11 @@ class ShoppingModule: RCTEventEmitter, FireworkVideoShoppingDelegate, CartViewCo
|
|
|
207
200
|
let callbackId = ShoppingModule.generateCallbackId()
|
|
208
201
|
self.productInfoViewConfigurator = (callbackId, productInfoViewConfigurator)
|
|
209
202
|
productInfoViewConfigurator.shoppingCartIconConfiguration.isHidden = !self.cartIconVisible
|
|
203
|
+
productInfoViewConfigurator.shoppingCartIconConfiguration.indicator.isHidden = itemCounts == 0
|
|
204
|
+
|
|
205
|
+
if let productInfoViewConfiguration = productInfoViewConfiguration {
|
|
206
|
+
ShoppingModule.hydrateProductViewConfig(productInfoViewConfiguration, productInfoViewConfigurator)
|
|
207
|
+
}
|
|
210
208
|
|
|
211
209
|
#if DEBUG
|
|
212
210
|
let formatter = DateFormatter()
|
|
@@ -290,21 +288,32 @@ extension ShoppingModule {
|
|
|
290
288
|
_ config: ProductInfoViewConfiguration,
|
|
291
289
|
_ productInfoViewConfigurator: ProductInfoViewConfigurable
|
|
292
290
|
) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
291
|
+
var productDetailsConfiguration = productInfoViewConfigurator.productDetailsConfiguration
|
|
292
|
+
|
|
293
|
+
if let addToCartButtonConfiguration = config.addToCartButton {
|
|
294
|
+
if let backgroundColor = addToCartButtonConfiguration.backgroundColor,
|
|
296
295
|
backgroundColor.count > 0 {
|
|
297
|
-
|
|
296
|
+
productDetailsConfiguration.addToCartButton.backgroundColor = backgroundColor.uicolor()
|
|
298
297
|
}
|
|
299
|
-
|
|
298
|
+
|
|
299
|
+
if let textColor = addToCartButtonConfiguration.textColor,
|
|
300
300
|
textColor.count > 0 {
|
|
301
|
-
|
|
301
|
+
productDetailsConfiguration.addToCartButton.textColor = textColor.uicolor()
|
|
302
302
|
}
|
|
303
|
-
|
|
304
|
-
|
|
303
|
+
|
|
304
|
+
if let fontSize = addToCartButtonConfiguration.fontSize {
|
|
305
|
+
let iOSFontInfo = addToCartButtonConfiguration.iOSFontInfo ?? FontInfo()
|
|
306
|
+
productDetailsConfiguration.addToCartButton.font = iOSFontInfo.getFont(fontSize)
|
|
305
307
|
}
|
|
306
|
-
productInfoViewConfigurator.productDetailsConfiguration = config
|
|
307
308
|
}
|
|
309
|
+
|
|
310
|
+
if let linkButtonConfiguration = config.linkButton {
|
|
311
|
+
if let isHidden = linkButtonConfiguration.isHidden {
|
|
312
|
+
productDetailsConfiguration.linkButtonConfiguration.isHidden = isHidden
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
productInfoViewConfigurator.productDetailsConfiguration = productDetailsConfiguration
|
|
308
317
|
}
|
|
309
318
|
|
|
310
319
|
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Bundle+FWSwizzle.swift
|
|
3
|
+
//
|
|
4
|
+
// Created by linjie jiang on 2023/2/7.
|
|
5
|
+
//
|
|
6
|
+
|
|
7
|
+
import Foundation
|
|
8
|
+
import FireworkVideo
|
|
9
|
+
|
|
10
|
+
public extension Bundle {
|
|
11
|
+
static func swizzleMethodsForBundle() {
|
|
12
|
+
FWSwizzleUtil.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 = FWAppLanguageManager.shared.appLanguage,
|
|
24
|
+
let languageCode = FWAppLanguageManager.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 = FWLanguageUtil.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,118 @@
|
|
|
1
|
+
//
|
|
2
|
+
// FWAppLanguageManager.swift
|
|
3
|
+
//
|
|
4
|
+
// Created by linjie jiang on 2023/2/7.
|
|
5
|
+
//
|
|
6
|
+
|
|
7
|
+
import Foundation
|
|
8
|
+
|
|
9
|
+
private let appLanguageStorageKey = "firework_sdk_app_language_storage_key"
|
|
10
|
+
|
|
11
|
+
public enum AppLanguageLayoutDirection: Int {
|
|
12
|
+
case ltr, rtl, unsupported
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
public class FWAppLanguageManager {
|
|
16
|
+
public static let shared = FWAppLanguageManager()
|
|
17
|
+
|
|
18
|
+
private var _systemLanguage: String?
|
|
19
|
+
private var _systemLanguageCode: String? {
|
|
20
|
+
guard let language = _systemLanguage else {
|
|
21
|
+
return nil
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return FWLanguageUtil.getLanguageCode(language)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public var appLanguage: String? {
|
|
28
|
+
didSet {
|
|
29
|
+
if appLanguage != nil {
|
|
30
|
+
FWAppLanguageManager.swizzelMethods()
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public var appLanguageCode: String? {
|
|
36
|
+
guard let language = appLanguage else {
|
|
37
|
+
return nil
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return FWLanguageUtil.getLanguageCode(language)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public var appLanguageLayoutDirection: AppLanguageLayoutDirection? {
|
|
44
|
+
guard let languageCode = appLanguageCode else {
|
|
45
|
+
return nil
|
|
46
|
+
}
|
|
47
|
+
let direction = Locale.characterDirection(forLanguage: languageCode)
|
|
48
|
+
switch direction {
|
|
49
|
+
case .leftToRight:
|
|
50
|
+
return .ltr
|
|
51
|
+
case .rightToLeft:
|
|
52
|
+
return .rtl
|
|
53
|
+
default:
|
|
54
|
+
return .unsupported
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public var shouldHorizontalFlip: Bool {
|
|
59
|
+
guard let appLanguageCode = appLanguageCode else {
|
|
60
|
+
return false
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
guard let systemLanguageCode = _systemLanguageCode else {
|
|
64
|
+
return false
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
let appLanguageDirection = Locale.characterDirection(forLanguage: appLanguageCode)
|
|
68
|
+
let systemLanguageDirection = Locale.characterDirection(forLanguage: systemLanguageCode)
|
|
69
|
+
|
|
70
|
+
if appLanguageDirection == .leftToRight, systemLanguageDirection == .rightToLeft {
|
|
71
|
+
return true
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
if appLanguageDirection == .rightToLeft, systemLanguageDirection == .leftToRight {
|
|
75
|
+
return true
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
return false
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
private static func swizzelMethods() {
|
|
82
|
+
DispatchQueue.once {
|
|
83
|
+
UIViewController.swizzleMethodsForViewController()
|
|
84
|
+
Bundle.swizzleMethodsForBundle()
|
|
85
|
+
URLSession.swizzleMethodsForURLSession()
|
|
86
|
+
NumberFormatter.swizzleMethodsForNumberFormatter()
|
|
87
|
+
UIImageView.swizzleMethodsForImageView()
|
|
88
|
+
UILabel.swizzleMethodsForLabel()
|
|
89
|
+
UITextField.swizzleMethodsForTextField()
|
|
90
|
+
UITextView.swizzleMethodsForTextView()
|
|
91
|
+
UIWindow.swizzleMethodsForWindow()
|
|
92
|
+
UIView.swizzleMethodsForView()
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private init() {
|
|
97
|
+
self._systemLanguage = Locale.preferredLanguages.first
|
|
98
|
+
self.appLanguage = UserDefaults.standard.object(forKey: appLanguageStorageKey) as? String
|
|
99
|
+
#if DEBUG
|
|
100
|
+
print("""
|
|
101
|
+
FWAppLanguageManager init method
|
|
102
|
+
current app language: \(self.appLanguage ?? "")
|
|
103
|
+
system language: \(self._systemLanguage ?? "")
|
|
104
|
+
""")
|
|
105
|
+
#endif
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
public func changeAppLanguage(_ language: String) -> Bool {
|
|
109
|
+
if FWLanguageUtil.isValidLanguage(language) {
|
|
110
|
+
appLanguage = language
|
|
111
|
+
UserDefaults.standard.set(language, forKey: appLanguageStorageKey)
|
|
112
|
+
UserDefaults.standard.synchronize()
|
|
113
|
+
return true
|
|
114
|
+
} else {
|
|
115
|
+
return false
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
//
|
|
2
|
+
// FWLanguageUtil.swift
|
|
3
|
+
//
|
|
4
|
+
// Created by linjie jiang on 2023/2/9.
|
|
5
|
+
//
|
|
6
|
+
|
|
7
|
+
import Foundation
|
|
8
|
+
|
|
9
|
+
public class FWLanguageUtil {
|
|
10
|
+
public 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
|
+
public static func isValidLanguage(_ language: String) -> Bool {
|
|
29
|
+
guard language.count > 0 else {
|
|
30
|
+
return false
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
let languageWithUnderline = language.replacingOccurrences(of: "-", with: "_")
|
|
34
|
+
|
|
35
|
+
let availableIdentifiers = Locale.availableIdentifiers
|
|
36
|
+
|
|
37
|
+
return availableIdentifiers.contains(language) || availableIdentifiers.contains(languageWithUnderline)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
//
|
|
2
|
+
// NumberFormatter+FWSwizzle.swift
|
|
3
|
+
//
|
|
4
|
+
// Created by linjie jiang on 2023/2/20.
|
|
5
|
+
//
|
|
6
|
+
|
|
7
|
+
import Foundation
|
|
8
|
+
|
|
9
|
+
public extension NumberFormatter {
|
|
10
|
+
static func swizzleMethodsForNumberFormatter() {
|
|
11
|
+
FWSwizzleUtil.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 = FWAppLanguageManager.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,91 @@
|
|
|
1
|
+
//
|
|
2
|
+
// UIImageView+FWSwizzle.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 swizzleMethodsForImageView() {
|
|
20
|
+
FWSwizzleUtil.swizzleSelector(
|
|
21
|
+
cls: self,
|
|
22
|
+
originalSelector: #selector(UIImageView.didMoveToWindow),
|
|
23
|
+
customSelector: #selector(UIImageView.fw_imageViewDidMoveToWindow))
|
|
24
|
+
FWSwizzleUtil.swizzleSelector(
|
|
25
|
+
cls: self,
|
|
26
|
+
originalSelector: #selector(setter: UIImageView.image),
|
|
27
|
+
customSelector: #selector(UIImageView.fw_setImage(_:))
|
|
28
|
+
)
|
|
29
|
+
FWSwizzleUtil.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.fwrtl_viewType = shouldFlipImage(image) ? FWRTLViewTypeFlip : FWRTLViewTypeAuto
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private func shouldFlipImage(_ image: UIImage?) -> Bool {
|
|
56
|
+
guard let image = image else {
|
|
57
|
+
return false
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if FWAppLanguageManager.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 FWAppLanguageManager.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+FWSwizzle.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 fwHasCalculatedTextAlignment = "fwHasCalculatedTextAlignmentKey"
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private var fwHasCalculatedTextAlignment: Bool {
|
|
15
|
+
get {
|
|
16
|
+
let result = objc_getAssociatedObject(self, &AssociatedKeys.fwHasCalculatedTextAlignment) as? Bool
|
|
17
|
+
return result ?? false
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
set {
|
|
21
|
+
objc_setAssociatedObject(
|
|
22
|
+
self,
|
|
23
|
+
&AssociatedKeys.fwHasCalculatedTextAlignment,
|
|
24
|
+
newValue,
|
|
25
|
+
.OBJC_ASSOCIATION_RETAIN_NONATOMIC
|
|
26
|
+
)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
static func swizzleMethodsForLabel() {
|
|
31
|
+
FWSwizzleUtil.swizzleSelector(cls: self,
|
|
32
|
+
originalSelector: #selector(setter: UILabel.textAlignment),
|
|
33
|
+
customSelector: #selector(UILabel.fw_setLabelTextAlignment(_:)))
|
|
34
|
+
FWSwizzleUtil.swizzleSelector(cls: self,
|
|
35
|
+
originalSelector: #selector(UILabel.didMoveToWindow),
|
|
36
|
+
customSelector: #selector(UILabel.fw_labelDidMoveToWindow))
|
|
37
|
+
FWSwizzleUtil.swizzleSelector(cls: self,
|
|
38
|
+
originalSelector: #selector(UILabel.removeFromSuperview),
|
|
39
|
+
customSelector: #selector(UILabel.fw_labelRemoveFromSuperview))
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
@objc func fw_setLabelTextAlignment(_ textAlignment: NSTextAlignment) {
|
|
43
|
+
self.fwrtl_addReloadBlock(forKey: "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.fwHasCalculatedTextAlignment,
|
|
56
|
+
self.isIOSSDKView {
|
|
57
|
+
self.textAlignment = self.textAlignment
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
@objc func fw_labelRemoveFromSuperview() {
|
|
62
|
+
fw_labelRemoveFromSuperview()
|
|
63
|
+
self.fwHasCalculatedTextAlignment = false
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
private func calculatedTextAlignment(_ textAlignment: NSTextAlignment) -> NSTextAlignment {
|
|
67
|
+
if shouldCalculateTextAlignment(),
|
|
68
|
+
let layoutDirection = FWAppLanguageManager.shared.appLanguageLayoutDirection {
|
|
69
|
+
self.fwHasCalculatedTextAlignment = 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 FWAppLanguageManager.shared.shouldHorizontalFlip,
|
|
89
|
+
self.isIOSSDKView,
|
|
90
|
+
let layoutDirection = FWAppLanguageManager.shared.appLanguageLayoutDirection,
|
|
91
|
+
layoutDirection != .unsupported,
|
|
92
|
+
fwrtl_shouldUseCalculatedTextAlignment() {
|
|
93
|
+
return true
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return false
|
|
97
|
+
}
|
|
98
|
+
}
|