@viafoura/sdk-react-native 0.1.2 → 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/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 +30 -7
- package/android/src/main/java/expo/modules/viafourasdk/PreviewCommentsModule.kt +3 -2
- package/android/src/main/java/expo/modules/viafourasdk/PreviewCommentsView.kt +38 -9
- package/android/src/main/java/expo/modules/viafourasdk/ProfileModule.kt +3 -2
- package/android/src/main/java/expo/modules/viafourasdk/ProfileView.kt +30 -7
- 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
|
@@ -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,8 +20,6 @@ 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
|
|
@@ -40,11 +38,22 @@ class NewCommentView(context: Context, 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, 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, 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, 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,4 +160,16 @@ class NewCommentView(context: Context, 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
|
}
|
|
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
|
+
}
|
|
152
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,8 +20,6 @@ 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
|
|
@@ -38,6 +36,16 @@ class PreviewCommentsView(context: Context, 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, 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, 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, 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,33 +135,54 @@ class PreviewCommentsView(context: Context, 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
141
|
val payload = mutableMapOf<String, Any>()
|
|
133
142
|
action.newCommentAction?.content?.toString()?.let { payload["content"] = it }
|
|
134
143
|
action.newCommentAction?.type?.toString()?.let { payload["actionType"] = it }
|
|
144
|
+
actionPayload.putAll(payload)
|
|
135
145
|
onNewComment(payload)
|
|
136
146
|
}
|
|
137
147
|
VFActionType.openProfilePressed -> {
|
|
138
148
|
val payload = mutableMapOf<String, Any>()
|
|
139
149
|
action.openProfileAction?.presentationType?.toString()?.let { payload["presentationType"] = it }
|
|
140
150
|
action.openProfileAction?.userUUID?.toString()?.let { payload["userUUID"] = it }
|
|
151
|
+
actionPayload.putAll(payload)
|
|
141
152
|
onOpenProfile(payload)
|
|
142
153
|
}
|
|
143
154
|
VFActionType.trendingArticlePressed -> {
|
|
144
|
-
val url = action.trendingPressedAction?.articleMetadata?.url?.toString()
|
|
155
|
+
val url = action.trendingPressedAction?.articleMetadata?.url?.toString()
|
|
145
156
|
val containerId = action.trendingPressedAction?.containerId ?: ""
|
|
146
|
-
|
|
157
|
+
url?.let { actionPayload["articleUrl"] = it }
|
|
158
|
+
actionPayload["containerId"] = containerId
|
|
159
|
+
if (url != null) {
|
|
160
|
+
onArticlePressed(mapOf("articleUrl" to url, "containerId" to containerId))
|
|
161
|
+
}
|
|
147
162
|
}
|
|
148
163
|
VFActionType.authPressed -> {
|
|
164
|
+
actionPayload["requireLogin"] = true
|
|
149
165
|
onAuthNeeded(mapOf("requireLogin" to true))
|
|
150
166
|
}
|
|
151
167
|
else -> {}
|
|
152
168
|
}
|
|
169
|
+
onAction(actionPayload)
|
|
153
170
|
}
|
|
154
171
|
|
|
155
172
|
// VFLayoutInterface
|
|
156
173
|
override fun containerHeightUpdated(fragment: VFFragment, containerId: String, height: Int) {
|
|
157
174
|
onHeightChanged(mapOf("newHeight" to height, "containerId" to containerId))
|
|
158
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
|
+
}
|
|
159
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,8 +17,6 @@ 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
|
|
@@ -31,10 +29,21 @@ class ProfileView(context: Context, appContext: AppContext) :
|
|
|
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,11 +71,10 @@ class ProfileView(context: Context, 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
|
|
@@ -77,7 +85,7 @@ class ProfileView(context: Context, appContext: AppContext) :
|
|
|
77
85
|
val frag = VFProfileFragmentBuilder(uuid, pres, settings).build()
|
|
78
86
|
frag.setActionCallback(this)
|
|
79
87
|
frag.setCustomUICallback(this)
|
|
80
|
-
frag.setTheme(
|
|
88
|
+
frag.setTheme(resolvedTheme)
|
|
81
89
|
|
|
82
90
|
activity.supportFragmentManager
|
|
83
91
|
.beginTransaction()
|
|
@@ -105,15 +113,18 @@ class ProfileView(context: Context, appContext: AppContext) :
|
|
|
105
113
|
|
|
106
114
|
// VFActionsInterface
|
|
107
115
|
override fun onNewAction(actionType: VFActionType, action: VFActionData) {
|
|
116
|
+
val actionPayload = mutableMapOf<String, Any>("type" to actionType.toString())
|
|
108
117
|
when (actionType) {
|
|
109
118
|
VFActionType.closeProfilePressed -> {
|
|
110
119
|
onCloseProfile(emptyMap<String, Any>())
|
|
111
120
|
}
|
|
112
121
|
VFActionType.authPressed -> {
|
|
122
|
+
actionPayload["requireLogin"] = true
|
|
113
123
|
onAuthNeeded(mapOf("requireLogin" to true))
|
|
114
124
|
}
|
|
115
125
|
else -> {}
|
|
116
126
|
}
|
|
127
|
+
onAction(actionPayload)
|
|
117
128
|
}
|
|
118
129
|
|
|
119
130
|
// VFCustomUIInterface
|
|
@@ -129,4 +140,16 @@ class ProfileView(context: Context, appContext: AppContext) :
|
|
|
129
140
|
containerId: String,
|
|
130
141
|
height: Int
|
|
131
142
|
) { /* no-op for profile */ }
|
|
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
|
+
}
|
|
132
155
|
}
|
|
@@ -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
|
}
|