react-native-chatbot-ai 0.1.0 → 0.1.2

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 (144) hide show
  1. package/lib/module/assets/svgIcon/IconChatArrow.js +0 -1
  2. package/lib/module/assets/svgIcon/IconChatArrow.js.map +1 -1
  3. package/lib/module/assets/svgIcon/IconPdf.js +27 -0
  4. package/lib/module/assets/svgIcon/IconPdf.js.map +1 -0
  5. package/lib/module/assets/svgIcon/IconThinkingStep.js +0 -1
  6. package/lib/module/assets/svgIcon/IconThinkingStep.js.map +1 -1
  7. package/lib/module/components/chat/ChatEmpty.js +6 -1
  8. package/lib/module/components/chat/ChatEmpty.js.map +1 -1
  9. package/lib/module/components/chat/ChatMessageList.js +33 -6
  10. package/lib/module/components/chat/ChatMessageList.js.map +1 -1
  11. package/lib/module/components/chat/footer/index.js +328 -0
  12. package/lib/module/components/chat/footer/index.js.map +1 -0
  13. package/lib/module/components/chat/footer/item/UploadFileItem.js +163 -0
  14. package/lib/module/components/chat/footer/item/UploadFileItem.js.map +1 -0
  15. package/lib/module/components/chat/footer/item/UploadImageItem.js +94 -0
  16. package/lib/module/components/chat/footer/item/UploadImageItem.js.map +1 -0
  17. package/lib/module/components/chat/index.js +1 -1
  18. package/lib/module/components/chat/index.js.map +1 -1
  19. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js +114 -32
  20. package/lib/module/components/chat/item/ChatAIAnswerMessageItem.js.map +1 -1
  21. package/lib/module/components/chat/item/ChatAIThinkingMessageItem.js +18 -7
  22. package/lib/module/components/chat/item/ChatAIThinkingMessageItem.js.map +1 -1
  23. package/lib/module/components/chat/item/ChatUserMessageItem.js +122 -15
  24. package/lib/module/components/chat/item/ChatUserMessageItem.js.map +1 -1
  25. package/lib/module/components/portal/Toast.js +193 -0
  26. package/lib/module/components/portal/Toast.js.map +1 -0
  27. package/lib/module/components/portal/index.js +15 -0
  28. package/lib/module/components/portal/index.js.map +1 -0
  29. package/lib/module/constants/events.js +2 -1
  30. package/lib/module/constants/events.js.map +1 -1
  31. package/lib/module/constants/index.js +9 -0
  32. package/lib/module/constants/index.js.map +1 -0
  33. package/lib/module/context/ChatContext.js +8 -5
  34. package/lib/module/context/ChatContext.js.map +1 -1
  35. package/lib/module/hooks/message/useMessage.js +0 -1
  36. package/lib/module/hooks/message/useMessage.js.map +1 -1
  37. package/lib/module/hooks/message/useSendMessage.js +3 -3
  38. package/lib/module/hooks/message/useSendMessage.js.map +1 -1
  39. package/lib/module/hooks/upload/useFileUpload.js +94 -0
  40. package/lib/module/hooks/upload/useFileUpload.js.map +1 -0
  41. package/lib/module/hooks/upload/useImageUpload.js +92 -0
  42. package/lib/module/hooks/upload/useImageUpload.js.map +1 -0
  43. package/lib/module/hooks/useAndroidBackHandler.js +20 -0
  44. package/lib/module/hooks/useAndroidBackHandler.js.map +1 -0
  45. package/lib/module/services/endpoints.js +3 -0
  46. package/lib/module/services/endpoints.js.map +1 -1
  47. package/lib/module/types/index.js +1 -0
  48. package/lib/module/types/index.js.map +1 -1
  49. package/lib/module/types/ui.js +4 -0
  50. package/lib/module/types/ui.js.map +1 -0
  51. package/lib/module/utils/common.js +31 -0
  52. package/lib/module/utils/common.js.map +1 -0
  53. package/lib/module/utils/device.js +137 -0
  54. package/lib/module/utils/device.js.map +1 -0
  55. package/lib/module/utils/ui.js +28 -0
  56. package/lib/module/utils/ui.js.map +1 -0
  57. package/lib/typescript/src/assets/icons/index.d.ts.map +1 -1
  58. package/lib/typescript/src/assets/svgIcon/IconChatArrow.d.ts.map +1 -1
  59. package/lib/typescript/src/assets/svgIcon/IconPdf.d.ts +7 -0
  60. package/lib/typescript/src/assets/svgIcon/IconPdf.d.ts.map +1 -0
  61. package/lib/typescript/src/assets/svgIcon/IconThinkingStep.d.ts.map +1 -1
  62. package/lib/typescript/src/components/chat/ChatEmpty.d.ts.map +1 -1
  63. package/lib/typescript/src/components/chat/ChatMessageList.d.ts.map +1 -1
  64. package/lib/typescript/src/components/chat/footer/index.d.ts +16 -0
  65. package/lib/typescript/src/components/chat/footer/index.d.ts.map +1 -0
  66. package/lib/typescript/src/components/chat/footer/item/UploadFileItem.d.ts +9 -0
  67. package/lib/typescript/src/components/chat/footer/item/UploadFileItem.d.ts.map +1 -0
  68. package/lib/typescript/src/components/chat/footer/item/UploadImageItem.d.ts +9 -0
  69. package/lib/typescript/src/components/chat/footer/item/UploadImageItem.d.ts.map +1 -0
  70. package/lib/typescript/src/components/chat/item/ChatAIAnswerMessageItem.d.ts +9 -0
  71. package/lib/typescript/src/components/chat/item/ChatAIAnswerMessageItem.d.ts.map +1 -1
  72. package/lib/typescript/src/components/chat/item/ChatAIThinkingMessageItem.d.ts.map +1 -1
  73. package/lib/typescript/src/components/chat/item/ChatUserMessageItem.d.ts.map +1 -1
  74. package/lib/typescript/src/components/portal/Toast.d.ts +4 -0
  75. package/lib/typescript/src/components/portal/Toast.d.ts.map +1 -0
  76. package/lib/typescript/src/components/portal/index.d.ts +3 -0
  77. package/lib/typescript/src/components/portal/index.d.ts.map +1 -0
  78. package/lib/typescript/src/constants/events.d.ts +1 -0
  79. package/lib/typescript/src/constants/events.d.ts.map +1 -1
  80. package/lib/typescript/src/constants/index.d.ts +6 -0
  81. package/lib/typescript/src/constants/index.d.ts.map +1 -0
  82. package/lib/typescript/src/context/ChatContext.d.ts.map +1 -1
  83. package/lib/typescript/src/hooks/message/useMessage.d.ts.map +1 -1
  84. package/lib/typescript/src/hooks/message/useSendMessage.d.ts +2 -1
  85. package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
  86. package/lib/typescript/src/hooks/upload/useFileUpload.d.ts +15 -0
  87. package/lib/typescript/src/hooks/upload/useFileUpload.d.ts.map +1 -0
  88. package/lib/typescript/src/hooks/upload/useImageUpload.d.ts +15 -0
  89. package/lib/typescript/src/hooks/upload/useImageUpload.d.ts.map +1 -0
  90. package/lib/typescript/src/hooks/useAndroidBackHandler.d.ts +4 -0
  91. package/lib/typescript/src/hooks/useAndroidBackHandler.d.ts.map +1 -0
  92. package/lib/typescript/src/services/endpoints.d.ts +3 -0
  93. package/lib/typescript/src/services/endpoints.d.ts.map +1 -1
  94. package/lib/typescript/src/types/chat.d.ts +6 -0
  95. package/lib/typescript/src/types/chat.d.ts.map +1 -1
  96. package/lib/typescript/src/types/dto.d.ts +10 -1
  97. package/lib/typescript/src/types/dto.d.ts.map +1 -1
  98. package/lib/typescript/src/types/index.d.ts +1 -0
  99. package/lib/typescript/src/types/index.d.ts.map +1 -1
  100. package/lib/typescript/src/types/ui.d.ts +7 -0
  101. package/lib/typescript/src/types/ui.d.ts.map +1 -0
  102. package/lib/typescript/src/utils/common.d.ts +10 -0
  103. package/lib/typescript/src/utils/common.d.ts.map +1 -0
  104. package/lib/typescript/src/utils/device.d.ts +11 -0
  105. package/lib/typescript/src/utils/device.d.ts.map +1 -0
  106. package/lib/typescript/src/utils/ui.d.ts +12 -0
  107. package/lib/typescript/src/utils/ui.d.ts.map +1 -0
  108. package/package.json +11 -6
  109. package/src/assets/icons/index.ts +1 -1
  110. package/src/assets/svgIcon/IconChatArrow.tsx +1 -7
  111. package/src/assets/svgIcon/IconPdf.tsx +26 -0
  112. package/src/assets/svgIcon/IconThinkingStep.tsx +1 -7
  113. package/src/components/chat/ChatEmpty.tsx +5 -2
  114. package/src/components/chat/ChatMessageList.tsx +39 -5
  115. package/src/components/chat/footer/index.tsx +410 -0
  116. package/src/components/chat/footer/item/UploadFileItem.tsx +181 -0
  117. package/src/components/chat/footer/item/UploadImageItem.tsx +91 -0
  118. package/src/components/chat/index.tsx +1 -1
  119. package/src/components/chat/item/ChatAIAnswerMessageItem.tsx +152 -54
  120. package/src/components/chat/item/ChatAIThinkingMessageItem.tsx +37 -31
  121. package/src/components/chat/item/ChatUserMessageItem.tsx +145 -13
  122. package/src/components/portal/Toast.tsx +315 -0
  123. package/src/components/portal/index.tsx +13 -0
  124. package/src/constants/events.ts +1 -0
  125. package/src/constants/index.ts +9 -0
  126. package/src/context/ChatContext.tsx +6 -2
  127. package/src/hooks/message/useMessage.ts +0 -1
  128. package/src/hooks/message/useSendMessage.ts +4 -4
  129. package/src/hooks/upload/useFileUpload.ts +126 -0
  130. package/src/hooks/upload/useImageUpload.ts +123 -0
  131. package/src/hooks/useAndroidBackHandler.ts +29 -0
  132. package/src/services/endpoints.ts +3 -0
  133. package/src/types/chat.ts +2 -0
  134. package/src/types/dto.ts +16 -1
  135. package/src/types/index.ts +1 -0
  136. package/src/types/ui.ts +12 -0
  137. package/src/utils/common.ts +40 -0
  138. package/src/utils/device.ts +170 -0
  139. package/src/utils/ui.tsx +32 -0
  140. package/lib/module/components/chat/ChatFooter.js +0 -91
  141. package/lib/module/components/chat/ChatFooter.js.map +0 -1
  142. package/lib/typescript/src/components/chat/ChatFooter.d.ts +0 -3
  143. package/lib/typescript/src/components/chat/ChatFooter.d.ts.map +0 -1
  144. package/src/components/chat/ChatFooter.tsx +0 -99
