@viafoura/sdk-react-native 0.1.0

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.
Files changed (39) hide show
  1. package/README.md +40 -0
  2. package/android/build.gradle +48 -0
  3. package/android/src/main/AndroidManifest.xml +2 -0
  4. package/android/src/main/java/expo/modules/viafourasdk/NewCommentModule.kt +27 -0
  5. package/android/src/main/java/expo/modules/viafourasdk/NewCommentView.kt +153 -0
  6. package/android/src/main/java/expo/modules/viafourasdk/PreviewCommentsModule.kt +26 -0
  7. package/android/src/main/java/expo/modules/viafourasdk/PreviewCommentsView.kt +157 -0
  8. package/android/src/main/java/expo/modules/viafourasdk/ProfileModule.kt +21 -0
  9. package/android/src/main/java/expo/modules/viafourasdk/ProfileView.kt +134 -0
  10. package/android/src/main/java/expo/modules/viafourasdk/ViafouraModule.kt +123 -0
  11. package/build/NewCommentView.d.ts +4 -0
  12. package/build/NewCommentView.d.ts.map +1 -0
  13. package/build/NewCommentView.js +13 -0
  14. package/build/NewCommentView.js.map +1 -0
  15. package/build/PreviewCommentsView.d.ts +4 -0
  16. package/build/PreviewCommentsView.d.ts.map +1 -0
  17. package/build/PreviewCommentsView.js +7 -0
  18. package/build/PreviewCommentsView.js.map +1 -0
  19. package/build/ProfileView.d.ts +4 -0
  20. package/build/ProfileView.d.ts.map +1 -0
  21. package/build/ProfileView.js +13 -0
  22. package/build/ProfileView.js.map +1 -0
  23. package/build/Viafoura.types.d.ts +92 -0
  24. package/build/Viafoura.types.d.ts.map +1 -0
  25. package/build/Viafoura.types.js +2 -0
  26. package/build/Viafoura.types.js.map +1 -0
  27. package/build/ViafouraModule.d.ts +15 -0
  28. package/build/ViafouraModule.d.ts.map +1 -0
  29. package/build/ViafouraModule.js +3 -0
  30. package/build/ViafouraModule.js.map +1 -0
  31. package/build/index.d.ts +6 -0
  32. package/build/index.d.ts.map +1 -0
  33. package/build/index.js +6 -0
  34. package/build/index.js.map +1 -0
  35. package/expo-module.config.json +14 -0
  36. package/ios/PreviewCommentsModule.swift +195 -0
  37. package/ios/Viafoura.podspec +30 -0
  38. package/ios/ViafouraModule.swift +281 -0
  39. package/package.json +56 -0
