@droppii-org/chat-mobile 0.2.11 → 0.2.13

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 (132) hide show
  1. package/lib/module/components/ThreadCard/AvatarSection.js +2 -3
  2. package/lib/module/components/ThreadCard/AvatarSection.js.map +1 -1
  3. package/lib/module/components/flows/inputButtons/index.js +77 -0
  4. package/lib/module/components/flows/inputButtons/index.js.map +1 -0
  5. package/lib/module/components/messages/linkMessage/index.js +35 -7
  6. package/lib/module/components/messages/linkMessage/index.js.map +1 -1
  7. package/lib/module/config/api-endpoints.js +1 -0
  8. package/lib/module/config/api-endpoints.js.map +1 -1
  9. package/lib/module/context/ChatDetailContext.js +57 -0
  10. package/lib/module/context/ChatDetailContext.js.map +1 -0
  11. package/lib/module/hooks/flows/useCurrentConversationFlow.js +9 -0
  12. package/lib/module/hooks/flows/useCurrentConversationFlow.js.map +1 -0
  13. package/lib/module/hooks/flows/useFlow.js +57 -0
  14. package/lib/module/hooks/flows/useFlow.js.map +1 -0
  15. package/lib/module/hooks/message/useSendMessage.js +4 -2
  16. package/lib/module/hooks/message/useSendMessage.js.map +1 -1
  17. package/lib/module/hooks/query-keys.js +4 -1
  18. package/lib/module/hooks/query-keys.js.map +1 -1
  19. package/lib/module/hooks/useConversationList.js +1 -1
  20. package/lib/module/hooks/useConversationList.js.map +1 -1
  21. package/lib/module/hooks/useLinkPreview/useFetchUrlMetadata.js +6 -4
  22. package/lib/module/hooks/useLinkPreview/useFetchUrlMetadata.js.map +1 -1
  23. package/lib/module/hooks/useLinkPreview/useLinkPreview.js +2 -2
  24. package/lib/module/hooks/useLinkPreview/useLinkPreview.js.map +1 -1
  25. package/lib/module/screens/chat-detail/ChatComposer.js +41 -3
  26. package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
  27. package/lib/module/screens/chat-detail/ChatDetail.js +65 -60
  28. package/lib/module/screens/chat-detail/ChatDetail.js.map +1 -1
  29. package/lib/module/screens/chat-detail/ChatListLegend.js +45 -10
  30. package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
  31. package/lib/module/screens/chat-detail/ChatQuickActions.js +12 -3
  32. package/lib/module/screens/chat-detail/ChatQuickActions.js.map +1 -1
  33. package/lib/module/screens/chat-detail/conversationHeader.utils.js +1 -1
  34. package/lib/module/screens/chat-detail/conversationHeader.utils.js.map +1 -1
  35. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +6 -1
  36. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
  37. package/lib/module/screens/inbox/Inbox.js +1 -3
  38. package/lib/module/screens/inbox/Inbox.js.map +1 -1
  39. package/lib/module/screens/inbox/MessagesTab.js +2 -1
  40. package/lib/module/screens/inbox/MessagesTab.js.map +1 -1
  41. package/lib/module/services/endpoints.js +4 -1
  42. package/lib/module/services/endpoints.js.map +1 -1
  43. package/lib/module/translation/resources/i18n.js +3 -1
  44. package/lib/module/translation/resources/i18n.js.map +1 -1
  45. package/lib/module/types/chat.js.map +1 -1
  46. package/lib/module/types/flows.js +17 -0
  47. package/lib/module/types/flows.js.map +1 -0
  48. package/lib/module/utils/flows.js +11 -0
  49. package/lib/module/utils/flows.js.map +1 -0
  50. package/lib/module/utils/url.js +12 -1
  51. package/lib/module/utils/url.js.map +1 -1
  52. package/lib/typescript/src/components/ThreadCard/AvatarSection.d.ts +1 -1
  53. package/lib/typescript/src/components/ThreadCard/AvatarSection.d.ts.map +1 -1
  54. package/lib/typescript/src/components/flows/inputButtons/index.d.ts +9 -0
  55. package/lib/typescript/src/components/flows/inputButtons/index.d.ts.map +1 -0
  56. package/lib/typescript/src/components/messages/linkMessage/index.d.ts +2 -1
  57. package/lib/typescript/src/components/messages/linkMessage/index.d.ts.map +1 -1
  58. package/lib/typescript/src/config/api-endpoints.d.ts +1 -0
  59. package/lib/typescript/src/config/api-endpoints.d.ts.map +1 -1
  60. package/lib/typescript/src/context/ChatDetailContext.d.ts +5 -0
  61. package/lib/typescript/src/context/ChatDetailContext.d.ts.map +1 -0
  62. package/lib/typescript/src/hooks/flows/useCurrentConversationFlow.d.ts +3 -0
  63. package/lib/typescript/src/hooks/flows/useCurrentConversationFlow.d.ts.map +1 -0
  64. package/lib/typescript/src/hooks/flows/useFlow.d.ts +4 -0
  65. package/lib/typescript/src/hooks/flows/useFlow.d.ts.map +1 -0
  66. package/lib/typescript/src/hooks/message/useSendMessage.d.ts +3 -1
  67. package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
  68. package/lib/typescript/src/hooks/query-keys.d.ts +3 -0
  69. package/lib/typescript/src/hooks/query-keys.d.ts.map +1 -1
  70. package/lib/typescript/src/hooks/useConversationList.d.ts +2 -2
  71. package/lib/typescript/src/hooks/useConversationList.d.ts.map +1 -1
  72. package/lib/typescript/src/hooks/useLinkPreview/useFetchUrlMetadata.d.ts +6 -2
  73. package/lib/typescript/src/hooks/useLinkPreview/useFetchUrlMetadata.d.ts.map +1 -1
  74. package/lib/typescript/src/hooks/useLinkPreview/useLinkPreview.d.ts +6 -1
  75. package/lib/typescript/src/hooks/useLinkPreview/useLinkPreview.d.ts.map +1 -1
  76. package/lib/typescript/src/index.d.ts +1 -0
  77. package/lib/typescript/src/index.d.ts.map +1 -1
  78. package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts +1 -1
  79. package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
  80. package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts +1 -1
  81. package/lib/typescript/src/screens/chat-detail/ChatDetail.d.ts.map +1 -1
  82. package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts +1 -1
  83. package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts.map +1 -1
  84. package/lib/typescript/src/screens/chat-detail/ChatQuickActions.d.ts.map +1 -1
  85. package/lib/typescript/src/screens/chat-detail/conversationHeader.utils.d.ts.map +1 -1
  86. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +2 -1
  87. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
  88. package/lib/typescript/src/screens/chat-detail/types.d.ts +5 -10
  89. package/lib/typescript/src/screens/chat-detail/types.d.ts.map +1 -1
  90. package/lib/typescript/src/screens/inbox/Inbox.d.ts +1 -2
  91. package/lib/typescript/src/screens/inbox/Inbox.d.ts.map +1 -1
  92. package/lib/typescript/src/screens/inbox/MessagesTab.d.ts +1 -2
  93. package/lib/typescript/src/screens/inbox/MessagesTab.d.ts.map +1 -1
  94. package/lib/typescript/src/services/endpoints.d.ts +3 -0
  95. package/lib/typescript/src/services/endpoints.d.ts.map +1 -1
  96. package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
  97. package/lib/typescript/src/types/chat.d.ts +11 -1
  98. package/lib/typescript/src/types/chat.d.ts.map +1 -1
  99. package/lib/typescript/src/types/flows.d.ts +82 -0
  100. package/lib/typescript/src/types/flows.d.ts.map +1 -0
  101. package/lib/typescript/src/utils/flows.d.ts +4 -0
  102. package/lib/typescript/src/utils/flows.d.ts.map +1 -0
  103. package/lib/typescript/src/utils/url.d.ts.map +1 -1
  104. package/package.json +6 -4
  105. package/src/components/ThreadCard/AvatarSection.tsx +2 -2
  106. package/src/components/flows/inputButtons/index.tsx +105 -0
  107. package/src/components/messages/linkMessage/index.tsx +48 -8
  108. package/src/config/api-endpoints.ts +2 -0
  109. package/src/context/ChatDetailContext.tsx +85 -0
  110. package/src/hooks/flows/useCurrentConversationFlow.ts +11 -0
  111. package/src/hooks/flows/useFlow.ts +63 -0
  112. package/src/hooks/message/useSendMessage.ts +4 -0
  113. package/src/hooks/query-keys.ts +6 -0
  114. package/src/hooks/useConversationList.ts +15 -7
  115. package/src/hooks/useLinkPreview/useFetchUrlMetadata.ts +7 -3
  116. package/src/hooks/useLinkPreview/useLinkPreview.ts +2 -2
  117. package/src/index.tsx +1 -0
  118. package/src/screens/chat-detail/ChatComposer.tsx +41 -2
  119. package/src/screens/chat-detail/ChatDetail.tsx +81 -74
  120. package/src/screens/chat-detail/ChatListLegend.tsx +57 -3
  121. package/src/screens/chat-detail/ChatQuickActions.tsx +10 -3
  122. package/src/screens/chat-detail/conversationHeader.utils.ts +1 -4
  123. package/src/screens/chat-detail/legend/LegendChatMessage.tsx +7 -0
  124. package/src/screens/chat-detail/types.ts +9 -10
  125. package/src/screens/inbox/Inbox.tsx +3 -15
  126. package/src/screens/inbox/MessagesTab.tsx +48 -49
  127. package/src/services/endpoints.ts +6 -0
  128. package/src/translation/resources/i18n.ts +2 -0
  129. package/src/types/chat.ts +16 -1
  130. package/src/types/flows.ts +102 -0
  131. package/src/utils/flows.ts +18 -0
  132. package/src/utils/url.ts +30 -1
