@octopus-community/react-native 1.0.8 → 1.9.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.
- package/OctopusReactNativeSdk.podspec +1 -1
- package/README.md +40 -35
- package/android/build.gradle +2 -0
- package/android/gradle.properties +2 -2
- package/android/src/main/AndroidManifest.xml +2 -1
- package/android/src/main/AndroidManifestNew.xml +2 -1
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusActivity.kt +56 -0
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusContent.kt +396 -0
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusEventEmitter.kt +22 -0
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusEventSerializer.kt +339 -0
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusReactModule.kt +326 -0
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/{OctopusReactNativeSdkPackage.kt → OctopusReactPackage.kt} +3 -3
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusSDKInitializer.kt +22 -9
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusSSOAuthenticator.kt +5 -15
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusUIController.kt +17 -2
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusUIViewManager.kt +63 -0
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/ProfileFieldMapper.kt +2 -2
- package/ios/OctopusEventManager.swift +27 -0
- package/ios/OctopusEventSerializer.swift +271 -0
- package/ios/OctopusReactNativeSdk.mm +26 -1
- package/ios/OctopusReactNativeSdk.swift +216 -2
- package/ios/OctopusSSOAuthenticator.swift +1 -5
- package/ios/OctopusUIManager.swift +83 -0
- package/ios/OctopusUIViewManager.m +7 -0
- package/ios/OctopusUIViewManager.swift +37 -0
- package/lib/module/OctopusUIView.js +39 -0
- package/lib/module/OctopusUIView.js.map +1 -0
- package/lib/module/addHasAccessToCommunityListener.js +33 -0
- package/lib/module/addHasAccessToCommunityListener.js.map +1 -0
- package/lib/module/addNavigateToUrlListener.js +41 -0
- package/lib/module/addNavigateToUrlListener.js.map +1 -0
- package/lib/module/addNotSeenNotificationsCountListener.js +30 -0
- package/lib/module/addNotSeenNotificationsCountListener.js.map +1 -0
- package/lib/module/addSDKEventListener.js +48 -0
- package/lib/module/addSDKEventListener.js.map +1 -0
- package/lib/module/connectUser.js +24 -3
- package/lib/module/connectUser.js.map +1 -1
- package/lib/module/index.js +12 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/initialize.js +9 -12
- package/lib/module/initialize.js.map +1 -1
- package/lib/module/openUI.js +23 -2
- package/lib/module/openUI.js.map +1 -1
- package/lib/module/overrideCommunityAccess.js +36 -0
- package/lib/module/overrideCommunityAccess.js.map +1 -0
- package/lib/module/overrideDefaultLocale.js +75 -0
- package/lib/module/overrideDefaultLocale.js.map +1 -0
- package/lib/module/trackCommunityAccess.js +33 -0
- package/lib/module/trackCommunityAccess.js.map +1 -0
- package/lib/module/trackCustomEvent.js +36 -0
- package/lib/module/trackCustomEvent.js.map +1 -0
- package/lib/module/types/sdkEvents.js +2 -0
- package/lib/module/types/sdkEvents.js.map +1 -0
- package/lib/module/types/urlOpeningStrategy.js +23 -0
- package/lib/module/types/urlOpeningStrategy.js.map +1 -0
- package/lib/module/updateNotSeenNotificationsCount.js +33 -0
- package/lib/module/updateNotSeenNotificationsCount.js.map +1 -0
- package/lib/typescript/src/OctopusUIView.d.ts +32 -0
- package/lib/typescript/src/OctopusUIView.d.ts.map +1 -0
- package/lib/typescript/src/addHasAccessToCommunityListener.d.ts +27 -0
- package/lib/typescript/src/addHasAccessToCommunityListener.d.ts.map +1 -0
- package/lib/typescript/src/addNavigateToUrlListener.d.ts +31 -0
- package/lib/typescript/src/addNavigateToUrlListener.d.ts.map +1 -0
- package/lib/typescript/src/addNotSeenNotificationsCountListener.d.ts +24 -0
- package/lib/typescript/src/addNotSeenNotificationsCountListener.d.ts.map +1 -0
- package/lib/typescript/src/addSDKEventListener.d.ts +43 -0
- package/lib/typescript/src/addSDKEventListener.d.ts.map +1 -0
- package/lib/typescript/src/connectUser.d.ts +24 -8
- package/lib/typescript/src/connectUser.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +13 -0
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/initialize.d.ts +9 -12
- package/lib/typescript/src/initialize.d.ts.map +1 -1
- package/lib/typescript/src/openUI.d.ts +28 -1
- package/lib/typescript/src/openUI.d.ts.map +1 -1
- package/lib/typescript/src/overrideCommunityAccess.d.ts +30 -0
- package/lib/typescript/src/overrideCommunityAccess.d.ts.map +1 -0
- package/lib/typescript/src/overrideDefaultLocale.d.ts +37 -0
- package/lib/typescript/src/overrideDefaultLocale.d.ts.map +1 -0
- package/lib/typescript/src/trackCommunityAccess.d.ts +27 -0
- package/lib/typescript/src/trackCommunityAccess.d.ts.map +1 -0
- package/lib/typescript/src/trackCustomEvent.d.ts +30 -0
- package/lib/typescript/src/trackCustomEvent.d.ts.map +1 -0
- package/lib/typescript/src/types/sdkEvents.d.ts +222 -0
- package/lib/typescript/src/types/sdkEvents.d.ts.map +1 -0
- package/lib/typescript/src/types/urlOpeningStrategy.d.ts +20 -0
- package/lib/typescript/src/types/urlOpeningStrategy.d.ts.map +1 -0
- package/lib/typescript/src/updateNotSeenNotificationsCount.d.ts +27 -0
- package/lib/typescript/src/updateNotSeenNotificationsCount.d.ts.map +1 -0
- package/package.json +2 -1
- package/src/OctopusUIView.tsx +57 -0
- package/src/addHasAccessToCommunityListener.ts +38 -0
- package/src/addNavigateToUrlListener.ts +54 -0
- package/src/addNotSeenNotificationsCountListener.ts +35 -0
- package/src/addSDKEventListener.ts +49 -0
- package/src/connectUser.ts +24 -8
- package/src/index.ts +13 -0
- package/src/initialize.ts +9 -12
- package/src/openUI.ts +32 -2
- package/src/overrideCommunityAccess.ts +33 -0
- package/src/overrideDefaultLocale.ts +88 -0
- package/src/trackCommunityAccess.ts +30 -0
- package/src/trackCustomEvent.ts +36 -0
- package/src/types/sdkEvents.ts +315 -0
- package/src/types/urlOpeningStrategy.ts +20 -0
- package/src/updateNotSeenNotificationsCount.ts +30 -0
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusReactNativeSdkModule.kt +0 -155
- package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusUIActivity.kt +0 -434
package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusSDKInitializer.kt
CHANGED
|
@@ -9,11 +9,11 @@ import android.graphics.Color
|
|
|
9
9
|
|
|
10
10
|
class OctopusSDKInitializer {
|
|
11
11
|
|
|
12
|
-
fun initialize(context: ReactApplicationContext, options: ReadableMap, promise: Promise) {
|
|
12
|
+
fun initialize(context: ReactApplicationContext, options: ReadableMap, promise: Promise): Boolean {
|
|
13
13
|
val apiKey = options.getString("apiKey")
|
|
14
14
|
if (apiKey == null) {
|
|
15
15
|
promise.reject("INITIALIZE_ERROR", "Missing API key")
|
|
16
|
-
return
|
|
16
|
+
return false
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
try {
|
|
@@ -27,16 +27,28 @@ class OctopusSDKInitializer {
|
|
|
27
27
|
val uiConfiguration = parseUIConfiguration(options)
|
|
28
28
|
OctopusUIConfigurationManager.setUIConfiguration(uiConfiguration)
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
30
|
+
// For "octopus" mode, don't pass connectionMode (it's the default)
|
|
31
|
+
// For "sso" mode, pass the ConnectionMode.SSO
|
|
32
|
+
if (connectionMode != null) {
|
|
33
|
+
OctopusSDK.initialize(
|
|
34
|
+
context = context,
|
|
35
|
+
apiKey = apiKey,
|
|
36
|
+
connectionMode = connectionMode
|
|
37
|
+
)
|
|
38
|
+
} else {
|
|
39
|
+
OctopusSDK.initialize(
|
|
40
|
+
context = context,
|
|
41
|
+
apiKey = apiKey
|
|
42
|
+
)
|
|
43
|
+
}
|
|
35
44
|
promise.resolve(null)
|
|
45
|
+
return true
|
|
36
46
|
} catch (e: InvalidConnectionModeException) {
|
|
37
47
|
promise.reject("INITIALIZE_ERROR", e.message, e)
|
|
48
|
+
return false
|
|
38
49
|
} catch (e: Exception) {
|
|
39
50
|
promise.reject("INITIALIZE_ERROR", "Failed to initialize Octopus SDK", e)
|
|
51
|
+
return false
|
|
40
52
|
}
|
|
41
53
|
}
|
|
42
54
|
|
|
@@ -209,7 +221,7 @@ class OctopusSDKInitializer {
|
|
|
209
221
|
}
|
|
210
222
|
}
|
|
211
223
|
|
|
212
|
-
private fun parseConnectionMode(options: ReadableMap): ConnectionMode {
|
|
224
|
+
private fun parseConnectionMode(options: ReadableMap): ConnectionMode? {
|
|
213
225
|
val connectionModeMap = options.getMap("connectionMode")
|
|
214
226
|
return when (val connectionModeType = connectionModeMap?.getString("type")) {
|
|
215
227
|
"sso" -> {
|
|
@@ -221,7 +233,8 @@ class OctopusSDKInitializer {
|
|
|
221
233
|
}
|
|
222
234
|
|
|
223
235
|
"octopus" -> {
|
|
224
|
-
|
|
236
|
+
// For "octopus" mode, return null - OctopusSDK.initialize() will use default mode
|
|
237
|
+
null
|
|
225
238
|
}
|
|
226
239
|
|
|
227
240
|
else -> {
|
package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusSSOAuthenticator.kt
CHANGED
|
@@ -4,8 +4,7 @@ import com.facebook.react.bridge.ReadableMap
|
|
|
4
4
|
import com.facebook.react.bridge.Promise
|
|
5
5
|
import com.octopuscommunity.sdk.OctopusSDK
|
|
6
6
|
import com.octopuscommunity.sdk.domain.model.ClientUser
|
|
7
|
-
import com.octopuscommunity.sdk.domain.model.
|
|
8
|
-
import com.octopuscommunity.sdk.domain.model.Image
|
|
7
|
+
import com.octopuscommunity.sdk.domain.model.Resource
|
|
9
8
|
import kotlinx.coroutines.CoroutineScope
|
|
10
9
|
import kotlinx.coroutines.Dispatchers
|
|
11
10
|
import kotlinx.coroutines.launch
|
|
@@ -103,24 +102,16 @@ class OctopusSSOAuthenticator(
|
|
|
103
102
|
return ClientUser.Profile()
|
|
104
103
|
}
|
|
105
104
|
|
|
106
|
-
val ageInformation = if (profileParams.hasKey("legalAgeReached")) {
|
|
107
|
-
if (profileParams.getBoolean("legalAgeReached")) {
|
|
108
|
-
AgeInformation.LegalAgeReached
|
|
109
|
-
} else {
|
|
110
|
-
AgeInformation.Underage
|
|
111
|
-
}
|
|
112
|
-
} else null
|
|
113
|
-
|
|
114
105
|
val profilePicture = profileParams.getString("profilePicture")?.let { pictureUrl ->
|
|
115
106
|
if (pictureUrl.startsWith("http://") || pictureUrl.startsWith("https://")) {
|
|
116
|
-
|
|
107
|
+
Resource.Remote(url = pictureUrl)
|
|
117
108
|
} else if (pictureUrl.startsWith("file") || pictureUrl.startsWith("android.resource")) {
|
|
118
|
-
|
|
109
|
+
Resource.Local(pictureUrl)
|
|
119
110
|
} else if(pictureUrl.isNotBlank()) {
|
|
120
111
|
// Asset names like "assets_images_logo" need conversion
|
|
121
112
|
// Convert to drawable resource URI
|
|
122
113
|
val resourceId = context.resources.getIdentifier(pictureUrl, "drawable", context.packageName)
|
|
123
|
-
|
|
114
|
+
Resource.Local(
|
|
124
115
|
if (resourceId != 0) {
|
|
125
116
|
"android.resource://${context.packageName}/$resourceId"
|
|
126
117
|
} else {
|
|
@@ -136,8 +127,7 @@ class OctopusSSOAuthenticator(
|
|
|
136
127
|
return ClientUser.Profile(
|
|
137
128
|
nickname = profileParams.getString("username"),
|
|
138
129
|
bio = profileParams.getString("biography"),
|
|
139
|
-
|
|
140
|
-
avatar = profilePicture
|
|
130
|
+
picture = profilePicture
|
|
141
131
|
)
|
|
142
132
|
}
|
|
143
133
|
}
|
package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusUIController.kt
CHANGED
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
package com.octopuscommunity.octopusreactnativesdk
|
|
2
2
|
|
|
3
3
|
import android.content.Intent
|
|
4
|
+
import android.net.Uri
|
|
4
5
|
import com.facebook.react.bridge.Promise
|
|
5
6
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
7
|
+
import com.facebook.react.bridge.ReadableMap
|
|
6
8
|
|
|
7
9
|
class OctopusUIController(private val reactContext: ReactApplicationContext) {
|
|
8
10
|
|
|
9
|
-
fun openUI(promise: Promise) {
|
|
11
|
+
fun openUI(options: ReadableMap?, promise: Promise) {
|
|
10
12
|
try {
|
|
11
|
-
val intent = Intent(reactContext,
|
|
13
|
+
val intent = Intent(reactContext, OctopusActivity::class.java)
|
|
12
14
|
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
15
|
+
val interceptUrls = options?.hasKey("interceptUrls") == true &&
|
|
16
|
+
options.getBoolean("interceptUrls")
|
|
17
|
+
intent.putExtra(OctopusActivity.EXTRA_INTERCEPT_URLS, interceptUrls)
|
|
13
18
|
reactContext.startActivity(intent)
|
|
14
19
|
promise.resolve(null)
|
|
15
20
|
} catch (e: Exception) {
|
|
@@ -28,6 +33,16 @@ class OctopusUIController(private val reactContext: ReactApplicationContext) {
|
|
|
28
33
|
}
|
|
29
34
|
}
|
|
30
35
|
|
|
36
|
+
fun openUrlInBrowser(url: String) {
|
|
37
|
+
try {
|
|
38
|
+
val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
|
|
39
|
+
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
|
40
|
+
reactContext.startActivity(intent)
|
|
41
|
+
} catch (e: Exception) {
|
|
42
|
+
// Ignore if no app can handle the URL
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
31
46
|
companion object {
|
|
32
47
|
const val CLOSE_UI_ACTION = "com.octopuscommunity.octopusreactnativesdk.CLOSE_UI"
|
|
33
48
|
}
|
package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/OctopusUIViewManager.kt
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
package com.octopuscommunity.octopusreactnativesdk
|
|
2
|
+
|
|
3
|
+
import android.view.ViewGroup
|
|
4
|
+
import androidx.compose.foundation.layout.WindowInsets
|
|
5
|
+
import androidx.compose.foundation.layout.captionBar
|
|
6
|
+
import androidx.compose.foundation.layout.consumeWindowInsets
|
|
7
|
+
import androidx.compose.foundation.layout.displayCutout
|
|
8
|
+
import androidx.compose.foundation.layout.fillMaxSize
|
|
9
|
+
import androidx.compose.foundation.layout.ime
|
|
10
|
+
import androidx.compose.foundation.layout.mandatorySystemGestures
|
|
11
|
+
import androidx.compose.foundation.layout.navigationBars
|
|
12
|
+
import androidx.compose.foundation.layout.safeContent
|
|
13
|
+
import androidx.compose.foundation.layout.safeDrawing
|
|
14
|
+
import androidx.compose.foundation.layout.safeGestures
|
|
15
|
+
import androidx.compose.foundation.layout.statusBars
|
|
16
|
+
import androidx.compose.foundation.layout.systemBars
|
|
17
|
+
import androidx.compose.foundation.layout.systemGestures
|
|
18
|
+
import androidx.compose.foundation.layout.tappableElement
|
|
19
|
+
import androidx.compose.foundation.layout.waterfall
|
|
20
|
+
import androidx.compose.material3.MaterialTheme
|
|
21
|
+
import androidx.compose.ui.Modifier
|
|
22
|
+
import androidx.compose.ui.platform.ComposeView
|
|
23
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
24
|
+
import com.facebook.react.uimanager.SimpleViewManager
|
|
25
|
+
import com.facebook.react.uimanager.ThemedReactContext
|
|
26
|
+
import com.facebook.react.uimanager.annotations.ReactProp
|
|
27
|
+
|
|
28
|
+
class OctopusUIViewManager(private val reactContext: ReactApplicationContext) :
|
|
29
|
+
SimpleViewManager<ComposeView>() {
|
|
30
|
+
|
|
31
|
+
private var interceptUrls: Boolean = false
|
|
32
|
+
|
|
33
|
+
override fun getName(): String = REACT_CLASS_NAME
|
|
34
|
+
|
|
35
|
+
override fun createViewInstance(reactContext: ThemedReactContext) =
|
|
36
|
+
ComposeView(reactContext).apply {
|
|
37
|
+
layoutParams = ViewGroup.LayoutParams(
|
|
38
|
+
ViewGroup.LayoutParams.MATCH_PARENT,
|
|
39
|
+
ViewGroup.LayoutParams.MATCH_PARENT
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
setContent {
|
|
43
|
+
MaterialTheme {
|
|
44
|
+
OctopusContent(
|
|
45
|
+
modifier = Modifier.fillMaxSize()
|
|
46
|
+
.consumeWindowInsets(WindowInsets.statusBars)
|
|
47
|
+
.consumeWindowInsets(WindowInsets.navigationBars)
|
|
48
|
+
.consumeWindowInsets(WindowInsets.systemBars),
|
|
49
|
+
interceptUrls = interceptUrls
|
|
50
|
+
)
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@ReactProp(name = "interceptUrls")
|
|
56
|
+
fun setInterceptUrls(view: ComposeView, interceptUrls: Boolean) {
|
|
57
|
+
this.interceptUrls = interceptUrls
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
companion object Companion {
|
|
61
|
+
const val REACT_CLASS_NAME = "OctopusUIView"
|
|
62
|
+
}
|
|
63
|
+
}
|
package/android/src/main/java/com/octopuscommunity/octopusreactnativesdk/ProfileFieldMapper.kt
CHANGED
|
@@ -23,7 +23,7 @@ object ProfileFieldMapper {
|
|
|
23
23
|
return when (fieldName) {
|
|
24
24
|
"username" -> ProfileField.NICKNAME
|
|
25
25
|
"biography" -> ProfileField.BIO
|
|
26
|
-
"profilePicture" -> ProfileField.
|
|
26
|
+
"profilePicture" -> ProfileField.PICTURE
|
|
27
27
|
else -> null
|
|
28
28
|
}
|
|
29
29
|
}
|
|
@@ -32,7 +32,7 @@ object ProfileFieldMapper {
|
|
|
32
32
|
return when (profileField) {
|
|
33
33
|
ProfileField.NICKNAME -> "username"
|
|
34
34
|
ProfileField.BIO -> "biography"
|
|
35
|
-
ProfileField.
|
|
35
|
+
ProfileField.PICTURE -> "profilePicture"
|
|
36
36
|
else -> null
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -30,6 +30,33 @@ class OctopusEventManager {
|
|
|
30
30
|
}
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
+
func emitNotSeenNotificationsCountChanged(count: Int) {
|
|
34
|
+
if hasListeners {
|
|
35
|
+
let eventBody = ["count": count]
|
|
36
|
+
bridge?.eventDispatcher().sendAppEvent(withName: "notSeenNotificationsCountChanged", body: eventBody)
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
func emitHasAccessToCommunityChanged(hasAccess: Bool) {
|
|
41
|
+
if hasListeners {
|
|
42
|
+
let eventBody = ["hasAccess": hasAccess]
|
|
43
|
+
bridge?.eventDispatcher().sendAppEvent(withName: "hasAccessToCommunityChanged", body: eventBody)
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
func emitSDKEvent(eventData: [String: Any]) {
|
|
48
|
+
if hasListeners {
|
|
49
|
+
bridge?.eventDispatcher().sendAppEvent(withName: "sdkEvent", body: eventData)
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
func emitNavigateToUrl(url: String) {
|
|
54
|
+
if hasListeners {
|
|
55
|
+
let eventBody = ["url": url]
|
|
56
|
+
bridge?.eventDispatcher().sendAppEvent(withName: "navigateToUrl", body: eventBody)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
33
60
|
func startObserving() {
|
|
34
61
|
hasListeners = true
|
|
35
62
|
}
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Octopus
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Serializes OctopusEvent objects to dictionaries for React Native bridge.
|
|
6
|
+
*/
|
|
7
|
+
class OctopusEventSerializer {
|
|
8
|
+
|
|
9
|
+
static func serializeEvent(_ event: OctopusEvent) -> [String: Any]? {
|
|
10
|
+
switch event {
|
|
11
|
+
case .postCreated(let context):
|
|
12
|
+
var contentList: [String] = []
|
|
13
|
+
if context.content.contains(.text) { contentList.append("text") }
|
|
14
|
+
if context.content.contains(.image) { contentList.append("image") }
|
|
15
|
+
if context.content.contains(.poll) { contentList.append("poll") }
|
|
16
|
+
return [
|
|
17
|
+
"type": "postCreated",
|
|
18
|
+
"postId": context.postId,
|
|
19
|
+
"content": contentList,
|
|
20
|
+
"topicId": context.topicId,
|
|
21
|
+
"textLength": context.textLength
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
case .commentCreated(let context):
|
|
25
|
+
return [
|
|
26
|
+
"type": "commentCreated",
|
|
27
|
+
"commentId": context.commentId,
|
|
28
|
+
"postId": context.postId,
|
|
29
|
+
"textLength": context.textLength
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
case .replyCreated(let context):
|
|
33
|
+
return [
|
|
34
|
+
"type": "replyCreated",
|
|
35
|
+
"replyId": context.replyId,
|
|
36
|
+
"commentId": context.commentId,
|
|
37
|
+
"textLength": context.textLength
|
|
38
|
+
]
|
|
39
|
+
|
|
40
|
+
case .contentDeleted(let context):
|
|
41
|
+
return [
|
|
42
|
+
"type": "contentDeleted",
|
|
43
|
+
"contentId": context.contentId,
|
|
44
|
+
"contentKind": serializeContentKind(context.kind)
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
case .reactionModified(let context):
|
|
48
|
+
var data: [String: Any] = [
|
|
49
|
+
"type": "reactionModified",
|
|
50
|
+
"contentId": context.contentId,
|
|
51
|
+
"contentKind": serializeContentKind(context.contentKind)
|
|
52
|
+
]
|
|
53
|
+
if let prev = context.previousReaction {
|
|
54
|
+
data["previousReaction"] = serializeReactionKind(prev)
|
|
55
|
+
}
|
|
56
|
+
if let next = context.newReaction {
|
|
57
|
+
data["newReaction"] = serializeReactionKind(next)
|
|
58
|
+
}
|
|
59
|
+
return data
|
|
60
|
+
|
|
61
|
+
case .pollVoted(let context):
|
|
62
|
+
return [
|
|
63
|
+
"type": "pollVoted",
|
|
64
|
+
"contentId": context.contentId,
|
|
65
|
+
"optionId": context.optionId
|
|
66
|
+
]
|
|
67
|
+
|
|
68
|
+
case .contentReported(let context):
|
|
69
|
+
return [
|
|
70
|
+
"type": "contentReported",
|
|
71
|
+
"contentId": context.contentId,
|
|
72
|
+
"reasons": context.reasons.map { serializeReportReason($0) }
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
case .gamificationPointsGained(let context):
|
|
76
|
+
return [
|
|
77
|
+
"type": "gamificationPointsGained",
|
|
78
|
+
"points": context.pointsGained,
|
|
79
|
+
"action": serializeGamificationPointsGainedAction(context.action)
|
|
80
|
+
]
|
|
81
|
+
|
|
82
|
+
case .gamificationPointsRemoved(let context):
|
|
83
|
+
return [
|
|
84
|
+
"type": "gamificationPointsRemoved",
|
|
85
|
+
"points": context.pointsRemoved,
|
|
86
|
+
"action": serializeGamificationPointsRemovedAction(context.action)
|
|
87
|
+
]
|
|
88
|
+
|
|
89
|
+
case .screenDisplayed(let context):
|
|
90
|
+
return [
|
|
91
|
+
"type": "screenDisplayed",
|
|
92
|
+
"screen": serializeScreen(context.screen)
|
|
93
|
+
]
|
|
94
|
+
|
|
95
|
+
case .notificationClicked(let context):
|
|
96
|
+
var data: [String: Any] = [
|
|
97
|
+
"type": "notificationClicked",
|
|
98
|
+
"notificationId": context.notificationId
|
|
99
|
+
]
|
|
100
|
+
if let contentId = context.contentId {
|
|
101
|
+
data["contentId"] = contentId
|
|
102
|
+
}
|
|
103
|
+
return data
|
|
104
|
+
|
|
105
|
+
case .postClicked(let context):
|
|
106
|
+
return [
|
|
107
|
+
"type": "postClicked",
|
|
108
|
+
"postId": context.postId,
|
|
109
|
+
"source": serializePostClickedSource(context.source)
|
|
110
|
+
]
|
|
111
|
+
|
|
112
|
+
case .translationButtonClicked(let context):
|
|
113
|
+
return [
|
|
114
|
+
"type": "translationButtonClicked",
|
|
115
|
+
"contentId": context.contentId,
|
|
116
|
+
"viewTranslated": context.viewTranslated,
|
|
117
|
+
"contentKind": serializeContentKind(context.contentKind)
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
case .commentButtonClicked(let context):
|
|
121
|
+
return [
|
|
122
|
+
"type": "commentButtonClicked",
|
|
123
|
+
"postId": context.postId
|
|
124
|
+
]
|
|
125
|
+
|
|
126
|
+
case .replyButtonClicked(let context):
|
|
127
|
+
return [
|
|
128
|
+
"type": "replyButtonClicked",
|
|
129
|
+
"commentId": context.commentId
|
|
130
|
+
]
|
|
131
|
+
|
|
132
|
+
case .seeRepliesButtonClicked(let context):
|
|
133
|
+
return [
|
|
134
|
+
"type": "seeRepliesButtonClicked",
|
|
135
|
+
"commentId": context.commentId
|
|
136
|
+
]
|
|
137
|
+
|
|
138
|
+
case .profileModified(let context):
|
|
139
|
+
var data: [String: Any] = [
|
|
140
|
+
"type": "profileModified",
|
|
141
|
+
"nicknameUpdated": context.nickname.isUpdated,
|
|
142
|
+
"bioUpdated": context.bio.isUpdated,
|
|
143
|
+
"pictureUpdated": context.picture.isUpdated
|
|
144
|
+
]
|
|
145
|
+
if case .updated(let bioContext) = context.bio {
|
|
146
|
+
data["bioLength"] = bioContext.bioLength
|
|
147
|
+
}
|
|
148
|
+
if case .updated(let pictureContext) = context.picture {
|
|
149
|
+
data["hasPicture"] = pictureContext.hasPicture
|
|
150
|
+
}
|
|
151
|
+
return data
|
|
152
|
+
|
|
153
|
+
case .sessionStarted(let context):
|
|
154
|
+
return [
|
|
155
|
+
"type": "sessionStarted",
|
|
156
|
+
"sessionId": context.sessionId
|
|
157
|
+
]
|
|
158
|
+
|
|
159
|
+
case .sessionStopped(let context):
|
|
160
|
+
return [
|
|
161
|
+
"type": "sessionStopped",
|
|
162
|
+
"sessionId": context.sessionId
|
|
163
|
+
]
|
|
164
|
+
|
|
165
|
+
@unknown default:
|
|
166
|
+
return nil
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
private static func serializeContentKind(_ kind: OctopusEvent.ContentKind) -> String {
|
|
171
|
+
switch kind {
|
|
172
|
+
case .post: return "post"
|
|
173
|
+
case .comment: return "comment"
|
|
174
|
+
case .reply: return "reply"
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
private static func serializeReactionKind(_ kind: OctopusEvent.ReactionKind) -> String {
|
|
179
|
+
switch kind {
|
|
180
|
+
case .heart: return "heart"
|
|
181
|
+
case .joy: return "joy"
|
|
182
|
+
case .mouthOpen: return "mouthOpen"
|
|
183
|
+
case .clap: return "clap"
|
|
184
|
+
case .cry: return "cry"
|
|
185
|
+
case .rage: return "rage"
|
|
186
|
+
case .unknown: return "unknown"
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
private static func serializeReportReason(_ reason: OctopusEvent.ReportReason) -> String {
|
|
191
|
+
switch reason {
|
|
192
|
+
case .hateSpeechOrDiscriminationOrHarassment: return "hateSpeech"
|
|
193
|
+
case .explicitOrInappropriateContent: return "explicit"
|
|
194
|
+
case .violenceAndTerrorism: return "violence"
|
|
195
|
+
case .spamAndScams: return "spam"
|
|
196
|
+
case .suicideAndSelfHarm: return "suicide"
|
|
197
|
+
case .fakeProfilesAndImpersonation: return "fakeProfile"
|
|
198
|
+
case .childExploitationOrAbuse: return "childExploitation"
|
|
199
|
+
case .intellectualPropertyViolation: return "intellectualProperty"
|
|
200
|
+
case .other: return "other"
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
private static func serializeGamificationPointsGainedAction(_ action: OctopusEvent.GamificationPointsGainedAction) -> String {
|
|
205
|
+
switch action {
|
|
206
|
+
case .post: return "post"
|
|
207
|
+
case .comment: return "comment"
|
|
208
|
+
case .reply: return "reply"
|
|
209
|
+
case .reaction: return "reaction"
|
|
210
|
+
case .vote: return "vote"
|
|
211
|
+
case .postCommented: return "postCommented"
|
|
212
|
+
case .profileCompleted: return "profileCompleted"
|
|
213
|
+
case .dailySession: return "dailySession"
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
private static func serializeGamificationPointsRemovedAction(_ action: OctopusEvent.GamificationPointsRemovedAction) -> String {
|
|
218
|
+
switch action {
|
|
219
|
+
case .postDeleted: return "postDeleted"
|
|
220
|
+
case .commentDeleted: return "commentDeleted"
|
|
221
|
+
case .replyDeleted: return "replyDeleted"
|
|
222
|
+
case .reactionDeleted: return "reactionDeleted"
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
private static func serializePostClickedSource(_ source: OctopusEvent.PostClickedSource) -> String {
|
|
227
|
+
switch source {
|
|
228
|
+
case .feed: return "feed"
|
|
229
|
+
case .profile: return "profile"
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
private static func serializeScreen(_ screen: OctopusEvent.Screen) -> [String: Any] {
|
|
234
|
+
switch screen {
|
|
235
|
+
case .postsFeed(let context):
|
|
236
|
+
var data: [String: Any] = ["type": "postsFeed", "feedId": context.feedId]
|
|
237
|
+
if let relatedTopicId = context.relatedTopicId {
|
|
238
|
+
data["relatedTopicId"] = relatedTopicId
|
|
239
|
+
}
|
|
240
|
+
return data
|
|
241
|
+
case .postDetail(let context):
|
|
242
|
+
return ["type": "postDetail", "postId": context.postId]
|
|
243
|
+
case .commentDetail(let context):
|
|
244
|
+
return ["type": "commentDetail", "commentId": context.commentId]
|
|
245
|
+
case .createPost:
|
|
246
|
+
return ["type": "createPost"]
|
|
247
|
+
case .profile:
|
|
248
|
+
return ["type": "profile"]
|
|
249
|
+
case .otherUserProfile(let context):
|
|
250
|
+
return ["type": "otherUserProfile", "profileId": context.profileId]
|
|
251
|
+
case .editProfile:
|
|
252
|
+
return ["type": "editProfile"]
|
|
253
|
+
case .reportContent:
|
|
254
|
+
return ["type": "reportContent"]
|
|
255
|
+
case .reportProfile:
|
|
256
|
+
return ["type": "reportProfile"]
|
|
257
|
+
case .validateNickname:
|
|
258
|
+
return ["type": "validateNickname"]
|
|
259
|
+
case .settingsList:
|
|
260
|
+
return ["type": "settingsList"]
|
|
261
|
+
case .settingsAccount:
|
|
262
|
+
return ["type": "settingsAccount"]
|
|
263
|
+
case .settingsAbout:
|
|
264
|
+
return ["type": "settingsAbout"]
|
|
265
|
+
case .reportExplanation:
|
|
266
|
+
return ["type": "reportExplanation"]
|
|
267
|
+
case .deleteAccount:
|
|
268
|
+
return ["type": "deleteAccount"]
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
}
|
|
@@ -6,9 +6,13 @@ RCT_EXTERN_METHOD(initialize:(NSDictionary *)options
|
|
|
6
6
|
withResolver:(RCTPromiseResolveBlock)resolve
|
|
7
7
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
8
8
|
|
|
9
|
-
RCT_EXTERN_METHOD(openUI:(
|
|
9
|
+
RCT_EXTERN_METHOD(openUI:(NSDictionary *)options
|
|
10
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
10
11
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
11
12
|
|
|
13
|
+
RCT_EXTERN_METHOD(handleUrlStrategy:(NSString *)url
|
|
14
|
+
withStrategy:(NSString *)strategy)
|
|
15
|
+
|
|
12
16
|
RCT_EXTERN_METHOD(closeUI:(RCTPromiseResolveBlock)resolve
|
|
13
17
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
14
18
|
|
|
@@ -36,6 +40,27 @@ RCT_EXTERN_METHOD(updateTheme:(NSDictionary *)themeOptions
|
|
|
36
40
|
withResolver:(RCTPromiseResolveBlock)resolve
|
|
37
41
|
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
38
42
|
|
|
43
|
+
RCT_EXTERN_METHOD(updateNotSeenNotificationsCount:(RCTPromiseResolveBlock)resolve
|
|
44
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
45
|
+
|
|
46
|
+
RCT_EXTERN_METHOD(trackCustomEvent:(NSString *)name
|
|
47
|
+
withProperties:(NSDictionary *)properties
|
|
48
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
49
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
50
|
+
|
|
51
|
+
RCT_EXTERN_METHOD(overrideDefaultLocale:(NSString *)languageCode
|
|
52
|
+
withCountryCode:(NSString *)countryCode
|
|
53
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
54
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
55
|
+
|
|
56
|
+
RCT_EXTERN_METHOD(overrideCommunityAccess:(BOOL)hasAccess
|
|
57
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
58
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
59
|
+
|
|
60
|
+
RCT_EXTERN_METHOD(trackCommunityAccess:(BOOL)hasAccess
|
|
61
|
+
withResolver:(RCTPromiseResolveBlock)resolve
|
|
62
|
+
withRejecter:(RCTPromiseRejectBlock)reject)
|
|
63
|
+
|
|
39
64
|
RCT_EXTERN_METHOD(addListener:(NSString *)eventName)
|
|
40
65
|
|
|
41
66
|
RCT_EXTERN_METHOD(removeListeners:(NSInteger)count)
|