@viafoura/sdk-react-native 0.1.1 → 0.1.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/build.gradle +1 -0
- package/android/src/main/java/expo/modules/viafourasdk/Colors.kt +68 -0
- package/android/src/main/java/expo/modules/viafourasdk/NewCommentModule.kt +3 -2
- package/android/src/main/java/expo/modules/viafourasdk/NewCommentView.kt +31 -9
- package/android/src/main/java/expo/modules/viafourasdk/PreviewCommentsModule.kt +3 -2
- package/android/src/main/java/expo/modules/viafourasdk/PreviewCommentsView.kt +47 -16
- package/android/src/main/java/expo/modules/viafourasdk/ProfileModule.kt +3 -2
- package/android/src/main/java/expo/modules/viafourasdk/ProfileView.kt +32 -11
- package/android/src/main/java/expo/modules/viafourasdk/ViafouraModule.kt +9 -9
- package/build/Viafoura.types.d.ts +58 -1
- package/build/Viafoura.types.d.ts.map +1 -1
- package/build/Viafoura.types.js.map +1 -1
- package/ios/PreviewCommentsModule.swift +137 -8
- package/package.json +1 -1
package/android/build.gradle
CHANGED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
package expo.modules.viafourasdk
|
|
2
|
+
|
|
3
|
+
import android.graphics.Color
|
|
4
|
+
import com.viafourasdk.src.Constants
|
|
5
|
+
import com.viafourasdk.src.model.local.VFColors
|
|
6
|
+
import com.viafourasdk.src.model.local.VFDefaultColors
|
|
7
|
+
import com.viafourasdk.src.model.local.VFTheme
|
|
8
|
+
|
|
9
|
+
private const val KEY_COLOR_PRIMARY = "colorPrimary"
|
|
10
|
+
private const val KEY_COLOR_PRIMARY_LIGHT = "colorPrimaryLight"
|
|
11
|
+
private const val KEY_COLOR_AVATARS = "colorAvatars"
|
|
12
|
+
private const val KEY_PRIMARY = "primary"
|
|
13
|
+
private const val KEY_PRIMARY_LIGHT = "primaryLight"
|
|
14
|
+
private const val KEY_AVATARS = "avatars"
|
|
15
|
+
|
|
16
|
+
internal fun resolveVFColors(colors: Map<String, Any?>?, theme: VFTheme?): VFColors {
|
|
17
|
+
val defaults = VFDefaultColors.getInstance()
|
|
18
|
+
val defaultPrimary = defaults.colorPrimaryDefault(null)
|
|
19
|
+
val defaultPrimaryLight = defaults.colorPrimaryLightDefault(null)
|
|
20
|
+
|
|
21
|
+
val primary =
|
|
22
|
+
parseColorOrNull(colors?.get(KEY_COLOR_PRIMARY) ?: colors?.get(KEY_PRIMARY))
|
|
23
|
+
?: defaultPrimary
|
|
24
|
+
val primaryLight =
|
|
25
|
+
parseColorOrNull(colors?.get(KEY_COLOR_PRIMARY_LIGHT) ?: colors?.get(KEY_PRIMARY_LIGHT))
|
|
26
|
+
?: defaultPrimaryLight
|
|
27
|
+
|
|
28
|
+
val vfColors = VFColors(primary, primaryLight)
|
|
29
|
+
parseAvatarColors(colors?.get(KEY_COLOR_AVATARS) ?: colors?.get(KEY_AVATARS))
|
|
30
|
+
?.let { vfColors.setColorAvatars(it) }
|
|
31
|
+
theme?.let { vfColors.setTheme(it) }
|
|
32
|
+
|
|
33
|
+
return vfColors
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
private fun parseColorOrNull(value: Any?): Int? {
|
|
37
|
+
return when (value) {
|
|
38
|
+
is Int -> value
|
|
39
|
+
is Long -> value.toInt()
|
|
40
|
+
is Number -> value.toInt()
|
|
41
|
+
is String -> {
|
|
42
|
+
if (value.isBlank()) return null
|
|
43
|
+
try {
|
|
44
|
+
Color.parseColor(value)
|
|
45
|
+
} catch (_: IllegalArgumentException) {
|
|
46
|
+
null
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
else -> null
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private fun parseAvatarColors(value: Any?): IntArray? {
|
|
54
|
+
val list = when (value) {
|
|
55
|
+
is List<*> -> value
|
|
56
|
+
is Array<*> -> value.asList()
|
|
57
|
+
else -> return null
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
if (list.size != Constants.AVATAR_COLORS.size) return null
|
|
61
|
+
|
|
62
|
+
val parsed = IntArray(list.size)
|
|
63
|
+
for (index in list.indices) {
|
|
64
|
+
val color = parseColorOrNull(list[index]) ?: return null
|
|
65
|
+
parsed[index] = color
|
|
66
|
+
}
|
|
67
|
+
return parsed
|
|
68
|
+
}
|
|
@@ -18,10 +18,11 @@ class NewCommentModule : Module() {
|
|
|
18
18
|
Prop("articleUrl") { view: NewCommentView, v: String -> view.articleUrl = v }
|
|
19
19
|
Prop("articleThumbnailUrl") { view: NewCommentView, v: String -> view.articleThumbnailUrl = v }
|
|
20
20
|
Prop("darkMode") { view: NewCommentView, v: Boolean? -> view.darkMode = v ?: false }
|
|
21
|
+
Prop("theme") { view: NewCommentView, v: String? -> view.theme = v }
|
|
22
|
+
Prop("colors") { view: NewCommentView, v: Map<String, Any?>? -> view.colors = v }
|
|
21
23
|
|
|
22
24
|
// Events
|
|
23
|
-
Events("onAuthNeeded", "onCloseNewComment", "onHeightChanged")
|
|
25
|
+
Events("onAuthNeeded", "onCloseNewComment", "onHeightChanged", "onAction")
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
|
|
@@ -20,14 +20,12 @@ import com.viafourasdk.src.interfaces.VFLayoutInterface
|
|
|
20
20
|
import com.viafourasdk.src.model.local.VFActionData
|
|
21
21
|
import com.viafourasdk.src.model.local.VFActionType
|
|
22
22
|
import com.viafourasdk.src.model.local.VFArticleMetadata
|
|
23
|
-
import com.viafourasdk.src.model.local.VFColors
|
|
24
|
-
import com.viafourasdk.src.model.local.VFDefaultColors
|
|
25
23
|
import com.viafourasdk.src.model.local.VFSettings
|
|
26
24
|
import com.viafourasdk.src.model.local.VFTheme
|
|
27
25
|
import java.net.URL
|
|
28
26
|
import java.util.UUID
|
|
29
27
|
|
|
30
|
-
class NewCommentView(context: Context,
|
|
28
|
+
class NewCommentView(context: Context, appContext: AppContext) :
|
|
31
29
|
ExpoView(context, appContext), VFCustomUIInterface, VFActionsInterface, VFLayoutInterface {
|
|
32
30
|
|
|
33
31
|
// Props
|
|
@@ -40,11 +38,22 @@ class NewCommentView(context: Context, private val appContext: AppContext) :
|
|
|
40
38
|
var articleUrl: String? = null
|
|
41
39
|
var articleThumbnailUrl: String? = null
|
|
42
40
|
var darkMode: Boolean = false
|
|
41
|
+
set(value) {
|
|
42
|
+
field = value
|
|
43
|
+
applyThemeIfReady()
|
|
44
|
+
}
|
|
45
|
+
var theme: String? = null
|
|
46
|
+
set(value) {
|
|
47
|
+
field = value
|
|
48
|
+
applyThemeIfReady()
|
|
49
|
+
}
|
|
50
|
+
var colors: Map<String, Any?>? = null
|
|
43
51
|
|
|
44
52
|
// Events
|
|
45
53
|
private val onAuthNeeded by EventDispatcher()
|
|
46
54
|
private val onCloseNewComment by EventDispatcher()
|
|
47
55
|
private val onHeightChanged by EventDispatcher()
|
|
56
|
+
private val onAction by EventDispatcher()
|
|
48
57
|
|
|
49
58
|
// Internals
|
|
50
59
|
private val container = FrameLayout(context).also {
|
|
@@ -72,17 +81,16 @@ class NewCommentView(context: Context, private val appContext: AppContext) :
|
|
|
72
81
|
val activity = currentActivity() ?: return
|
|
73
82
|
|
|
74
83
|
try {
|
|
84
|
+
val resolvedTheme = resolveTheme()
|
|
75
85
|
val metadata = VFArticleMetadata(
|
|
76
86
|
URL(requireNotNull(articleUrl)),
|
|
77
87
|
requireNotNull(articleTitle),
|
|
78
88
|
articleSubtitle ?: "",
|
|
79
89
|
URL(requireNotNull(articleThumbnailUrl))
|
|
80
90
|
)
|
|
81
|
-
val
|
|
82
|
-
|
|
83
|
-
VFDefaultColors.getInstance().colorPrimaryLightDefault(null)
|
|
91
|
+
val settings = VFSettings(
|
|
92
|
+
resolveVFColors(colors, resolvedTheme)
|
|
84
93
|
)
|
|
85
|
-
val settings = VFSettings(colors)
|
|
86
94
|
|
|
87
95
|
val type = when (newCommentActionType) {
|
|
88
96
|
"edit" -> VFNewCommentAction.VFNewCommentActionType.edit
|
|
@@ -99,7 +107,7 @@ class NewCommentView(context: Context, private val appContext: AppContext) :
|
|
|
99
107
|
val frag = builder.build()
|
|
100
108
|
frag.setActionCallback(this)
|
|
101
109
|
frag.setCustomUICallback(this)
|
|
102
|
-
frag.setTheme(
|
|
110
|
+
frag.setTheme(resolvedTheme)
|
|
103
111
|
|
|
104
112
|
activity.supportFragmentManager
|
|
105
113
|
.beginTransaction()
|
|
@@ -127,15 +135,18 @@ class NewCommentView(context: Context, private val appContext: AppContext) :
|
|
|
127
135
|
|
|
128
136
|
// VFActionsInterface
|
|
129
137
|
override fun onNewAction(actionType: VFActionType, action: VFActionData) {
|
|
138
|
+
val actionPayload = mutableMapOf<String, Any>("type" to actionType.toString())
|
|
130
139
|
when (actionType) {
|
|
131
140
|
VFActionType.closeNewCommentPressed -> {
|
|
132
141
|
onCloseNewComment(emptyMap<String, Any>())
|
|
133
142
|
}
|
|
134
143
|
VFActionType.authPressed -> {
|
|
144
|
+
actionPayload["requireLogin"] = true
|
|
135
145
|
onAuthNeeded(mapOf("requireLogin" to true))
|
|
136
146
|
}
|
|
137
147
|
else -> {}
|
|
138
148
|
}
|
|
149
|
+
onAction(actionPayload)
|
|
139
150
|
}
|
|
140
151
|
|
|
141
152
|
// VFCustomUIInterface
|
|
@@ -149,5 +160,16 @@ class NewCommentView(context: Context, private val appContext: AppContext) :
|
|
|
149
160
|
override fun containerHeightUpdated(fragment: VFFragment, containerId: String, height: Int) {
|
|
150
161
|
onHeightChanged(mapOf("newHeight" to height, "containerId" to containerId))
|
|
151
162
|
}
|
|
152
|
-
}
|
|
153
163
|
|
|
164
|
+
private fun resolveTheme(): VFTheme {
|
|
165
|
+
return when (theme?.lowercase()) {
|
|
166
|
+
"dark" -> VFTheme.dark
|
|
167
|
+
"light" -> VFTheme.light
|
|
168
|
+
else -> if (darkMode) VFTheme.dark else VFTheme.light
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
private fun applyThemeIfReady() {
|
|
173
|
+
fragment?.setTheme(resolveTheme())
|
|
174
|
+
}
|
|
175
|
+
}
|
|
@@ -17,10 +17,11 @@ class PreviewCommentsModule : Module() {
|
|
|
17
17
|
Prop("articleThumbnailUrl") { view: PreviewCommentsView, v: String -> view.articleThumbnailUrl = v }
|
|
18
18
|
Prop("syndicationKey") { view: PreviewCommentsView, v: String? -> view.syndicationKey = v }
|
|
19
19
|
Prop("darkMode") { view: PreviewCommentsView, v: Boolean? -> view.darkMode = v ?: false }
|
|
20
|
+
Prop("theme") { view: PreviewCommentsView, v: String? -> view.theme = v }
|
|
21
|
+
Prop("colors") { view: PreviewCommentsView, v: Map<String, Any?>? -> view.colors = v }
|
|
20
22
|
|
|
21
23
|
// Events
|
|
22
|
-
Events("onHeightChanged", "onAuthNeeded", "onOpenProfile", "onNewComment", "onArticlePressed")
|
|
24
|
+
Events("onHeightChanged", "onAuthNeeded", "onOpenProfile", "onNewComment", "onArticlePressed", "onAction")
|
|
23
25
|
}
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
|
-
|
|
@@ -20,13 +20,11 @@ import com.viafourasdk.src.interfaces.VFLayoutInterface
|
|
|
20
20
|
import com.viafourasdk.src.model.local.VFActionData
|
|
21
21
|
import com.viafourasdk.src.model.local.VFActionType
|
|
22
22
|
import com.viafourasdk.src.model.local.VFArticleMetadata
|
|
23
|
-
import com.viafourasdk.src.model.local.VFColors
|
|
24
|
-
import com.viafourasdk.src.model.local.VFDefaultColors
|
|
25
23
|
import com.viafourasdk.src.model.local.VFSettings
|
|
26
24
|
import com.viafourasdk.src.model.local.VFTheme
|
|
27
25
|
import java.net.URL
|
|
28
26
|
|
|
29
|
-
class PreviewCommentsView(context: Context,
|
|
27
|
+
class PreviewCommentsView(context: Context, appContext: AppContext) :
|
|
30
28
|
ExpoView(context, appContext), VFCustomUIInterface, VFActionsInterface, VFLayoutInterface {
|
|
31
29
|
|
|
32
30
|
// Props
|
|
@@ -38,6 +36,16 @@ class PreviewCommentsView(context: Context, private val appContext: AppContext)
|
|
|
38
36
|
var articleThumbnailUrl: String? = null
|
|
39
37
|
var syndicationKey: String? = null
|
|
40
38
|
var darkMode: Boolean = false
|
|
39
|
+
set(value) {
|
|
40
|
+
field = value
|
|
41
|
+
applyThemeIfReady()
|
|
42
|
+
}
|
|
43
|
+
var theme: String? = null
|
|
44
|
+
set(value) {
|
|
45
|
+
field = value
|
|
46
|
+
applyThemeIfReady()
|
|
47
|
+
}
|
|
48
|
+
var colors: Map<String, Any?>? = null
|
|
41
49
|
|
|
42
50
|
// Events
|
|
43
51
|
private val onHeightChanged by EventDispatcher()
|
|
@@ -45,6 +53,7 @@ class PreviewCommentsView(context: Context, private val appContext: AppContext)
|
|
|
45
53
|
private val onOpenProfile by EventDispatcher()
|
|
46
54
|
private val onNewComment by EventDispatcher()
|
|
47
55
|
private val onArticlePressed by EventDispatcher()
|
|
56
|
+
private val onAction by EventDispatcher()
|
|
48
57
|
|
|
49
58
|
// Internals
|
|
50
59
|
private val container = FrameLayout(context).also {
|
|
@@ -73,17 +82,16 @@ class PreviewCommentsView(context: Context, private val appContext: AppContext)
|
|
|
73
82
|
val activity = currentActivity() ?: return
|
|
74
83
|
|
|
75
84
|
try {
|
|
85
|
+
val resolvedTheme = resolveTheme()
|
|
76
86
|
val meta = VFArticleMetadata(
|
|
77
87
|
URL(requireNotNull(articleUrl)),
|
|
78
88
|
requireNotNull(articleTitle),
|
|
79
89
|
articleSubtitle ?: "",
|
|
80
90
|
URL(requireNotNull(articleThumbnailUrl))
|
|
81
91
|
)
|
|
82
|
-
val
|
|
83
|
-
|
|
84
|
-
VFDefaultColors.getInstance().colorPrimaryLightDefault(null)
|
|
92
|
+
val settings = VFSettings(
|
|
93
|
+
resolveVFColors(colors, resolvedTheme)
|
|
85
94
|
)
|
|
86
|
-
val settings = VFSettings(colors)
|
|
87
95
|
|
|
88
96
|
val builder = VFPreviewCommentsFragmentBuilder(requireNotNull(containerId), meta, settings)
|
|
89
97
|
syndicationKey?.let { builder.syndicationKey(it) }
|
|
@@ -91,7 +99,7 @@ class PreviewCommentsView(context: Context, private val appContext: AppContext)
|
|
|
91
99
|
frag.setActionCallback(this)
|
|
92
100
|
frag.setLayoutCallback(this)
|
|
93
101
|
frag.setCustomUICallback(this)
|
|
94
|
-
frag.setTheme(
|
|
102
|
+
frag.setTheme(resolvedTheme)
|
|
95
103
|
authorId?.let { if (it.isNotEmpty()) frag.setAuthorIds(listOf(it)) }
|
|
96
104
|
|
|
97
105
|
activity.supportFragmentManager
|
|
@@ -127,31 +135,54 @@ class PreviewCommentsView(context: Context, private val appContext: AppContext)
|
|
|
127
135
|
|
|
128
136
|
// VFActionsInterface
|
|
129
137
|
override fun onNewAction(actionType: VFActionType, action: VFActionData) {
|
|
138
|
+
val actionPayload = mutableMapOf<String, Any>("type" to actionType.toString())
|
|
130
139
|
when (actionType) {
|
|
131
140
|
VFActionType.writeNewCommentPressed -> {
|
|
132
|
-
val
|
|
133
|
-
|
|
134
|
-
|
|
141
|
+
val payload = mutableMapOf<String, Any>()
|
|
142
|
+
action.newCommentAction?.content?.toString()?.let { payload["content"] = it }
|
|
143
|
+
action.newCommentAction?.type?.toString()?.let { payload["actionType"] = it }
|
|
144
|
+
actionPayload.putAll(payload)
|
|
145
|
+
onNewComment(payload)
|
|
135
146
|
}
|
|
136
147
|
VFActionType.openProfilePressed -> {
|
|
137
|
-
val
|
|
138
|
-
|
|
139
|
-
|
|
148
|
+
val payload = mutableMapOf<String, Any>()
|
|
149
|
+
action.openProfileAction?.presentationType?.toString()?.let { payload["presentationType"] = it }
|
|
150
|
+
action.openProfileAction?.userUUID?.toString()?.let { payload["userUUID"] = it }
|
|
151
|
+
actionPayload.putAll(payload)
|
|
152
|
+
onOpenProfile(payload)
|
|
140
153
|
}
|
|
141
154
|
VFActionType.trendingArticlePressed -> {
|
|
142
|
-
val url = action.trendingPressedAction?.articleMetadata?.url?.toString()
|
|
155
|
+
val url = action.trendingPressedAction?.articleMetadata?.url?.toString()
|
|
143
156
|
val containerId = action.trendingPressedAction?.containerId ?: ""
|
|
144
|
-
|
|
157
|
+
url?.let { actionPayload["articleUrl"] = it }
|
|
158
|
+
actionPayload["containerId"] = containerId
|
|
159
|
+
if (url != null) {
|
|
160
|
+
onArticlePressed(mapOf("articleUrl" to url, "containerId" to containerId))
|
|
161
|
+
}
|
|
145
162
|
}
|
|
146
163
|
VFActionType.authPressed -> {
|
|
164
|
+
actionPayload["requireLogin"] = true
|
|
147
165
|
onAuthNeeded(mapOf("requireLogin" to true))
|
|
148
166
|
}
|
|
149
167
|
else -> {}
|
|
150
168
|
}
|
|
169
|
+
onAction(actionPayload)
|
|
151
170
|
}
|
|
152
171
|
|
|
153
172
|
// VFLayoutInterface
|
|
154
173
|
override fun containerHeightUpdated(fragment: VFFragment, containerId: String, height: Int) {
|
|
155
174
|
onHeightChanged(mapOf("newHeight" to height, "containerId" to containerId))
|
|
156
175
|
}
|
|
176
|
+
|
|
177
|
+
private fun resolveTheme(): VFTheme {
|
|
178
|
+
return when (theme?.lowercase()) {
|
|
179
|
+
"dark" -> VFTheme.dark
|
|
180
|
+
"light" -> VFTheme.light
|
|
181
|
+
else -> if (darkMode) VFTheme.dark else VFTheme.light
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
private fun applyThemeIfReady() {
|
|
186
|
+
fragment?.setTheme(resolveTheme())
|
|
187
|
+
}
|
|
157
188
|
}
|
|
@@ -12,10 +12,11 @@ class ProfileModule : Module() {
|
|
|
12
12
|
Prop("userUUID") { view: ProfileView, v: String -> view.userUUID = v }
|
|
13
13
|
Prop("presentationType") { view: ProfileView, v: String? -> view.presentationType = v }
|
|
14
14
|
Prop("darkMode") { view: ProfileView, v: Boolean? -> view.darkMode = v ?: false }
|
|
15
|
+
Prop("theme") { view: ProfileView, v: String? -> view.theme = v }
|
|
16
|
+
Prop("colors") { view: ProfileView, v: Map<String, Any?>? -> view.colors = v }
|
|
15
17
|
|
|
16
18
|
// Events
|
|
17
|
-
Events("onAuthNeeded", "onCloseProfile")
|
|
19
|
+
Events("onAuthNeeded", "onCloseProfile", "onAction")
|
|
18
20
|
}
|
|
19
21
|
}
|
|
20
22
|
}
|
|
21
|
-
|
|
@@ -17,24 +17,33 @@ import com.viafourasdk.src.interfaces.VFCustomUIInterface
|
|
|
17
17
|
import com.viafourasdk.src.interfaces.VFLayoutInterface
|
|
18
18
|
import com.viafourasdk.src.model.local.VFActionData
|
|
19
19
|
import com.viafourasdk.src.model.local.VFActionType
|
|
20
|
-
import com.viafourasdk.src.model.local.VFDefaultColors
|
|
21
|
-
import com.viafourasdk.src.model.local.VFColors
|
|
22
20
|
import com.viafourasdk.src.model.local.VFSettings
|
|
23
21
|
import com.viafourasdk.src.model.local.VFProfilePresentationType
|
|
24
22
|
import com.viafourasdk.src.model.local.VFTheme
|
|
25
23
|
import java.util.UUID
|
|
26
24
|
|
|
27
|
-
class ProfileView(context: Context,
|
|
25
|
+
class ProfileView(context: Context, appContext: AppContext) :
|
|
28
26
|
ExpoView(context, appContext), VFCustomUIInterface, VFActionsInterface, VFLayoutInterface {
|
|
29
27
|
|
|
30
28
|
// Props
|
|
31
29
|
var userUUID: String? = null
|
|
32
30
|
var presentationType: String? = null // "profile" | "feed"
|
|
33
31
|
var darkMode: Boolean = false
|
|
32
|
+
set(value) {
|
|
33
|
+
field = value
|
|
34
|
+
applyThemeIfReady()
|
|
35
|
+
}
|
|
36
|
+
var theme: String? = null
|
|
37
|
+
set(value) {
|
|
38
|
+
field = value
|
|
39
|
+
applyThemeIfReady()
|
|
40
|
+
}
|
|
41
|
+
var colors: Map<String, Any?>? = null
|
|
34
42
|
|
|
35
43
|
// Events
|
|
36
44
|
private val onAuthNeeded by EventDispatcher()
|
|
37
45
|
private val onCloseProfile by EventDispatcher()
|
|
46
|
+
private val onAction by EventDispatcher()
|
|
38
47
|
|
|
39
48
|
// Internals
|
|
40
49
|
private val container = FrameLayout(context).also {
|
|
@@ -62,23 +71,21 @@ class ProfileView(context: Context, private val appContext: AppContext) :
|
|
|
62
71
|
val activity = currentActivity() ?: return
|
|
63
72
|
|
|
64
73
|
try {
|
|
65
|
-
val
|
|
66
|
-
|
|
67
|
-
|
|
74
|
+
val resolvedTheme = resolveTheme()
|
|
75
|
+
val settings = VFSettings(
|
|
76
|
+
resolveVFColors(colors, resolvedTheme)
|
|
68
77
|
)
|
|
69
|
-
val settings = VFSettings(colors)
|
|
70
78
|
|
|
71
79
|
val pres = when (presentationType) {
|
|
72
80
|
"feed" -> VFProfilePresentationType.feed
|
|
73
|
-
|
|
74
|
-
else -> null
|
|
81
|
+
else -> VFProfilePresentationType.profile
|
|
75
82
|
}
|
|
76
83
|
|
|
77
84
|
val uuid = UUID.fromString(requireNotNull(userUUID))
|
|
78
85
|
val frag = VFProfileFragmentBuilder(uuid, pres, settings).build()
|
|
79
86
|
frag.setActionCallback(this)
|
|
80
87
|
frag.setCustomUICallback(this)
|
|
81
|
-
frag.setTheme(
|
|
88
|
+
frag.setTheme(resolvedTheme)
|
|
82
89
|
|
|
83
90
|
activity.supportFragmentManager
|
|
84
91
|
.beginTransaction()
|
|
@@ -106,15 +113,18 @@ class ProfileView(context: Context, private val appContext: AppContext) :
|
|
|
106
113
|
|
|
107
114
|
// VFActionsInterface
|
|
108
115
|
override fun onNewAction(actionType: VFActionType, action: VFActionData) {
|
|
116
|
+
val actionPayload = mutableMapOf<String, Any>("type" to actionType.toString())
|
|
109
117
|
when (actionType) {
|
|
110
118
|
VFActionType.closeProfilePressed -> {
|
|
111
119
|
onCloseProfile(emptyMap<String, Any>())
|
|
112
120
|
}
|
|
113
121
|
VFActionType.authPressed -> {
|
|
122
|
+
actionPayload["requireLogin"] = true
|
|
114
123
|
onAuthNeeded(mapOf("requireLogin" to true))
|
|
115
124
|
}
|
|
116
125
|
else -> {}
|
|
117
126
|
}
|
|
127
|
+
onAction(actionPayload)
|
|
118
128
|
}
|
|
119
129
|
|
|
120
130
|
// VFCustomUIInterface
|
|
@@ -130,5 +140,16 @@ class ProfileView(context: Context, private val appContext: AppContext) :
|
|
|
130
140
|
containerId: String,
|
|
131
141
|
height: Int
|
|
132
142
|
) { /* no-op for profile */ }
|
|
133
|
-
}
|
|
134
143
|
|
|
144
|
+
private fun resolveTheme(): VFTheme {
|
|
145
|
+
return when (theme?.lowercase()) {
|
|
146
|
+
"dark" -> VFTheme.dark
|
|
147
|
+
"light" -> VFTheme.light
|
|
148
|
+
else -> if (darkMode) VFTheme.dark else VFTheme.light
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
private fun applyThemeIfReady() {
|
|
153
|
+
fragment?.setTheme(resolveTheme())
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -36,7 +36,7 @@ class ViafouraModule : Module() {
|
|
|
36
36
|
promise.resolve(null)
|
|
37
37
|
}
|
|
38
38
|
override fun onError(err: NetworkError) {
|
|
39
|
-
promise.reject("E_VF_LOGIN", err.message ?: "Login failed")
|
|
39
|
+
promise.reject("E_VF_LOGIN", err.message ?: "Login failed", null)
|
|
40
40
|
}
|
|
41
41
|
})
|
|
42
42
|
}
|
|
@@ -47,7 +47,7 @@ class ViafouraModule : Module() {
|
|
|
47
47
|
promise.resolve(null)
|
|
48
48
|
}
|
|
49
49
|
override fun onError(err: NetworkError) {
|
|
50
|
-
promise.reject("E_VF_SIGNUP", err.message ?: "Signup failed")
|
|
50
|
+
promise.reject("E_VF_SIGNUP", err.message ?: "Signup failed", null)
|
|
51
51
|
}
|
|
52
52
|
})
|
|
53
53
|
}
|
|
@@ -59,7 +59,7 @@ class ViafouraModule : Module() {
|
|
|
59
59
|
promise.resolve(null)
|
|
60
60
|
}
|
|
61
61
|
override fun onError(err: NetworkError) {
|
|
62
|
-
promise.reject("E_VF_SOCIAL", err.message ?: "Social login failed")
|
|
62
|
+
promise.reject("E_VF_SOCIAL", err.message ?: "Social login failed", null)
|
|
63
63
|
}
|
|
64
64
|
})
|
|
65
65
|
}
|
|
@@ -70,7 +70,7 @@ class ViafouraModule : Module() {
|
|
|
70
70
|
promise.resolve(null)
|
|
71
71
|
}
|
|
72
72
|
override fun onError(err: NetworkError) {
|
|
73
|
-
promise.reject("E_VF_OPENID", err.message ?: "OpenID login failed")
|
|
73
|
+
promise.reject("E_VF_OPENID", err.message ?: "OpenID login failed", null)
|
|
74
74
|
}
|
|
75
75
|
})
|
|
76
76
|
}
|
|
@@ -81,7 +81,7 @@ class ViafouraModule : Module() {
|
|
|
81
81
|
promise.resolve(null)
|
|
82
82
|
}
|
|
83
83
|
override fun onError(err: NetworkError) {
|
|
84
|
-
promise.reject("E_VF_COOKIE", err.message ?: "Cookie login failed")
|
|
84
|
+
promise.reject("E_VF_COOKIE", err.message ?: "Cookie login failed", null)
|
|
85
85
|
}
|
|
86
86
|
})
|
|
87
87
|
}
|
|
@@ -92,7 +92,7 @@ class ViafouraModule : Module() {
|
|
|
92
92
|
promise.resolve(null)
|
|
93
93
|
}
|
|
94
94
|
override fun onError(err: NetworkError) {
|
|
95
|
-
promise.reject("E_VF_RESET", err.message ?: "Password reset failed")
|
|
95
|
+
promise.reject("E_VF_RESET", err.message ?: "Password reset failed", null)
|
|
96
96
|
}
|
|
97
97
|
})
|
|
98
98
|
}
|
|
@@ -102,11 +102,11 @@ class ViafouraModule : Module() {
|
|
|
102
102
|
val context = appContext.reactContext?.applicationContext
|
|
103
103
|
?: appContext.currentActivity?.applicationContext
|
|
104
104
|
if (context == null) {
|
|
105
|
-
promise.reject("E_VF_INIT", "No application context available")
|
|
105
|
+
promise.reject("E_VF_INIT", "No application context available", null)
|
|
106
106
|
return@AsyncFunction
|
|
107
107
|
}
|
|
108
108
|
if (siteUUID.isBlank() || siteDomain.isBlank()) {
|
|
109
|
-
promise.reject("E_VF_INIT", "Invalid Viafoura initialization parameters")
|
|
109
|
+
promise.reject("E_VF_INIT", "Invalid Viafoura initialization parameters", null)
|
|
110
110
|
return@AsyncFunction
|
|
111
111
|
}
|
|
112
112
|
try {
|
|
@@ -114,7 +114,7 @@ class ViafouraModule : Module() {
|
|
|
114
114
|
ViafouraSDK.initialize(context, siteUUID, siteDomain)
|
|
115
115
|
promise.resolve(null)
|
|
116
116
|
} catch (e: Exception) {
|
|
117
|
-
promise.reject("E_VF_INIT", e.message ?: "Viafoura initialization failed")
|
|
117
|
+
promise.reject("E_VF_INIT", e.message ?: "Viafoura initialization failed", e)
|
|
118
118
|
}
|
|
119
119
|
}
|
|
120
120
|
|
|
@@ -5,7 +5,49 @@ export type ViafouraModuleEvents = {
|
|
|
5
5
|
export type ChangeEventPayload = {
|
|
6
6
|
value: string;
|
|
7
7
|
};
|
|
8
|
-
export type PreviewCommentsEvents = 'onHeightChanged' | 'onAuthNeeded' | 'onOpenProfile' | 'onNewComment' | 'onArticlePressed';
|
|
8
|
+
export type PreviewCommentsEvents = 'onHeightChanged' | 'onAuthNeeded' | 'onOpenProfile' | 'onNewComment' | 'onArticlePressed' | 'onAction';
|
|
9
|
+
export type ViafouraColors = {
|
|
10
|
+
colorPrimary?: string;
|
|
11
|
+
colorPrimaryLight?: string;
|
|
12
|
+
colorAvatars?: string[];
|
|
13
|
+
};
|
|
14
|
+
export type ActionCallbackType = 'writeNewCommentPressed' | 'trendingArticlePressed' | 'openProfilePressed' | 'seeMoreCommentsPressed' | 'notificationPressed' | 'commentPosted' | 'replyPosted' | 'authPressed' | 'closeNewCommentPressed' | 'closeProfilePressed';
|
|
15
|
+
export type ActionCallbackPayload = {
|
|
16
|
+
type: 'writeNewCommentPressed';
|
|
17
|
+
actionType?: 'create' | 'edit' | 'reply';
|
|
18
|
+
content?: string;
|
|
19
|
+
} | {
|
|
20
|
+
type: 'trendingArticlePressed';
|
|
21
|
+
containerId?: string;
|
|
22
|
+
articleUrl?: string;
|
|
23
|
+
} | {
|
|
24
|
+
type: 'openProfilePressed';
|
|
25
|
+
userUUID?: string;
|
|
26
|
+
presentationType?: 'profile' | 'feed';
|
|
27
|
+
} | {
|
|
28
|
+
type: 'seeMoreCommentsPressed';
|
|
29
|
+
} | {
|
|
30
|
+
type: 'notificationPressed';
|
|
31
|
+
presentationType?: 'profile' | 'content';
|
|
32
|
+
userUUID?: string;
|
|
33
|
+
containerUUID?: string;
|
|
34
|
+
contentUUID?: string;
|
|
35
|
+
containerId?: string;
|
|
36
|
+
articleUrl?: string;
|
|
37
|
+
} | {
|
|
38
|
+
type: 'commentPosted';
|
|
39
|
+
content?: string;
|
|
40
|
+
} | {
|
|
41
|
+
type: 'replyPosted';
|
|
42
|
+
content?: string;
|
|
43
|
+
} | {
|
|
44
|
+
type: 'authPressed';
|
|
45
|
+
requireLogin?: boolean;
|
|
46
|
+
} | {
|
|
47
|
+
type: 'closeNewCommentPressed';
|
|
48
|
+
} | {
|
|
49
|
+
type: 'closeProfilePressed';
|
|
50
|
+
};
|
|
9
51
|
export type PreviewCommentsHeightChangedPayload = {
|
|
10
52
|
newHeight: number;
|
|
11
53
|
containerId: string;
|
|
@@ -34,6 +76,8 @@ export type PreviewCommentsViewProps = {
|
|
|
34
76
|
articleThumbnailUrl: string;
|
|
35
77
|
syndicationKey?: string;
|
|
36
78
|
darkMode?: boolean;
|
|
79
|
+
theme?: 'light' | 'dark';
|
|
80
|
+
colors?: ViafouraColors;
|
|
37
81
|
onHeightChanged?: (event: {
|
|
38
82
|
nativeEvent: PreviewCommentsHeightChangedPayload;
|
|
39
83
|
}) => void;
|
|
@@ -49,6 +93,9 @@ export type PreviewCommentsViewProps = {
|
|
|
49
93
|
onArticlePressed?: (event: {
|
|
50
94
|
nativeEvent: PreviewCommentsArticlePressedPayload;
|
|
51
95
|
}) => void;
|
|
96
|
+
onAction?: (event: {
|
|
97
|
+
nativeEvent: ActionCallbackPayload;
|
|
98
|
+
}) => void;
|
|
52
99
|
style?: StyleProp<ViewStyle>;
|
|
53
100
|
};
|
|
54
101
|
export type ProfileAuthNeededPayload = {
|
|
@@ -58,12 +105,17 @@ export type ProfileViewProps = {
|
|
|
58
105
|
userUUID: string;
|
|
59
106
|
presentationType?: 'profile' | 'feed';
|
|
60
107
|
darkMode?: boolean;
|
|
108
|
+
theme?: 'light' | 'dark';
|
|
109
|
+
colors?: ViafouraColors;
|
|
61
110
|
onAuthNeeded?: (event: {
|
|
62
111
|
nativeEvent: ProfileAuthNeededPayload;
|
|
63
112
|
}) => void;
|
|
64
113
|
onCloseProfile?: (event: {
|
|
65
114
|
nativeEvent: Record<string, never>;
|
|
66
115
|
}) => void;
|
|
116
|
+
onAction?: (event: {
|
|
117
|
+
nativeEvent: ActionCallbackPayload;
|
|
118
|
+
}) => void;
|
|
67
119
|
style?: StyleProp<ViewStyle>;
|
|
68
120
|
};
|
|
69
121
|
export type NewCommentHeightChangedPayload = PreviewCommentsHeightChangedPayload;
|
|
@@ -78,6 +130,8 @@ export type NewCommentViewProps = {
|
|
|
78
130
|
articleUrl: string;
|
|
79
131
|
articleThumbnailUrl: string;
|
|
80
132
|
darkMode?: boolean;
|
|
133
|
+
theme?: 'light' | 'dark';
|
|
134
|
+
colors?: ViafouraColors;
|
|
81
135
|
onHeightChanged?: (event: {
|
|
82
136
|
nativeEvent: NewCommentHeightChangedPayload;
|
|
83
137
|
}) => void;
|
|
@@ -87,6 +141,9 @@ export type NewCommentViewProps = {
|
|
|
87
141
|
onCloseNewComment?: (event: {
|
|
88
142
|
nativeEvent: Record<string, never>;
|
|
89
143
|
}) => void;
|
|
144
|
+
onAction?: (event: {
|
|
145
|
+
nativeEvent: ActionCallbackPayload;
|
|
146
|
+
}) => void;
|
|
90
147
|
style?: StyleProp<ViewStyle>;
|
|
91
148
|
};
|
|
92
149
|
//# sourceMappingURL=Viafoura.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Viafoura.types.d.ts","sourceRoot":"","sources":["../src/Viafoura.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEzD,MAAM,MAAM,oBAAoB,GAAG;IACjC,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;CAChD,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AAGF,MAAM,MAAM,qBAAqB,GAC7B,iBAAiB,GACjB,cAAc,GACd,eAAe,GACf,cAAc,GACd,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"Viafoura.types.d.ts","sourceRoot":"","sources":["../src/Viafoura.types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Viafoura.types.js","sourceRoot":"","sources":["../src/Viafoura.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StyleProp, ViewStyle } from 'react-native';\n\nexport type ViafouraModuleEvents = {\n onChange: (params: ChangeEventPayload) => void;\n};\n\nexport type ChangeEventPayload = {\n value: string;\n};\n\n\nexport type PreviewCommentsEvents =\n | 'onHeightChanged'\n | 'onAuthNeeded'\n | 'onOpenProfile'\n | 'onNewComment'\n | 'onArticlePressed';\n\nexport type PreviewCommentsHeightChangedPayload = {\n newHeight: number;\n containerId: string;\n};\n\nexport type PreviewCommentsAuthNeededPayload = {\n requireLogin?: boolean;\n};\n\nexport type PreviewCommentsOpenProfilePayload = {\n userUUID: string;\n presentationType?: string;\n};\n\nexport type PreviewCommentsNewCommentPayload = {\n content?: string;\n actionType?: string;\n};\n\nexport type PreviewCommentsArticlePressedPayload = {\n articleUrl: string;\n containerId: string;\n};\n\nexport type PreviewCommentsViewProps = {\n containerId: string;\n authorId?: string;\n articleUrl: string;\n articleTitle: string;\n articleSubtitle?: string;\n articleThumbnailUrl: string;\n syndicationKey?: string;\n darkMode?: boolean;\n onHeightChanged?: (event: { nativeEvent: PreviewCommentsHeightChangedPayload }) => void;\n onAuthNeeded?: (event: { nativeEvent: PreviewCommentsAuthNeededPayload }) => void;\n onOpenProfile?: (event: { nativeEvent: PreviewCommentsOpenProfilePayload }) => void;\n onNewComment?: (event: { nativeEvent: PreviewCommentsNewCommentPayload }) => void;\n onArticlePressed?: (event: { nativeEvent: PreviewCommentsArticlePressedPayload }) => void;\n style?: StyleProp<ViewStyle>;\n};\n\nexport type ProfileAuthNeededPayload = {\n requireLogin?: boolean;\n};\n\nexport type ProfileViewProps = {\n userUUID: string;\n presentationType?: 'profile' | 'feed';\n darkMode?: boolean;\n onAuthNeeded?: (event: { nativeEvent: ProfileAuthNeededPayload }) => void;\n onCloseProfile?: (event: { nativeEvent: Record<string, never> }) => void;\n style?: StyleProp<ViewStyle>;\n};\n\nexport type NewCommentHeightChangedPayload = PreviewCommentsHeightChangedPayload;\nexport type NewCommentAuthNeededPayload = PreviewCommentsAuthNeededPayload;\n\nexport type NewCommentViewProps = {\n newCommentActionType: 'create' | 'edit' | 'reply';\n content?: string; // UUID as string\n containerId: string;\n syndicationKey?: string;\n articleTitle: string;\n articleSubtitle?: string;\n articleUrl: string;\n articleThumbnailUrl: string;\n darkMode?: boolean;\n onHeightChanged?: (event: { nativeEvent: NewCommentHeightChangedPayload }) => void;\n onAuthNeeded?: (event: { nativeEvent: NewCommentAuthNeededPayload }) => void;\n onCloseNewComment?: (event: { nativeEvent: Record<string, never> }) => void;\n style?: StyleProp<ViewStyle>;\n};\n"]}
|
|
1
|
+
{"version":3,"file":"Viafoura.types.js","sourceRoot":"","sources":["../src/Viafoura.types.ts"],"names":[],"mappings":"","sourcesContent":["import type { StyleProp, ViewStyle } from 'react-native';\n\nexport type ViafouraModuleEvents = {\n onChange: (params: ChangeEventPayload) => void;\n};\n\nexport type ChangeEventPayload = {\n value: string;\n};\n\n\nexport type PreviewCommentsEvents =\n | 'onHeightChanged'\n | 'onAuthNeeded'\n | 'onOpenProfile'\n | 'onNewComment'\n | 'onArticlePressed'\n | 'onAction';\n\nexport type ViafouraColors = {\n colorPrimary?: string;\n colorPrimaryLight?: string;\n colorAvatars?: string[];\n};\n\nexport type ActionCallbackType =\n | 'writeNewCommentPressed'\n | 'trendingArticlePressed'\n | 'openProfilePressed'\n | 'seeMoreCommentsPressed'\n | 'notificationPressed'\n | 'commentPosted'\n | 'replyPosted'\n | 'authPressed'\n | 'closeNewCommentPressed'\n | 'closeProfilePressed';\n\nexport type ActionCallbackPayload =\n | {\n type: 'writeNewCommentPressed';\n actionType?: 'create' | 'edit' | 'reply';\n content?: string;\n }\n | {\n type: 'trendingArticlePressed';\n containerId?: string;\n articleUrl?: string;\n }\n | {\n type: 'openProfilePressed';\n userUUID?: string;\n presentationType?: 'profile' | 'feed';\n }\n | {\n type: 'seeMoreCommentsPressed';\n }\n | {\n type: 'notificationPressed';\n presentationType?: 'profile' | 'content';\n userUUID?: string;\n containerUUID?: string;\n contentUUID?: string;\n containerId?: string;\n articleUrl?: string;\n }\n | {\n type: 'commentPosted';\n content?: string;\n }\n | {\n type: 'replyPosted';\n content?: string;\n }\n | {\n type: 'authPressed';\n requireLogin?: boolean;\n }\n | {\n type: 'closeNewCommentPressed';\n }\n | {\n type: 'closeProfilePressed';\n };\n\nexport type PreviewCommentsHeightChangedPayload = {\n newHeight: number;\n containerId: string;\n};\n\nexport type PreviewCommentsAuthNeededPayload = {\n requireLogin?: boolean;\n};\n\nexport type PreviewCommentsOpenProfilePayload = {\n userUUID: string;\n presentationType?: string;\n};\n\nexport type PreviewCommentsNewCommentPayload = {\n content?: string;\n actionType?: string;\n};\n\nexport type PreviewCommentsArticlePressedPayload = {\n articleUrl: string;\n containerId: string;\n};\n\nexport type PreviewCommentsViewProps = {\n containerId: string;\n authorId?: string;\n articleUrl: string;\n articleTitle: string;\n articleSubtitle?: string;\n articleThumbnailUrl: string;\n syndicationKey?: string;\n darkMode?: boolean;\n theme?: 'light' | 'dark';\n colors?: ViafouraColors;\n onHeightChanged?: (event: { nativeEvent: PreviewCommentsHeightChangedPayload }) => void;\n onAuthNeeded?: (event: { nativeEvent: PreviewCommentsAuthNeededPayload }) => void;\n onOpenProfile?: (event: { nativeEvent: PreviewCommentsOpenProfilePayload }) => void;\n onNewComment?: (event: { nativeEvent: PreviewCommentsNewCommentPayload }) => void;\n onArticlePressed?: (event: { nativeEvent: PreviewCommentsArticlePressedPayload }) => void;\n onAction?: (event: { nativeEvent: ActionCallbackPayload }) => void;\n style?: StyleProp<ViewStyle>;\n};\n\nexport type ProfileAuthNeededPayload = {\n requireLogin?: boolean;\n};\n\nexport type ProfileViewProps = {\n userUUID: string;\n presentationType?: 'profile' | 'feed';\n darkMode?: boolean;\n theme?: 'light' | 'dark';\n colors?: ViafouraColors;\n onAuthNeeded?: (event: { nativeEvent: ProfileAuthNeededPayload }) => void;\n onCloseProfile?: (event: { nativeEvent: Record<string, never> }) => void;\n onAction?: (event: { nativeEvent: ActionCallbackPayload }) => void;\n style?: StyleProp<ViewStyle>;\n};\n\nexport type NewCommentHeightChangedPayload = PreviewCommentsHeightChangedPayload;\nexport type NewCommentAuthNeededPayload = PreviewCommentsAuthNeededPayload;\n\nexport type NewCommentViewProps = {\n newCommentActionType: 'create' | 'edit' | 'reply';\n content?: string; // UUID as string\n containerId: string;\n syndicationKey?: string;\n articleTitle: string;\n articleSubtitle?: string;\n articleUrl: string;\n articleThumbnailUrl: string;\n darkMode?: boolean;\n theme?: 'light' | 'dark';\n colors?: ViafouraColors;\n onHeightChanged?: (event: { nativeEvent: NewCommentHeightChangedPayload }) => void;\n onAuthNeeded?: (event: { nativeEvent: NewCommentAuthNeededPayload }) => void;\n onCloseNewComment?: (event: { nativeEvent: Record<string, never> }) => void;\n onAction?: (event: { nativeEvent: ActionCallbackPayload }) => void;\n style?: StyleProp<ViewStyle>;\n};\n"]}
|
|
@@ -13,7 +13,17 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
13
13
|
var syndicationKey: String = ""
|
|
14
14
|
var articleSubtitle: String = ""
|
|
15
15
|
var articleThumbnailUrl: String = ""
|
|
16
|
-
var darkMode: Bool = false
|
|
16
|
+
var darkMode: Bool = false {
|
|
17
|
+
didSet {
|
|
18
|
+
applyThemeIfReady()
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
var theme: String? = nil {
|
|
22
|
+
didSet {
|
|
23
|
+
applyThemeIfReady()
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
var colors: [String: Any] = [:]
|
|
17
27
|
|
|
18
28
|
// Events
|
|
19
29
|
let onHeightChanged = EventDispatcher()
|
|
@@ -21,6 +31,7 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
21
31
|
let onOpenProfile = EventDispatcher()
|
|
22
32
|
let onNewComment = EventDispatcher()
|
|
23
33
|
let onArticlePressed = EventDispatcher()
|
|
34
|
+
let onAction = EventDispatcher()
|
|
24
35
|
|
|
25
36
|
// Internals
|
|
26
37
|
let fontBold = UIFont.boldSystemFont(ofSize: 17)
|
|
@@ -39,10 +50,13 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
private func initializeSettings() {
|
|
42
|
-
let
|
|
43
|
-
|
|
44
|
-
|
|
53
|
+
let resolvedTheme = resolveTheme()
|
|
54
|
+
var colors = VFColors(
|
|
55
|
+
colorPrimary: resolveColor(key: "colorPrimary", fallbackKey: "primary", fallback: UIColor(red: 0.00, green: 0.45, blue: 0.91, alpha: 1.00)),
|
|
56
|
+
colorPrimaryLight: resolveColor(key: "colorPrimaryLight", fallbackKey: "primaryLight", fallback: UIColor(red: 0.90, green: 0.95, blue: 1.00, alpha: 1.00)),
|
|
57
|
+
colorAvatars: resolveAvatarColors() ?? Constants.AvatarColors.colors
|
|
45
58
|
)
|
|
59
|
+
colors.setTheme(theme: resolvedTheme)
|
|
46
60
|
let fonts = VFFonts(fontBold: fontBold)
|
|
47
61
|
settings = VFSettings(colors: colors, fonts: fonts)
|
|
48
62
|
|
|
@@ -68,13 +82,19 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
68
82
|
guard let self else { return }
|
|
69
83
|
switch type {
|
|
70
84
|
case .writeNewCommentPressed(let actionType):
|
|
85
|
+
self.emitAction(type: "writeNewCommentPressed", payload: ["actionType": self.stringForActionType(actionType)])
|
|
71
86
|
self.presentNewCommentViewController(actionType: actionType)
|
|
72
87
|
case .trendingArticlePressed(let metadata, let containerId):
|
|
88
|
+
self.emitAction(type: "trendingArticlePressed", payload: ["containerId": containerId, "articleUrl": metadata.url.absoluteString])
|
|
73
89
|
self.onArticlePressed(["containerId": containerId, "articleUrl": metadata.url.absoluteString])
|
|
74
90
|
case .openProfilePressed(let userUUID, let presentationType):
|
|
75
91
|
// Emit event and present profile for parity with Android
|
|
76
|
-
|
|
92
|
+
let presentation = self.stringForPresentationType(presentationType)
|
|
93
|
+
self.emitAction(type: "openProfilePressed", payload: ["userUUID": userUUID.uuidString, "presentationType": presentation])
|
|
94
|
+
self.onOpenProfile(["userUUID": userUUID.uuidString, "presentationType": presentation])
|
|
77
95
|
self.presentProfileViewController(userUUID: userUUID, presentationType: presentationType)
|
|
96
|
+
case .seeMoreCommentsPressed:
|
|
97
|
+
self.emitAction(type: "seeMoreCommentsPressed")
|
|
78
98
|
default:
|
|
79
99
|
break
|
|
80
100
|
}
|
|
@@ -107,7 +127,22 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
107
127
|
switch type {
|
|
108
128
|
case .trendingArticlePressed(let metadata, let containerId):
|
|
109
129
|
profileVC.dismiss(animated: true)
|
|
130
|
+
self.emitAction(type: "trendingArticlePressed", payload: ["containerId": containerId, "articleUrl": metadata.url.absoluteString])
|
|
110
131
|
self.onArticlePressed(["containerId": containerId, "articleUrl": metadata.url.absoluteString])
|
|
132
|
+
case .notificationPressed(let presentation):
|
|
133
|
+
var payload: [String: Any] = [:]
|
|
134
|
+
switch presentation {
|
|
135
|
+
case .profile(let userUUID):
|
|
136
|
+
payload["presentationType"] = "profile"
|
|
137
|
+
payload["userUUID"] = userUUID.uuidString
|
|
138
|
+
case .content(let containerUUID, let contentUUID, let containerId, let articleMetadata):
|
|
139
|
+
payload["presentationType"] = "content"
|
|
140
|
+
payload["containerUUID"] = containerUUID.uuidString
|
|
141
|
+
payload["contentUUID"] = contentUUID.uuidString
|
|
142
|
+
payload["containerId"] = containerId
|
|
143
|
+
payload["articleUrl"] = articleMetadata.url.absoluteString
|
|
144
|
+
}
|
|
145
|
+
self.emitAction(type: "notificationPressed", payload: payload)
|
|
111
146
|
default: break
|
|
112
147
|
}
|
|
113
148
|
}
|
|
@@ -129,8 +164,11 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
129
164
|
let callbacks: VFActionsCallbacks = { [weak self] type in
|
|
130
165
|
guard let self else { return }
|
|
131
166
|
switch type {
|
|
132
|
-
case .commentPosted:
|
|
133
|
-
self.
|
|
167
|
+
case .commentPosted(let contentUUID):
|
|
168
|
+
self.emitAction(type: "commentPosted", payload: ["content": contentUUID.uuidString])
|
|
169
|
+
self.onNewComment(["content": contentUUID.uuidString])
|
|
170
|
+
case .replyPosted(let contentUUID):
|
|
171
|
+
self.emitAction(type: "replyPosted", payload: ["content": contentUUID.uuidString])
|
|
134
172
|
default: break
|
|
135
173
|
}
|
|
136
174
|
}
|
|
@@ -139,6 +177,74 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
139
177
|
parentVC.present(newCommentVC, animated: true)
|
|
140
178
|
}
|
|
141
179
|
|
|
180
|
+
private func emitAction(type: String, payload: [String: Any] = [:]) {
|
|
181
|
+
var event = payload
|
|
182
|
+
event["type"] = type
|
|
183
|
+
onAction(event)
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
private func resolveTheme() -> VFTheme {
|
|
187
|
+
switch theme?.lowercased() {
|
|
188
|
+
case "dark":
|
|
189
|
+
return .dark
|
|
190
|
+
case "light":
|
|
191
|
+
return .light
|
|
192
|
+
default:
|
|
193
|
+
return darkMode ? .dark : .light
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
private func applyThemeIfReady() {
|
|
198
|
+
previewCommentsViewController?.setTheme(theme: resolveTheme())
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
private func resolveColor(key: String, fallbackKey: String, fallback: UIColor) -> UIColor {
|
|
202
|
+
let hex = (colors[key] as? String) ?? (colors[fallbackKey] as? String)
|
|
203
|
+
if let hex, let parsed = UIColor.vfColor(fromHex: hex) {
|
|
204
|
+
return parsed
|
|
205
|
+
}
|
|
206
|
+
return fallback
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
private func resolveAvatarColors() -> [UIColor]? {
|
|
210
|
+
let raw = colors["colorAvatars"] ?? colors["avatars"]
|
|
211
|
+
let list: [String]? = (raw as? [String]) ?? (raw as? [Any])?.compactMap { $0 as? String }
|
|
212
|
+
guard let list, list.count == Constants.AvatarColors.colors.count else {
|
|
213
|
+
return nil
|
|
214
|
+
}
|
|
215
|
+
var parsed: [UIColor] = []
|
|
216
|
+
parsed.reserveCapacity(list.count)
|
|
217
|
+
for hex in list {
|
|
218
|
+
guard let color = UIColor.vfColor(fromHex: hex) else { return nil }
|
|
219
|
+
parsed.append(color)
|
|
220
|
+
}
|
|
221
|
+
return parsed
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
private func stringForActionType(_ actionType: VFNewCommentActionType) -> String {
|
|
225
|
+
switch actionType {
|
|
226
|
+
case .create:
|
|
227
|
+
return "create"
|
|
228
|
+
case .edit:
|
|
229
|
+
return "edit"
|
|
230
|
+
case .reply:
|
|
231
|
+
return "reply"
|
|
232
|
+
@unknown default:
|
|
233
|
+
return "create"
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
private func stringForPresentationType(_ presentationType: VFProfilePresentationType) -> String {
|
|
238
|
+
switch presentationType {
|
|
239
|
+
case .profile:
|
|
240
|
+
return "profile"
|
|
241
|
+
case .feed:
|
|
242
|
+
return "feed"
|
|
243
|
+
@unknown default:
|
|
244
|
+
return "profile"
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
|
|
142
248
|
// MARK: VFLayoutDelegate
|
|
143
249
|
func containerHeightUpdated(viewController: VFUIViewController, height: CGFloat) {
|
|
144
250
|
onHeightChanged(["newHeight": height, "containerId": containerId])
|
|
@@ -146,6 +252,7 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
146
252
|
|
|
147
253
|
// MARK: VFLoginDelegate
|
|
148
254
|
func startLogin() {
|
|
255
|
+
emitAction(type: "authPressed", payload: ["requireLogin": true])
|
|
149
256
|
onAuthNeeded(["requireLogin": true])
|
|
150
257
|
}
|
|
151
258
|
|
|
@@ -154,6 +261,26 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
154
261
|
func generateAd(viewController: VFUIViewController, adPosition: Int) -> VFAdView? { VFAdView() }
|
|
155
262
|
}
|
|
156
263
|
|
|
264
|
+
extension UIColor {
|
|
265
|
+
static func vfColor(fromHex hex: String) -> UIColor? {
|
|
266
|
+
var value = hex.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
267
|
+
if value.hasPrefix("#") {
|
|
268
|
+
value.removeFirst()
|
|
269
|
+
}
|
|
270
|
+
if value.count == 6 {
|
|
271
|
+
value = "FF" + value
|
|
272
|
+
}
|
|
273
|
+
guard value.count == 8, let hexNumber = UInt64(value, radix: 16) else {
|
|
274
|
+
return nil
|
|
275
|
+
}
|
|
276
|
+
let alpha = CGFloat((hexNumber & 0xFF000000) >> 24) / 255.0
|
|
277
|
+
let red = CGFloat((hexNumber & 0x00FF0000) >> 16) / 255.0
|
|
278
|
+
let green = CGFloat((hexNumber & 0x0000FF00) >> 8) / 255.0
|
|
279
|
+
let blue = CGFloat(hexNumber & 0x000000FF) / 255.0
|
|
280
|
+
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
157
284
|
extension UIView {
|
|
158
285
|
var parentViewController: UIViewController? {
|
|
159
286
|
var parentResponder: UIResponder? = self
|
|
@@ -187,9 +314,11 @@ public class PreviewCommentsModule: Module {
|
|
|
187
314
|
Prop("articleThumbnailUrl") { (view: RNPreviewComments, v: String) in view.articleThumbnailUrl = v }
|
|
188
315
|
Prop("syndicationKey") { (view: RNPreviewComments, v: String?) in view.syndicationKey = v ?? "" }
|
|
189
316
|
Prop("darkMode") { (view: RNPreviewComments, v: Bool?) in view.darkMode = v ?? false }
|
|
317
|
+
Prop("theme") { (view: RNPreviewComments, v: String?) in view.theme = v }
|
|
318
|
+
Prop("colors") { (view: RNPreviewComments, v: [String: Any]?) in view.colors = v ?? [:] }
|
|
190
319
|
|
|
191
320
|
// Events
|
|
192
|
-
Events("onHeightChanged", "onAuthNeeded", "onOpenProfile", "onNewComment", "onArticlePressed")
|
|
321
|
+
Events("onHeightChanged", "onAuthNeeded", "onOpenProfile", "onNewComment", "onArticlePressed", "onAction")
|
|
193
322
|
}
|
|
194
323
|
}
|
|
195
324
|
}
|