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,834 @@
1
+ "use strict";
2
+
3
+ // src/ChatScreen.tsx
4
+ import { useState, useEffect, useRef, useMemo } from 'react';
5
+ import { View, Text, TextInput, TouchableOpacity, SectionList, StyleSheet, SafeAreaView, KeyboardAvoidingView, Platform, Image, ActivityIndicator, Alert, Linking, Dimensions } from 'react-native';
6
+ import io from 'socket.io-client';
7
+ import { pick, types } from '@react-native-documents/picker';
8
+ import { ConnectXMobileSdk } from 'connect-x-react-native-sdk';
9
+ import { apiGet, uploadFile, BASE_URL_LIVE_CHAT, apiPost } from "./api.js";
10
+ import Svg, { Path } from 'react-native-svg';
11
+ import hexToRgba from 'hex-to-rgba';
12
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
13
+ const SendIcon = ({
14
+ color,
15
+ size
16
+ }) => /*#__PURE__*/_jsx(Svg, {
17
+ width: size,
18
+ height: size,
19
+ viewBox: "0 0 24 24",
20
+ fill: "none",
21
+ children: /*#__PURE__*/_jsx(Path, {
22
+ d: "M22 2L15 22L11 13L2 9L22 2Z",
23
+ stroke: color,
24
+ strokeWidth: "2",
25
+ strokeLinecap: "round",
26
+ strokeLinejoin: "round"
27
+ })
28
+ });
29
+
30
+ // Component หลักของหน้าแชท
31
+ export const ChatScreen = ({
32
+ onClose,
33
+ token,
34
+ orgId,
35
+ channelId
36
+ }) => {
37
+ const [messages, setMessages] = useState([]);
38
+ const [inputText, setInputText] = useState('');
39
+ const [loading, setLoading] = useState(true);
40
+ const socketRef = useRef(null);
41
+ const [userId, setUserId] = useState(null);
42
+ const [selectedFile, setSelectedFile] = useState(null);
43
+ const [styleSettings, setStyleSettings] = useState(null);
44
+ const [styles, setStyles] = useState({});
45
+ const sectionListRef = useRef(null);
46
+ const [chatPhase, setChatPhase] = useState('chatting');
47
+ useEffect(() => {
48
+ const findCustomer = async unknownId => {
49
+ try {
50
+ const res = await apiPost(`liveChat/${orgId}/${channelId}/setLiveChatConnector`, {
51
+ externalValue: "Siwakorn'",
52
+ //'ปุ้นซู่ซ่า', //sdf0001111111111 //78e839c38397b8cac97437d17b1c91b568a5adb4
53
+ userId: unknownId
54
+ }, token);
55
+ console.log('Found customer:', res);
56
+ if (res) {
57
+ setUserId(res?.userId);
58
+ } else {
59
+ // initializeUserId();
60
+ }
61
+ } catch (error) {
62
+ // initializeUserId();
63
+ console.log('Error finding customer:', error);
64
+ }
65
+ };
66
+ const initializeUserId = async () => {
67
+ try {
68
+ const res = await ConnectXMobileSdk.getUnknownId();
69
+ console.log('Generated userId:', res);
70
+ // setUserId(res);
71
+ findCustomer(res);
72
+ } catch (error) {
73
+ console.log('Error generating userId:', error);
74
+ }
75
+ };
76
+ if (!userId) {
77
+ initializeUserId();
78
+ }
79
+ });
80
+ useEffect(() => {
81
+ const initializeChat = async () => {
82
+ if (!userId) return;
83
+ try {
84
+ console.log('Checking domain/app permissions...');
85
+ const settings = await apiGet(`liveChat/${orgId}/${channelId}/getSettingConnector`, token);
86
+ setStyleSettings(settings);
87
+ setStyles(getDynamicStyles(settings.styles));
88
+ const history = await apiGet(`liveChat/${orgId}/${channelId}/getChatHistory/${userId}`, token);
89
+ console.log('Chat history:', history);
90
+ setMessages(history);
91
+ const socket = io(`${BASE_URL_LIVE_CHAT}/liveChat`, {
92
+ transports: ['websocket']
93
+ });
94
+ socketRef.current = socket;
95
+ socket.on('connect', () => {
96
+ console.log('Socket connected!');
97
+ socket.emit('joinRoom', {
98
+ userId,
99
+ socketId: socket.id
100
+ });
101
+ });
102
+ socket.on('receiveMessage', payload => {
103
+ console.log('Received message:', payload.message);
104
+ setMessages(prev => [...prev, payload.message]);
105
+ });
106
+ socket.on('disconnect', reason => {
107
+ console.log(`Socket disconnected: ${reason}`);
108
+ });
109
+ } catch (error) {
110
+ console.log('Initialization failed:', error);
111
+ // Alert.alert('Error', 'Could not initialize chat.');
112
+ } finally {
113
+ setLoading(false);
114
+ }
115
+ };
116
+ initializeChat();
117
+ return () => {
118
+ socketRef.current?.disconnect();
119
+ };
120
+ }, [userId, orgId, channelId, token]);
121
+ const messageSections = useMemo(() => {
122
+ if (!messages || messages.length === 0) return [];
123
+ const groupedMessages = messages.reduce((acc, message) => {
124
+ const dateKey = new Date(message.timestamp).toLocaleDateString('en-CA'); // YYYY-MM-DD format for reliable sorting
125
+ if (!acc[dateKey]) {
126
+ acc[dateKey] = [];
127
+ }
128
+ acc[dateKey].push(message);
129
+ return acc;
130
+ }, {});
131
+ return Object.keys(groupedMessages).sort().map(date => ({
132
+ title: new Date(date).toLocaleDateString('en-GB', {
133
+ day: '2-digit',
134
+ month: '2-digit',
135
+ year: 'numeric'
136
+ }),
137
+ data: groupedMessages[date] ?? []
138
+ }));
139
+ }, [messages]);
140
+
141
+ // eslint-disable-next-line react/no-unstable-nested-components
142
+ const PreChatForm = ({
143
+ onSubmit,
144
+ headerColor
145
+ }) => {
146
+ const [formData, setFormData] = useState({});
147
+ const [consentChecked, setConsentChecked] = useState(false);
148
+ const handleInputChange = (field, value) => {
149
+ setFormData(prev => ({
150
+ ...prev,
151
+ [field]: value
152
+ }));
153
+ };
154
+ const handleStartChat = () => {
155
+ if (!consentChecked) {
156
+ Alert.alert('Consent Required', 'Please click the consent checkbox to continue.');
157
+ return;
158
+ }
159
+ onSubmit(formData);
160
+ };
161
+ return /*#__PURE__*/_jsxs(SafeAreaView, {
162
+ style: styles.safeArea,
163
+ children: [/*#__PURE__*/_jsxs(View, {
164
+ style: styles.formContainer,
165
+ children: [/*#__PURE__*/_jsx(Text, {
166
+ style: styles.formWelcomeText,
167
+ children: "Hello there! Are you looking for an automation program in branding for your product?"
168
+ }), /*#__PURE__*/_jsxs(View, {
169
+ style: styles.formInputContainer,
170
+ children: [/*#__PURE__*/_jsx(Text, {
171
+ style: styles.formLabel,
172
+ children: "First Name"
173
+ }), /*#__PURE__*/_jsx(TextInput, {
174
+ style: styles.formInput,
175
+ placeholder: "First Name",
176
+ placeholderTextColor: '#BBC1C3',
177
+ onChangeText: text => handleInputChange('firstName', text)
178
+ })]
179
+ }), /*#__PURE__*/_jsxs(View, {
180
+ style: styles.formInputContainer,
181
+ children: [/*#__PURE__*/_jsx(Text, {
182
+ style: styles.formLabel,
183
+ children: "Lorem"
184
+ }), /*#__PURE__*/_jsx(TextInput, {
185
+ style: styles.formInput,
186
+ placeholder: "Lorem",
187
+ placeholderTextColor: '#BBC1C3',
188
+ onChangeText: text => handleInputChange('lorem', text)
189
+ })]
190
+ })]
191
+ }), /*#__PURE__*/_jsxs(View, {
192
+ style: styles.consentContainer,
193
+ children: [/*#__PURE__*/_jsx(TouchableOpacity, {
194
+ onPress: () => setConsentChecked(!consentChecked),
195
+ style: [styles.checkboxBase, {
196
+ backgroundColor: consentChecked ? '#3761DF' : '#fff'
197
+ }],
198
+ accessibilityRole: "checkbox",
199
+ accessibilityState: {
200
+ checked: consentChecked
201
+ },
202
+ children: consentChecked && /*#__PURE__*/_jsx(Text, {
203
+ style: styles.checkmark,
204
+ children: "\u2713"
205
+ })
206
+ }), /*#__PURE__*/_jsxs(Text, {
207
+ style: styles.consentText,
208
+ children: [/*#__PURE__*/_jsx(Text, {
209
+ style: {
210
+ color: 'red'
211
+ },
212
+ children: "*"
213
+ }), " Click", ' ', /*#__PURE__*/_jsx(Text, {
214
+ style: styles.consentLink,
215
+ children: "Consent"
216
+ })]
217
+ })]
218
+ }), /*#__PURE__*/_jsx(View, {
219
+ style: styles.formFooter,
220
+ children: /*#__PURE__*/_jsx(TouchableOpacity, {
221
+ style: [styles.startButton, {
222
+ backgroundColor: headerColor
223
+ }],
224
+ onPress: handleStartChat,
225
+ children: /*#__PURE__*/_jsx(Text, {
226
+ style: styles.startButtonText,
227
+ children: "Start Chat"
228
+ })
229
+ })
230
+ })]
231
+ });
232
+ };
233
+ useEffect(() => {
234
+ console.log('Message sections updated:', messageSections);
235
+ try {
236
+ if (sectionListRef.current && messageSections.length > 0) {
237
+ setTimeout(() => {
238
+ const lastSectionIndex = messageSections.length - 1;
239
+ const lastSection = messageSections[lastSectionIndex];
240
+ console.log('Scrolling to last section:', lastSectionIndex, lastSection);
241
+ if (lastSection && lastSection?.data && lastSection?.data?.length > 0) {
242
+ sectionListRef.current?.scrollToLocation({
243
+ sectionIndex: lastSectionIndex,
244
+ itemIndex: lastSection?.data?.length - 1,
245
+ viewPosition: 0,
246
+ animated: true
247
+ });
248
+ }
249
+ }, 400);
250
+ }
251
+ } catch (error) {
252
+ console.error('Error scrolling to last section:', error);
253
+ }
254
+ }, [messageSections]);
255
+ const handleScrollToIndexFailed = info => {
256
+ console.warn('Scroll to index failed:', info);
257
+ // As a fallback, scroll to the last rendered item, which is a safer option.
258
+ try {
259
+ sectionListRef.current?.scrollToLocation({
260
+ sectionIndex: info.highestMeasuredFrameIndex,
261
+ itemIndex: 0,
262
+ viewPosition: 0,
263
+ animated: false
264
+ });
265
+ } catch (error) {
266
+ console.log('Fallback scroll failed:', error);
267
+ }
268
+ };
269
+ const sendMessage = messageBody => {
270
+ if (!socketRef.current) return;
271
+ const fullMessage = {
272
+ ...messageBody,
273
+ sender: 'user',
274
+ timestamp: Date.now(),
275
+ type: messageBody.type || 'text'
276
+ };
277
+ socketRef.current.emit('sendMessage', {
278
+ organizeId: orgId,
279
+ channelId: channelId,
280
+ userId: userId,
281
+ message: fullMessage
282
+ }, () => {
283
+ if (fullMessage.type === 'text') {
284
+ setInputText('');
285
+ }
286
+ });
287
+ };
288
+ const handleSendText = () => {
289
+ if (inputText.trim()) {
290
+ sendMessage({
291
+ type: 'text',
292
+ text: inputText.trim()
293
+ });
294
+ }
295
+ };
296
+ const handleSelectFile = async () => {
297
+ try {
298
+ const result = await pick({
299
+ type: [types.images, types.doc, types.pdf],
300
+ allowMultiSelection: false
301
+ });
302
+ setSelectedFile(result[0]);
303
+ } catch (err) {
304
+ if (err?.code !== 'DOCUMENT_PICKER_CANCELED') {
305
+ Alert.alert('File-Picker Error', 'An error occurred during file selection.');
306
+ }
307
+ }
308
+ };
309
+ const handleCancelUpload = () => {
310
+ setSelectedFile(null);
311
+ };
312
+ const handleConfirmUpload = async () => {
313
+ if (!selectedFile) return;
314
+ try {
315
+ const fileUrl = await uploadFile(selectedFile, orgId, channelId);
316
+ const type = selectedFile.type?.startsWith('image/') ? 'image' : 'file';
317
+ sendMessage({
318
+ type,
319
+ fileName: selectedFile.name || 'file',
320
+ url: fileUrl
321
+ });
322
+ } catch (error) {
323
+ Alert.alert('Upload Error', 'Failed to upload the file.');
324
+ console.error('Upload failed', error);
325
+ } finally {
326
+ setSelectedFile(null);
327
+ }
328
+ };
329
+ const formatTimestamp = timestamp => {
330
+ const now = Date.now();
331
+ const messageTime = new Date(timestamp).getTime();
332
+ const differenceInSeconds = (now - messageTime) / 1000;
333
+ if (differenceInSeconds < 60) {
334
+ return 'Just now';
335
+ }
336
+ return new Date(timestamp).toLocaleTimeString('en-US', {
337
+ hour: '2-digit',
338
+ minute: '2-digit',
339
+ hour12: false
340
+ });
341
+ };
342
+ const renderMessage = ({
343
+ item
344
+ }) => {
345
+ const handleFilePress = () => {
346
+ if (item.url) {
347
+ Linking.openURL(item.url).catch(err => {
348
+ console.log('Failed to open URL:', err);
349
+ // Alert.alert('Cannot open file');
350
+ });
351
+ }
352
+ };
353
+ return /*#__PURE__*/_jsxs(View, {
354
+ style: [styles.messageRow, item.sender === 'user' ? styles.userRow : styles.agentRow],
355
+ children: [item.sender === 'agent' && styleSettings?.styles?.styleLogoUrl && /*#__PURE__*/_jsx(Image, {
356
+ source: {
357
+ uri: styleSettings.styles.styleLogoUrl
358
+ },
359
+ style: styles.avatar
360
+ }), /*#__PURE__*/_jsxs(View, {
361
+ style: item.sender === 'agent' ? styles.messageAgentContainer : styles.messageContainer,
362
+ children: [/*#__PURE__*/_jsx(Text, {
363
+ style: styles.timestampText,
364
+ children: formatTimestamp(item.timestamp)
365
+ }), /*#__PURE__*/_jsxs(View, {
366
+ style: [styles.messageBubble, item.sender === 'user' ? styles.userBubble : styles.agentBubble],
367
+ children: [item.type === 'text' && /*#__PURE__*/_jsx(Text, {
368
+ style: item.sender === 'user' ? styles.customerChatText : styles.agentChatText,
369
+ children: item.text
370
+ }), item.type === 'image' && /*#__PURE__*/_jsx(Image, {
371
+ source: {
372
+ uri: item.url
373
+ },
374
+ style: styles.imageMessage,
375
+ resizeMode: "cover"
376
+ }), item.type === 'file' && /*#__PURE__*/_jsx(TouchableOpacity, {
377
+ onPress: handleFilePress,
378
+ children: /*#__PURE__*/_jsx(Text, {
379
+ style: [styles.fileLink, item.sender === 'user' ? styles.customerChatText : styles.agentChatText],
380
+ children: item.fileName
381
+ })
382
+ })]
383
+ })]
384
+ })]
385
+ });
386
+ };
387
+ if (loading) {
388
+ return /*#__PURE__*/_jsx(View, {
389
+ style: {
390
+ flex: 1,
391
+ justifyContent: 'center',
392
+ alignItems: 'center'
393
+ },
394
+ children: /*#__PURE__*/_jsx(ActivityIndicator, {
395
+ size: "large",
396
+ color: '#3761DF'
397
+ })
398
+ });
399
+ }
400
+
401
+ // const agentProfile = {
402
+ // name: styleSettings?.name,
403
+ // avatarUrl: styleSettings?.styleLogoUrl,
404
+ // };
405
+
406
+ return /*#__PURE__*/_jsxs(SafeAreaView, {
407
+ style: styles.safeArea,
408
+ children: [/*#__PURE__*/_jsxs(View, {
409
+ style: styles.header,
410
+ children: [/*#__PURE__*/_jsxs(View, {
411
+ style: styles.headerProfile,
412
+ children: [styleSettings?.styles?.styleLogoUrl && /*#__PURE__*/_jsx(Image, {
413
+ source: {
414
+ uri: styleSettings.styles.styleLogoUrl
415
+ },
416
+ style: styles.headerAvatar
417
+ }), /*#__PURE__*/_jsx(Text, {
418
+ style: styles.headerTitle,
419
+ children: styleSettings?.styles.name || 'Live Chat'
420
+ })]
421
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
422
+ onPress: onClose,
423
+ children: /*#__PURE__*/_jsx(Text, {
424
+ style: styles.closeButtonText,
425
+ children: "\u2715"
426
+ })
427
+ })]
428
+ }), /*#__PURE__*/_jsx(KeyboardAvoidingView, {
429
+ style: styles.container,
430
+ children: chatPhase === 'pre-chat' ? /*#__PURE__*/_jsx(PreChatForm, {
431
+ onSubmit: () => setChatPhase('chatting')
432
+ // agentProfile={agentProfile}
433
+ // styles={styles}
434
+ ,
435
+ headerColor: styleSettings?.styles?.styleHeadColor
436
+ }) : /*#__PURE__*/_jsxs(_Fragment, {
437
+ children: [/*#__PURE__*/_jsx(SectionList, {
438
+ ref: sectionListRef,
439
+ sections: messageSections,
440
+ renderItem: renderMessage,
441
+ renderSectionHeader: ({
442
+ section: {
443
+ title
444
+ }
445
+ }) => /*#__PURE__*/_jsx(View, {
446
+ style: styles.datePartition,
447
+ children: /*#__PURE__*/_jsx(Text, {
448
+ style: styles.datePartitionText,
449
+ children: title
450
+ })
451
+ }),
452
+ keyExtractor: item => item.timestamp.toString(),
453
+ style: styles.messageList,
454
+ onScrollToIndexFailed: handleScrollToIndexFailed
455
+ }), /*#__PURE__*/_jsx(View, {
456
+ style: styles.inputContainer,
457
+ children: selectedFile ? /*#__PURE__*/_jsxs(View, {
458
+ style: styles.uploadPreviewContainer,
459
+ children: [/*#__PURE__*/_jsxs(View, {
460
+ style: styles.fileInfoContainer,
461
+ children: [/*#__PURE__*/_jsx(Text, {
462
+ style: {
463
+ fontSize: 20
464
+ },
465
+ children: "\uD83D\uDCCE"
466
+ }), /*#__PURE__*/_jsx(Text, {
467
+ style: styles.fileNameText,
468
+ numberOfLines: 1,
469
+ children: selectedFile.name
470
+ })]
471
+ }), /*#__PURE__*/_jsxs(View, {
472
+ style: styles.buttonRow,
473
+ children: [/*#__PURE__*/_jsx(TouchableOpacity, {
474
+ style: [styles.actionButton, styles.uploadButton],
475
+ onPress: handleConfirmUpload,
476
+ children: /*#__PURE__*/_jsx(Text, {
477
+ style: styles.uploadButtonText,
478
+ children: "Upload a file"
479
+ })
480
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
481
+ style: [styles.actionButton, styles.cancelButton],
482
+ onPress: handleCancelUpload,
483
+ children: /*#__PURE__*/_jsx(Text, {
484
+ style: styles.cancelButtonText,
485
+ children: "Cancel"
486
+ })
487
+ })]
488
+ })]
489
+ }) : /*#__PURE__*/_jsxs(View, {
490
+ style: styles.normalInputContainer,
491
+ children: [/*#__PURE__*/_jsx(TouchableOpacity, {
492
+ onPress: handleSelectFile,
493
+ style: styles.attachmentButton,
494
+ children: /*#__PURE__*/_jsxs(View, {
495
+ style: styles.plusIconContainer,
496
+ children: [/*#__PURE__*/_jsx(View, {
497
+ style: [styles.plusIconBar, styles.plusIconBarHorizontal]
498
+ }), /*#__PURE__*/_jsx(View, {
499
+ style: [styles.plusIconBar, styles.plusIconBarVertical]
500
+ })]
501
+ })
502
+ }), /*#__PURE__*/_jsx(TextInput, {
503
+ style: styles.input,
504
+ value: inputText,
505
+ onChangeText: setInputText,
506
+ placeholder: "Enter a message...",
507
+ placeholderTextColor: "#9E9E9E"
508
+ }), /*#__PURE__*/_jsx(TouchableOpacity, {
509
+ onPress: handleSendText,
510
+ style: styles.sendButton,
511
+ children: /*#__PURE__*/_jsx(SendIcon, {
512
+ size: 22,
513
+ color: styleSettings?.styles?.styleTextColor || '#FFFFFF'
514
+ })
515
+ })]
516
+ })
517
+ })]
518
+ })
519
+ })]
520
+ });
521
+ };
522
+ const getDynamicStyles = (settingStyle = {}) => {
523
+ const screenWidth = Dimensions.get('window').width;
524
+ // const screenHeight = Dimensions.get('window').height;
525
+ return StyleSheet.create({
526
+ safeArea: {
527
+ flex: 1,
528
+ backgroundColor: '#FFFFFF'
529
+ // padding: 12,
530
+ },
531
+ container: {
532
+ flex: 1,
533
+ backgroundColor: '#F4F7FC'
534
+ },
535
+ centered: {
536
+ flex: 1,
537
+ justifyContent: 'center',
538
+ alignItems: 'center'
539
+ },
540
+ header: {
541
+ flexDirection: 'row',
542
+ justifyContent: 'space-between',
543
+ alignItems: 'center',
544
+ backgroundColor: settingStyle?.styleHeadColor || '#3761DF',
545
+ paddingVertical: 10,
546
+ paddingHorizontal: 15,
547
+ paddingTop: Platform.OS === 'android' ? 15 : 15
548
+ },
549
+ headerProfile: {
550
+ flexDirection: 'row',
551
+ alignItems: 'center'
552
+ },
553
+ headerAvatar: {
554
+ width: 40,
555
+ height: 40,
556
+ borderRadius: 20,
557
+ marginRight: 10
558
+ },
559
+ headerTitle: {
560
+ fontSize: 18,
561
+ fontWeight: 'bold',
562
+ color: settingStyle?.styleTextColor || '#FFFFFF'
563
+ },
564
+ closeButtonText: {
565
+ fontSize: 20,
566
+ color: settingStyle?.styleTextColor || '#FFFFFF',
567
+ fontWeight: 'bold'
568
+ },
569
+ messageList: {
570
+ flex: 1,
571
+ paddingHorizontal: 10
572
+ },
573
+ messageRow: {
574
+ flexDirection: 'row',
575
+ alignItems: 'flex-end',
576
+ marginVertical: 5
577
+ },
578
+ agentRow: {
579
+ justifyContent: 'flex-start'
580
+ },
581
+ userRow: {
582
+ justifyContent: 'flex-end'
583
+ },
584
+ messageContainer: {
585
+ maxWidth: '80%',
586
+ alignItems: 'flex-start',
587
+ flexDirection: 'row'
588
+ // marginBottom: 10,
589
+ },
590
+ messageAgentContainer: {
591
+ maxWidth: '80%',
592
+ alignItems: 'flex-start',
593
+ flexDirection: 'row-reverse',
594
+ marginVertical: 0
595
+ },
596
+ avatar: {
597
+ width: 36,
598
+ height: 36,
599
+ borderRadius: 20,
600
+ marginRight: 8
601
+ },
602
+ messageBubble: {
603
+ paddingHorizontal: 8,
604
+ paddingVertical: 8,
605
+ borderRadius: 12
606
+ // width: '80%',
607
+ },
608
+ agentBubble: {
609
+ backgroundColor: settingStyle.styleAgentColor || '#E0E0E0'
610
+ },
611
+ userBubble: {
612
+ backgroundColor: settingStyle.styleCustomerColor || '#E0E0E0'
613
+ },
614
+ customerChatText: {
615
+ color: settingStyle.styleCustomerTextColor || '#000000'
616
+ },
617
+ agentChatText: {
618
+ color: settingStyle.styleAgentTextColor || '#000000'
619
+ },
620
+ fileLink: {
621
+ textDecorationLine: 'underline',
622
+ elevation: 4,
623
+ width: screenWidth * 0.6
624
+ },
625
+ timestampText: {
626
+ fontSize: 12,
627
+ color: '#888',
628
+ marginTop: 5,
629
+ alignSelf: 'flex-end',
630
+ marginHorizontal: 8
631
+ },
632
+ datePartition: {
633
+ alignSelf: 'center',
634
+ backgroundColor: 'rgb(244, 243, 244)',
635
+ borderRadius: 16,
636
+ paddingVertical: 5,
637
+ paddingHorizontal: 12,
638
+ marginVertical: 15
639
+ },
640
+ datePartitionText: {
641
+ color: 'rgb(130, 135, 143)',
642
+ fontSize: 12,
643
+ fontWeight: '600'
644
+ },
645
+ inputContainer: {
646
+ paddingVertical: 10,
647
+ paddingHorizontal: 15,
648
+ borderTopWidth: 1,
649
+ borderTopColor: '#E0E0E0',
650
+ backgroundColor: 'white'
651
+ },
652
+ normalInputContainer: {
653
+ flexDirection: 'row',
654
+ alignItems: 'center'
655
+ },
656
+ input: {
657
+ flex: 1,
658
+ height: 42,
659
+ backgroundColor: '#F0F0F0',
660
+ borderRadius: 22.5,
661
+ paddingHorizontal: 15,
662
+ fontSize: 16,
663
+ marginHorizontal: 10
664
+ },
665
+ attachmentButton: {
666
+ padding: 5
667
+ },
668
+ sendButton: {
669
+ paddingRight: 3,
670
+ paddingTop: 2,
671
+ width: 42,
672
+ height: 42,
673
+ borderRadius: 24,
674
+ backgroundColor: settingStyle?.styleHeadColor || '#3761DF',
675
+ justifyContent: 'center',
676
+ alignItems: 'center'
677
+ },
678
+ uploadPreviewContainer: {
679
+ alignItems: 'center'
680
+ },
681
+ fileInfoContainer: {
682
+ flexDirection: 'row',
683
+ alignItems: 'center',
684
+ backgroundColor: '#F0F0F0',
685
+ borderRadius: 22.5,
686
+ paddingHorizontal: 15,
687
+ paddingVertical: 12,
688
+ width: '100%'
689
+ },
690
+ fileNameText: {
691
+ flex: 1,
692
+ marginLeft: 10,
693
+ fontSize: 16,
694
+ color: '#333'
695
+ },
696
+ buttonRow: {
697
+ flexDirection: 'row',
698
+ justifyContent: 'center',
699
+ marginTop: 10,
700
+ width: '100%'
701
+ },
702
+ actionButton: {
703
+ flex: 1,
704
+ paddingVertical: 10,
705
+ borderRadius: 8,
706
+ alignItems: 'center',
707
+ marginHorizontal: 5
708
+ },
709
+ uploadButton: {
710
+ backgroundColor: settingStyle?.styleHeadColor || '#3761DF'
711
+ },
712
+ uploadButtonText: {
713
+ color: settingStyle?.styleTextColor || '#FFFFFF',
714
+ fontWeight: 'bold',
715
+ fontSize: 16
716
+ },
717
+ cancelButton: {
718
+ backgroundColor: '#E0E0E0'
719
+ },
720
+ cancelButtonText: {
721
+ color: '#333',
722
+ fontWeight: 'bold',
723
+ fontSize: 16
724
+ },
725
+ plusIconContainer: {
726
+ width: 24,
727
+ height: 24,
728
+ justifyContent: 'center',
729
+ alignItems: 'center'
730
+ },
731
+ plusIconBar: {
732
+ position: 'absolute',
733
+ backgroundColor: '#8A8A8A'
734
+ },
735
+ plusIconBarHorizontal: {
736
+ width: 20,
737
+ height: 2,
738
+ borderRadius: 1
739
+ },
740
+ plusIconBarVertical: {
741
+ width: 2,
742
+ height: 20,
743
+ borderRadius: 1
744
+ },
745
+ imageMessage: {
746
+ width: 200,
747
+ height: 200,
748
+ borderRadius: 10
749
+ },
750
+ formContainer: {
751
+ // flex: 1,
752
+ backgroundColor: hexToRgba(settingStyle?.styleHeadColor, '0.5') || hexToRgba('#3761DF', '0.5'),
753
+ // opacity: 0.5,
754
+ padding: 14,
755
+ margin: 14,
756
+ borderRadius: 6
757
+ },
758
+ formWelcomeText: {
759
+ fontSize: 16,
760
+ color: '#2D3335',
761
+ marginBottom: 20,
762
+ borderRadius: 10
763
+ },
764
+ formInputContainer: {
765
+ marginBottom: 15
766
+ },
767
+ formLabel: {
768
+ fontSize: 14,
769
+ color: '#2D3335',
770
+ marginBottom: 5,
771
+ fontWeight: '600'
772
+ },
773
+ formInput: {
774
+ borderWidth: 1,
775
+ borderColor: '#ccc',
776
+ backgroundColor: '#fff',
777
+ color: '#2D3335',
778
+ borderRadius: 8,
779
+ padding: 12,
780
+ fontSize: 16
781
+ },
782
+ consentContainer: {
783
+ flexDirection: 'row',
784
+ alignItems: 'center',
785
+ marginHorizontal: 14
786
+ },
787
+ consentText: {
788
+ marginLeft: 2,
789
+ fontSize: 14,
790
+ color: '#333'
791
+ },
792
+ consentLink: {
793
+ color: '#3761DF',
794
+ textDecorationLine: 'underline'
795
+ },
796
+ checkboxChecked: {
797
+ width: 14,
798
+ height: 14,
799
+ backgroundColor: settingStyle?.styleHeadColor || '#3761DF'
800
+ },
801
+ formFooter: {
802
+ flex: 1,
803
+ justifyContent: 'flex-end',
804
+ padding: 16,
805
+ backgroundColor: 'white'
806
+ },
807
+ startButton: {
808
+ padding: 12,
809
+ borderRadius: 12,
810
+ alignItems: 'center'
811
+ },
812
+ startButtonText: {
813
+ color: 'white',
814
+ fontSize: 16
815
+ // fontWeight: 'bold',
816
+ },
817
+ checkboxBase: {
818
+ width: 20,
819
+ height: 20,
820
+ borderWidth: 2,
821
+ borderColor: '#3761DF',
822
+ borderRadius: 4,
823
+ alignItems: 'center',
824
+ justifyContent: 'center',
825
+ marginRight: 3
826
+ },
827
+ checkmark: {
828
+ color: '#fff',
829
+ fontSize: 12,
830
+ fontWeight: 'bold'
831
+ }
832
+ });
833
+ };
834
+ //# sourceMappingURL=ChatScreen.js.map