@@ -15,6 +15,7 @@ interface LegendChatMessageProps {
15
15
  isOutgoing: boolean;
16
16
  createdAtTime: number;
17
17
  onMediaPress?: (items: MediaItem[], index?: number) => void;
18
+ onPressUrl?: (url: string) => void;
18
19
  }
19
20
 
20
21
  // OpenIM message types (not all exposed as MessageType enum)
@@ -41,6 +42,7 @@ export const LegendChatMessage = memo(
41
42
  isOutgoing,
42
43
  createdAtTime,
43
44
  onMediaPress,
45
+ onPressUrl,
44
46
  }: LegendChatMessageProps) => {
45
47
  const MessageComponent =
46
48
  messageComponentMap[message?.contentType] ?? TextMessage;
@@ -53,6 +55,8 @@ export const LegendChatMessage = memo(
53
55
  ];
54
56
  const hasMediaPress =
55
57
  mediaTypes.includes(message?.contentType) && onMediaPress;
58
+ const hasUrlPress =
59
+ onPressUrl && message?.contentType === MessageType.UrlTextMessage;
56
60
 
57
61
  const props: any = {
58
62
  message,
@@ -63,6 +67,9 @@ export const LegendChatMessage = memo(
63
67
  if (hasMediaPress) {
64
68
  props.onMediaPress = onMediaPress;
65
69
  }
70
+ if (hasUrlPress) {
71
+ props.onPressUrl = onPressUrl;
72
+ }
66
73
 
67
74
  return <MessageComponent {...props} />;
68
75
  }
@@ -1,7 +1,11 @@
1
1
  import type { ReactNode } from 'react';
2
2
 
3
3
  import type { MediaItem } from '../../hooks/useMediaViewer';
4
- import type { DConversationItem, DMessageItem } from '../../types/chat';
4
+ import type {
5
+ DChatApplicationType,
6
+ DConversationItem,
7
+ DMessageItem,
8
+ } from '../../types/chat';
5
9
  import type { IUrlMetadata } from '../../types/common';
6
10
  import type { PeerType } from '@droppii/openim-rn-client-sdk';
7
11
 
@@ -75,6 +79,7 @@ export interface ChatComposerProps {
75
79
  renderQuickActions?: ChatQuickActionsProps['renderQuickActions'];
76
80
  renderAttachmentAction?: ChatAttachmentPanelProps['renderAction'];
77
81
  attachmentColumns?: number;
82
+ isEmptyMessage: boolean;
78
83
  }
79
84
 
80
85
  export interface ChatListProps {
@@ -89,6 +94,7 @@ export interface ChatListProps {
89
94
  isLoadingNewer?: boolean;
90
95
  hasMoreNewer?: boolean;
91
96
  onMediaPress?: (items: MediaItem[], index?: number) => void;
97
+ onPressUrl?: (url: string) => void;
92
98
  }
93
99
 
94
100
  export interface ChatDetailProps extends Omit<
@@ -108,25 +114,17 @@ export interface ChatDetailProps extends Omit<
108
114
  avatarUri?: string | null;
109
115
  avatarFullName?: string;
110
116
  peerType?: PeerType;
111
- applicationType?: DConversationItem['applicationType'];
117
+ applicationType?: DChatApplicationType;
112
118
  showAddMember?: boolean;
113
119
  getSubtitle?: (conversation: DConversationItem) => string | undefined;
114
120
  renderChat?: (item: DMessageItem) => ReactNode;
115
121
  showQuickActions?: boolean;
116
122
  showAttachmentActions?: boolean;
117
- onLoadEarlier?: () => void;
118
- isLoading?: boolean;
119
- isLoadingEarlier?: boolean;
120
- hasMoreEarlier?: boolean;
121
- onLoadNewer?: () => void;
122
- isLoadingNewer?: boolean;
123
- hasMoreNewer?: boolean;
124
123
  quickActions?: DChatQuickAction[];
125
124
  getQuickActions?: (
126
125
  conversation: DConversationItem
127
126
  ) => DChatQuickAction[] | undefined;
128
127
  attachmentActions?: DChatAttachmentAction[];
129
- inputValue?: string;
130
128
  inputPlaceholder?: string;
131
129
  onChangeInput?: (text: string) => void;
132
130
  onSend?: () => void;
@@ -138,4 +136,5 @@ export interface ChatDetailProps extends Omit<
138
136
  renderQuickActions?: ChatQuickActionsProps['renderQuickActions'];
139
137
  renderAttachmentAction?: ChatAttachmentPanelProps['renderAction'];
140
138
  attachmentColumns?: number;
139
+ onPressUrl?: (url: string) => void;
141
140
  }
@@ -5,7 +5,6 @@ import { KContainer, KImage, KLabel, KColors } from '@droppii/libs';
5
5
  import { MessagesTab } from './MessagesTab';
6
6
 
7
7
  interface InboxProps {
8
- applicationType: string;
9
8
  onPressThread?: (item: string) => void;
10
9
  onPressSearch?: () => void;
11
10
  onPressEdit?: () => void;
@@ -15,13 +14,7 @@ interface InboxProps {
15
14
  type TabRoute = { key: string; title: string };
16
15
 
17
16
  const Inbox = memo(
18
- ({
19
- applicationType,
20
- onPressThread,
21
- onPressSearch,
22
- onPressEdit,
23
- onPressGroup,
24
- }: InboxProps) => {
17
+ ({ onPressThread, onPressSearch, onPressEdit, onPressGroup }: InboxProps) => {
25
18
  const [index, setIndex] = useState(0);
26
19
  const [routes] = useState<TabRoute[]>([
27
20
  { key: 'messages', title: 'Tin nhắn' },
@@ -30,16 +23,11 @@ const Inbox = memo(
30
23
  const renderScene = useCallback(
31
24
  ({ route }: { route: TabRoute }) => {
32
25
  if (route.key === 'messages') {
33
- return (
34
- <MessagesTab
35
- applicationType={applicationType}
36
- onPressThread={onPressThread}
37
- />
38
- );
26
+ return <MessagesTab onPressThread={onPressThread} />;
39
27
  }
40
28
  return null;
41
29
  },
42
- [applicationType, onPressThread]
30
+ [onPressThread]
43
31
  );
44
32
 
45
33
  const renderTabBar = useCallback(
@@ -4,69 +4,68 @@ import { KContainer, KDivider, KLabel, KColors } from '@droppii/libs';
4
4
  import { useConversationList } from '../../hooks/useConversationList';
5
5
  import { ThreadCard } from '../../components/ThreadCard';
6
6
  import { useConversationStore } from '../../store';
7
+ import { useChatContext } from '../../context';
7
8
 
8
9
  interface MessagesTabProps {
9
- applicationType: string;
10
10
  onPressThread?: (item: string) => void;
11
11
  }
12
12
 
13
13
  const Separator = () => <KDivider type="line" size="hairline" />;
14
14
  const keyExtractor = (item: string) => item;
15
15
 
16
- export const MessagesTab = memo(
17
- ({ applicationType, onPressThread }: MessagesTabProps) => {
18
- const data = useConversationStore((state) => state.list);
16
+ export const MessagesTab = memo(({ onPressThread }: MessagesTabProps) => {
17
+ const data = useConversationStore((state) => state.list);
18
+ const applicationType = useChatContext().applicationType;
19
19
 
20
- const { isLoading, refetch, isRefetching } = useConversationList({
21
- applicationType,
22
- page: 1,
23
- });
20
+ const { isLoading, refetch, isRefetching } = useConversationList({
21
+ applicationType,
22
+ page: 1,
23
+ });
24
24
 
25
- const handleThreadPress = useCallback(
26
- (params: { item: string; event: GestureResponderEvent }) => {
27
- onPressThread?.(params.item);
28
- },
29
- [onPressThread]
30
- );
25
+ const handleThreadPress = useCallback(
26
+ (params: { item: string; event: GestureResponderEvent }) => {
27
+ onPressThread?.(params.item);
28
+ },
29
+ [onPressThread]
30
+ );
31
31
 
32
- const renderItem = useCallback(
33
- ({ item }: { item: string }) => (
34
- <ThreadCard item={item} onPress={handleThreadPress} />
35
- ),
36
- [handleThreadPress]
37
- );
32
+ const renderItem = useCallback(
33
+ ({ item }: { item: string }) => (
34
+ <ThreadCard item={item} onPress={handleThreadPress} />
35
+ ),
36
+ [handleThreadPress]
37
+ );
38
38
 
39
- const LoadingComponent = (
40
- <KContainer.View center flex paddingV="3rem">
41
- <ActivityIndicator size="large" color={KColors.palette.primary.w400} />
42
- </KContainer.View>
43
- );
39
+ const LoadingComponent = (
40
+ <KContainer.View center flex paddingV="3rem">
41
+ <ActivityIndicator size="large" color={KColors.palette.primary.w400} />
42
+ </KContainer.View>
43
+ );
44
44
 
45
- const EmptyComponent = isLoading ? null : (
46
- <KContainer.View center flex paddingV="3rem">
47
- <KLabel.Text typo="TextSmNormal" color={KColors.palette.gray.w400}>
48
- Không có tin nhắn nào
49
- </KLabel.Text>
50
- </KContainer.View>
51
- );
45
+ const EmptyComponent = isLoading ? null : (
46
+ <KContainer.View center flex paddingV="3rem">
47
+ <KLabel.Text typo="TextSmNormal" color={KColors.palette.gray.w400}>
48
+ Không có tin nhắn nào
49
+ </KLabel.Text>
50
+ </KContainer.View>
51
+ );
52
52
 
53
- if (isLoading && data.length === 0) {
54
- return LoadingComponent;
55
- }
56
-
57
- return (
58
- <KContainer.FlatList
59
- data={data}
60
- renderItem={renderItem}
61
- keyExtractor={keyExtractor}
62
- ItemSeparatorComponent={Separator}
63
- ListEmptyComponent={EmptyComponent}
64
- refreshing={isRefetching}
65
- onRefresh={refetch}
66
- showsVerticalScrollIndicator={false}
67
- />
68
- );
53
+ if (isLoading && data.length === 0) {
54
+ return LoadingComponent;
69
55
  }
70
- );
56
+
57
+ return (
58
+ <KContainer.FlatList
59
+ data={data}
60
+ renderItem={renderItem}
61
+ keyExtractor={keyExtractor}
62
+ ItemSeparatorComponent={Separator}
63
+ ListEmptyComponent={EmptyComponent}
64
+ refreshing={isRefetching}
65
+ onRefresh={refetch}
66
+ showsVerticalScrollIndicator={false}
67
+ />
68
+ );
69
+ });
71
70
 
72
71
  MessagesTab.displayName = 'MessagesTab';
@@ -16,6 +16,12 @@ export const ENDPOINTS = {
16
16
  get urlMetadata() {
17
17
  return getApiEndpoint('urlMetadata');
18
18
  },
19
+ conversationFlow: (id: string) =>
20
+ `${getApiEndpoint('conversationFlow')}/${id}`,
21
+ resetConversationFlow: (id: string) =>
22
+ `${getApiEndpoint('conversationFlow')}/${id}/bot-flows/reset`,
23
+ runConversationFlow: (id: string) =>
24
+ `${getApiEndpoint('conversationFlow')}/${id}/bot-flows/run`,
19
25
  },
20
26
  uploaderService: {
21
27
  get uploadImage() {
@@ -21,6 +21,8 @@ const i18nKey: Record<string, string> = {
21
21
  'msg_type_file': '[File đính kèm]',
22
22
  'msg_type_link': '[Liên kết]',
23
23
  'msg_type_revoke': 'Đã thu hồi tin nhắn',
24
+ 'start': 'Bắt đầu',
25
+ 'restart': 'Bắt đầu lại',
24
26
  };
25
27
 
26
28
  export default {
package/src/types/chat.ts CHANGED
@@ -5,6 +5,11 @@ import {
5
5
  } from '@droppii/openim-rn-client-sdk';
6
6
  import type { PropsWithChildren } from 'react';
7
7
  import type { IUrlMetadata } from './common';
8
+ import type {
9
+ IConversationFlow,
10
+ IConversationFlowStep,
11
+ IRunConversationFlowPayload,
12
+ } from './flows';
8
13
 
9
14
  export const EventProvider = {
10
15
  ga: 'ga',
@@ -66,7 +71,7 @@ export interface DConversationItem extends ConversationItem {
66
71
  conversationId: string;
67
72
  chatCategory: DChatCategory;
68
73
  chatType: PeerType;
69
- applicationType: string;
74
+ applicationType: DChatApplicationType;
70
75
  memberRole: DMemberRole;
71
76
  pinnedAt: string | null;
72
77
  isMuted: boolean;
@@ -123,6 +128,7 @@ export interface IMessageItemEx {
123
128
  content: string;
124
129
  };
125
130
  urlMetadata?: IUrlMetadata;
131
+ flow?: IRunConversationFlowPayload;
126
132
  }
127
133
 
128
134
  export interface MessageStore {
@@ -135,3 +141,12 @@ export interface MessageStore {
135
141
  deleteOneMessage: (clientMsgID: string) => void;
136
142
  reset: () => void;
137
143
  }
144
+
145
+ export interface ChatDetailContextType {
146
+ conversationFlow?: IConversationFlow;
147
+ refetchConversationFlow: () => void;
148
+ isBotConversation: boolean;
149
+ setConverationFlowStep: (step: IConversationFlowStep) => void;
150
+ }
151
+
152
+ export interface ChatDetailProviderProps extends PropsWithChildren {}
@@ -0,0 +1,102 @@
1
+ import type { PeerType } from '@droppii/openim-rn-client-sdk';
2
+ import type { DChatApplicationType, DChatCategory } from './chat';
3
+
4
+ /** START NODE TYPE */
5
+ export const NodeTypes = {
6
+ BubbleText: 'bubble-text',
7
+ BubbleImage: 'bubble-image',
8
+ InputText: 'input-text',
9
+ InputButtons: 'input-buttons',
10
+ LogicCsTeam: 'logic-cs-team',
11
+ } as const;
12
+
13
+ export type NodeTypes = (typeof NodeTypes)[keyof typeof NodeTypes];
14
+
15
+ export const ReactFlowsNodeTypes = {
16
+ Group: 'group',
17
+ Start: 'start',
18
+ } as const;
19
+
20
+ export type ReactFlowsNodeTypes =
21
+ (typeof ReactFlowsNodeTypes)[keyof typeof ReactFlowsNodeTypes];
22
+
23
+ export interface BaseNodeData {
24
+ id: string;
25
+ type: NodeTypes;
26
+ parentId: string;
27
+ }
28
+
29
+ export interface BubbleTextNodeData {
30
+ content?: string;
31
+ plainText?: string;
32
+ }
33
+
34
+ export interface BubbleImageNodeData {
35
+ sourceType: 'link' | 'upload' | 'giphy' | 'unsplash' | 'icon';
36
+ url?: string;
37
+ onClickLink?: boolean;
38
+ }
39
+
40
+ export interface InputButtonItem {
41
+ id: string;
42
+ label: string;
43
+ }
44
+
45
+ export interface LogicCsTeamNodeData {
46
+ csTeamId?: string;
47
+ }
48
+
49
+ export interface InputButtonsNodeData {
50
+ buttons?: InputButtonItem[];
51
+ }
52
+
53
+ export interface InputTextNodeData {
54
+ longText?: boolean;
55
+ placeholder?: string;
56
+ buttonLabel?: string;
57
+ }
58
+
59
+ export type NodeDataMap = {
60
+ [NodeTypes.BubbleText]: BubbleTextNodeData;
61
+ [NodeTypes.BubbleImage]: BubbleImageNodeData;
62
+ [NodeTypes.InputText]: InputTextNodeData;
63
+ [NodeTypes.InputButtons]: InputButtonsNodeData;
64
+ [NodeTypes.LogicCsTeam]: LogicCsTeamNodeData;
65
+ };
66
+
67
+ export type GroupChild<T extends NodeTypes = NodeTypes> = {
68
+ data: NodeDataMap[T];
69
+ } & BaseNodeData;
70
+
71
+ export interface GroupNodeData {
72
+ label: string;
73
+ children: GroupChild[];
74
+ }
75
+
76
+ /** END NODE TYPE */
77
+
78
+ export interface IConversationFlowStep {
79
+ id: string;
80
+ type: ReactFlowsNodeTypes;
81
+ data: GroupNodeData;
82
+ }
83
+
84
+ export interface IConversationFlow {
85
+ conversationId: string;
86
+ chatCategory: DChatCategory;
87
+ chatType: PeerType;
88
+ applicationType: DChatApplicationType;
89
+ flowCurrentStep: IConversationFlowStep | null;
90
+ }
91
+
92
+ export interface IRunConversationFlowResponse {
93
+ flowNextStep: IConversationFlowStep | null;
94
+ }
95
+
96
+ export interface IRunConversationFlowPayload {
97
+ groupId: string;
98
+ childId: string | null;
99
+ actionId: string | null;
100
+ //for send msg
101
+ plainText?: string;
102
+ }
@@ -0,0 +1,18 @@
1
+ import {
2
+ NodeTypes,
3
+ type GroupChild,
4
+ type IConversationFlowStep,
5
+ } from '../types/flows';
6
+
7
+ export const getFlowInputButtonsNode = (
8
+ step?: IConversationFlowStep | null
9
+ ) => {
10
+ if (!step) return null;
11
+ const childrenNode = step?.data?.children || [];
12
+ const inputButtonsNode = childrenNode?.find(
13
+ (f) => f.type === NodeTypes.InputButtons
14
+ ) as GroupChild<'input-buttons'>;
15
+ return inputButtonsNode;
16
+ };
17
+
18
+ export const DEFAULT_BUTTON_ID = 'default-item-button';
package/src/utils/url.ts CHANGED
@@ -1,4 +1,33 @@
1
- const URL_REGEX = /\bhttps?:\/\/[^\s<>"']*[^\s<>"',.!?()[\]{}]/g;
1
+ // Generic TLDs
2
+ const GENERIC_TLDS =
3
+ 'com|net|org|edu|gov|mil|int|biz|info|name|pro|mobi|travel|jobs|museum|coop|aero';
4
+
5
+ // New gTLDs (popular tech/startup)
6
+ const NEW_TLDS =
7
+ 'io|app|dev|ai|co|me|tv|cc|gg|ly|fm|im|link|click|page|live|site|web|xyz|' +
8
+ 'tech|digital|online|store|shop|cloud|media|news|blog|studio|agency|' +
9
+ 'design|finance|health|legal|academy|solutions|ventures|capital|group';
10
+
11
+ // Country codes (Vietnam + Southeast Asia + popular worldwide)
12
+ const CC_TLDS =
13
+ 'vn|jp|kr|cn|sg|th|ph|id|my|tw|hk|' +
14
+ 'uk|us|ca|au|de|fr|it|es|nl|ru|br|in|' +
15
+ 'ac|ad|ae|am|at|az|ba|be|bg|bh|bn|by|bz|' +
16
+ 'ch|cl|cz|dk|dz|ec|ee|eg|es|eu|fi|ga|ge|' +
17
+ 'gr|gt|hr|hu|ie|il|iq|ir|is|jo|ke|kh|kw|' +
18
+ 'kz|la|lb|li|lk|lt|lu|lv|ma|mc|md|mk|mm|' +
19
+ 'mn|mo|mt|mx|mz|na|ng|no|np|nz|om|pa|pe|' +
20
+ 'pk|pl|pt|qa|ro|rs|sa|se|sk|sl|sr|sv|sy|' +
21
+ 'tn|to|tr|tt|ua|ug|uy|uz|va|vc|ve|vu|ws|za|zm|zw';
22
+
23
+ const TLD_LIST = `${GENERIC_TLDS}|${NEW_TLDS}|${CC_TLDS}`;
24
+
25
+ // Matches: https://... | http://... | www.... | bare domain with known TLD (t.me, droppii.com)
26
+ const URL_REGEX = new RegExp(
27
+ `\\b(?:https?:\\/\\/|www\\.)[^\\s<>"']*[^\\s<>"',.!?()[\\]{}]` +
28
+ `|\\b[a-zA-Z0-9][\\w-]*(?:\\.[a-zA-Z0-9][\\w-]*)*\\.(?:${TLD_LIST})(?:[/?#][^\\s<>"']*[^\\s<>"',.!?()[\\]{}])?(?=\\s|$|[,!?()\\[\\]{}"'])`,
29
+ 'g'
30
+ );
2
31
 
3
32
  export function extractUrls(text: string): string[] {
4
33
  return text.match(URL_REGEX) ?? [];