@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
@@ -0,0 +1,123 @@
1
+ package expo.modules.viafourasdk
2
+
3
+ import expo.modules.kotlin.Promise
4
+ import expo.modules.kotlin.modules.Module
5
+ import expo.modules.kotlin.modules.ModuleDefinition
6
+ import java.net.URL
7
+
8
+ // Viafoura SDK imports. Ensure the SDK is added to the app.
9
+ import com.viafourasdk.src.ViafouraSDK
10
+ import com.viafourasdk.src.model.network.authentication.cookieLogin.CookieLoginResponse
11
+ import com.viafourasdk.src.model.network.authentication.login.LoginResponse
12
+ import com.viafourasdk.src.model.network.authentication.openId.OpenIdLoginResponse
13
+ import com.viafourasdk.src.model.network.authentication.signup.SignUpResponse
14
+ import com.viafourasdk.src.model.network.authentication.socialLogin.SocialLoginResponse
15
+ import com.viafourasdk.src.model.network.error.NetworkError
16
+ import com.viafourasdk.src.services.auth.VFAuthService
17
+
18
+ class ViafouraModule : Module() {
19
+ // Each module class must implement the definition function. The definition consists of components
20
+ // that describes the module's functionality and behavior.
21
+ // See https://docs.expo.dev/modules/module-api for more details about available components.
22
+ override fun definition() = ModuleDefinition {
23
+ // Sets the name of the module that JavaScript code will use to refer to the module. Takes a string as an argument.
24
+ // Can be inferred from module's class name, but it's recommended to set it explicitly for clarity.
25
+ // The module will be accessible from `requireNativeModule('Viafoura')` in JavaScript.
26
+ Name("Viafoura")
27
+
28
+ // MARK: - Auth API
29
+ AsyncFunction("logout") {
30
+ ViafouraSDK.auth().logout()
31
+ }
32
+
33
+ AsyncFunction("login") { email: String, password: String, promise: Promise ->
34
+ ViafouraSDK.auth().login(email, password, object : VFAuthService.LoginCallback {
35
+ override fun onSuccess(loginResponse: LoginResponse) {
36
+ promise.resolve(null)
37
+ }
38
+ override fun onError(err: NetworkError) {
39
+ promise.reject("E_VF_LOGIN", err.message ?: "Login failed")
40
+ }
41
+ })
42
+ }
43
+
44
+ AsyncFunction("signup") { name: String, email: String, password: String, promise: Promise ->
45
+ ViafouraSDK.auth().signup(name, email, password, object : VFAuthService.SignUpCallback {
46
+ override fun onSuccess(loginResponse: SignUpResponse) {
47
+ promise.resolve(null)
48
+ }
49
+ override fun onError(err: NetworkError) {
50
+ promise.reject("E_VF_SIGNUP", err.message ?: "Signup failed")
51
+ }
52
+ })
53
+ }
54
+
55
+ // Provider parameter is optional on Android SDK; ignored if provided
56
+ AsyncFunction("socialLogin") { token: String, provider: String?, promise: Promise ->
57
+ ViafouraSDK.auth().socialLogin(token, object : VFAuthService.SocialLoginCallback {
58
+ override fun onSuccess(loginResponse: SocialLoginResponse) {
59
+ promise.resolve(null)
60
+ }
61
+ override fun onError(err: NetworkError) {
62
+ promise.reject("E_VF_SOCIAL", err.message ?: "Social login failed")
63
+ }
64
+ })
65
+ }
66
+
67
+ AsyncFunction("openIdLogin") { token: String, promise: Promise ->
68
+ ViafouraSDK.auth().openIdLogin(token, object : VFAuthService.OpenIdLoginCallback {
69
+ override fun onSuccess(loginResponse: OpenIdLoginResponse) {
70
+ promise.resolve(null)
71
+ }
72
+ override fun onError(err: NetworkError) {
73
+ promise.reject("E_VF_OPENID", err.message ?: "OpenID login failed")
74
+ }
75
+ })
76
+ }
77
+
78
+ AsyncFunction("cookieLogin") { token: String, promise: Promise ->
79
+ ViafouraSDK.auth().cookieLogin(token, object : VFAuthService.CookieLoginCallback {
80
+ override fun onSuccess(loginResponse: CookieLoginResponse) {
81
+ promise.resolve(null)
82
+ }
83
+ override fun onError(err: NetworkError) {
84
+ promise.reject("E_VF_COOKIE", err.message ?: "Cookie login failed")
85
+ }
86
+ })
87
+ }
88
+
89
+ AsyncFunction("resetPassword") { email: String, promise: Promise ->
90
+ ViafouraSDK.auth().passwordReset(email, object : VFAuthService.PasswordResetCallback {
91
+ override fun onSuccess() {
92
+ promise.resolve(null)
93
+ }
94
+ override fun onError(err: NetworkError) {
95
+ promise.reject("E_VF_RESET", err.message ?: "Password reset failed")
96
+ }
97
+ })
98
+ }
99
+
100
+ // MARK: - Core API
101
+ AsyncFunction("initialize") { siteUUID: String, siteDomain: String, enableLogging: Boolean?, promise: Promise ->
102
+ val context = appContext.reactContext?.applicationContext
103
+ ?: appContext.currentActivity?.applicationContext
104
+ if (context == null) {
105
+ promise.reject("E_VF_INIT", "No application context available")
106
+ return@AsyncFunction
107
+ }
108
+ if (siteUUID.isBlank() || siteDomain.isBlank()) {
109
+ promise.reject("E_VF_INIT", "Invalid Viafoura initialization parameters")
110
+ return@AsyncFunction
111
+ }
112
+ try {
113
+ enableLogging?.let { ViafouraSDK.isLoggingEnabled = it }
114
+ ViafouraSDK.initialize(context, siteUUID, siteDomain)
115
+ promise.resolve(null)
116
+ } catch (e: Exception) {
117
+ promise.reject("E_VF_INIT", e.message ?: "Viafoura initialization failed")
118
+ }
119
+ }
120
+
121
+ // No additional native view here. PreviewComments is exposed via a separate module.
122
+ }
123
+ }
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import { NewCommentViewProps } from './Viafoura.types';
3
+ export default function NewCommentView(props: NewCommentViewProps): React.JSX.Element;
4
+ //# sourceMappingURL=NewCommentView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NewCommentView.d.ts","sourceRoot":"","sources":["../src/NewCommentView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAWvD,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,KAAK,EAAE,mBAAmB,qBAEhE"}
@@ -0,0 +1,13 @@
1
+ import { requireNativeViewManager } from 'expo-modules-core';
2
+ import * as React from 'react';
3
+ import { Platform } from 'react-native';
4
+ function NewCommentFallbackView(_props) {
5
+ return null;
6
+ }
7
+ const NativeView = Platform.OS === 'android'
8
+ ? requireNativeViewManager('NewComment')
9
+ : NewCommentFallbackView;
10
+ export default function NewCommentView(props) {
11
+ return <NativeView {...props}/>;
12
+ }
13
+ //# sourceMappingURL=NewCommentView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NewCommentView.js","sourceRoot":"","sources":["../src/NewCommentView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,SAAS,sBAAsB,CAAC,MAA2B;IACzD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,GACd,QAAQ,CAAC,EAAE,KAAK,SAAS;IACvB,CAAC,CAAC,wBAAwB,CAAC,YAAY,CAAC;IACxC,CAAC,CAAC,sBAAsB,CAAC;AAE7B,MAAM,CAAC,OAAO,UAAU,cAAc,CAAC,KAA0B;IAC/D,OAAO,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AACnC,CAAC","sourcesContent":["import { requireNativeViewManager } from 'expo-modules-core';\nimport * as React from 'react';\nimport { Platform } from 'react-native';\n\nimport { NewCommentViewProps } from './Viafoura.types';\n\nfunction NewCommentFallbackView(_props: NewCommentViewProps) {\n return null;\n}\n\nconst NativeView: React.ComponentType<NewCommentViewProps> =\n Platform.OS === 'android'\n ? requireNativeViewManager('NewComment')\n : NewCommentFallbackView;\n\nexport default function NewCommentView(props: NewCommentViewProps) {\n return <NativeView {...props} />;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import { PreviewCommentsViewProps } from './Viafoura.types';
3
+ export default function PreviewCommentsView(props: PreviewCommentsViewProps): React.JSX.Element;
4
+ //# sourceMappingURL=PreviewCommentsView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewCommentsView.d.ts","sourceRoot":"","sources":["../src/PreviewCommentsView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AAK5D,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,qBAE1E"}
@@ -0,0 +1,7 @@
1
+ import { requireNativeViewManager } from 'expo-modules-core';
2
+ import * as React from 'react';
3
+ const NativeView = requireNativeViewManager('PreviewComments');
4
+ export default function PreviewCommentsView(props) {
5
+ return <NativeView {...props}/>;
6
+ }
7
+ //# sourceMappingURL=PreviewCommentsView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PreviewCommentsView.js","sourceRoot":"","sources":["../src/PreviewCommentsView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAI/B,MAAM,UAAU,GACd,wBAAwB,CAAC,iBAAiB,CAAC,CAAC;AAE9C,MAAM,CAAC,OAAO,UAAU,mBAAmB,CAAC,KAA+B;IACzE,OAAO,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AACnC,CAAC","sourcesContent":["import { requireNativeViewManager } from 'expo-modules-core';\nimport * as React from 'react';\n\nimport { PreviewCommentsViewProps } from './Viafoura.types';\n\nconst NativeView: React.ComponentType<PreviewCommentsViewProps> =\n requireNativeViewManager('PreviewComments');\n\nexport default function PreviewCommentsView(props: PreviewCommentsViewProps) {\n return <NativeView {...props} />;\n}\n"]}
@@ -0,0 +1,4 @@
1
+ import * as React from 'react';
2
+ import { ProfileViewProps } from './Viafoura.types';
3
+ export default function ProfileView(props: ProfileViewProps): React.JSX.Element;
4
+ //# sourceMappingURL=ProfileView.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProfileView.d.ts","sourceRoot":"","sources":["../src/ProfileView.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAG/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAWpD,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,KAAK,EAAE,gBAAgB,qBAE1D"}
@@ -0,0 +1,13 @@
1
+ import { requireNativeViewManager } from 'expo-modules-core';
2
+ import * as React from 'react';
3
+ import { Platform } from 'react-native';
4
+ function ProfileFallbackView(_props) {
5
+ return null;
6
+ }
7
+ const NativeView = Platform.OS === 'android'
8
+ ? requireNativeViewManager('Profile')
9
+ : ProfileFallbackView;
10
+ export default function ProfileView(props) {
11
+ return <NativeView {...props}/>;
12
+ }
13
+ //# sourceMappingURL=ProfileView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ProfileView.js","sourceRoot":"","sources":["../src/ProfileView.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AAIxC,SAAS,mBAAmB,CAAC,MAAwB;IACnD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,GACd,QAAQ,CAAC,EAAE,KAAK,SAAS;IACvB,CAAC,CAAC,wBAAwB,CAAC,SAAS,CAAC;IACrC,CAAC,CAAC,mBAAmB,CAAC;AAE1B,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,KAAuB;IACzD,OAAO,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,EAAG,CAAC;AACnC,CAAC","sourcesContent":["import { requireNativeViewManager } from 'expo-modules-core';\nimport * as React from 'react';\nimport { Platform } from 'react-native';\n\nimport { ProfileViewProps } from './Viafoura.types';\n\nfunction ProfileFallbackView(_props: ProfileViewProps) {\n return null;\n}\n\nconst NativeView: React.ComponentType<ProfileViewProps> =\n Platform.OS === 'android'\n ? requireNativeViewManager('Profile')\n : ProfileFallbackView;\n\nexport default function ProfileView(props: ProfileViewProps) {\n return <NativeView {...props} />;\n}\n"]}
@@ -0,0 +1,92 @@
1
+ import type { StyleProp, ViewStyle } from 'react-native';
2
+ export type ViafouraModuleEvents = {
3
+ onChange: (params: ChangeEventPayload) => void;
4
+ };
5
+ export type ChangeEventPayload = {
6
+ value: string;
7
+ };
8
+ export type PreviewCommentsEvents = 'onHeightChanged' | 'onAuthNeeded' | 'onOpenProfile' | 'onNewComment' | 'onArticlePressed';
9
+ export type PreviewCommentsHeightChangedPayload = {
10
+ newHeight: number;
11
+ containerId: string;
12
+ };
13
+ export type PreviewCommentsAuthNeededPayload = {
14
+ requireLogin?: boolean;
15
+ };
16
+ export type PreviewCommentsOpenProfilePayload = {
17
+ userUUID: string;
18
+ presentationType?: string;
19
+ };
20
+ export type PreviewCommentsNewCommentPayload = {
21
+ content?: string;
22
+ actionType?: string;
23
+ };
24
+ export type PreviewCommentsArticlePressedPayload = {
25
+ articleUrl: string;
26
+ containerId: string;
27
+ };
28
+ export type PreviewCommentsViewProps = {
29
+ containerId: string;
30
+ authorId?: string;
31
+ articleUrl: string;
32
+ articleTitle: string;
33
+ articleSubtitle?: string;
34
+ articleThumbnailUrl: string;
35
+ syndicationKey?: string;
36
+ darkMode?: boolean;
37
+ onHeightChanged?: (event: {
38
+ nativeEvent: PreviewCommentsHeightChangedPayload;
39
+ }) => void;
40
+ onAuthNeeded?: (event: {
41
+ nativeEvent: PreviewCommentsAuthNeededPayload;
42
+ }) => void;
43
+ onOpenProfile?: (event: {
44
+ nativeEvent: PreviewCommentsOpenProfilePayload;
45
+ }) => void;
46
+ onNewComment?: (event: {
47
+ nativeEvent: PreviewCommentsNewCommentPayload;
48
+ }) => void;
49
+ onArticlePressed?: (event: {
50
+ nativeEvent: PreviewCommentsArticlePressedPayload;
51
+ }) => void;
52
+ style?: StyleProp<ViewStyle>;
53
+ };
54
+ export type ProfileAuthNeededPayload = {
55
+ requireLogin?: boolean;
56
+ };
57
+ export type ProfileViewProps = {
58
+ userUUID: string;
59
+ presentationType?: 'profile' | 'feed';
60
+ darkMode?: boolean;
61
+ onAuthNeeded?: (event: {
62
+ nativeEvent: ProfileAuthNeededPayload;
63
+ }) => void;
64
+ onCloseProfile?: (event: {
65
+ nativeEvent: Record<string, never>;
66
+ }) => void;
67
+ style?: StyleProp<ViewStyle>;
68
+ };
69
+ export type NewCommentHeightChangedPayload = PreviewCommentsHeightChangedPayload;
70
+ export type NewCommentAuthNeededPayload = PreviewCommentsAuthNeededPayload;
71
+ export type NewCommentViewProps = {
72
+ newCommentActionType: 'create' | 'edit' | 'reply';
73
+ content?: string;
74
+ containerId: string;
75
+ syndicationKey?: string;
76
+ articleTitle: string;
77
+ articleSubtitle?: string;
78
+ articleUrl: string;
79
+ articleThumbnailUrl: string;
80
+ darkMode?: boolean;
81
+ onHeightChanged?: (event: {
82
+ nativeEvent: NewCommentHeightChangedPayload;
83
+ }) => void;
84
+ onAuthNeeded?: (event: {
85
+ nativeEvent: NewCommentAuthNeededPayload;
86
+ }) => void;
87
+ onCloseNewComment?: (event: {
88
+ nativeEvent: Record<string, never>;
89
+ }) => void;
90
+ style?: StyleProp<ViewStyle>;
91
+ };
92
+ //# sourceMappingURL=Viafoura.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Viafoura.types.d.ts","sourceRoot":"","sources":["../src/Viafoura.types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=Viafoura.types.js.map
@@ -0,0 +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"]}
@@ -0,0 +1,15 @@
1
+ import { NativeModule } from 'expo-modules-core';
2
+ import { ViafouraModuleEvents } from './Viafoura.types';
3
+ declare class ViafouraModule extends NativeModule<ViafouraModuleEvents> {
4
+ logout(): Promise<void>;
5
+ login(email: string, password: string): Promise<void>;
6
+ signup(name: string, email: string, password: string): Promise<void>;
7
+ socialLogin(token: string, provider?: string): Promise<void>;
8
+ openIdLogin(token: string): Promise<void>;
9
+ cookieLogin(token: string): Promise<void>;
10
+ resetPassword(email: string): Promise<void>;
11
+ initialize(siteUUID: string, siteDomain: string, enableLogging?: boolean): Promise<void>;
12
+ }
13
+ declare const _default: ViafouraModule;
14
+ export default _default;
15
+ //# sourceMappingURL=ViafouraModule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ViafouraModule.d.ts","sourceRoot":"","sources":["../src/ViafouraModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAuB,MAAM,mBAAmB,CAAC;AAEtE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kBAAkB,CAAC;AAExD,OAAO,OAAO,cAAe,SAAQ,YAAY,CAAC,oBAAoB,CAAC;IACrE,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IACvB,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACrD,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACpE,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC5D,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACzC,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACzC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3C,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CACzF;;AAED,wBAA+D"}
@@ -0,0 +1,3 @@
1
+ import { requireNativeModule } from 'expo-modules-core';
2
+ export default requireNativeModule('Viafoura');
3
+ //# sourceMappingURL=ViafouraModule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ViafouraModule.js","sourceRoot":"","sources":["../src/ViafouraModule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAetE,eAAe,mBAAmB,CAAiB,UAAU,CAAC,CAAC","sourcesContent":["import { NativeModule, requireNativeModule } from 'expo-modules-core';\n\nimport { ViafouraModuleEvents } from './Viafoura.types';\n\ndeclare class ViafouraModule extends NativeModule<ViafouraModuleEvents> {\n logout(): Promise<void>;\n login(email: string, password: string): Promise<void>;\n signup(name: string, email: string, password: string): Promise<void>;\n socialLogin(token: string, provider?: string): Promise<void>;\n openIdLogin(token: string): Promise<void>;\n cookieLogin(token: string): Promise<void>;\n resetPassword(email: string): Promise<void>;\n initialize(siteUUID: string, siteDomain: string, enableLogging?: boolean): Promise<void>;\n}\n\nexport default requireNativeModule<ViafouraModule>('Viafoura');\n"]}
@@ -0,0 +1,6 @@
1
+ export { default } from './ViafouraModule';
2
+ export * from './Viafoura.types';
3
+ export { default as PreviewCommentsView } from './PreviewCommentsView';
4
+ export { default as ProfileView } from './ProfileView';
5
+ export { default as NewCommentView } from './NewCommentView';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,cAAe,kBAAkB,CAAC;AAClC,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC"}
package/build/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { default } from './ViafouraModule';
2
+ export * from './Viafoura.types';
3
+ export { default as PreviewCommentsView } from './PreviewCommentsView';
4
+ export { default as ProfileView } from './ProfileView';
5
+ export { default as NewCommentView } from './NewCommentView';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,cAAe,kBAAkB,CAAC;AAClC,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AACvE,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACvD,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,kBAAkB,CAAC","sourcesContent":["export { default } from './ViafouraModule';\nexport * from './Viafoura.types';\nexport { default as PreviewCommentsView } from './PreviewCommentsView';\nexport { default as ProfileView } from './ProfileView';\nexport { default as NewCommentView } from './NewCommentView';\n"]}
@@ -0,0 +1,14 @@
1
+ {
2
+ "platforms": ["apple", "android"],
3
+ "apple": {
4
+ "modules": ["ViafouraModule", "PreviewCommentsModule"]
5
+ },
6
+ "android": {
7
+ "modules": [
8
+ "expo.modules.viafourasdk.ViafouraModule",
9
+ "expo.modules.viafourasdk.PreviewCommentsModule",
10
+ "expo.modules.viafourasdk.ProfileModule",
11
+ "expo.modules.viafourasdk.NewCommentModule"
12
+ ]
13
+ }
14
+ }
@@ -0,0 +1,195 @@
1
+ import ExpoModulesCore
2
+ import UIKit
3
+
4
+ #if canImport(ViafouraSDK)
5
+ import ViafouraSDK
6
+
7
+ class RNPreviewComments: ExpoView, VFLoginDelegate, VFLayoutDelegate, VFAdDelegate {
8
+ // Props
9
+ var containerId: String = ""
10
+ var authorId: String = ""
11
+ var articleUrl: String = ""
12
+ var articleTitle: String = ""
13
+ var syndicationKey: String = ""
14
+ var articleSubtitle: String = ""
15
+ var articleThumbnailUrl: String = ""
16
+ var darkMode: Bool = false
17
+
18
+ // Events
19
+ let onHeightChanged = EventDispatcher()
20
+ let onAuthNeeded = EventDispatcher()
21
+ let onOpenProfile = EventDispatcher()
22
+ let onNewComment = EventDispatcher()
23
+ let onArticlePressed = EventDispatcher()
24
+
25
+ // Internals
26
+ let fontBold = UIFont.boldSystemFont(ofSize: 17)
27
+ weak var previewCommentsViewController: VFPreviewCommentsViewController?
28
+ var settings: VFSettings?
29
+ var articleMetadata: VFArticleMetadata?
30
+
31
+ override func layoutSubviews() {
32
+ super.layoutSubviews()
33
+ if previewCommentsViewController == nil {
34
+ initializeSettings()
35
+ embed()
36
+ } else {
37
+ previewCommentsViewController?.view.frame = bounds
38
+ }
39
+ }
40
+
41
+ private func initializeSettings() {
42
+ 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)
45
+ )
46
+ let fonts = VFFonts(fontBold: fontBold)
47
+ settings = VFSettings(colors: colors, fonts: fonts)
48
+
49
+ guard let url = URL(string: articleUrl), let thumb = URL(string: articleThumbnailUrl) else {
50
+ return
51
+ }
52
+ articleMetadata = VFArticleMetadata(url: url, title: articleTitle, subtitle: articleSubtitle, thumbnailUrl: thumb)
53
+ }
54
+
55
+ private func embed() {
56
+ guard let parentVC = parentViewController, let settings, let articleMetadata else { return }
57
+
58
+ let vc = VFPreviewCommentsViewController.new(
59
+ containerId: containerId,
60
+ articleMetadata: articleMetadata,
61
+ loginDelegate: self,
62
+ settings: settings,
63
+ defaultSort: .newest,
64
+ syndicationKey: syndicationKey.isEmpty ? nil : syndicationKey
65
+ )
66
+
67
+ let callbacks: VFActionsCallbacks = { [weak self] type in
68
+ guard let self else { return }
69
+ switch type {
70
+ case .writeNewCommentPressed(let actionType):
71
+ self.presentNewCommentViewController(actionType: actionType)
72
+ case .trendingArticlePressed(let metadata, let containerId):
73
+ self.onArticlePressed(["containerId": containerId, "articleUrl": metadata.url.absoluteString])
74
+ case .openProfilePressed(let userUUID, let presentationType):
75
+ // Emit event and present profile for parity with Android
76
+ self.onOpenProfile(["userUUID": userUUID.uuidString, "presentationType": String(describing: presentationType)])
77
+ self.presentProfileViewController(userUUID: userUUID, presentationType: presentationType)
78
+ default:
79
+ break
80
+ }
81
+ }
82
+
83
+ vc.setActionCallbacks(callbacks: callbacks)
84
+ vc.setLayoutDelegate(layoutDelegate: self)
85
+ if !authorId.isEmpty { vc.setAuthorsIds(authors: [authorId]) }
86
+ vc.setAdDelegate(adDelegate: self)
87
+
88
+ parentVC.addChild(vc)
89
+ addSubview(vc.view)
90
+ vc.view.frame = bounds
91
+ vc.didMove(toParent: parentVC)
92
+ vc.setTheme(theme: darkMode ? .dark : .light)
93
+ self.previewCommentsViewController = vc
94
+ }
95
+
96
+ private func presentProfileViewController(userUUID: UUID, presentationType: VFProfilePresentationType) {
97
+ guard let parentVC = parentViewController, let settings else { return }
98
+ let profileVC = VFProfileViewController.new(
99
+ userUUID: userUUID,
100
+ presentationType: presentationType,
101
+ loginDelegate: self,
102
+ settings: settings
103
+ )
104
+
105
+ let callbacks: VFActionsCallbacks = { [weak self] type in
106
+ guard let self else { return }
107
+ switch type {
108
+ case .trendingArticlePressed(let metadata, let containerId):
109
+ profileVC.dismiss(animated: true)
110
+ self.onArticlePressed(["containerId": containerId, "articleUrl": metadata.url.absoluteString])
111
+ default: break
112
+ }
113
+ }
114
+ profileVC.setActionCallbacks(callbacks: callbacks)
115
+ profileVC.setTheme(theme: darkMode ? .dark : .light)
116
+ parentVC.present(profileVC, animated: true)
117
+ }
118
+
119
+ private func presentNewCommentViewController(actionType: VFNewCommentActionType) {
120
+ guard let parentVC = parentViewController, let settings, let articleMetadata else { return }
121
+ let newCommentVC = VFNewCommentViewController.new(
122
+ newCommentActionType: actionType,
123
+ containerId: containerId,
124
+ articleMetadata: articleMetadata,
125
+ loginDelegate: self,
126
+ settings: settings,
127
+ syndicationKey: syndicationKey.isEmpty ? nil : syndicationKey
128
+ )
129
+ let callbacks: VFActionsCallbacks = { [weak self] type in
130
+ guard let self else { return }
131
+ switch type {
132
+ case .commentPosted:
133
+ self.onNewComment([:])
134
+ default: break
135
+ }
136
+ }
137
+ newCommentVC.setActionCallbacks(callbacks: callbacks)
138
+ newCommentVC.setTheme(theme: darkMode ? .dark : .light)
139
+ parentVC.present(newCommentVC, animated: true)
140
+ }
141
+
142
+ // MARK: VFLayoutDelegate
143
+ func containerHeightUpdated(viewController: VFUIViewController, height: CGFloat) {
144
+ onHeightChanged(["newHeight": height, "containerId": containerId])
145
+ }
146
+
147
+ // MARK: VFLoginDelegate
148
+ func startLogin() {
149
+ onAuthNeeded(["requireLogin": true])
150
+ }
151
+
152
+ // MARK: VFAdDelegate
153
+ func getAdInterval(viewController: VFUIViewController) -> Int { 5 }
154
+ func generateAd(viewController: VFUIViewController, adPosition: Int) -> VFAdView? { VFAdView() }
155
+ }
156
+
157
+ extension UIView {
158
+ var parentViewController: UIViewController? {
159
+ var parentResponder: UIResponder? = self
160
+ while let responder = parentResponder {
161
+ parentResponder = responder.next
162
+ if let vc = parentResponder as? UIViewController {
163
+ return vc
164
+ }
165
+ }
166
+ return nil
167
+ }
168
+ }
169
+
170
+ #else
171
+
172
+ class RNPreviewComments: ExpoView {}
173
+
174
+ #endif
175
+
176
+ public class PreviewCommentsModule: Module {
177
+ public func definition() -> ModuleDefinition {
178
+ Name("PreviewComments")
179
+
180
+ View(RNPreviewComments.self) {
181
+ // Props
182
+ Prop("containerId") { (view: RNPreviewComments, v: String) in view.containerId = v }
183
+ Prop("authorId") { (view: RNPreviewComments, v: String?) in view.authorId = v ?? "" }
184
+ Prop("articleUrl") { (view: RNPreviewComments, v: String) in view.articleUrl = v }
185
+ Prop("articleTitle") { (view: RNPreviewComments, v: String) in view.articleTitle = v }
186
+ Prop("articleSubtitle") { (view: RNPreviewComments, v: String?) in view.articleSubtitle = v ?? "" }
187
+ Prop("articleThumbnailUrl") { (view: RNPreviewComments, v: String) in view.articleThumbnailUrl = v }
188
+ Prop("syndicationKey") { (view: RNPreviewComments, v: String?) in view.syndicationKey = v ?? "" }
189
+ Prop("darkMode") { (view: RNPreviewComments, v: Bool?) in view.darkMode = v ?? false }
190
+
191
+ // Events
192
+ Events("onHeightChanged", "onAuthNeeded", "onOpenProfile", "onNewComment", "onArticlePressed")
193
+ }
194
+ }
195
+ }
@@ -0,0 +1,30 @@
1
+ require 'json'
2
+
3
+ package = JSON.parse(File.read(File.join(__dir__, '..', 'package.json')))
4
+
5
+ Pod::Spec.new do |s|
6
+ s.name = 'Viafoura'
7
+ s.version = package['version']
8
+ s.summary = package['description']
9
+ s.description = package['description']
10
+ s.license = package['license']
11
+ s.author = package['author']
12
+ s.homepage = package['homepage']
13
+ # Support iOS only; ViafouraCore is iOS-only. Keep a reasonable minimum.
14
+ s.platform = :ios
15
+ s.ios.deployment_target = '13.0'
16
+ s.swift_versions = ['5.5', '5.6', '5.7', '5.8', '5.9']
17
+ s.source = { git: 'https://github.com/viafoura/sdk-react-native' }
18
+ s.static_framework = true
19
+
20
+ s.dependency 'ExpoModulesCore'
21
+ # Add Viafoura iOS SDK (CocoaPods pod name is ViafouraCore, Swift module is ViafouraSDK)
22
+ s.dependency 'ViafouraCore'
23
+
24
+ # Swift/Objective-C compatibility
25
+ s.pod_target_xcconfig = {
26
+ 'DEFINES_MODULE' => 'YES',
27
+ }
28
+
29
+ s.source_files = "**/*.{h,m,mm,swift,hpp,cpp}"
30
+ end