package/src/types/chat.ts CHANGED
@@ -5,12 +5,14 @@ export interface ChatContextType {
5
5
  apiAddress: string;
6
6
  userId: string;
7
7
  cartButton?: JSX.Element;
8
+ openImageViewer?: (images: { url: string }[], index: number) => void;
8
9
  }
9
10
 
10
11
  export interface ChatProviderProps {
11
12
  apiAddress: string;
12
13
  userId: string;
13
14
  cartButton?: JSX.Element;
15
+ openImageViewer?: (images: { url: string }[], index: number) => void;
14
16
  }
15
17
 
16
18
  export interface SessionStore {
package/src/types/dto.ts CHANGED
@@ -11,6 +11,21 @@ export interface SuggetionResponse {
11
11
  suggestions: ISuggestionItem[];
12
12
  }
13
13
 
14
+ export interface IAttachment {
15
+ type: 'image' | 'file';
16
+ source_type: 'url';
17
+ data: string;
18
+ name?: string;
19
+ size?: number;
20
+ loading?: boolean;
21
+ mime_type:
22
+ | 'image/jpeg'
23
+ | 'image/png'
24
+ | 'image/webp'
25
+ | 'image/jpg'
26
+ | 'application/pdf';
27
+ }
28
+
14
29
  export interface IMessageItem {
15
30
  id: string;
16
31
  content: string;
@@ -22,7 +37,7 @@ export interface IMessageItem {
22
37
  metadata: Record<string, any>;
23
38
  created_at: string;
24
39
  modified_at: string;
25
- attachments: any[];
40
+ attachments: IAttachment[];
26
41
  }
27
42
 
28
43
  export interface SessionDetailResponse {
@@ -1,3 +1,4 @@
1
1
  export * from './common';
2
2
  export * from './dto';
3
3
  export * from './chat';
4
+ export * from './ui';
@@ -0,0 +1,12 @@
1
+ // @ts-ignore
2
+ import { KToastBarProps } from '@droppii/libs';
3
+ // @ts-ignore
4
+ import { StyleProp, ViewStyle } from 'react-native';
5
+
6
+ export interface WithToastProps {
7
+ open: (
8
+ // @ts-ignore
9
+ payload: KToastBarProps & { contentContainerStyle?: StyleProp<ViewStyle> }
10
+ ) => void;
11
+ dismiss: () => void;
12
+ }
@@ -0,0 +1,40 @@
1
+ export const isSameFile = (a: any, b: any) =>
2
+ a.filename === b.filename && a.size === b.size && a.mime === b.mime;
3
+
4
+ export const formatFileSize = (bytes: number): string => {
5
+ if (bytes === 0) return '0 B';
6
+
7
+ const k = 1024;
8
+ const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
9
+
10
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
11
+ const size = parseFloat((bytes / Math.pow(k, i)).toFixed(2));
12
+
13
+ return `${size} ${sizes[i]}`;
14
+ };
15
+
16
+ interface ShortenOptions {
17
+ maxLength?: number;
18
+ keepStart?: number;
19
+ keepEnd?: number;
20
+ }
21
+
22
+ export const shortenFileName = (name: string, options: ShortenOptions = {}) => {
23
+ const { maxLength = 30, keepStart = 8, keepEnd = 2 } = options;
24
+
25
+ if (name.length <= maxLength) return name;
26
+
27
+ const dotIndex = name.lastIndexOf('.');
28
+ const ext = dotIndex !== -1 ? name.slice(dotIndex) : '';
29
+ const base = dotIndex !== -1 ? name.slice(0, dotIndex) : name;
30
+
31
+ // Tính toán độ dài phần đầu & cuối
32
+ const available = maxLength - ext.length - 3; // trừ "...”
33
+ const startLen = keepStart ?? Math.floor(available / 2);
34
+ const endLen = keepEnd ?? Math.floor(available / 2);
35
+
36
+ const start = base.slice(0, startLen);
37
+ const end = base.slice(-endLen);
38
+
39
+ return `${start}...${end}${ext}`;
40
+ };
@@ -0,0 +1,170 @@
1
+ import { DocumentPickerOptions, pick } from '@react-native-documents/picker';
2
+ import UIUtils from '../utils/ui';
3
+ import { PermissionsAndroid, Platform } from 'react-native';
4
+ import {
5
+ Image,
6
+ openCamera,
7
+ openPicker,
8
+ Options,
9
+ PossibleArray,
10
+ } from 'react-native-image-crop-picker';
11
+ import { check, PERMISSIONS, request } from 'react-native-permissions';
12
+
13
+ type MediaType<O> = O extends { mediaType: 'photo' } ? Image : never;
14
+
15
+ const READ_MEDIA_IMAGES = 'android.permission.READ_MEDIA_IMAGES';
16
+
17
+ const pickerOptions = {
18
+ writeTempFile: true,
19
+ mediaType: 'photo',
20
+ compressImageQuality: 0.8,
21
+ width: 1280,
22
+ height: 1280,
23
+ compressImageMaxHeight: 1280,
24
+ compressImageMaxWidth: 1280,
25
+ cropping: false,
26
+ cropperCircleOverlay: true,
27
+ waitAnimationEnd: true,
28
+ includeExif: false,
29
+ forceJpg: true,
30
+ cropperChooseText: 'Hoàn tất',
31
+ cropperCancelText: 'Hủy',
32
+ } as Options;
33
+
34
+ const requestPermission = async (
35
+ perm: any,
36
+ requestMessage?: string,
37
+ disableToast = false
38
+ ) => {
39
+ try {
40
+ //handle android function check can't return status code blocked
41
+ let granted =
42
+ Platform.OS === 'android' ? await request(perm) : await check(perm);
43
+ if (granted === 'unavailable') {
44
+ UIUtils.toast.open({
45
+ title: 'Tính năng hiện tại không khả dụng, vui lòng thử lại sau',
46
+ });
47
+ return false;
48
+ }
49
+ if (granted === 'granted' || granted === 'limited') {
50
+ return true;
51
+ }
52
+ if (granted === 'denied' && Platform.OS === 'ios') {
53
+ const result = await request(perm);
54
+ if (result === 'granted' || result === 'limited') {
55
+ return true;
56
+ }
57
+ }
58
+ if (requestMessage && granted === 'blocked') {
59
+ UIUtils.toast.open({
60
+ title: requestMessage,
61
+ });
62
+ }
63
+
64
+ return false;
65
+ } catch (err) {
66
+ if (!disableToast) {
67
+ UIUtils.toast.open({
68
+ title: 'Có lỗi xảy ra, vui lòng thử lại',
69
+ });
70
+ }
71
+ return false;
72
+ }
73
+ };
74
+ const requestReadPhotoPermission = async (disableToast = false) => {
75
+ const perm = Platform.select({
76
+ ios: PERMISSIONS.IOS.PHOTO_LIBRARY,
77
+ default:
78
+ (Platform.Version as number) >= 33
79
+ ? READ_MEDIA_IMAGES
80
+ : PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
81
+ });
82
+ return requestPermission(
83
+ perm as any,
84
+ 'Vui lòng cấp quyền truy cập vào "Thư viện ảnh" của bạn trước khi sử dụng tính năng này',
85
+ disableToast
86
+ );
87
+ };
88
+
89
+ const requestCameraPermission = async () => {
90
+ const perm = Platform.select({
91
+ ios: PERMISSIONS.IOS.CAMERA,
92
+ default: PERMISSIONS.ANDROID.CAMERA,
93
+ });
94
+ return requestPermission(perm, 'Droppii cần truy cập vào "Máy ảnh" của bạn');
95
+ };
96
+
97
+ export const openImagePicker = (
98
+ options?: Options
99
+ ): Promise<PossibleArray<Options, MediaType<Options>> | undefined> => {
100
+ return new Promise(async (resolve) => {
101
+ try {
102
+ const isGranted = await requestReadPhotoPermission();
103
+ if (!isGranted) {
104
+ throw new Error('No permission');
105
+ }
106
+ const value = await openPicker({
107
+ ...pickerOptions,
108
+ ...options,
109
+ });
110
+ resolve(value);
111
+ } catch (error) {
112
+ resolve(undefined);
113
+ }
114
+ });
115
+ };
116
+
117
+ export const openImageMultiplePicker = (
118
+ options?: Options
119
+ ): Promise<PossibleArray<Options, MediaType<Options>[]> | undefined> => {
120
+ return new Promise(async (resolve) => {
121
+ try {
122
+ const isGranted = await requestReadPhotoPermission();
123
+ if (!isGranted) {
124
+ throw new Error('No permission');
125
+ }
126
+ const value = await openPicker({
127
+ ...pickerOptions,
128
+ ...options,
129
+ multiple: true,
130
+ });
131
+ resolve(value);
132
+ } catch (error) {
133
+ resolve([]);
134
+ }
135
+ });
136
+ };
137
+
138
+ export const openCameraPicker = (
139
+ options?: Options
140
+ ): Promise<PossibleArray<Options, MediaType<Options>> | undefined> => {
141
+ return new Promise(async (resolve) => {
142
+ try {
143
+ const isGranted = await requestCameraPermission();
144
+ if (!isGranted) {
145
+ throw new Error('No permission');
146
+ }
147
+
148
+ const value = await openCamera({
149
+ ...pickerOptions,
150
+ ...options,
151
+ });
152
+ resolve(value);
153
+ } catch (error) {
154
+ resolve(undefined);
155
+ }
156
+ });
157
+ };
158
+
159
+ export const openDocumentPicker = async (options?: DocumentPickerOptions) => {
160
+ try {
161
+ const [result] = await pick({
162
+ mode: 'open',
163
+ ...options,
164
+ });
165
+ console.log(result);
166
+ return result;
167
+ } catch (err) {
168
+ return undefined;
169
+ }
170
+ };
@@ -0,0 +1,32 @@
1
+ // @ts-ignore
2
+ import { StyleProp, ViewStyle } from 'react-native';
3
+ import { toastRef } from '../constants';
4
+ // @ts-ignore
5
+ import type { KToastBarProps } from '@droppii/libs';
6
+
7
+ class UIUtils {
8
+ toast = {
9
+ open: (
10
+ // @ts-ignore
11
+ params: KToastBarProps & { contentContainerStyle?: StyleProp<ViewStyle> }
12
+ ) => {
13
+ toastRef.current?.open(params);
14
+ },
15
+ dismiss: () => {
16
+ toastRef.current?.dismiss();
17
+ },
18
+ showError: (error: any, withToast = true) => {
19
+ const msg =
20
+ error?.message ||
21
+ error?.response?.message ||
22
+ error?.data?.message ||
23
+ error?.response?.data?.message ||
24
+ 'Có lỗi xảy ra, vui lòng thử lại';
25
+ withToast &&
26
+ toastRef.current?.open({ title: msg, theme: 'danger', stretch: true });
27
+ return msg;
28
+ },
29
+ };
30
+ }
31
+
32
+ export default new UIUtils();
@@ -1,91 +0,0 @@
1
- "use strict";
2
-
3
- import { KButton, KColors, KContainer, KImage, KInput, KSpacingValue } from '@droppii/libs';
4
- import { useCallback, useState } from 'react';
5
- import { StyleSheet } from 'react-native';
6
- import debounce from 'lodash/debounce';
7
- import { useSendMessage } from "../../hooks/message/useSendMessage.js";
8
- import useStreamMessageStore from "../../store/streamMessage.js";
9
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
10
- const ChatFooter = () => {
11
- const {
12
- onSendMessage,
13
- stopStream
14
- } = useSendMessage();
15
- const [message, setMessage] = useState('');
16
- const isStreaming = useStreamMessageStore(state => state.isStreaming);
17
- const debouncedMessage = debounce(message => {
18
- setMessage(message);
19
- }, 200);
20
- const onPressSend = useCallback(() => {
21
- if (isStreaming) {
22
- stopStream();
23
- return;
24
- }
25
- onSendMessage(message?.trim());
26
- setMessage('');
27
- }, [message, isStreaming, onSendMessage, stopStream]);
28
- return /*#__PURE__*/_jsxs(KContainer.View, {
29
- style: styles.container,
30
- children: [/*#__PURE__*/_jsx(KInput.TextArea, {
31
- paddingV: '0.25rem',
32
- paddingH: '0.25rem',
33
- placeholder: "B\u1EA1n mu\u1ED1n h\u1ECFi g\xEC h\xF4m nay?",
34
- clearButtonMode: "hidden",
35
- onChangeText: debouncedMessage,
36
- value: message,
37
- multiline: true,
38
- style: styles.input,
39
- blurOnSubmit: false,
40
- textAlignVertical: "top"
41
- }), /*#__PURE__*/_jsxs(KContainer.View, {
42
- style: styles.actions,
43
- children: [/*#__PURE__*/_jsx(KImage.VectorIcons, {
44
- name: "image-o",
45
- size: 24,
46
- color: KColors.gray.dark
47
- }), /*#__PURE__*/_jsx(KImage.VectorIcons, {
48
- name: "paperclip-o",
49
- size: 24,
50
- color: KColors.gray.dark
51
- }), /*#__PURE__*/_jsx(KContainer.View, {
52
- flex: true
53
- }), /*#__PURE__*/_jsx(KButton.Solid, {
54
- kind: "primary",
55
- icon: {
56
- vectorName: isStreaming ? 'square-b' : 'send-b',
57
- size: 20,
58
- tintColor: KColors.white
59
- },
60
- onPress: onPressSend,
61
- br: "round",
62
- disabled: !isStreaming && message.trim() === ''
63
- })]
64
- })]
65
- });
66
- };
67
- export default ChatFooter;
68
- const styles = StyleSheet.create({
69
- container: {
70
- paddingHorizontal: KSpacingValue['0.75rem'],
71
- paddingVertical: KSpacingValue['0.5rem'],
72
- gap: KSpacingValue['0.5rem'],
73
- borderWidth: 1,
74
- borderColor: KColors.hexToRgba(KColors.black, 0.15),
75
- borderBottomWidth: 0,
76
- borderTopLeftRadius: KSpacingValue['1.25rem'],
77
- borderTopRightRadius: KSpacingValue['1.25rem']
78
- },
79
- actions: {
80
- flexDirection: 'row',
81
- alignItems: 'center',
82
- gap: KSpacingValue['1rem']
83
- },
84
- sendButton: {
85
- alignSelf: 'flex-end'
86
- },
87
- input: {
88
- maxHeight: 100
89
- }
90
- });
91
- //# sourceMappingURL=ChatFooter.js.map
@@ -1 +0,0 @@
1
- {"version":3,"names":["KButton","KColors","KContainer","KImage","KInput","KSpacingValue","useCallback","useState","StyleSheet","debounce","useSendMessage","useStreamMessageStore","jsx","_jsx","jsxs","_jsxs","ChatFooter","onSendMessage","stopStream","message","setMessage","isStreaming","state","debouncedMessage","onPressSend","trim","View","style","styles","container","children","TextArea","paddingV","paddingH","placeholder","clearButtonMode","onChangeText","value","multiline","input","blurOnSubmit","textAlignVertical","actions","VectorIcons","name","size","color","gray","dark","flex","Solid","kind","icon","vectorName","tintColor","white","onPress","br","disabled","create","paddingHorizontal","paddingVertical","gap","borderWidth","borderColor","hexToRgba","black","borderBottomWidth","borderTopLeftRadius","borderTopRightRadius","flexDirection","alignItems","sendButton","alignSelf","maxHeight"],"sourceRoot":"../../../../src","sources":["components/chat/ChatFooter.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,3 +0,0 @@
1
- declare const ChatFooter: () => import("react/jsx-runtime").JSX.Element;
2
- export default ChatFooter;
3
- //# sourceMappingURL=ChatFooter.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ChatFooter.d.ts","sourceRoot":"","sources":["../../../../../src/components/chat/ChatFooter.tsx"],"names":[],"mappings":"AAcA,QAAA,MAAM,UAAU,+CA0Df,CAAC;AAEF,eAAe,UAAU,CAAC"}
@@ -1,99 +0,0 @@
1
- import {
2
- KButton,
3
- KColors,
4
- KContainer,
5
- KImage,
6
- KInput,
7
- KSpacingValue,
8
- } from '@droppii/libs';
9
- import { useCallback, useState } from 'react';
10
- import { StyleSheet } from 'react-native';
11
- import debounce from 'lodash/debounce';
12
- import { useSendMessage } from '../../hooks/message/useSendMessage';
13
- import useStreamMessageStore from '../../store/streamMessage';
14
-
15
- const ChatFooter = () => {
16
- const { onSendMessage, stopStream } = useSendMessage();
17
- const [message, setMessage] = useState('');
18
- const isStreaming = useStreamMessageStore((state) => state.isStreaming);
19
-
20
- const debouncedMessage = debounce((message: string) => {
21
- setMessage(message);
22
- }, 200);
23
-
24
- const onPressSend = useCallback(() => {
25
- if (isStreaming) {
26
- stopStream();
27
- return;
28
- }
29
- onSendMessage(message?.trim());
30
- setMessage('');
31
- }, [message, isStreaming, onSendMessage, stopStream]);
32
-
33
- return (
34
- <KContainer.View style={styles.container}>
35
- <KInput.TextArea
36
- paddingV={'0.25rem'}
37
- paddingH={'0.25rem'}
38
- placeholder="Bạn muốn hỏi gì hôm nay?"
39
- clearButtonMode="hidden"
40
- onChangeText={debouncedMessage}
41
- value={message}
42
- multiline
43
- style={styles.input}
44
- blurOnSubmit={false}
45
- textAlignVertical="top"
46
- />
47
- <KContainer.View style={styles.actions}>
48
- <KImage.VectorIcons
49
- name="image-o"
50
- size={24}
51
- color={KColors.gray.dark}
52
- />
53
- <KImage.VectorIcons
54
- name="paperclip-o"
55
- size={24}
56
- color={KColors.gray.dark}
57
- />
58
- <KContainer.View flex />
59
- <KButton.Solid
60
- kind="primary"
61
- icon={{
62
- vectorName: isStreaming ? 'square-b' : 'send-b',
63
- size: 20,
64
- tintColor: KColors.white,
65
- }}
66
- onPress={onPressSend}
67
- br="round"
68
- disabled={!isStreaming && message.trim() === ''}
69
- />
70
- </KContainer.View>
71
- </KContainer.View>
72
- );
73
- };
74
-
75
- export default ChatFooter;
76
-
77
- const styles = StyleSheet.create({
78
- container: {
79
- paddingHorizontal: KSpacingValue['0.75rem'],
80
- paddingVertical: KSpacingValue['0.5rem'],
81
- gap: KSpacingValue['0.5rem'],
82
- borderWidth: 1,
83
- borderColor: KColors.hexToRgba(KColors.black, 0.15),
84
- borderBottomWidth: 0,
85
- borderTopLeftRadius: KSpacingValue['1.25rem'],
86
- borderTopRightRadius: KSpacingValue['1.25rem'],
87
- },
88
- actions: {
89
- flexDirection: 'row',
90
- alignItems: 'center',
91
- gap: KSpacingValue['1rem'],
92
- },
93
- sendButton: {
94
- alignSelf: 'flex-end',
95
- },
96
- input: {
97
- maxHeight: 100,
98
- },
99
- });