react-native-firework-sdk 1.0.0-beta
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/README.md +39 -0
- package/android/build.gradle +193 -0
- package/android/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/android/gradle/wrapper/gradle-wrapper.properties +5 -0
- package/android/gradle.properties +5 -0
- package/android/gradlew +185 -0
- package/android/gradlew.bat +89 -0
- package/android/publish.gradle +65 -0
- package/android/src/main/AndroidManifest.xml +16 -0
- package/android/src/main/java/com/reactnativefireworksdk/FireworkSDKPackage.kt +20 -0
- package/android/src/main/java/com/reactnativefireworksdk/components/videofeed/FWVideoFeed.kt +123 -0
- package/android/src/main/java/com/reactnativefireworksdk/constants/FWCommandConstant.kt +6 -0
- package/android/src/main/java/com/reactnativefireworksdk/constants/FWVideoPlayerConstant.kt +20 -0
- package/android/src/main/java/com/reactnativefireworksdk/manager/FWVideoFeedManager.kt +88 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWEventName.kt +35 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoFeedConfigModel.kt +27 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoFeedItemDetailsModel.kt +11 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoFeedMode.kt +7 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoFeedSource.kt +7 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoFeedTitlePosition.kt +7 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoPlaybackDetails.kt +19 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoPlayerConfigModel.kt +20 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoShoppingInterface.kt +13 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FWVideoShoppingProduct.kt +34 -0
- package/android/src/main/java/com/reactnativefireworksdk/models/FireworkSDKInterface.kt +12 -0
- package/android/src/main/java/com/reactnativefireworksdk/module/FWVideoShoppingModule.kt +190 -0
- package/android/src/main/java/com/reactnativefireworksdk/module/FireworkSDKModule.kt +248 -0
- package/android/src/main/java/com/reactnativefireworksdk/pages/FWVideoShoppingCartActivity.kt +43 -0
- package/android/src/main/java/com/reactnativefireworksdk/utils/FWEventUtils.kt +127 -0
- package/android/src/main/java/com/reactnativefireworksdk/utils/FWJsonUtils.kt +57 -0
- package/android/src/main/java/com/reactnativefireworksdk/utils/FWLogUtils.kt +147 -0
- package/android/src/main/java/com/reactnativefireworksdk/utils/FWUrlUtils.kt +68 -0
- package/android/src/main/java/com/reactnativefireworksdk/utils/FWVideoPlayerUtils.kt +18 -0
- package/android/src/main/res/layout/fwrn_fragment_shoppingcart.xml +8 -0
- package/android/src/main/res/layout/fwrn_fragment_videofeed.xml +20 -0
- package/android/src/main/res/values/styles.xml +43 -0
- package/ios/Component/VideoFeed.swift +262 -0
- package/ios/Component/VideoFeedConfiguration.swift +32 -0
- package/ios/Component/VideoFeedManager.m +51 -0
- package/ios/Component/VideoFeedManager.swift +40 -0
- package/ios/Component/VideoPlayerConfiguration.swift +30 -0
- package/ios/FireworkSdk-Bridging-Header.h +6 -0
- package/ios/FireworkSdk.xcodeproj/project.pbxproj +291 -0
- package/ios/Models/FireworkJsEvent.swift +34 -0
- package/ios/Models/FireworkSDK+JsModel.swift +62 -0
- package/ios/Models/RCTConvert+FireworkSDKModule.swift +91 -0
- package/ios/Models/RCTConvert+Shopping.swift +49 -0
- package/ios/Models/RCTConvert+VideoFeed.swift +69 -0
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule+CTA.swift +17 -0
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule+EventTracking.swift +74 -0
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.m +19 -0
- package/ios/Modules/FireworkSDKModule/FireworkSDKModule.swift +106 -0
- package/ios/Modules/FireworkSDKModule/MobileADConfiguration.swift +17 -0
- package/ios/Modules/Shopping/CartViewController.swift +98 -0
- package/ios/Modules/Shopping/Product.swift +33 -0
- package/ios/Modules/Shopping/ProductInfoViewConfiguration.swift +24 -0
- package/ios/Modules/Shopping/ShoppingModule.m +19 -0
- package/ios/Modules/Shopping/ShoppingModule.swift +214 -0
- package/ios/Utils/String+Color.swift +38 -0
- package/ios/Utils/UIView+Constraints.swift +91 -0
- package/ios/Utils/UIView+ParentViewController.swift +21 -0
- package/ios/Utils/UIViewController+AttachChild.swift +69 -0
- package/lib/commonjs/FireworkSDK.js +171 -0
- package/lib/commonjs/FireworkSDK.js.map +1 -0
- package/lib/commonjs/VideoShopping.js +146 -0
- package/lib/commonjs/VideoShopping.js.map +1 -0
- package/lib/commonjs/components/CartContainer.js +35 -0
- package/lib/commonjs/components/CartContainer.js.map +1 -0
- package/lib/commonjs/components/FWVideoFeed.js +18 -0
- package/lib/commonjs/components/FWVideoFeed.js.map +1 -0
- package/lib/commonjs/components/VideoFeed.js +82 -0
- package/lib/commonjs/components/VideoFeed.js.map +1 -0
- package/lib/commonjs/constants/FWErrorMessage.js +15 -0
- package/lib/commonjs/constants/FWErrorMessage.js.map +1 -0
- package/lib/commonjs/index.js +44 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/models/ADConfig.js +2 -0
- package/lib/commonjs/models/ADConfig.js.map +1 -0
- package/lib/commonjs/models/AddToCartResult.js +2 -0
- package/lib/commonjs/models/AddToCartResult.js.map +1 -0
- package/lib/commonjs/models/FWError.js +2 -0
- package/lib/commonjs/models/FWError.js.map +1 -0
- package/lib/commonjs/models/FWEvents.js +20 -0
- package/lib/commonjs/models/FWEvents.js.map +1 -0
- package/lib/commonjs/models/FeedItemDetails.js +2 -0
- package/lib/commonjs/models/FeedItemDetails.js.map +1 -0
- package/lib/commonjs/models/Product.js +2 -0
- package/lib/commonjs/models/Product.js.map +1 -0
- package/lib/commonjs/models/ProductInfoViewConfiguration.js +2 -0
- package/lib/commonjs/models/ProductInfoViewConfiguration.js.map +1 -0
- package/lib/commonjs/models/ProductUnit.js +2 -0
- package/lib/commonjs/models/ProductUnit.js.map +1 -0
- package/lib/commonjs/models/VideoFeedConfiguration.js +2 -0
- package/lib/commonjs/models/VideoFeedConfiguration.js.map +1 -0
- package/lib/commonjs/models/VideoPlaybackDetails.js +2 -0
- package/lib/commonjs/models/VideoPlaybackDetails.js.map +1 -0
- package/lib/commonjs/models/VideoPlaybackEventName.js +23 -0
- package/lib/commonjs/models/VideoPlaybackEventName.js.map +1 -0
- package/lib/commonjs/models/VideoPlayerConfiguration.js +2 -0
- package/lib/commonjs/models/VideoPlayerConfiguration.js.map +1 -0
- package/lib/commonjs/modules/FireworkSDKModule.js +20 -0
- package/lib/commonjs/modules/FireworkSDKModule.js.map +1 -0
- package/lib/commonjs/modules/ShoppingModule.js +20 -0
- package/lib/commonjs/modules/ShoppingModule.js.map +1 -0
- package/lib/module/FireworkSDK.js +153 -0
- package/lib/module/FireworkSDK.js.map +1 -0
- package/lib/module/VideoShopping.js +134 -0
- package/lib/module/VideoShopping.js.map +1 -0
- package/lib/module/components/CartContainer.js +18 -0
- package/lib/module/components/CartContainer.js.map +1 -0
- package/lib/module/components/FWVideoFeed.js +8 -0
- package/lib/module/components/FWVideoFeed.js.map +1 -0
- package/lib/module/components/VideoFeed.js +66 -0
- package/lib/module/components/VideoFeed.js.map +1 -0
- package/lib/module/constants/FWErrorMessage.js +7 -0
- package/lib/module/constants/FWErrorMessage.js.map +1 -0
- package/lib/module/index.js +10 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/models/ADConfig.js +2 -0
- package/lib/module/models/ADConfig.js.map +1 -0
- package/lib/module/models/AddToCartResult.js +2 -0
- package/lib/module/models/AddToCartResult.js.map +1 -0
- package/lib/module/models/FWError.js +2 -0
- package/lib/module/models/FWError.js.map +1 -0
- package/lib/module/models/FWEvents.js +13 -0
- package/lib/module/models/FWEvents.js.map +1 -0
- package/lib/module/models/FeedItemDetails.js +2 -0
- package/lib/module/models/FeedItemDetails.js.map +1 -0
- package/lib/module/models/Product.js +2 -0
- package/lib/module/models/Product.js.map +1 -0
- package/lib/module/models/ProductInfoViewConfiguration.js +2 -0
- package/lib/module/models/ProductInfoViewConfiguration.js.map +1 -0
- package/lib/module/models/ProductUnit.js +2 -0
- package/lib/module/models/ProductUnit.js.map +1 -0
- package/lib/module/models/VideoFeedConfiguration.js +2 -0
- package/lib/module/models/VideoFeedConfiguration.js.map +1 -0
- package/lib/module/models/VideoPlaybackDetails.js +2 -0
- package/lib/module/models/VideoPlaybackDetails.js.map +1 -0
- package/lib/module/models/VideoPlaybackEventName.js +16 -0
- package/lib/module/models/VideoPlaybackEventName.js.map +1 -0
- package/lib/module/models/VideoPlayerConfiguration.js +2 -0
- package/lib/module/models/VideoPlayerConfiguration.js.map +1 -0
- package/lib/module/modules/FireworkSDKModule.js +10 -0
- package/lib/module/modules/FireworkSDKModule.js.map +1 -0
- package/lib/module/modules/ShoppingModule.js +10 -0
- package/lib/module/modules/ShoppingModule.js.map +1 -0
- package/lib/typescript/FireworkSDK.d.ts +74 -0
- package/lib/typescript/VideoShopping.d.ts +54 -0
- package/lib/typescript/components/CartContainer.d.ts +3 -0
- package/lib/typescript/components/FWVideoFeed.d.ts +2 -0
- package/lib/typescript/components/VideoFeed.d.ts +53 -0
- package/lib/typescript/constants/FWErrorMessage.d.ts +2 -0
- package/lib/typescript/index.d.ts +25 -0
- package/lib/typescript/models/ADConfig.d.ts +10 -0
- package/lib/typescript/models/AddToCartResult.d.ts +10 -0
- package/lib/typescript/models/FWError.d.ts +10 -0
- package/lib/typescript/models/FWEvents.d.ts +55 -0
- package/lib/typescript/models/FeedItemDetails.d.ts +14 -0
- package/lib/typescript/models/Product.d.ts +19 -0
- package/lib/typescript/models/ProductInfoViewConfiguration.d.ts +18 -0
- package/lib/typescript/models/ProductUnit.d.ts +22 -0
- package/lib/typescript/models/VideoFeedConfiguration.d.ts +32 -0
- package/lib/typescript/models/VideoPlaybackDetails.d.ts +31 -0
- package/lib/typescript/models/VideoPlaybackEventName.d.ts +39 -0
- package/lib/typescript/models/VideoPlayerConfiguration.d.ts +25 -0
- package/lib/typescript/modules/FireworkSDKModule.d.ts +12 -0
- package/lib/typescript/modules/ShoppingModule.d.ts +13 -0
- package/package.json +147 -0
- package/react-native-firework-sdk.podspec +22 -0
- package/src/FireworkSDK.ts +153 -0
- package/src/VideoShopping.ts +165 -0
- package/src/components/CartContainer.tsx +20 -0
- package/src/components/FWVideoFeed.tsx +10 -0
- package/src/components/VideoFeed.tsx +109 -0
- package/src/constants/FWErrorMessage.ts +11 -0
- package/src/index.tsx +109 -0
- package/src/models/ADConfig.ts +10 -0
- package/src/models/AddToCartResult.ts +10 -0
- package/src/models/FWError.ts +10 -0
- package/src/models/FWEvents.ts +63 -0
- package/src/models/FeedItemDetails.ts +14 -0
- package/src/models/Product.ts +20 -0
- package/src/models/ProductInfoViewConfiguration.ts +20 -0
- package/src/models/ProductUnit.ts +23 -0
- package/src/models/VideoFeedConfiguration.ts +35 -0
- package/src/models/VideoPlaybackDetails.ts +33 -0
- package/src/models/VideoPlaybackEventName.ts +40 -0
- package/src/models/VideoPlayerConfiguration.ts +26 -0
- package/src/modules/FireworkSDKModule.ts +27 -0
- package/src/modules/ShoppingModule.ts +29 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
package com.reactnativefireworksdk.module
|
|
2
|
+
|
|
3
|
+
import android.annotation.SuppressLint
|
|
4
|
+
import android.content.pm.PackageManager
|
|
5
|
+
import android.provider.Settings
|
|
6
|
+
import com.facebook.react.bridge.*
|
|
7
|
+
import com.loopnow.fireworklibrary.FwSDK
|
|
8
|
+
import com.loopnow.fireworklibrary.SdkStatus
|
|
9
|
+
import com.loopnow.fireworklibrary.VideoEvent
|
|
10
|
+
import com.reactnativefireworksdk.models.FWVideoPlaybackDetails
|
|
11
|
+
import com.reactnativefireworksdk.models.FWVideoPlaybackSubEventName
|
|
12
|
+
import com.reactnativefireworksdk.models.FWVideoPlayerConfigModel
|
|
13
|
+
import com.reactnativefireworksdk.utils.*
|
|
14
|
+
import org.json.JSONObject
|
|
15
|
+
import com.facebook.react.bridge.ReactMethod
|
|
16
|
+
import com.reactnativefireworksdk.models.FireworkSDKInterface
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
class FireworkSDKModule(
|
|
20
|
+
reactContext: ReactApplicationContext
|
|
21
|
+
) : ReactContextBaseJavaModule(reactContext), FireworkSDKInterface {
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Initializes FW SDK
|
|
25
|
+
*
|
|
26
|
+
* You must add the appid to the AndroidManifest file.
|
|
27
|
+
* Please contact Firework business team, if you don't have one.
|
|
28
|
+
*
|
|
29
|
+
* This method will always return immediately and must be called on the main thread.
|
|
30
|
+
* It is recommended that you initialize FW SDK when application created. FW SDK must be initialized
|
|
31
|
+
* before using any of the features.
|
|
32
|
+
*
|
|
33
|
+
* @param userId an id to uniquely identify device or user. If you don't have a unique id
|
|
34
|
+
* We will use hashed Android_ID as it is
|
|
35
|
+
* If id passed is not unique, it will affect the quality of content recommended to the user.
|
|
36
|
+
*/
|
|
37
|
+
@ReactMethod
|
|
38
|
+
override fun init(userId: String?, adConfig: ReadableMap?) {
|
|
39
|
+
init(userId)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* play video from url with encoded parameters
|
|
44
|
+
*
|
|
45
|
+
* When user clicks on player_url shared @see setBasePlayerUrl and
|
|
46
|
+
* you handle the universal link in your app, you can launch the video playback
|
|
47
|
+
* based on the encodedParameters present in the link
|
|
48
|
+
* the custom player_url is in the format
|
|
49
|
+
* If you used https://example.com as base url the player_url will be in the following format
|
|
50
|
+
* https://example.com#fwplayer=eyJjaGFubmVsX2lkIjoiTFJZMUdYIiwiZmVlZF9pZCI6NDIwLCJmZWVkX3R5cGUiOiJkaXNjb3ZlciIsInYiOjEsInZpZGVvX2lkIjoiZ0syNmJkIn0
|
|
51
|
+
* @param url https://example.com#fwplayer=xxx
|
|
52
|
+
* @param config { NativeMap: {"playerStyle":"full","videoCompleteAction":"loop","showShareButton":false,"ctaButtonStyle":{"backgroundColor":"#0f7bdf","fontSize":14,"textColor":"#ffffff"}} }
|
|
53
|
+
*/
|
|
54
|
+
@ReactMethod
|
|
55
|
+
override fun openVideoPlayer(url: String, config: ReadableMap?) {
|
|
56
|
+
val encodedParameters = FWUrlUtils.queryParamString(url, "fwplayer")
|
|
57
|
+
if (encodedParameters.isNullOrBlank()) {
|
|
58
|
+
FWLogUtils.e { "The parameter url is invalid" }
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// set configuration
|
|
63
|
+
val configMap = config?.toHashMap()
|
|
64
|
+
val videoPlayerContentConfigModel = FWJsonUtils.fromMap(configMap, FWVideoPlayerConfigModel::class.java)
|
|
65
|
+
FWVideoPlayerUtils.setVideoPlayerConfig(videoPlayerContentConfigModel)
|
|
66
|
+
|
|
67
|
+
// open player
|
|
68
|
+
UiThreadUtil.runOnUiThread {
|
|
69
|
+
FwSDK.play(encodedParameters)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The function allows you to set the base url and query parameters to construct
|
|
75
|
+
* the player_url that is shared when user uses share feature.
|
|
76
|
+
* The custom url should only be used, if you want to support universal link and
|
|
77
|
+
* handle opening of the url in the app first before opening it in the web browser.
|
|
78
|
+
* @param url for example https://example.com
|
|
79
|
+
*
|
|
80
|
+
*/
|
|
81
|
+
@ReactMethod
|
|
82
|
+
override fun setShareBaseURL(url: String?) {
|
|
83
|
+
if (!url.isNullOrBlank()) {
|
|
84
|
+
FwSDK.setBasePlayerUrl(url)
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
@ReactMethod
|
|
89
|
+
override fun setCustomCTAClickEnabled(value: Boolean?) {
|
|
90
|
+
FWVideoPlayerUtils.customCTAClickEnabled = value?:false
|
|
91
|
+
handleCustomCTAClick()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@ReactMethod
|
|
95
|
+
override fun setVideoPlaybackEventEnabled(value: Boolean?) {
|
|
96
|
+
FWVideoPlayerUtils.videoPlaybackEventEnabled = value?:false
|
|
97
|
+
handleVideoPlaybackEvent()
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
private fun init(userId: String?) {
|
|
101
|
+
val clientId = getAppid()
|
|
102
|
+
if (clientId.isNullOrBlank()) {
|
|
103
|
+
val errorMsg = "The appid is invalid"
|
|
104
|
+
FWLogUtils.e { errorMsg }
|
|
105
|
+
FWEventUtils.sendInitFailedEvent(reactApplicationContext, errorMsg)
|
|
106
|
+
return
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
val uid = if (userId.isNullOrBlank()) { getHashedAndroidId() } else userId
|
|
110
|
+
|
|
111
|
+
UiThreadUtil.runOnUiThread {
|
|
112
|
+
FwSDK.initialize(
|
|
113
|
+
reactApplicationContext,
|
|
114
|
+
clientId,
|
|
115
|
+
uid,
|
|
116
|
+
object : FwSDK.SdkStatusListener {
|
|
117
|
+
override fun currentStatus(status: SdkStatus, extra: String) {
|
|
118
|
+
when (status) {
|
|
119
|
+
SdkStatus.Initialized -> {
|
|
120
|
+
FWEventUtils.sendInitSuccessEvent(reactApplicationContext)
|
|
121
|
+
}
|
|
122
|
+
SdkStatus.InitializationFailed -> {
|
|
123
|
+
FWEventUtils.sendInitFailedEvent(reactApplicationContext, extra)
|
|
124
|
+
}
|
|
125
|
+
SdkStatus.RefreshTokenFailed -> {
|
|
126
|
+
FWEventUtils.sendInitFailedEvent(reactApplicationContext, extra)
|
|
127
|
+
}
|
|
128
|
+
SdkStatus.LoadingContent -> {
|
|
129
|
+
FWLogUtils.d { "LoadingContent" }
|
|
130
|
+
}
|
|
131
|
+
SdkStatus.LoadingContentFailed -> {
|
|
132
|
+
FWLogUtils.e { "LoadingContentFailed" }
|
|
133
|
+
}
|
|
134
|
+
SdkStatus.ContentLoaded -> {
|
|
135
|
+
FWLogUtils.d { "ContentLoaded" }
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
})
|
|
140
|
+
handleVideoPlaybackEvent()
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
private fun getAppid(): String? {
|
|
145
|
+
val ai = reactApplicationContext.packageManager.getApplicationInfo(
|
|
146
|
+
reactApplicationContext.packageName,
|
|
147
|
+
PackageManager.GET_META_DATA
|
|
148
|
+
)
|
|
149
|
+
val value = ai.metaData.get("Firework:Appid")
|
|
150
|
+
return value?.let {
|
|
151
|
+
it as String
|
|
152
|
+
} ?: run {
|
|
153
|
+
null
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
@SuppressLint("HardwareIds")
|
|
158
|
+
private fun getHashedAndroidId(): String {
|
|
159
|
+
val androidId = Settings.Secure.getString(
|
|
160
|
+
reactApplicationContext.contentResolver,
|
|
161
|
+
Settings.Secure.ANDROID_ID
|
|
162
|
+
)
|
|
163
|
+
return FwSDK.getHash(androidId)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
private fun handleCustomCTAClick() {
|
|
167
|
+
if (!FWVideoPlayerUtils.customCTAClickEnabled) {
|
|
168
|
+
return
|
|
169
|
+
}
|
|
170
|
+
FwSDK.ctaClickHandler = object: FwSDK.CtaClickHandler {
|
|
171
|
+
override fun ctaClicked(label: String, actionUrl: String?): Boolean {
|
|
172
|
+
FWLogUtils.d { "ctaClicked" }
|
|
173
|
+
FWEventUtils.sendCustomCTAClickEvent(reactApplicationContext, actionUrl)
|
|
174
|
+
return FWVideoPlayerUtils.customCTAClickEnabled
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
private fun handleVideoPlaybackEvent() {
|
|
180
|
+
if (!FWVideoPlayerUtils.videoPlaybackEventEnabled) {
|
|
181
|
+
return
|
|
182
|
+
}
|
|
183
|
+
FwSDK.addVideoEventListener(object: FwSDK.VideoEventListener {
|
|
184
|
+
override fun event(event: String, jsonObject: JSONObject) {
|
|
185
|
+
val videoPlaybackDetails = FWJsonUtils.fromJson(jsonObject.toString(), FWVideoPlaybackDetails::class.java)
|
|
186
|
+
|
|
187
|
+
when (event) {
|
|
188
|
+
VideoEvent.videoImpression -> {
|
|
189
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.Impression.rawValue, videoPlaybackDetails)
|
|
190
|
+
}
|
|
191
|
+
VideoEvent.videoStart -> {
|
|
192
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.Start.rawValue, videoPlaybackDetails)
|
|
193
|
+
}
|
|
194
|
+
VideoEvent.videoFirstQuartile -> {
|
|
195
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.FirstQuartile.rawValue, videoPlaybackDetails)
|
|
196
|
+
}
|
|
197
|
+
VideoEvent.videoMidpoint -> {
|
|
198
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.Midpoint.rawValue, videoPlaybackDetails)
|
|
199
|
+
}
|
|
200
|
+
VideoEvent.videoThirdQuartile -> {
|
|
201
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.ThirdQuartile.rawValue, videoPlaybackDetails)
|
|
202
|
+
}
|
|
203
|
+
VideoEvent.videoComplete -> {
|
|
204
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.Complete.rawValue, videoPlaybackDetails)
|
|
205
|
+
}
|
|
206
|
+
VideoEvent.videoSession -> {
|
|
207
|
+
|
|
208
|
+
}
|
|
209
|
+
VideoEvent.videoAdStart -> {
|
|
210
|
+
|
|
211
|
+
}
|
|
212
|
+
VideoEvent.videoAdEnd -> {
|
|
213
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.AdEnd.rawValue, videoPlaybackDetails)
|
|
214
|
+
}
|
|
215
|
+
VideoEvent.videoClickCta -> {
|
|
216
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.ClickCTA.rawValue, videoPlaybackDetails)
|
|
217
|
+
}
|
|
218
|
+
VideoEvent.videoShare -> {
|
|
219
|
+
FWEventUtils.sendVideoPlaybackEvent(reactApplicationContext, FWVideoPlaybackSubEventName.ClickShare.rawValue, videoPlaybackDetails)
|
|
220
|
+
}
|
|
221
|
+
VideoEvent.videoStartError -> {
|
|
222
|
+
|
|
223
|
+
}
|
|
224
|
+
VideoEvent.videoAdStartError -> {
|
|
225
|
+
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
})
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
@ReactMethod
|
|
233
|
+
fun addListener(eventName: String?) {
|
|
234
|
+
// Set up any upstream listeners or background tasks as necessary
|
|
235
|
+
FWLogUtils.d { "addListener: $eventName" }
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
@ReactMethod
|
|
239
|
+
fun removeListeners(count: Int?) {
|
|
240
|
+
// Remove upstream listeners, stop unnecessary background tasks
|
|
241
|
+
FWLogUtils.d { "removeListeners: $count" }
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
override fun getName(): String {
|
|
245
|
+
return "FireworkSDK"
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
package com.reactnativefireworksdk.pages
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Intent
|
|
5
|
+
import android.os.Bundle
|
|
6
|
+
import androidx.appcompat.app.AppCompatActivity
|
|
7
|
+
import androidx.fragment.app.Fragment
|
|
8
|
+
import com.reactnativefireworksdk.R
|
|
9
|
+
import com.facebook.react.ReactFragment
|
|
10
|
+
import com.facebook.react.modules.core.DefaultHardwareBackBtnHandler
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class FWVideoShoppingCartActivity : AppCompatActivity(), DefaultHardwareBackBtnHandler {
|
|
14
|
+
|
|
15
|
+
override fun onCreate(savedInstanceState: Bundle?) {
|
|
16
|
+
super.onCreate(savedInstanceState)
|
|
17
|
+
setContentView(R.layout.fwrn_fragment_shoppingcart)
|
|
18
|
+
|
|
19
|
+
val reactNativeFragment: Fragment = ReactFragment.Builder()
|
|
20
|
+
.setComponentName("FWShoppingCartPage")
|
|
21
|
+
.setLaunchOptions(null)
|
|
22
|
+
.build()
|
|
23
|
+
|
|
24
|
+
supportFragmentManager
|
|
25
|
+
.beginTransaction()
|
|
26
|
+
.add(R.id.shopping_cart_container, reactNativeFragment)
|
|
27
|
+
.commit()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
companion object {
|
|
31
|
+
|
|
32
|
+
fun createIntent(activity: Activity): Intent {
|
|
33
|
+
val intent = Intent(activity, FWVideoShoppingCartActivity::class.java)
|
|
34
|
+
intent.flags = Intent.FLAG_ACTIVITY_NO_ANIMATION
|
|
35
|
+
activity.overridePendingTransition(0, 0)
|
|
36
|
+
return intent
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
override fun invokeDefaultOnBackPressed() {
|
|
41
|
+
super.onBackPressed();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
package com.reactnativefireworksdk.utils
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.bridge.Arguments
|
|
4
|
+
import com.facebook.react.bridge.ReactContext
|
|
5
|
+
import com.facebook.react.bridge.WritableMap
|
|
6
|
+
import com.facebook.react.modules.core.DeviceEventManagerModule
|
|
7
|
+
import com.facebook.react.uimanager.events.RCTEventEmitter
|
|
8
|
+
import com.reactnativefireworksdk.models.*
|
|
9
|
+
|
|
10
|
+
object FWEventUtils {
|
|
11
|
+
|
|
12
|
+
fun sendInitSuccessEvent(reactContext: ReactContext) {
|
|
13
|
+
sendEvent(reactContext, FWEventName.SDKIni.rawValue, Arguments.createMap())
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
fun sendInitFailedEvent(reactContext: ReactContext, reason: String?) {
|
|
17
|
+
val eventMap = Arguments.createMap()
|
|
18
|
+
val contentMap = Arguments.createMap()
|
|
19
|
+
contentMap.putString(FWSDKInitSubEventName.InitFailed.rawValue, reason?:"unknown")
|
|
20
|
+
eventMap.putMap("error", contentMap)
|
|
21
|
+
sendEvent(reactContext, FWEventName.SDKIni.rawValue, eventMap)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
fun sendVideoFeedClickEvent(reactContext: ReactContext, info: FWVideoFeedItemDetailsModel) {
|
|
25
|
+
val eventMap = Arguments.createMap()
|
|
26
|
+
val contentMap = Arguments.createMap()
|
|
27
|
+
contentMap.putInt("index", info.index?:0)
|
|
28
|
+
contentMap.putString("videoId", info.id)
|
|
29
|
+
contentMap.putInt("duration", info.videoDuration?:0)
|
|
30
|
+
eventMap.putMap("info", contentMap)
|
|
31
|
+
sendEvent(reactContext, FWEventName.VideoFeedClick.rawValue, eventMap)
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
fun sendCustomCTAClickEvent(reactContext: ReactContext, url: String?) {
|
|
35
|
+
val eventMap = Arguments.createMap()
|
|
36
|
+
eventMap.putString("url", url)
|
|
37
|
+
sendEvent(reactContext, FWEventName.CustomCTAClick.rawValue, eventMap)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
fun sendVideoPlaybackEvent(reactContext: ReactContext, eventName: String, info: FWVideoPlaybackDetails?) {
|
|
41
|
+
val eventMap = Arguments.createMap()
|
|
42
|
+
eventMap.putString("eventName", eventName)
|
|
43
|
+
|
|
44
|
+
val contentMap = Arguments.createMap()
|
|
45
|
+
if (!info?.videoId.isNullOrBlank()) {
|
|
46
|
+
contentMap.putString("videoId", info?.videoId)
|
|
47
|
+
}
|
|
48
|
+
if (info?.duration != null) {
|
|
49
|
+
contentMap.putDouble("duration", info.duration.toDouble())
|
|
50
|
+
}
|
|
51
|
+
if (info?.caption.isNullOrBlank()) {
|
|
52
|
+
contentMap.putString("caption", info?.caption)
|
|
53
|
+
}
|
|
54
|
+
if (info?.badge.isNullOrBlank()) {
|
|
55
|
+
contentMap.putString("badge", info?.badge)
|
|
56
|
+
}
|
|
57
|
+
if (info?.width != null || info?.height != null) {
|
|
58
|
+
val playerSizeMap = Arguments.createMap()
|
|
59
|
+
if (info.width != null) {
|
|
60
|
+
playerSizeMap.putInt("width", info.width)
|
|
61
|
+
}
|
|
62
|
+
if (info.height != null) {
|
|
63
|
+
playerSizeMap.putInt("height", info.height)
|
|
64
|
+
}
|
|
65
|
+
contentMap.putMap("playerSize", playerSizeMap)
|
|
66
|
+
}
|
|
67
|
+
if (info?.hasCta != null) {
|
|
68
|
+
contentMap.putBoolean("hasCTA", info.hasCta)
|
|
69
|
+
}
|
|
70
|
+
eventMap.putMap("info", contentMap)
|
|
71
|
+
|
|
72
|
+
sendEvent(reactContext, FWEventName.VideoPlayback.rawValue, eventMap)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fun sendAddToCartClickEvent(reactContext: ReactContext, productId: String?, unitId: String?, callbackId: Int?) {
|
|
76
|
+
val eventMap = Arguments.createMap()
|
|
77
|
+
eventMap.putString("productId", productId)
|
|
78
|
+
eventMap.putString("unitId", unitId)
|
|
79
|
+
eventMap.putInt("callbackId", callbackId?:0)
|
|
80
|
+
sendEvent(reactContext, FWVideoShoppingEventName.AddToCart.rawValue, eventMap)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
fun sendCartIconClickEvent(reactContext: ReactContext, callbackId: Int?) {
|
|
84
|
+
val eventMap = Arguments.createMap()
|
|
85
|
+
eventMap.putInt("callbackId", callbackId?:0)
|
|
86
|
+
sendEvent(reactContext, FWVideoShoppingEventName.ClickCartIcon.rawValue, eventMap)
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
fun sendUpdateProductDetailsEvent(reactContext: ReactContext, productId: String?, callbackId: Int?) {
|
|
90
|
+
val eventMap = Arguments.createMap()
|
|
91
|
+
eventMap.putString("productId", productId)
|
|
92
|
+
eventMap.putInt("callbackId", callbackId?:0)
|
|
93
|
+
sendEvent(reactContext, FWVideoShoppingEventName.UpdateProductDetails.rawValue, eventMap)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
private fun sendEvent(reactContext: ReactContext, eventName: String, params: WritableMap?) {
|
|
97
|
+
reactContext
|
|
98
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
99
|
+
.emit(eventName, params)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
fun receiveVideoFeedLoadFinished(reactContext: ReactContext, targetTag: Int, eventName: String, name: String?, reason: String?) {
|
|
103
|
+
val eventMap = Arguments.createMap()
|
|
104
|
+
eventMap.putString("name", name)
|
|
105
|
+
eventMap.putString("reason", reason)
|
|
106
|
+
receiveEvent(reactContext, targetTag, FWFeedViewEventName.VideoFeedLoadFinished.rawValue, eventMap)
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
private fun receiveEvent(reactContext: ReactContext, targetTag: Int, eventName: String, event: WritableMap?) {
|
|
110
|
+
reactContext.getJSModule(RCTEventEmitter::class.java).receiveEvent(
|
|
111
|
+
targetTag,
|
|
112
|
+
eventName,
|
|
113
|
+
event
|
|
114
|
+
)
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* ERROR Invariant Violation: Module RCTModernEventEmitter is not a registered callable module (calling receiveEvent). A frequent cause of the error is that the application entry file path is incorrect.
|
|
118
|
+
* This can also happen when the JS bundle is corrupt or there is an early initialization error when loading React Native.
|
|
119
|
+
*/
|
|
120
|
+
// reactContext.getJSModule(RCTModernEventEmitter::class.java).receiveEvent(
|
|
121
|
+
// -1,
|
|
122
|
+
// id,
|
|
123
|
+
// "onVideoFeedLoadFinished",
|
|
124
|
+
// event
|
|
125
|
+
// )
|
|
126
|
+
}
|
|
127
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
package com.reactnativefireworksdk.utils
|
|
2
|
+
|
|
3
|
+
import android.os.Looper
|
|
4
|
+
import com.fasterxml.jackson.annotation.JsonInclude
|
|
5
|
+
import com.fasterxml.jackson.databind.DeserializationFeature
|
|
6
|
+
import com.fasterxml.jackson.databind.ObjectMapper
|
|
7
|
+
import com.fasterxml.jackson.databind.SerializationFeature
|
|
8
|
+
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
|
|
9
|
+
import java.util.*
|
|
10
|
+
|
|
11
|
+
object FWJsonUtils {
|
|
12
|
+
val mapper: ObjectMapper by lazy {
|
|
13
|
+
jacksonObjectMapper()
|
|
14
|
+
// .setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE)
|
|
15
|
+
.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true)
|
|
16
|
+
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
|
|
17
|
+
.setSerializationInclusion(JsonInclude.Include.NON_NULL)
|
|
18
|
+
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
|
|
19
|
+
.configure(SerializationFeature.WRITE_DATES_WITH_ZONE_ID, true)
|
|
20
|
+
.setTimeZone(TimeZone.getDefault())
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
private fun logJsonError(e: Exception) {
|
|
24
|
+
val loggedError = RuntimeException("Json Read Error!", e)
|
|
25
|
+
if (Looper.myLooper() != Looper.getMainLooper()) {
|
|
26
|
+
throw loggedError
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@JvmStatic
|
|
31
|
+
fun <T> fromMap(map: Map<*, *>?, cls: Class<T>): T? {
|
|
32
|
+
if (map.isNullOrEmpty()) {
|
|
33
|
+
return null
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
return mapper.convertValue(map, cls)
|
|
37
|
+
} catch (e: Exception) {
|
|
38
|
+
e.printStackTrace()
|
|
39
|
+
logJsonError(e)
|
|
40
|
+
}
|
|
41
|
+
return null
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
@JvmStatic
|
|
45
|
+
fun <T> fromJson(json: String?, cls: Class<T>): T? {
|
|
46
|
+
if (json.isNullOrBlank()) {
|
|
47
|
+
return null
|
|
48
|
+
}
|
|
49
|
+
try {
|
|
50
|
+
return mapper.readValue(json, cls)
|
|
51
|
+
} catch (e: Exception) {
|
|
52
|
+
e.printStackTrace()
|
|
53
|
+
logJsonError(e)
|
|
54
|
+
}
|
|
55
|
+
return null
|
|
56
|
+
}
|
|
57
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
package com.reactnativefireworksdk.utils
|
|
2
|
+
|
|
3
|
+
import android.os.Looper
|
|
4
|
+
import android.os.SystemClock
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import com.reactnativefireworksdk.BuildConfig
|
|
7
|
+
import kotlin.math.max
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* We need to set the [BuildConfig.LOG_LEVEL] to ensure that
|
|
11
|
+
* the log message whose log level is larger than [BuildConfig.LOG_LEVEL]
|
|
12
|
+
* can be printed in any environment (Debug / Release).
|
|
13
|
+
*
|
|
14
|
+
* P.S The value of [BuildConfig.LOG_LEVEL] is different in the Debug or Release environment.
|
|
15
|
+
* see the file - [build.gradle] for detail.
|
|
16
|
+
*/
|
|
17
|
+
object FWLogUtils {
|
|
18
|
+
|
|
19
|
+
@JvmStatic
|
|
20
|
+
var logLevel: Int = BuildConfig.LOG_LEVEL
|
|
21
|
+
|
|
22
|
+
@JvmStatic
|
|
23
|
+
val isDebugEnabled: Boolean get() = logLevel <= Log.DEBUG
|
|
24
|
+
|
|
25
|
+
@JvmStatic
|
|
26
|
+
fun d(lazyMessage: () -> String?) {
|
|
27
|
+
log(Log.DEBUG, lazyMessage)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@JvmStatic
|
|
31
|
+
fun i(lazyMessage: () -> String?) {
|
|
32
|
+
log(Log.INFO, lazyMessage)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
@JvmStatic
|
|
36
|
+
fun w(lazyMessage: () -> String?) {
|
|
37
|
+
log(Log.WARN, lazyMessage)
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
@JvmStatic
|
|
41
|
+
fun e(lazyMessage: () -> String?) {
|
|
42
|
+
log(Log.ERROR, lazyMessage)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
@JvmStatic
|
|
46
|
+
fun d(e: Throwable?) {
|
|
47
|
+
log(Log.DEBUG, e = e)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@JvmStatic
|
|
51
|
+
fun i(e: Throwable?) {
|
|
52
|
+
log(Log.INFO, e = e)
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@JvmStatic
|
|
56
|
+
fun w(e: Throwable?) {
|
|
57
|
+
log(Log.WARN, e = e)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
@JvmStatic
|
|
61
|
+
@JvmOverloads
|
|
62
|
+
fun e(e: Throwable?, lazyMessage: (() -> String?)? = null) {
|
|
63
|
+
log(Log.ERROR, lazyMessage, e)
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
@JvmStatic
|
|
67
|
+
fun enableMainThreadLog() {
|
|
68
|
+
var mainThreadStartTime = -1L
|
|
69
|
+
Looper.getMainLooper().setMessageLogging {
|
|
70
|
+
if (it.startsWith(">>>>>")) {
|
|
71
|
+
mainThreadStartTime = SystemClock.uptimeMillis()
|
|
72
|
+
} else if (it.startsWith("<<<<<")) {
|
|
73
|
+
val time = SystemClock.uptimeMillis() - mainThreadStartTime
|
|
74
|
+
// 1000 / 50 = 20+ frames
|
|
75
|
+
if (time > 50) d {
|
|
76
|
+
"Using ${time}ms ${it.substring(6)}"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
private fun log(level: Int, lazyMessage: (() -> String?)? = null, e: Throwable? = null) {
|
|
83
|
+
if (level >= logLevel) {
|
|
84
|
+
var message = lazyMessage?.let { it() }.orEmpty()
|
|
85
|
+
if (message.isEmpty()) {
|
|
86
|
+
if (e == null) {
|
|
87
|
+
return
|
|
88
|
+
} else {
|
|
89
|
+
message = "null"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
val (tag, lineNumber) = generateTag()
|
|
93
|
+
val lineTag = when {
|
|
94
|
+
lineNumber < 10 -> "__$lineNumber"
|
|
95
|
+
lineNumber < 100 -> "_$lineNumber"
|
|
96
|
+
else -> "$lineNumber"
|
|
97
|
+
}
|
|
98
|
+
while (message.length > 4000) {
|
|
99
|
+
val subMessage = message.substring(0, 4000)
|
|
100
|
+
message = message.substring(4000)
|
|
101
|
+
when (level) {
|
|
102
|
+
Log.DEBUG -> {
|
|
103
|
+
Log.d(lineTag, "$tag: $subMessage")
|
|
104
|
+
}
|
|
105
|
+
Log.INFO -> {
|
|
106
|
+
Log.i(lineTag, "$tag: $subMessage")
|
|
107
|
+
}
|
|
108
|
+
Log.WARN -> {
|
|
109
|
+
Log.w(lineTag, "$tag: $subMessage")
|
|
110
|
+
}
|
|
111
|
+
Log.ERROR -> {
|
|
112
|
+
Log.e(lineTag, "$tag: $subMessage")
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
when (level) {
|
|
117
|
+
Log.DEBUG -> {
|
|
118
|
+
Log.d(lineTag, "$tag: $message", e)
|
|
119
|
+
}
|
|
120
|
+
Log.INFO -> {
|
|
121
|
+
Log.i(lineTag, "$tag: $message", e)
|
|
122
|
+
}
|
|
123
|
+
Log.WARN -> {
|
|
124
|
+
Log.w(lineTag, "$tag: $message", e)
|
|
125
|
+
}
|
|
126
|
+
Log.ERROR -> {
|
|
127
|
+
Log.e(lineTag, "$tag: $message", e)
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private val NO_LOG_LIST = setOf(Thread::class.java.name, FWLogUtils::class.java.name)
|
|
134
|
+
|
|
135
|
+
internal fun generateTag(): Pair<String, Int> {
|
|
136
|
+
val stackTrace = Thread.currentThread().stackTrace
|
|
137
|
+
for (i in 2 until stackTrace.size) {
|
|
138
|
+
val className = stackTrace[i].className
|
|
139
|
+
val fileName = stackTrace[i].fileName
|
|
140
|
+
val lineNumber = stackTrace[i].lineNumber
|
|
141
|
+
if (className !in NO_LOG_LIST) {
|
|
142
|
+
return Pair(fileName.substring(0, max(fileName.lastIndexOf('.'), 0)), lineNumber)
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return Pair(javaClass.simpleName, 0)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
package com.reactnativefireworksdk.utils
|
|
2
|
+
|
|
3
|
+
import android.net.Uri
|
|
4
|
+
|
|
5
|
+
object FWUrlUtils {
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Get parameters in URL
|
|
9
|
+
*
|
|
10
|
+
* @param urlStr url
|
|
11
|
+
* @param key key
|
|
12
|
+
* @return string
|
|
13
|
+
* e.g. queryParamString("https://www.example.com?a=1&c=2", "a") will return "1"
|
|
14
|
+
* e.g. queryParamString("https://www.example.com#a=1&c=2", "a") will return "1"
|
|
15
|
+
*/
|
|
16
|
+
fun queryParamString(urlStr: String?, key: String?): String? {
|
|
17
|
+
if (urlStr.isNullOrBlank() || key.isNullOrBlank()) {
|
|
18
|
+
return null
|
|
19
|
+
}
|
|
20
|
+
return if (urlStr.contains("#")) {
|
|
21
|
+
queryHashParamString(urlStr, key)
|
|
22
|
+
} else {
|
|
23
|
+
queryBrowserParamString(urlStr, key)
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get browser parameters in URL
|
|
29
|
+
*
|
|
30
|
+
* @param urlStr url
|
|
31
|
+
* @param key key
|
|
32
|
+
* @return string
|
|
33
|
+
* e.g. queryParamString("https://www.example.com?a=1&c=2", "a") will return "1"
|
|
34
|
+
*/
|
|
35
|
+
private fun queryBrowserParamString(urlStr: String?, key: String?): String? {
|
|
36
|
+
if (urlStr.isNullOrBlank() || key.isNullOrBlank()) {
|
|
37
|
+
return null
|
|
38
|
+
}
|
|
39
|
+
val uri = Uri.parse(urlStr)
|
|
40
|
+
return uri?.getQueryParameter(key)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Get hash parameters in URL
|
|
45
|
+
*
|
|
46
|
+
* @param urlStr url
|
|
47
|
+
* @param key key
|
|
48
|
+
* @return string
|
|
49
|
+
* e.g. queryParamString("https://www.example.com#a=1&c=2", "a") will return "1"
|
|
50
|
+
*/
|
|
51
|
+
private fun queryHashParamString(urlStr: String?, key: String?): String? {
|
|
52
|
+
if (urlStr.isNullOrBlank() || key.isNullOrBlank()) {
|
|
53
|
+
return null
|
|
54
|
+
}
|
|
55
|
+
val urlParts = urlStr.split("#").filter(String::isNotEmpty)
|
|
56
|
+
if (urlParts.size < 2) {
|
|
57
|
+
return null
|
|
58
|
+
}
|
|
59
|
+
val query = urlParts[1]
|
|
60
|
+
val queryParts = query.split("&")
|
|
61
|
+
|
|
62
|
+
for (queryPart in queryParts) {
|
|
63
|
+
val paramParts = queryPart.split("=")
|
|
64
|
+
if (paramParts[0] == key) return paramParts[1]
|
|
65
|
+
}
|
|
66
|
+
return null
|
|
67
|
+
}
|
|
68
|
+
}
|