connect-x-reactnative-livechat-sdk 0.2.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 (38) hide show
  1. package/ConnectXReactnativeLivechatSdk.podspec +20 -0
  2. package/LICENSE +20 -0
  3. package/README.md +34 -0
  4. package/android/build.gradle +83 -0
  5. package/android/gradle.properties +5 -0
  6. package/android/src/main/AndroidManifest.xml +2 -0
  7. package/android/src/main/java/com/connectxreactnativelivechatsdk/ConnectXReactnativeLivechatSdkModule.kt +23 -0
  8. package/android/src/main/java/com/connectxreactnativelivechatsdk/ConnectXReactnativeLivechatSdkPackage.kt +33 -0
  9. package/ios/ConnectXReactnativeLivechatSdk.h +5 -0
  10. package/ios/ConnectXReactnativeLivechatSdk.mm +18 -0
  11. package/lib/module/ChatScreen.js +834 -0
  12. package/lib/module/ChatScreen.js.map +1 -0
  13. package/lib/module/NativeConnectXReactnativeLivechatSdk.js +5 -0
  14. package/lib/module/NativeConnectXReactnativeLivechatSdk.js.map +1 -0
  15. package/lib/module/SendIcon.js +35 -0
  16. package/lib/module/SendIcon.js.map +1 -0
  17. package/lib/module/api.js +66 -0
  18. package/lib/module/api.js.map +1 -0
  19. package/lib/module/index.js +78 -0
  20. package/lib/module/index.js.map +1 -0
  21. package/lib/module/package.json +1 -0
  22. package/lib/typescript/package.json +1 -0
  23. package/lib/typescript/src/ChatScreen.d.ts +7 -0
  24. package/lib/typescript/src/ChatScreen.d.ts.map +1 -0
  25. package/lib/typescript/src/NativeConnectXReactnativeLivechatSdk.d.ts +7 -0
  26. package/lib/typescript/src/NativeConnectXReactnativeLivechatSdk.d.ts.map +1 -0
  27. package/lib/typescript/src/SendIcon.d.ts +3 -0
  28. package/lib/typescript/src/SendIcon.d.ts.map +1 -0
  29. package/lib/typescript/src/api.d.ts +5 -0
  30. package/lib/typescript/src/api.d.ts.map +1 -0
  31. package/lib/typescript/src/index.d.ts +20 -0
  32. package/lib/typescript/src/index.d.ts.map +1 -0
  33. package/package.json +176 -0
  34. package/src/ChatScreen.tsx +914 -0
  35. package/src/NativeConnectXReactnativeLivechatSdk.ts +8 -0
  36. package/src/SendIcon.tsx +25 -0
  37. package/src/api.ts +79 -0
  38. package/src/index.tsx +91 -0