package/README.md ADDED
@@ -0,0 +1,40 @@
1
+ # @viafoura/sdk-react-native
2
+
3
+ Basic install and usage.
4
+
5
+ # Install
6
+
7
+ ```
8
+ npm install @viafoura/sdk-react-native
9
+ ```
10
+
11
+ iOS:
12
+
13
+ ```
14
+ npx pod-install
15
+ ```
16
+
17
+ # Usage
18
+
19
+ Initialize the SDK once at app startup (e.g., in `App.tsx` or a bootstrap module):
20
+
21
+ ```ts
22
+ import Viafoura from '@viafoura/sdk-react-native';
23
+
24
+ await Viafoura.initialize('SITE_UUID', 'your.domain.com', true);
25
+ ```
26
+
27
+ Then render the views you need:
28
+
29
+ ```tsx
30
+ import { PreviewCommentsView } from '@viafoura/sdk-react-native';
31
+
32
+ <PreviewCommentsView
33
+ containerId="YOUR_CONTAINER_ID"
34
+ articleUrl="https://example.com/article"
35
+ articleTitle="Title"
36
+ articleThumbnailUrl="https://example.com/thumb.jpg"
37
+ />
38
+ ```
39
+
40
+ `ProfileView` and `NewCommentView` are Android-only. On iOS they render as empty views.
@@ -0,0 +1,48 @@
1
+ apply plugin: 'com.android.library'
2
+
3
+ group = 'expo.modules.viafourasdk'
4
+ version = '0.1.0'
5
+
6
+ def expoModulesCorePlugin = new File(project(":expo-modules-core").projectDir.absolutePath, "ExpoModulesCorePlugin.gradle")
7
+ apply from: expoModulesCorePlugin
8
+ applyKotlinExpoModulesCorePlugin()
9
+ useCoreDependencies()
10
+ useExpoPublishing()
11
+
12
+ // If you want to use the managed Android SDK versions from expo-modules-core, set this to true.
13
+ // The Android SDK versions will be bumped from time to time in SDK releases and may introduce breaking changes in your module code.
14
+ // Most of the time, you may like to manage the Android SDK versions yourself.
15
+ def useManagedAndroidSdkVersions = false
16
+ if (useManagedAndroidSdkVersions) {
17
+ useDefaultAndroidSdkVersions()
18
+ } else {
19
+ buildscript {
20
+ // Simple helper that allows the root project to override versions declared by this library.
21
+ ext.safeExtGet = { prop, fallback ->
22
+ rootProject.ext.has(prop) ? rootProject.ext.get(prop) : fallback
23
+ }
24
+ }
25
+ project.android {
26
+ compileSdkVersion safeExtGet("compileSdkVersion", 36)
27
+ defaultConfig {
28
+ minSdkVersion safeExtGet("minSdkVersion", 24)
29
+ targetSdkVersion safeExtGet("targetSdkVersion", 36)
30
+ }
31
+ }
32
+ }
33
+
34
+ android {
35
+ namespace "expo.modules.viafourasdk"
36
+ defaultConfig {
37
+ versionCode 1
38
+ versionName "0.1.0"
39
+ }
40
+ lintOptions {
41
+ abortOnError false
42
+ }
43
+ }
44
+
45
+ dependencies {
46
+ // Viafoura Android SDK (published artifact)
47
+ implementation 'com.viafoura:android:2.0.52'
48
+ }
@@ -0,0 +1,2 @@
1
+ <manifest>
2
+ </manifest>
@@ -0,0 +1,27 @@
1
+ package expo.modules.viafourasdk
2
+
3
+ import expo.modules.kotlin.modules.Module
4
+ import expo.modules.kotlin.modules.ModuleDefinition
5
+
6
+ class NewCommentModule : Module() {
7
+ override fun definition() = ModuleDefinition {
8
+ Name("NewComment")
9
+
10
+ View(NewCommentView::class) {
11
+ // Props
12
+ Prop("newCommentActionType") { view: NewCommentView, v: String -> view.newCommentActionType = v }
13
+ Prop("content") { view: NewCommentView, v: String? -> view.content = v }
14
+ Prop("containerId") { view: NewCommentView, v: String -> view.containerId = v }
15
+ Prop("syndicationKey") { view: NewCommentView, v: String? -> view.syndicationKey = v }
16
+ Prop("articleTitle") { view: NewCommentView, v: String -> view.articleTitle = v }
17
+ Prop("articleSubtitle") { view: NewCommentView, v: String? -> view.articleSubtitle = v }
18
+ Prop("articleUrl") { view: NewCommentView, v: String -> view.articleUrl = v }
19
+ Prop("articleThumbnailUrl") { view: NewCommentView, v: String -> view.articleThumbnailUrl = v }
20
+ Prop("darkMode") { view: NewCommentView, v: Boolean? -> view.darkMode = v ?: false }
21
+
22
+ // Events
23
+ Events("onAuthNeeded", "onCloseNewComment", "onHeightChanged")
24
+ }
25
+ }
26
+ }
27
+
@@ -0,0 +1,153 @@
1
+ package expo.modules.viafourasdk
2
+
3
+ import android.content.Context
4
+ import android.widget.FrameLayout
5
+ import androidx.core.view.ViewCompat
6
+ import androidx.fragment.app.Fragment
7
+ import androidx.fragment.app.FragmentActivity
8
+ import expo.modules.kotlin.AppContext
9
+ import expo.modules.kotlin.viewevent.EventDispatcher
10
+ import expo.modules.kotlin.views.ExpoView
11
+
12
+ // Viafoura SDK imports
13
+ import com.viafourasdk.src.fragments.base.VFFragment
14
+ import com.viafourasdk.src.fragments.newcomment.VFNewCommentFragment
15
+ import com.viafourasdk.src.fragments.newcomment.VFNewCommentFragmentBuilder
16
+ import com.viafourasdk.src.model.local.VFNewCommentAction
17
+ import com.viafourasdk.src.interfaces.VFActionsInterface
18
+ import com.viafourasdk.src.interfaces.VFCustomUIInterface
19
+ import com.viafourasdk.src.interfaces.VFLayoutInterface
20
+ import com.viafourasdk.src.model.local.VFActionData
21
+ import com.viafourasdk.src.model.local.VFActionType
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
+ import com.viafourasdk.src.model.local.VFSettings
26
+ import com.viafourasdk.src.model.local.VFTheme
27
+ import java.net.URL
28
+ import java.util.UUID
29
+
30
+ class NewCommentView(context: Context, private val appContext: AppContext) :
31
+ ExpoView(context, appContext), VFCustomUIInterface, VFActionsInterface, VFLayoutInterface {
32
+
33
+ // Props
34
+ var newCommentActionType: String = "create" // create | edit | reply
35
+ var content: String? = null
36
+ var containerId: String? = null
37
+ var syndicationKey: String? = null
38
+ var articleTitle: String? = null
39
+ var articleSubtitle: String? = null
40
+ var articleUrl: String? = null
41
+ var articleThumbnailUrl: String? = null
42
+ var darkMode: Boolean = false
43
+
44
+ // Events
45
+ private val onAuthNeeded by EventDispatcher()
46
+ private val onCloseNewComment by EventDispatcher()
47
+ private val onHeightChanged by EventDispatcher()
48
+
49
+ // Internals
50
+ private val container = FrameLayout(context).also {
51
+ it.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
52
+ it.id = ViewCompat.generateViewId()
53
+ addView(it)
54
+ }
55
+ private var fragment: VFNewCommentFragment? = null
56
+
57
+ override fun onAttachedToWindow() {
58
+ super.onAttachedToWindow()
59
+ ensureFragment()
60
+ }
61
+
62
+ override fun onDetachedFromWindow() {
63
+ super.onDetachedFromWindow()
64
+ destroyFragment()
65
+ }
66
+
67
+ private fun currentActivity(): FragmentActivity? =
68
+ appContext.currentActivity as? FragmentActivity
69
+
70
+ private fun ensureFragment() {
71
+ if (fragment != null) return
72
+ val activity = currentActivity() ?: return
73
+
74
+ try {
75
+ val metadata = VFArticleMetadata(
76
+ URL(requireNotNull(articleUrl)),
77
+ requireNotNull(articleTitle),
78
+ articleSubtitle ?: "",
79
+ URL(requireNotNull(articleThumbnailUrl))
80
+ )
81
+ val colors = VFColors(
82
+ VFDefaultColors.getInstance().colorPrimaryDefault(null),
83
+ VFDefaultColors.getInstance().colorPrimaryLightDefault(null)
84
+ )
85
+ val settings = VFSettings(colors)
86
+
87
+ val type = when (newCommentActionType) {
88
+ "edit" -> VFNewCommentAction.VFNewCommentActionType.edit
89
+ "reply" -> VFNewCommentAction.VFNewCommentActionType.reply
90
+ else -> VFNewCommentAction.VFNewCommentActionType.create
91
+ }
92
+ val action = VFNewCommentAction(type)
93
+ content?.let { c ->
94
+ if (c.isNotEmpty()) action.content = UUID.fromString(c)
95
+ }
96
+
97
+ val builder = VFNewCommentFragmentBuilder(action, requireNotNull(containerId), metadata, settings)
98
+ syndicationKey?.let { builder.syndicationKey(it) }
99
+ val frag = builder.build()
100
+ frag.setActionCallback(this)
101
+ frag.setCustomUICallback(this)
102
+ frag.setTheme(if (darkMode) VFTheme.dark else VFTheme.light)
103
+
104
+ activity.supportFragmentManager
105
+ .beginTransaction()
106
+ .replace(container.id, frag, container.id.toString())
107
+ .commit()
108
+
109
+ fragment = frag
110
+ } catch (_: Exception) {
111
+ // Swallow; invalid input
112
+ }
113
+ }
114
+
115
+ private fun destroyFragment() {
116
+ val activity = currentActivity() ?: return
117
+ val tag = container.id.toString()
118
+ val frag: Fragment? = activity.supportFragmentManager.findFragmentByTag(tag)
119
+ if (frag != null) {
120
+ activity.supportFragmentManager
121
+ .beginTransaction()
122
+ .remove(frag)
123
+ .commit()
124
+ }
125
+ fragment = null
126
+ }
127
+
128
+ // VFActionsInterface
129
+ override fun onNewAction(actionType: VFActionType, action: VFActionData) {
130
+ when (actionType) {
131
+ VFActionType.closeNewCommentPressed -> {
132
+ onCloseNewComment(emptyMap<String, Any>())
133
+ }
134
+ VFActionType.authPressed -> {
135
+ onAuthNeeded(mapOf("requireLogin" to true))
136
+ }
137
+ else -> {}
138
+ }
139
+ }
140
+
141
+ // VFCustomUIInterface
142
+ override fun customizeView(
143
+ theme: com.viafourasdk.src.model.local.VFTheme?,
144
+ customViewType: com.viafourasdk.src.model.local.VFCustomViewType?,
145
+ view: android.view.View?
146
+ ) { /* no-op */ }
147
+
148
+ // VFLayoutInterface
149
+ override fun containerHeightUpdated(fragment: VFFragment, containerId: String, height: Int) {
150
+ onHeightChanged(mapOf("newHeight" to height, "containerId" to containerId))
151
+ }
152
+ }
153
+
@@ -0,0 +1,26 @@
1
+ package expo.modules.viafourasdk
2
+
3
+ import expo.modules.kotlin.modules.Module
4
+ import expo.modules.kotlin.modules.ModuleDefinition
5
+
6
+ class PreviewCommentsModule : Module() {
7
+ override fun definition() = ModuleDefinition {
8
+ Name("PreviewComments")
9
+
10
+ View(PreviewCommentsView::class) {
11
+ // Props
12
+ Prop("containerId") { view: PreviewCommentsView, v: String -> view.containerId = v }
13
+ Prop("authorId") { view: PreviewCommentsView, v: String? -> view.authorId = v }
14
+ Prop("articleUrl") { view: PreviewCommentsView, v: String -> view.articleUrl = v }
15
+ Prop("articleTitle") { view: PreviewCommentsView, v: String -> view.articleTitle = v }
16
+ Prop("articleSubtitle") { view: PreviewCommentsView, v: String? -> view.articleSubtitle = v }
17
+ Prop("articleThumbnailUrl") { view: PreviewCommentsView, v: String -> view.articleThumbnailUrl = v }
18
+ Prop("syndicationKey") { view: PreviewCommentsView, v: String? -> view.syndicationKey = v }
19
+ Prop("darkMode") { view: PreviewCommentsView, v: Boolean? -> view.darkMode = v ?: false }
20
+
21
+ // Events
22
+ Events("onHeightChanged", "onAuthNeeded", "onOpenProfile", "onNewComment", "onArticlePressed")
23
+ }
24
+ }
25
+ }
26
+
@@ -0,0 +1,157 @@
1
+ package expo.modules.viafourasdk
2
+
3
+ import android.content.Context
4
+ import android.view.ViewGroup
5
+ import android.widget.FrameLayout
6
+ import androidx.core.view.ViewCompat
7
+ import androidx.fragment.app.Fragment
8
+ import androidx.fragment.app.FragmentActivity
9
+ import expo.modules.kotlin.AppContext
10
+ import expo.modules.kotlin.viewevent.EventDispatcher
11
+ import expo.modules.kotlin.views.ExpoView
12
+
13
+ // Viafoura SDK imports
14
+ import com.viafourasdk.src.fragments.base.VFFragment
15
+ import com.viafourasdk.src.fragments.previewcomments.VFPreviewCommentsFragment
16
+ import com.viafourasdk.src.fragments.previewcomments.VFPreviewCommentsFragmentBuilder
17
+ import com.viafourasdk.src.interfaces.VFActionsInterface
18
+ import com.viafourasdk.src.interfaces.VFCustomUIInterface
19
+ import com.viafourasdk.src.interfaces.VFLayoutInterface
20
+ import com.viafourasdk.src.model.local.VFActionData
21
+ import com.viafourasdk.src.model.local.VFActionType
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
+ import com.viafourasdk.src.model.local.VFSettings
26
+ import com.viafourasdk.src.model.local.VFTheme
27
+ import java.net.URL
28
+
29
+ class PreviewCommentsView(context: Context, private val appContext: AppContext) :
30
+ ExpoView(context, appContext), VFCustomUIInterface, VFActionsInterface, VFLayoutInterface {
31
+
32
+ // Props
33
+ var containerId: String? = null
34
+ var authorId: String? = null
35
+ var articleUrl: String? = null
36
+ var articleTitle: String? = null
37
+ var articleSubtitle: String? = null
38
+ var articleThumbnailUrl: String? = null
39
+ var syndicationKey: String? = null
40
+ var darkMode: Boolean = false
41
+
42
+ // Events
43
+ private val onHeightChanged by EventDispatcher()
44
+ private val onAuthNeeded by EventDispatcher()
45
+ private val onOpenProfile by EventDispatcher()
46
+ private val onNewComment by EventDispatcher()
47
+ private val onArticlePressed by EventDispatcher()
48
+
49
+ // Internals
50
+ private val container = FrameLayout(context).also {
51
+ it.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
52
+ it.id = ViewCompat.generateViewId()
53
+ addView(it)
54
+ }
55
+
56
+ private var fragment: VFPreviewCommentsFragment? = null
57
+
58
+ override fun onAttachedToWindow() {
59
+ super.onAttachedToWindow()
60
+ ensureFragment()
61
+ }
62
+
63
+ override fun onDetachedFromWindow() {
64
+ super.onDetachedFromWindow()
65
+ destroyFragment()
66
+ }
67
+
68
+ private fun currentActivity(): FragmentActivity? =
69
+ appContext.currentActivity as? FragmentActivity
70
+
71
+ private fun ensureFragment() {
72
+ if (fragment != null) return
73
+ val activity = currentActivity() ?: return
74
+
75
+ try {
76
+ val meta = VFArticleMetadata(
77
+ URL(requireNotNull(articleUrl)),
78
+ requireNotNull(articleTitle),
79
+ articleSubtitle ?: "",
80
+ URL(requireNotNull(articleThumbnailUrl))
81
+ )
82
+ val colors = VFColors(
83
+ VFDefaultColors.getInstance().colorPrimaryDefault(null),
84
+ VFDefaultColors.getInstance().colorPrimaryLightDefault(null)
85
+ )
86
+ val settings = VFSettings(colors)
87
+
88
+ val builder = VFPreviewCommentsFragmentBuilder(requireNotNull(containerId), meta, settings)
89
+ syndicationKey?.let { builder.syndicationKey(it) }
90
+ val frag = builder.build()
91
+ frag.setActionCallback(this)
92
+ frag.setLayoutCallback(this)
93
+ frag.setCustomUICallback(this)
94
+ frag.setTheme(if (darkMode) VFTheme.dark else VFTheme.light)
95
+ authorId?.let { if (it.isNotEmpty()) frag.setAuthorIds(listOf(it)) }
96
+
97
+ activity.supportFragmentManager
98
+ .beginTransaction()
99
+ .replace(container.id, frag, container.id.toString())
100
+ .commit()
101
+
102
+ fragment = frag
103
+ } catch (_: Exception) {
104
+ // Swallow; invalid input
105
+ }
106
+ }
107
+
108
+ private fun destroyFragment() {
109
+ val activity = currentActivity() ?: return
110
+ val tag = container.id.toString()
111
+ val frag = activity.supportFragmentManager.findFragmentByTag(tag)
112
+ if (frag != null) {
113
+ activity.supportFragmentManager
114
+ .beginTransaction()
115
+ .remove(frag)
116
+ .commit()
117
+ }
118
+ fragment = null
119
+ }
120
+
121
+ // VFCustomUIInterface
122
+ override fun customizeView(
123
+ theme: com.viafourasdk.src.model.local.VFTheme?,
124
+ customViewType: com.viafourasdk.src.model.local.VFCustomViewType?,
125
+ view: android.view.View?
126
+ ) { /* no-op */ }
127
+
128
+ // VFActionsInterface
129
+ override fun onNewAction(actionType: VFActionType, action: VFActionData) {
130
+ when (actionType) {
131
+ VFActionType.writeNewCommentPressed -> {
132
+ val content = action.newCommentAction?.content?.toString()
133
+ val type = action.newCommentAction?.type?.toString()
134
+ onNewComment(mapOf("content" to content, "actionType" to type).filterValues { it != null })
135
+ }
136
+ VFActionType.openProfilePressed -> {
137
+ val pres = action.openProfileAction?.presentationType?.toString()
138
+ val user = action.openProfileAction?.userUUID?.toString()
139
+ onOpenProfile(mapOf("presentationType" to pres, "userUUID" to user).filterValues { it != null })
140
+ }
141
+ VFActionType.trendingArticlePressed -> {
142
+ val url = action.trendingPressedAction?.articleMetadata?.url?.toString() ?: return
143
+ val containerId = action.trendingPressedAction?.containerId ?: ""
144
+ onArticlePressed(mapOf("articleUrl" to url, "containerId" to containerId))
145
+ }
146
+ VFActionType.authPressed -> {
147
+ onAuthNeeded(mapOf("requireLogin" to true))
148
+ }
149
+ else -> {}
150
+ }
151
+ }
152
+
153
+ // VFLayoutInterface
154
+ override fun containerHeightUpdated(fragment: VFFragment, containerId: String, height: Int) {
155
+ onHeightChanged(mapOf("newHeight" to height, "containerId" to containerId))
156
+ }
157
+ }
@@ -0,0 +1,21 @@
1
+ package expo.modules.viafourasdk
2
+
3
+ import expo.modules.kotlin.modules.Module
4
+ import expo.modules.kotlin.modules.ModuleDefinition
5
+
6
+ class ProfileModule : Module() {
7
+ override fun definition() = ModuleDefinition {
8
+ Name("Profile")
9
+
10
+ View(ProfileView::class) {
11
+ // Props
12
+ Prop("userUUID") { view: ProfileView, v: String -> view.userUUID = v }
13
+ Prop("presentationType") { view: ProfileView, v: String? -> view.presentationType = v }
14
+ Prop("darkMode") { view: ProfileView, v: Boolean? -> view.darkMode = v ?: false }
15
+
16
+ // Events
17
+ Events("onAuthNeeded", "onCloseProfile")
18
+ }
19
+ }
20
+ }
21
+
@@ -0,0 +1,134 @@
1
+ package expo.modules.viafourasdk
2
+
3
+ import android.content.Context
4
+ import android.widget.FrameLayout
5
+ import androidx.core.view.ViewCompat
6
+ import androidx.fragment.app.Fragment
7
+ import androidx.fragment.app.FragmentActivity
8
+ import expo.modules.kotlin.AppContext
9
+ import expo.modules.kotlin.viewevent.EventDispatcher
10
+ import expo.modules.kotlin.views.ExpoView
11
+
12
+ // Viafoura SDK imports
13
+ import com.viafourasdk.src.fragments.profile.VFProfileFragment
14
+ import com.viafourasdk.src.fragments.profile.VFProfileFragmentBuilder
15
+ import com.viafourasdk.src.interfaces.VFActionsInterface
16
+ import com.viafourasdk.src.interfaces.VFCustomUIInterface
17
+ import com.viafourasdk.src.interfaces.VFLayoutInterface
18
+ import com.viafourasdk.src.model.local.VFActionData
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
+ import com.viafourasdk.src.model.local.VFSettings
23
+ import com.viafourasdk.src.model.local.VFProfilePresentationType
24
+ import com.viafourasdk.src.model.local.VFTheme
25
+ import java.util.UUID
26
+
27
+ class ProfileView(context: Context, private val appContext: AppContext) :
28
+ ExpoView(context, appContext), VFCustomUIInterface, VFActionsInterface, VFLayoutInterface {
29
+
30
+ // Props
31
+ var userUUID: String? = null
32
+ var presentationType: String? = null // "profile" | "feed"
33
+ var darkMode: Boolean = false
34
+
35
+ // Events
36
+ private val onAuthNeeded by EventDispatcher()
37
+ private val onCloseProfile by EventDispatcher()
38
+
39
+ // Internals
40
+ private val container = FrameLayout(context).also {
41
+ it.layoutParams = LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)
42
+ it.id = ViewCompat.generateViewId()
43
+ addView(it)
44
+ }
45
+ private var fragment: VFProfileFragment? = null
46
+
47
+ override fun onAttachedToWindow() {
48
+ super.onAttachedToWindow()
49
+ ensureFragment()
50
+ }
51
+
52
+ override fun onDetachedFromWindow() {
53
+ super.onDetachedFromWindow()
54
+ destroyFragment()
55
+ }
56
+
57
+ private fun currentActivity(): FragmentActivity? =
58
+ appContext.currentActivity as? FragmentActivity
59
+
60
+ private fun ensureFragment() {
61
+ if (fragment != null) return
62
+ val activity = currentActivity() ?: return
63
+
64
+ try {
65
+ val colors = VFColors(
66
+ VFDefaultColors.getInstance().colorPrimaryDefault(null),
67
+ VFDefaultColors.getInstance().colorPrimaryLightDefault(null)
68
+ )
69
+ val settings = VFSettings(colors)
70
+
71
+ val pres = when (presentationType) {
72
+ "feed" -> VFProfilePresentationType.feed
73
+ "profile" -> VFProfilePresentationType.profile
74
+ else -> null
75
+ }
76
+
77
+ val uuid = UUID.fromString(requireNotNull(userUUID))
78
+ val frag = VFProfileFragmentBuilder(uuid, pres, settings).build()
79
+ frag.setActionCallback(this)
80
+ frag.setCustomUICallback(this)
81
+ frag.setTheme(if (darkMode) VFTheme.dark else VFTheme.light)
82
+
83
+ activity.supportFragmentManager
84
+ .beginTransaction()
85
+ .replace(container.id, frag, container.id.toString())
86
+ .commit()
87
+
88
+ fragment = frag
89
+ } catch (_: Exception) {
90
+ // Swallow; invalid input
91
+ }
92
+ }
93
+
94
+ private fun destroyFragment() {
95
+ val activity = currentActivity() ?: return
96
+ val tag = container.id.toString()
97
+ val frag: Fragment? = activity.supportFragmentManager.findFragmentByTag(tag)
98
+ if (frag != null) {
99
+ activity.supportFragmentManager
100
+ .beginTransaction()
101
+ .remove(frag)
102
+ .commit()
103
+ }
104
+ fragment = null
105
+ }
106
+
107
+ // VFActionsInterface
108
+ override fun onNewAction(actionType: VFActionType, action: VFActionData) {
109
+ when (actionType) {
110
+ VFActionType.closeProfilePressed -> {
111
+ onCloseProfile(emptyMap<String, Any>())
112
+ }
113
+ VFActionType.authPressed -> {
114
+ onAuthNeeded(mapOf("requireLogin" to true))
115
+ }
116
+ else -> {}
117
+ }
118
+ }
119
+
120
+ // VFCustomUIInterface
121
+ override fun customizeView(
122
+ theme: com.viafourasdk.src.model.local.VFTheme?,
123
+ customViewType: com.viafourasdk.src.model.local.VFCustomViewType?,
124
+ view: android.view.View?
125
+ ) { /* no-op */ }
126
+
127
+ // VFLayoutInterface
128
+ override fun containerHeightUpdated(
129
+ fragment: com.viafourasdk.src.fragments.base.VFFragment,
130
+ containerId: String,
131
+ height: Int
132
+ ) { /* no-op for profile */ }
133
+ }
134
+