@viafoura/sdk-react-native 0.1.2 → 0.1.4
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 -10
- 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)
|
|
@@ -40,8 +51,9 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
40
51
|
|
|
41
52
|
private func initializeSettings() {
|
|
42
53
|
let colors = VFColors(
|
|
43
|
-
colorPrimary: UIColor(red: 0.00, green: 0.45, blue: 0.91, alpha: 1.00),
|
|
44
|
-
colorPrimaryLight: UIColor(red: 0.90, green: 0.95, blue: 1.00, alpha: 1.00)
|
|
54
|
+
colorPrimary: resolveColor(key: "colorPrimary", fallbackKey: "primary", fallback: UIColor(red: 0.00, green: 0.45, blue: 0.91, alpha: 1.00)),
|
|
55
|
+
colorPrimaryLight: resolveColor(key: "colorPrimaryLight", fallbackKey: "primaryLight", fallback: UIColor(red: 0.90, green: 0.95, blue: 1.00, alpha: 1.00)),
|
|
56
|
+
colorAvatars: resolveAvatarColors() ?? Constants.AvatarColors.colors
|
|
45
57
|
)
|
|
46
58
|
let fonts = VFFonts(fontBold: fontBold)
|
|
47
59
|
settings = VFSettings(colors: colors, fonts: fonts)
|
|
@@ -68,13 +80,19 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
68
80
|
guard let self else { return }
|
|
69
81
|
switch type {
|
|
70
82
|
case .writeNewCommentPressed(let actionType):
|
|
83
|
+
self.emitAction(type: "writeNewCommentPressed", payload: ["actionType": self.stringForActionType(actionType)])
|
|
71
84
|
self.presentNewCommentViewController(actionType: actionType)
|
|
72
85
|
case .trendingArticlePressed(let metadata, let containerId):
|
|
86
|
+
self.emitAction(type: "trendingArticlePressed", payload: ["containerId": containerId, "articleUrl": metadata.url.absoluteString])
|
|
73
87
|
self.onArticlePressed(["containerId": containerId, "articleUrl": metadata.url.absoluteString])
|
|
74
88
|
case .openProfilePressed(let userUUID, let presentationType):
|
|
75
89
|
// Emit event and present profile for parity with Android
|
|
76
|
-
|
|
90
|
+
let presentation = self.stringForPresentationType(presentationType)
|
|
91
|
+
self.emitAction(type: "openProfilePressed", payload: ["userUUID": userUUID.uuidString, "presentationType": presentation])
|
|
92
|
+
self.onOpenProfile(["userUUID": userUUID.uuidString, "presentationType": presentation])
|
|
77
93
|
self.presentProfileViewController(userUUID: userUUID, presentationType: presentationType)
|
|
94
|
+
case .seeMoreCommentsPressed:
|
|
95
|
+
self.emitAction(type: "seeMoreCommentsPressed")
|
|
78
96
|
default:
|
|
79
97
|
break
|
|
80
98
|
}
|
|
@@ -89,7 +107,7 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
89
107
|
addSubview(vc.view)
|
|
90
108
|
vc.view.frame = bounds
|
|
91
109
|
vc.didMove(toParent: parentVC)
|
|
92
|
-
vc.setTheme(theme:
|
|
110
|
+
vc.setTheme(theme: resolveTheme())
|
|
93
111
|
self.previewCommentsViewController = vc
|
|
94
112
|
}
|
|
95
113
|
|
|
@@ -107,12 +125,27 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
107
125
|
switch type {
|
|
108
126
|
case .trendingArticlePressed(let metadata, let containerId):
|
|
109
127
|
profileVC.dismiss(animated: true)
|
|
128
|
+
self.emitAction(type: "trendingArticlePressed", payload: ["containerId": containerId, "articleUrl": metadata.url.absoluteString])
|
|
110
129
|
self.onArticlePressed(["containerId": containerId, "articleUrl": metadata.url.absoluteString])
|
|
130
|
+
case .notificationPressed(let presentation):
|
|
131
|
+
var payload: [String: Any] = [:]
|
|
132
|
+
switch presentation {
|
|
133
|
+
case .profile(let userUUID):
|
|
134
|
+
payload["presentationType"] = "profile"
|
|
135
|
+
payload["userUUID"] = userUUID.uuidString
|
|
136
|
+
case .content(let containerUUID, let contentUUID, let containerId, let articleMetadata):
|
|
137
|
+
payload["presentationType"] = "content"
|
|
138
|
+
payload["containerUUID"] = containerUUID.uuidString
|
|
139
|
+
payload["contentUUID"] = contentUUID.uuidString
|
|
140
|
+
payload["containerId"] = containerId
|
|
141
|
+
payload["articleUrl"] = articleMetadata.url.absoluteString
|
|
142
|
+
}
|
|
143
|
+
self.emitAction(type: "notificationPressed", payload: payload)
|
|
111
144
|
default: break
|
|
112
145
|
}
|
|
113
146
|
}
|
|
114
147
|
profileVC.setActionCallbacks(callbacks: callbacks)
|
|
115
|
-
profileVC.setTheme(theme:
|
|
148
|
+
profileVC.setTheme(theme: resolveTheme())
|
|
116
149
|
parentVC.present(profileVC, animated: true)
|
|
117
150
|
}
|
|
118
151
|
|
|
@@ -129,16 +162,87 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
129
162
|
let callbacks: VFActionsCallbacks = { [weak self] type in
|
|
130
163
|
guard let self else { return }
|
|
131
164
|
switch type {
|
|
132
|
-
case .commentPosted:
|
|
133
|
-
self.
|
|
165
|
+
case .commentPosted(let contentUUID):
|
|
166
|
+
self.emitAction(type: "commentPosted", payload: ["content": contentUUID.uuidString])
|
|
167
|
+
self.onNewComment(["content": contentUUID.uuidString])
|
|
168
|
+
case .replyPosted(let contentUUID):
|
|
169
|
+
self.emitAction(type: "replyPosted", payload: ["content": contentUUID.uuidString])
|
|
134
170
|
default: break
|
|
135
171
|
}
|
|
136
172
|
}
|
|
137
173
|
newCommentVC.setActionCallbacks(callbacks: callbacks)
|
|
138
|
-
newCommentVC.setTheme(theme:
|
|
174
|
+
newCommentVC.setTheme(theme: resolveTheme())
|
|
139
175
|
parentVC.present(newCommentVC, animated: true)
|
|
140
176
|
}
|
|
141
177
|
|
|
178
|
+
private func emitAction(type: String, payload: [String: Any] = [:]) {
|
|
179
|
+
var event = payload
|
|
180
|
+
event["type"] = type
|
|
181
|
+
onAction(event)
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
private func resolveTheme() -> VFTheme {
|
|
185
|
+
switch theme?.lowercased() {
|
|
186
|
+
case "dark":
|
|
187
|
+
return .dark
|
|
188
|
+
case "light":
|
|
189
|
+
return .light
|
|
190
|
+
default:
|
|
191
|
+
return darkMode ? .dark : .light
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
private func applyThemeIfReady() {
|
|
196
|
+
previewCommentsViewController?.setTheme(theme: resolveTheme())
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
private func resolveColor(key: String, fallbackKey: String, fallback: UIColor) -> UIColor {
|
|
200
|
+
let hex = (colors[key] as? String) ?? (colors[fallbackKey] as? String)
|
|
201
|
+
if let hex, let parsed = UIColor.vfColor(fromHex: hex) {
|
|
202
|
+
return parsed
|
|
203
|
+
}
|
|
204
|
+
return fallback
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
private func resolveAvatarColors() -> [UIColor]? {
|
|
208
|
+
let raw = colors["colorAvatars"] ?? colors["avatars"]
|
|
209
|
+
let list: [String]? = (raw as? [String]) ?? (raw as? [Any])?.compactMap { $0 as? String }
|
|
210
|
+
guard let list, list.count == Constants.AvatarColors.colors.count else {
|
|
211
|
+
return nil
|
|
212
|
+
}
|
|
213
|
+
var parsed: [UIColor] = []
|
|
214
|
+
parsed.reserveCapacity(list.count)
|
|
215
|
+
for hex in list {
|
|
216
|
+
guard let color = UIColor.vfColor(fromHex: hex) else { return nil }
|
|
217
|
+
parsed.append(color)
|
|
218
|
+
}
|
|
219
|
+
return parsed
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private func stringForActionType(_ actionType: VFNewCommentActionType) -> String {
|
|
223
|
+
switch actionType {
|
|
224
|
+
case .create:
|
|
225
|
+
return "create"
|
|
226
|
+
case .edit:
|
|
227
|
+
return "edit"
|
|
228
|
+
case .reply:
|
|
229
|
+
return "reply"
|
|
230
|
+
@unknown default:
|
|
231
|
+
return "create"
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
private func stringForPresentationType(_ presentationType: VFProfilePresentationType) -> String {
|
|
236
|
+
switch presentationType {
|
|
237
|
+
case .profile:
|
|
238
|
+
return "profile"
|
|
239
|
+
case .feed:
|
|
240
|
+
return "feed"
|
|
241
|
+
@unknown default:
|
|
242
|
+
return "profile"
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
142
246
|
// MARK: VFLayoutDelegate
|
|
143
247
|
func containerHeightUpdated(viewController: VFUIViewController, height: CGFloat) {
|
|
144
248
|
onHeightChanged(["newHeight": height, "containerId": containerId])
|
|
@@ -146,6 +250,7 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
146
250
|
|
|
147
251
|
// MARK: VFLoginDelegate
|
|
148
252
|
func startLogin() {
|
|
253
|
+
emitAction(type: "authPressed", payload: ["requireLogin": true])
|
|
149
254
|
onAuthNeeded(["requireLogin": true])
|
|
150
255
|
}
|
|
151
256
|
|
|
@@ -154,6 +259,26 @@ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelega
|
|
|
154
259
|
func generateAd(viewController: VFUIViewController, adPosition: Int) -> VFAdView? { VFAdView() }
|
|
155
260
|
}
|
|
156
261
|
|
|
262
|
+
extension UIColor {
|
|
263
|
+
static func vfColor(fromHex hex: String) -> UIColor? {
|
|
264
|
+
var value = hex.trimmingCharacters(in: .whitespacesAndNewlines)
|
|
265
|
+
if value.hasPrefix("#") {
|
|
266
|
+
value.removeFirst()
|
|
267
|
+
}
|
|
268
|
+
if value.count == 6 {
|
|
269
|
+
value = "FF" + value
|
|
270
|
+
}
|
|
271
|
+
guard value.count == 8, let hexNumber = UInt64(value, radix: 16) else {
|
|
272
|
+
return nil
|
|
273
|
+
}
|
|
274
|
+
let alpha = CGFloat((hexNumber & 0xFF000000) >> 24) / 255.0
|
|
275
|
+
let red = CGFloat((hexNumber & 0x00FF0000) >> 16) / 255.0
|
|
276
|
+
let green = CGFloat((hexNumber & 0x0000FF00) >> 8) / 255.0
|
|
277
|
+
let blue = CGFloat(hexNumber & 0x000000FF) / 255.0
|
|
278
|
+
return UIColor(red: red, green: green, blue: blue, alpha: alpha)
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
157
282
|
extension UIView {
|
|
158
283
|
var parentViewController: UIViewController? {
|
|
159
284
|
var parentResponder: UIResponder? = self
|
|
@@ -187,9 +312,11 @@ public class PreviewCommentsModule: Module {
|
|
|
187
312
|
Prop("articleThumbnailUrl") { (view: RNPreviewComments, v: String) in view.articleThumbnailUrl = v }
|
|
188
313
|
Prop("syndicationKey") { (view: RNPreviewComments, v: String?) in view.syndicationKey = v ?? "" }
|
|
189
314
|
Prop("darkMode") { (view: RNPreviewComments, v: Bool?) in view.darkMode = v ?? false }
|
|
315
|
+
Prop("theme") { (view: RNPreviewComments, v: String?) in view.theme = v }
|
|
316
|
+
Prop("colors") { (view: RNPreviewComments, v: [String: Any]?) in view.colors = v ?? [:] }
|
|
190
317
|
|
|
191
318
|
// Events
|
|
192
|
-
Events("onHeightChanged", "onAuthNeeded", "onOpenProfile", "onNewComment", "onArticlePressed")
|
|
319
|
+
Events("onHeightChanged", "onAuthNeeded", "onOpenProfile", "onNewComment", "onArticlePressed", "onAction")
|
|
193
320
|
}
|
|
194
321
|
}
|
|
195
322
|
}
|