@@ -0,0 +1,8 @@
1
+ import type { TurboModule } from 'react-native';
2
+ import { TurboModuleRegistry } from 'react-native';
3
+
4
+ export interface Spec extends TurboModule {
5
+ multiply(a: number, b: number): number;
6
+ }
7
+
8
+ export default TurboModuleRegistry.getEnforcing<Spec>('ConnectXReactnativeLivechatSdk');
@@ -0,0 +1,25 @@
1
+ const SendIcon = (props: any) => (
2
+ <svg
3
+ xmlns="http://www.w3.org/2000/svg"
4
+ width={33}
5
+ height={32}
6
+ fill="none"
7
+ {...props}
8
+ >
9
+ <rect width={32} height={32} x={0.5} fill="#006CFD" rx={16} />
10
+ <g clipPath="url(#a)">
11
+ <path
12
+ fill="#fff"
13
+ fillRule="evenodd"
14
+ d="m21.492 11.008-10.494 3.795 3.496 2.023 3.083-3.084a.833.833 0 1 1 1.178 1.18l-3.083 3.083 2.025 3.495 3.795-10.492Zm.269-1.87c.996-.36 1.96.604 1.6 1.6L18.959 22.91c-.361.998-1.725 1.12-2.257.201l-2.681-4.632-4.632-2.68c-.919-.533-.797-1.896.201-2.258l12.171-4.402Z"
15
+ clipRule="evenodd"
16
+ />
17
+ </g>
18
+ <defs>
19
+ <clipPath id="a">
20
+ <path fill="#fff" d="M6.5 6h20v20h-20z" />
21
+ </clipPath>
22
+ </defs>
23
+ </svg>
24
+ );
25
+ export default SendIcon;
package/src/api.ts ADDED
@@ -0,0 +1,79 @@
1
+ export const BASE_URL_LIVE_CHAT =
2
+ 'https://df99-2001-44c8-4287-b85c-2407-5b2-9e79-9451.ngrok-free.app'; //'https://live-chat.connect-x.tech';
3
+ const BASE_URL_TRACKING = 'https://tracking.connect-x.tech';
4
+ export const apiGet = async (path: string, token: string) => {
5
+ console.log(`GET ${BASE_URL_LIVE_CHAT}/connectx/api/${path}`);
6
+ const headers = {
7
+ 'Authorization': `Bearer ${token}`,
8
+ 'x-type': 'mobile',
9
+ };
10
+
11
+ const response = await fetch(`${BASE_URL_LIVE_CHAT}/connectx/api/${path}`, {
12
+ method: 'GET',
13
+ headers: headers,
14
+ });
15
+
16
+ if (!response.ok) {
17
+ const errorData = await response.json().catch(() => null);
18
+ throw errorData || new Error('API request failed');
19
+ }
20
+ console.log('Response:', response);
21
+ return response.json();
22
+ };
23
+
24
+ export const apiPost = async (path: string, body: any, token: string) => {
25
+ console.log('Finding customer with userId:', body.userId, body.externalValue);
26
+ console.log(`POST ${BASE_URL_LIVE_CHAT}/connectx/api/${path}`);
27
+ console.log('Request body:', body);
28
+ const response = await fetch(`${BASE_URL_LIVE_CHAT}/connectx/api/${path}`, {
29
+ method: 'POST',
30
+ headers: {
31
+ 'Content-Type': 'application/json',
32
+ 'Authorization': `Bearer ${token}`,
33
+ 'x-type': 'mobile',
34
+ },
35
+ body: JSON.stringify(body),
36
+ });
37
+ if (!response.ok) {
38
+ const errorData = await response.json().catch(() => null);
39
+ throw errorData || new Error('API POST request failed');
40
+ }
41
+ console.log('Response:', response);
42
+ return response.json();
43
+ };
44
+
45
+ export const uploadFile = async (
46
+ file: any,
47
+ organizeId: string,
48
+ channelId: string
49
+ ) => {
50
+ const APIEndpoint = `${BASE_URL_TRACKING}/connectx/api/storage/uploadFile`;
51
+ const formData = new FormData();
52
+
53
+ formData.append('file', {
54
+ uri: file.uri,
55
+ name: file.name,
56
+ type: file.type,
57
+ });
58
+ formData.append(
59
+ 'path',
60
+ `Organizes/${organizeId}/connector/liveChat/channel/${channelId}`
61
+ );
62
+ formData.append('isPublic', 'true');
63
+
64
+ const response = await fetch(APIEndpoint, {
65
+ method: 'POST',
66
+ body: formData,
67
+ headers: {
68
+ 'Content-Type': 'multipart/form-data',
69
+ },
70
+ });
71
+
72
+ if (!response.ok) {
73
+ const errorData = await response.json().catch(() => null);
74
+ throw errorData || new Error('File upload failed');
75
+ }
76
+
77
+ const result = await response.json();
78
+ return result?.url;
79
+ };
package/src/index.tsx ADDED
@@ -0,0 +1,91 @@
1
+ import { useState, useEffect, type ReactNode, useRef } from 'react';
2
+ import { Modal } from 'react-native';
3
+ import { ChatScreen } from './ChatScreen';
4
+ import ConnectXReactnativeLivechatSdk from './NativeConnectXReactnativeLivechatSdk';
5
+
6
+ export function multiply(a: number, b: number): number {
7
+ return ConnectXReactnativeLivechatSdk.multiply(a, b);
8
+ }
9
+
10
+ type EventType = 'show' | 'hide';
11
+ type ShowPayload = { token: string; orgId: string; channelId: string };
12
+
13
+ // Event Emitter ที่รองรับการส่งข้อมูล
14
+ const chatEventEmitter = {
15
+ listeners: new Map<EventType, Set<(payload?: any) => void>>(),
16
+ on(event: EventType, callback: (payload?: any) => void) {
17
+ if (!this.listeners.has(event)) {
18
+ this.listeners.set(event, new Set());
19
+ }
20
+ this.listeners.get(event)!.add(callback);
21
+ return () => this.off(event, callback);
22
+ },
23
+ off(event: EventType, callback: (payload?: any) => void) {
24
+ this.listeners.get(event)?.delete(callback);
25
+ },
26
+ emit(event: EventType, payload?: any) {
27
+ this.listeners.get(event)?.forEach((callback) => callback(payload));
28
+ },
29
+ };
30
+
31
+ export const ChatProvider = ({ children }: { children: ReactNode }) => {
32
+ const [isModalVisible, setModalVisible] = useState(false);
33
+ // เก็บ config ที่ได้รับมา
34
+ const configRef = useRef<ShowPayload | null>(null);
35
+
36
+ useEffect(() => {
37
+ const showHandler = (payload: ShowPayload) => {
38
+ if (payload && payload.token && payload.orgId && payload.channelId) {
39
+ configRef.current = payload;
40
+ setModalVisible(true);
41
+ } else {
42
+ console.error('LiveChat.show() requires { token, orgId, channelId }');
43
+ }
44
+ };
45
+ const hideHandler = () => setModalVisible(false);
46
+
47
+ const showUnsubscribe = chatEventEmitter.on('show', showHandler);
48
+ const hideUnsubscribe = chatEventEmitter.on('hide', hideHandler);
49
+
50
+ return () => {
51
+ showUnsubscribe();
52
+ hideUnsubscribe();
53
+ };
54
+ }, []);
55
+
56
+ return (
57
+ <>
58
+ {children}
59
+ <Modal
60
+ visible={isModalVisible}
61
+ animationType="slide"
62
+ onRequestClose={() => setModalVisible(false)}
63
+ >
64
+ {/* ส่ง config ไปยัง ChatScreen เมื่อ Modal เปิด */}
65
+ {configRef.current && (
66
+ <ChatScreen
67
+ onClose={() => setModalVisible(false)}
68
+ token={configRef.current.token}
69
+ orgId={configRef.current.orgId}
70
+ channelId={configRef.current.channelId}
71
+ />
72
+ )}
73
+ </Modal>
74
+ </>
75
+ );
76
+ };
77
+
78
+ export const LiveChat = {
79
+ /**
80
+ * แสดงหน้าแชท
81
+ * @param config - ต้องมี orgId และ channelId
82
+ */
83
+ show: (config: ShowPayload) => {
84
+ chatEventEmitter.emit('show', config);
85
+ },
86
+ hide: () => {
87
+ chatEventEmitter.emit('hide');
88
+ },
89
+ };
90
+
91
+ export * from './ChatScreen';