@droppii-org/chat-mobile 0.2.63 → 0.2.65

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 (124) hide show
  1. package/lib/module/components/flows/inputButtons/index.js +11 -6
  2. package/lib/module/components/flows/inputButtons/index.js.map +1 -1
  3. package/lib/module/components/messages/linkMessage/index.js +4 -2
  4. package/lib/module/components/messages/linkMessage/index.js.map +1 -1
  5. package/lib/module/components/messages/quotedMessage/index.js +3 -2
  6. package/lib/module/components/messages/quotedMessage/index.js.map +1 -1
  7. package/lib/module/components/messages/styles.js +6 -1
  8. package/lib/module/components/messages/styles.js.map +1 -1
  9. package/lib/module/components/messages/textMessage/index.js +3 -2
  10. package/lib/module/components/messages/textMessage/index.js.map +1 -1
  11. package/lib/module/components/messages/types.js.map +1 -1
  12. package/lib/module/context/ChatDetailContext.js +29 -6
  13. package/lib/module/context/ChatDetailContext.js.map +1 -1
  14. package/lib/module/core/useChatListener.js +21 -10
  15. package/lib/module/core/useChatListener.js.map +1 -1
  16. package/lib/module/hooks/flows/useFlow.js +1 -1
  17. package/lib/module/hooks/flows/useFlow.js.map +1 -1
  18. package/lib/module/hooks/message/useSearchMessage.js +39 -14
  19. package/lib/module/hooks/message/useSearchMessage.js.map +1 -1
  20. package/lib/module/hooks/message/useSendMessage.js +13 -3
  21. package/lib/module/hooks/message/useSendMessage.js.map +1 -1
  22. package/lib/module/screens/SearchConversation/SearchAllResult.js +25 -10
  23. package/lib/module/screens/SearchConversation/SearchAllResult.js.map +1 -1
  24. package/lib/module/screens/SearchConversation/SearchEmpty.js +22 -3
  25. package/lib/module/screens/SearchConversation/SearchEmpty.js.map +1 -1
  26. package/lib/module/screens/SearchConversation/SearchMessagesResult.js +23 -7
  27. package/lib/module/screens/SearchConversation/SearchMessagesResult.js.map +1 -1
  28. package/lib/module/screens/SearchConversation/SearchResultItem.js +53 -12
  29. package/lib/module/screens/SearchConversation/SearchResultItem.js.map +1 -1
  30. package/lib/module/screens/SearchMessage/SearchMessageResult.js +24 -7
  31. package/lib/module/screens/SearchMessage/SearchMessageResult.js.map +1 -1
  32. package/lib/module/screens/SearchMessage/SearchResultItem.js +31 -3
  33. package/lib/module/screens/SearchMessage/SearchResultItem.js.map +1 -1
  34. package/lib/module/screens/chat-detail/ChatComposer.js +12 -1
  35. package/lib/module/screens/chat-detail/ChatComposer.js.map +1 -1
  36. package/lib/module/screens/chat-detail/ChatListLegend.js +26 -17
  37. package/lib/module/screens/chat-detail/ChatListLegend.js.map +1 -1
  38. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js +4 -2
  39. package/lib/module/screens/chat-detail/legend/LegendChatMessage.js.map +1 -1
  40. package/lib/module/store/message.js +3 -0
  41. package/lib/module/store/message.js.map +1 -1
  42. package/lib/module/translation/resources/i18n.js +7 -2
  43. package/lib/module/translation/resources/i18n.js.map +1 -1
  44. package/lib/module/types/chat.js.map +1 -1
  45. package/lib/module/types/events.js +2 -0
  46. package/lib/module/types/events.js.map +1 -1
  47. package/lib/module/utils/flows.js +4 -4
  48. package/lib/module/utils/flows.js.map +1 -1
  49. package/lib/module/utils/highlightSearch.js +38 -0
  50. package/lib/module/utils/highlightSearch.js.map +1 -0
  51. package/lib/module/utils/messageUtils.js +5 -1
  52. package/lib/module/utils/messageUtils.js.map +1 -1
  53. package/lib/typescript/src/components/flows/inputButtons/index.d.ts +1 -1
  54. package/lib/typescript/src/components/flows/inputButtons/index.d.ts.map +1 -1
  55. package/lib/typescript/src/components/messages/linkMessage/index.d.ts +1 -1
  56. package/lib/typescript/src/components/messages/linkMessage/index.d.ts.map +1 -1
  57. package/lib/typescript/src/components/messages/quotedMessage/index.d.ts.map +1 -1
  58. package/lib/typescript/src/components/messages/styles.d.ts +5 -0
  59. package/lib/typescript/src/components/messages/styles.d.ts.map +1 -1
  60. package/lib/typescript/src/components/messages/textMessage/index.d.ts +1 -1
  61. package/lib/typescript/src/components/messages/textMessage/index.d.ts.map +1 -1
  62. package/lib/typescript/src/components/messages/types.d.ts +1 -0
  63. package/lib/typescript/src/components/messages/types.d.ts.map +1 -1
  64. package/lib/typescript/src/context/ChatDetailContext.d.ts.map +1 -1
  65. package/lib/typescript/src/core/useChatListener.d.ts.map +1 -1
  66. package/lib/typescript/src/hooks/flows/useFlow.d.ts.map +1 -1
  67. package/lib/typescript/src/hooks/message/useSearchMessage.d.ts.map +1 -1
  68. package/lib/typescript/src/hooks/message/useSendMessage.d.ts.map +1 -1
  69. package/lib/typescript/src/screens/SearchConversation/SearchAllResult.d.ts.map +1 -1
  70. package/lib/typescript/src/screens/SearchConversation/SearchEmpty.d.ts +7 -1
  71. package/lib/typescript/src/screens/SearchConversation/SearchEmpty.d.ts.map +1 -1
  72. package/lib/typescript/src/screens/SearchConversation/SearchMessagesResult.d.ts.map +1 -1
  73. package/lib/typescript/src/screens/SearchConversation/SearchResultItem.d.ts +1 -0
  74. package/lib/typescript/src/screens/SearchConversation/SearchResultItem.d.ts.map +1 -1
  75. package/lib/typescript/src/screens/SearchMessage/SearchMessageResult.d.ts.map +1 -1
  76. package/lib/typescript/src/screens/SearchMessage/SearchResultItem.d.ts +1 -0
  77. package/lib/typescript/src/screens/SearchMessage/SearchResultItem.d.ts.map +1 -1
  78. package/lib/typescript/src/screens/chat-detail/ChatComposer.d.ts.map +1 -1
  79. package/lib/typescript/src/screens/chat-detail/ChatListLegend.d.ts.map +1 -1
  80. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts +2 -1
  81. package/lib/typescript/src/screens/chat-detail/legend/LegendChatMessage.d.ts.map +1 -1
  82. package/lib/typescript/src/store/message.d.ts.map +1 -1
  83. package/lib/typescript/src/translation/resources/i18n.d.ts.map +1 -1
  84. package/lib/typescript/src/types/chat.d.ts +3 -2
  85. package/lib/typescript/src/types/chat.d.ts.map +1 -1
  86. package/lib/typescript/src/types/events.d.ts +10 -1
  87. package/lib/typescript/src/types/events.d.ts.map +1 -1
  88. package/lib/typescript/src/types/flows.d.ts +4 -0
  89. package/lib/typescript/src/types/flows.d.ts.map +1 -1
  90. package/lib/typescript/src/utils/flows.d.ts +1 -1
  91. package/lib/typescript/src/utils/flows.d.ts.map +1 -1
  92. package/lib/typescript/src/utils/highlightSearch.d.ts +7 -0
  93. package/lib/typescript/src/utils/highlightSearch.d.ts.map +1 -0
  94. package/lib/typescript/src/utils/messageUtils.d.ts +1 -0
  95. package/lib/typescript/src/utils/messageUtils.d.ts.map +1 -1
  96. package/package.json +2 -2
  97. package/src/components/flows/inputButtons/index.tsx +20 -12
  98. package/src/components/messages/linkMessage/index.tsx +3 -0
  99. package/src/components/messages/quotedMessage/index.tsx +2 -1
  100. package/src/components/messages/styles.ts +6 -1
  101. package/src/components/messages/textMessage/index.tsx +7 -1
  102. package/src/components/messages/types.ts +1 -0
  103. package/src/context/ChatDetailContext.tsx +57 -11
  104. package/src/core/useChatListener.ts +53 -17
  105. package/src/hooks/flows/useFlow.ts +5 -1
  106. package/src/hooks/message/useSearchMessage.ts +46 -15
  107. package/src/hooks/message/useSendMessage.ts +21 -2
  108. package/src/screens/SearchConversation/SearchAllResult.tsx +24 -10
  109. package/src/screens/SearchConversation/SearchEmpty.tsx +38 -14
  110. package/src/screens/SearchConversation/SearchMessagesResult.tsx +39 -18
  111. package/src/screens/SearchConversation/SearchResultItem.tsx +72 -13
  112. package/src/screens/SearchMessage/SearchMessageResult.tsx +47 -20
  113. package/src/screens/SearchMessage/SearchResultItem.tsx +37 -5
  114. package/src/screens/chat-detail/ChatComposer.tsx +17 -1
  115. package/src/screens/chat-detail/ChatListLegend.tsx +48 -21
  116. package/src/screens/chat-detail/legend/LegendChatMessage.tsx +3 -0
  117. package/src/store/message.ts +2 -0
  118. package/src/translation/resources/i18n.ts +7 -2
  119. package/src/types/chat.ts +7 -1
  120. package/src/types/events.ts +12 -0
  121. package/src/types/flows.ts +4 -0
  122. package/src/utils/flows.ts +5 -6
  123. package/src/utils/highlightSearch.ts +48 -0
  124. package/src/utils/messageUtils.ts +16 -7
@@ -1 +1 @@
1
- {"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../../../src/types/flows.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../../../src/types/flows.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import { type GroupChild, type IConversationFlowStep } from '../types/flows';
2
- export declare const getFlowInputButtonsNode: (step?: IConversationFlowStep | null) => GroupChild<"input-buttons">;
2
+ export declare const getFlowInputButtonsNodes: (step?: IConversationFlowStep | null) => GroupChild<"input-buttons">[];
3
3
  export declare const DEFAULT_BUTTON_ID = "default-item-button";
4
4
  export declare const CONTEXT_BUTTON_PREFIX = "context:";
5
5
  export declare const isContextButton: (label: string) => boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../../../src/utils/flows.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,uBAAuB,GAClC,OAAO,qBAAqB,GAAG,IAAI,gCAQpC,CAAC;AAEF,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AAEvD,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAEhD,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,YAG5C,CAAC"}
1
+ {"version":3,"file":"flows.d.ts","sourceRoot":"","sources":["../../../../src/utils/flows.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,UAAU,EACf,KAAK,qBAAqB,EAC3B,MAAM,gBAAgB,CAAC;AAExB,eAAO,MAAM,wBAAwB,GACnC,OAAO,qBAAqB,GAAG,IAAI,kCAOpC,CAAC;AAEF,eAAO,MAAM,iBAAiB,wBAAwB,CAAC;AAEvD,eAAO,MAAM,qBAAqB,aAAa,CAAC;AAEhD,eAAO,MAAM,eAAe,GAAI,OAAO,MAAM,YAG5C,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface HighlightResult {
2
+ before: string;
3
+ match: string;
4
+ after: string;
5
+ }
6
+ export declare const highlightSearch: (text: string, keyword: string, maxLength?: number) => HighlightResult | null;
7
+ //# sourceMappingURL=highlightSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"highlightSearch.d.ts","sourceRoot":"","sources":["../../../../src/utils/highlightSearch.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;CACf;AAED,eAAO,MAAM,eAAe,GAC1B,MAAM,MAAM,EACZ,SAAS,MAAM,EACf,kBAAc,KACb,eAAe,GAAG,IAqCpB,CAAC"}
@@ -20,6 +20,7 @@ export interface PinnedMessagePreview {
20
20
  fileIcon?: number;
21
21
  }
22
22
  export declare const getPinnedMessagePreview: (message: MessageItem) => PinnedMessagePreview;
23
+ export declare const getSenderName: (message: MessageItem, currentUserId?: string, conversation?: ConversationItem) => string;
23
24
  export interface GetLastMessageTextParams {
24
25
  message: MessageItem | undefined;
25
26
  currentUserId?: string;
@@ -1 +1 @@
1
- {"version":3,"file":"messageUtils.d.ts","sourceRoot":"","sources":["../../../../src/utils/messageUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,KAAG,OACL,CAAC;AAEpD,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,KAAG,MAYzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,UAAU,WAAW,KAAG,MA0EzD,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,UAAU,WAAW,KACpB,SAUF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,UAAU,WAAW,KACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAGrC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,sBAAsB,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAmBD,eAAO,MAAM,uBAAuB,GAClC,SAAS,WAAW,KACnB,oBA0DF,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,eAAO,MAAM,kBAAkB,GAAI,0EAKhC,wBAAwB,KAAG,MAuB7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,WAAW,EACrB,gBAAgB,MAAM,EACtB,eAAe,gBAAgB,EAC/B,SAAS,OAAO,KACf,MAOF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,YAAY,GAAG,SAS7D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,WAAW,MAAM,KAAG,MAUhE,CAAC"}
1
+ {"version":3,"file":"messageUtils.d.ts","sourceRoot":"","sources":["../../../../src/utils/messageUtils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAGL,KAAK,gBAAgB,EACrB,KAAK,WAAW,EACjB,MAAM,+BAA+B,CAAC;AAIvC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAE9C,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,KAAG,OACL,CAAC;AAEpD,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,KAAG,MAYzD,CAAC;AAEF,eAAO,MAAM,iBAAiB,GAAI,UAAU,WAAW,KAAG,MA0EzD,CAAC;AAEF,eAAO,MAAM,0BAA0B,GACrC,UAAU,WAAW,KACpB,SAUF,CAAC;AAEF,eAAO,MAAM,sBAAsB,GACjC,UAAU,WAAW,KACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,SAAS,CAAA;CAGrC,CAAC;AAEH,MAAM,MAAM,sBAAsB,GAAG,OAAO,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;AAEzE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,sBAAsB,CAAC;IAClC,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAmBD,eAAO,MAAM,uBAAuB,GAClC,SAAS,WAAW,KACnB,oBA0DF,CAAC;AAEF,eAAO,MAAM,aAAa,GACxB,SAAS,WAAW,EACpB,gBAAgB,MAAM,EACtB,eAAe,gBAAgB,KAC9B,MASF,CAAC;AAEF,MAAM,WAAW,wBAAwB;IACvC,OAAO,EAAE,WAAW,GAAG,SAAS,CAAC;IACjC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,gBAAgB,CAAC;IAChC,6BAA6B,CAAC,EAAE,OAAO,CAAC;CACzC;AAED,eAAO,MAAM,kBAAkB,GAAI,0EAKhC,wBAAwB,KAAG,MAiB7B,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAC7B,UAAU,WAAW,EACrB,gBAAgB,MAAM,EACtB,eAAe,gBAAgB,EAC/B,SAAS,OAAO,KACf,MAOF,CAAC;AAEF,eAAO,MAAM,gBAAgB,GAAI,KAAK,MAAM,KAAG,YAAY,GAAG,SAS7D,CAAC;AAEF,eAAO,MAAM,cAAc,GAAI,MAAM,MAAM,EAAE,WAAW,MAAM,KAAG,MAUhE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@droppii-org/chat-mobile",
3
- "version": "0.2.63",
3
+ "version": "0.2.65",
4
4
  "description": "Droppii chat mobile",
5
5
  "keywords": [
6
6
  "react-native",
@@ -69,7 +69,7 @@
69
69
  "example-legacy": "yarn workspace @droppii-org/chat-mobile-example-legacy"
70
70
  },
71
71
  "dependencies": {
72
- "@droppii/openim-rn-client-sdk": "git+ssh://git@github.com/droppii/open-im-sdk-reactnative.git#v1.0.0-rc20",
72
+ "@droppii/openim-rn-client-sdk": "git+ssh://git@github.com/droppii/open-im-sdk-reactnative.git#v1.0.0-rc23",
73
73
  "@legendapp/list": "^3.0.6",
74
74
  "axios": "^1.16.1",
75
75
  "lodash": "^4.18.1",
@@ -18,40 +18,47 @@ import { DEFAULT_BUTTON_ID, isContextButton } from '../../../utils/flows';
18
18
  import { trans } from '../../../translation';
19
19
 
20
20
  interface IInputButtonFlow {
21
- nodeData: GroupChild<'input-buttons'> | null;
21
+ nodeData: GroupChild<'input-buttons'>[];
22
22
  onResetFlow: () => void;
23
23
  onRunFlow: (payload: IRunConversationFlowPayload) => void;
24
24
  }
25
25
 
26
+ type ButtonItem = InputButtonItem & { parentId: string; nodeId: string };
27
+
26
28
  export const InputButtonFlow = memo((props: IInputButtonFlow) => {
27
29
  const { nodeData, onResetFlow, onRunFlow } = props || {};
28
30
 
29
31
  const buttonList = useMemo(() => {
30
- return (
31
- nodeData?.data?.buttons?.filter(
32
- (n) => !isContextButton(n?.label || '')
33
- ) || []
32
+ return nodeData.flatMap(
33
+ (item) =>
34
+ item.data?.buttons
35
+ ?.filter((n) => !isContextButton(n?.label || ''))
36
+ ?.map((n) => ({
37
+ ...n,
38
+ parentId: item.parentId,
39
+ nodeId: item.id,
40
+ })) || []
34
41
  );
35
42
  }, [nodeData]);
36
43
 
37
44
  const onPressItem = useCallback(
38
- (item: InputButtonItem) => {
45
+ (item: ButtonItem) => {
39
46
  if (item.id === DEFAULT_BUTTON_ID) {
40
47
  onResetFlow?.();
41
48
  } else {
42
49
  onRunFlow?.({
43
50
  actionId: item.id,
44
- groupId: nodeData?.parentId || '',
45
- childId: nodeData?.id || '',
51
+ groupId: item.parentId || '',
52
+ childId: item.nodeId || '',
46
53
  plainText: item?.label || '',
47
54
  });
48
55
  }
49
56
  },
50
- [onRunFlow, onResetFlow, nodeData]
57
+ [onRunFlow, onResetFlow]
51
58
  );
52
59
 
53
60
  const renderButtonItem = useCallback(
54
- (item: InputButtonItem) => {
61
+ (item: ButtonItem) => {
55
62
  return (
56
63
  <KContainer.Touchable
57
64
  key={item.id}
@@ -74,7 +81,7 @@ export const InputButtonFlow = memo((props: IInputButtonFlow) => {
74
81
  [onPressItem]
75
82
  );
76
83
 
77
- if (!nodeData) return null;
84
+ if (!nodeData || buttonList.length === 0) return null;
78
85
 
79
86
  return (
80
87
  <KContainer.View style={styles.bubble}>
@@ -93,7 +100,8 @@ const styles = StyleSheet.create({
93
100
  borderRadius: KSpacingValue['1.25rem'],
94
101
  ...messageStyles.bubbleReceived,
95
102
  marginVertical: KSpacingValue['0.5rem'],
96
- width: '100%',
103
+ marginHorizontal: KSpacingValue['0.75rem'],
104
+ maxWidth: '80%',
97
105
  },
98
106
  buttonsContainer: {
99
107
  backgroundColor: KColors.white,
@@ -11,6 +11,7 @@ import { formatMessageTime } from '../types';
11
11
  import type { BaseLegendMessageProps } from '../types';
12
12
  import { CHAT_BUBBLE_COLORS } from '../../../screens/chat-detail/constants';
13
13
  import { parseUrlMetadata } from '../../../utils/messageUtils';
14
+ import { messageStyles } from '../styles';
14
15
 
15
16
  const renderTextWithLinks = (
16
17
  content: string,
@@ -62,6 +63,7 @@ export const LinkMessage = memo(
62
63
  isOutgoing,
63
64
  createdAtTime,
64
65
  onPressUrl,
66
+ isHighlighted,
65
67
  }: BaseLegendMessageProps & { onPressUrl?: (url: string) => void }) => {
66
68
  const content = message?.urlTextElem?.content;
67
69
  const urls = message?.urlTextElem?.urls ?? [];
@@ -74,6 +76,7 @@ export const LinkMessage = memo(
74
76
  style={[
75
77
  styles.bubble,
76
78
  isOutgoing ? styles.bubbleSent : styles.bubbleReceived,
79
+ isHighlighted && messageStyles.bubbleHighlighted,
77
80
  ]}
78
81
  >
79
82
  {!!content?.trim() && (
@@ -25,7 +25,7 @@ import { ChatEvent } from '../../../types/events';
25
25
  interface QuotedMessageProps extends BaseLegendMessageProps {}
26
26
 
27
27
  const QuotedMessage = memo((props: QuotedMessageProps) => {
28
- const { message, isOutgoing, createdAtTime } = props || {};
28
+ const { message, isOutgoing, createdAtTime, isHighlighted } = props || {};
29
29
 
30
30
  const { conversation } = useChatDetailContext();
31
31
 
@@ -70,6 +70,7 @@ const QuotedMessage = memo((props: QuotedMessageProps) => {
70
70
  messageStyles.bubble,
71
71
  styles.container,
72
72
  isOutgoing ? messageStyles.bubbleSent : messageStyles.bubbleReceived,
73
+ isHighlighted && messageStyles.bubbleHighlighted,
73
74
  ]}
74
75
  >
75
76
  <KContainer.Touchable
@@ -1,5 +1,5 @@
1
1
  import { StyleSheet } from 'react-native';
2
- import { KSpacingValue } from '@droppii/libs';
2
+ import { KColors, KSpacingValue } from '@droppii/libs';
3
3
  import { CHAT_BUBBLE_COLORS } from '../../screens/chat-detail/constants';
4
4
 
5
5
  export const messageStyles = StyleSheet.create({
@@ -11,6 +11,11 @@ export const messageStyles = StyleSheet.create({
11
11
  paddingVertical: KSpacingValue['0.5rem'],
12
12
  borderRadius: KSpacingValue['1.25rem'],
13
13
  },
14
+ bubbleHighlighted: {
15
+ borderRadius: KSpacingValue['1.25rem'],
16
+ borderColor: KColors.primary.normal,
17
+ borderWidth: 1,
18
+ },
14
19
  bubbleReceived: {
15
20
  backgroundColor: CHAT_BUBBLE_COLORS.received,
16
21
  },
@@ -7,7 +7,12 @@ import { formatMessageTime } from '../types';
7
7
  import type { BaseLegendMessageProps } from '../types';
8
8
  import { StyleSheet } from 'react-native';
9
9
  export const TextMessage = memo(
10
- ({ message, isOutgoing, createdAtTime }: BaseLegendMessageProps) => {
10
+ ({
11
+ message,
12
+ isOutgoing,
13
+ createdAtTime,
14
+ isHighlighted,
15
+ }: BaseLegendMessageProps) => {
11
16
  const messageText = getMessageText(message);
12
17
  const timeLabel = formatMessageTime(createdAtTime);
13
18
 
@@ -23,6 +28,7 @@ export const TextMessage = memo(
23
28
  isOutgoing
24
29
  ? messageStyles.bubbleSent
25
30
  : messageStyles.bubbleReceived,
31
+ isHighlighted && messageStyles.bubbleHighlighted,
26
32
  ]}
27
33
  >
28
34
  <KLabel.Text typo="TextMdNormal" color={CHAT_BUBBLE_COLORS.text}>
@@ -5,6 +5,7 @@ export interface BaseLegendMessageProps {
5
5
  message: MessageItem;
6
6
  isOutgoing: boolean;
7
7
  createdAtTime: number;
8
+ isHighlighted?: boolean;
8
9
  onMediaPress?: (items: MediaItem[], index?: number) => void;
9
10
  }
10
11
 
@@ -6,14 +6,20 @@ import {
6
6
  useMemo,
7
7
  useState,
8
8
  } from 'react';
9
+ import { DeviceEventEmitter } from 'react-native';
9
10
  import {
10
11
  DFlowState,
11
12
  type ChatDetailContextType,
12
13
  type ChatDetailProviderProps,
13
14
  } from '../types/chat';
14
15
  import { fechtCurrentConversationFlow } from '../hooks/flows/useCurrentConversationFlow';
16
+ import { ChatEvent, type GroupPermissionUpdatedPayload } from '../types/events';
15
17
  import { useConversationStore } from '../store';
16
- import { PeerType, type MessageItem } from '@droppii/openim-rn-client-sdk';
18
+ import OpenIMSDK, {
19
+ GroupPermission,
20
+ PeerType,
21
+ type MessageItem,
22
+ } from '@droppii/openim-rn-client-sdk';
17
23
  import {
18
24
  DFlowContext,
19
25
  NodeTypes,
@@ -33,6 +39,7 @@ export const ChatDetailContext = createContext<ChatDetailContextType>({
33
39
  conversation: undefined,
34
40
  quotedMessage: undefined,
35
41
  setQuotedMessage: () => {},
42
+ groupPermissions: [],
36
43
  });
37
44
 
38
45
  export const useChatDetailContext = (): ChatDetailContextType => {
@@ -60,6 +67,31 @@ export const ChatDetailProvider = ({ children }: ChatDetailProviderProps) => {
60
67
  undefined
61
68
  );
62
69
 
70
+ const [groupPermissions, setGroupPermissions] = useState<GroupPermission[]>(
71
+ []
72
+ );
73
+
74
+ useEffect(() => {
75
+ const groupId = conversation?.groupID;
76
+ if (!groupId) {
77
+ setGroupPermissions([]);
78
+ return;
79
+ }
80
+ OpenIMSDK.getSelfUserInfo(groupId)
81
+ .then((info) => setGroupPermissions(info?.permissions ?? []))
82
+ .catch(() => setGroupPermissions([]));
83
+ }, [conversation?.groupID]);
84
+
85
+ useEffect(() => {
86
+ const sub = DeviceEventEmitter.addListener(
87
+ ChatEvent.GroupPermissionUpdated,
88
+ ({ permissions }: GroupPermissionUpdatedPayload) => {
89
+ setGroupPermissions(permissions);
90
+ }
91
+ );
92
+ return () => sub.remove();
93
+ }, []);
94
+
63
95
  const flowState = useMemo(() => {
64
96
  return conversationFlow
65
97
  ? conversationFlow?.flowCurrentStep?.data?.children?.some(
@@ -80,15 +112,24 @@ export const ChatDetailProvider = ({ children }: ChatDetailProviderProps) => {
80
112
 
81
113
  const { mutateAsync: runFlow } = useRunFlow();
82
114
 
83
- const setConverationFlowStep = useCallback((step?: IConversationFlowStep) => {
84
- setConverationFlow(
85
- (prev) =>
86
- ({
87
- ...prev,
88
- flowCurrentStep: step,
89
- }) as IConversationFlow
90
- );
91
- }, []);
115
+ const setConverationFlowStep = useCallback(
116
+ (
117
+ step?: IConversationFlowStep,
118
+ isEnd?: boolean,
119
+ havingBotMessage?: boolean
120
+ ) => {
121
+ setConverationFlow(
122
+ (prev) =>
123
+ ({
124
+ ...prev,
125
+ flowCurrentStep: step,
126
+ havingBotMessage: havingBotMessage,
127
+ flowIsEnd: isEnd,
128
+ }) as IConversationFlow
129
+ );
130
+ },
131
+ []
132
+ );
92
133
 
93
134
  const getConversationFlow = useCallback(async () => {
94
135
  const res = await fechtCurrentConversationFlow(conversationId);
@@ -111,7 +152,11 @@ export const ChatDetailProvider = ({ children }: ChatDetailProviderProps) => {
111
152
  groupId: '',
112
153
  childId: '',
113
154
  });
114
- setConverationFlowStep(res?.flowNextStep || undefined);
155
+ setConverationFlowStep(
156
+ res?.flowNextStep || undefined,
157
+ res?.isEnd,
158
+ res?.havingBotMessage
159
+ );
115
160
  return res ? true : false;
116
161
  }
117
162
  return false;
@@ -137,6 +182,7 @@ export const ChatDetailProvider = ({ children }: ChatDetailProviderProps) => {
137
182
  quotedMessage,
138
183
  setQuotedMessage,
139
184
  conversationFlowMainMenu,
185
+ groupPermissions,
140
186
  }}
141
187
  >
142
188
  {children}
@@ -18,6 +18,8 @@ import isEmpty from 'lodash/isEmpty';
18
18
  import { markMessageRevoked, useMessageStore } from '../store/message';
19
19
  import { syncPinnedMessagesOnEvent } from '../hooks/message/usePinMessage';
20
20
  import { belongsToConversation } from '../utils/message';
21
+ import { DeviceEventEmitter } from 'react-native';
22
+ import { ChatEvent } from '../types/events';
21
23
 
22
24
  export const useChatListener = () => {
23
25
  const updateOneMessage = useMessageStore((state) => state.updateOneMessage);
@@ -40,20 +42,25 @@ export const useChatListener = () => {
40
42
  const onConversationChanged = useCallback(
41
43
  (conversations: ConversationItem[]) => {
42
44
  const oldMap = useConversationStore.getState().map;
43
- if (isShowFLashMessage) {
44
- for (const conversation of conversations) {
45
- const oldConversation = oldMap[conversation.conversationID];
46
- if (
47
- conversation.recvMsgOpt === MessageReceiveOptType.NotNotify ||
48
- isEmpty(conversation?.latestMsg) ||
49
- oldConversation?.latestMsgSendTime ===
50
- conversation?.latestMsgSendTime
51
- ) {
52
- continue;
53
- }
54
- const latestMsg: MessageItem = JSON.parse(
55
- conversation.latestMsg || '{}'
56
- );
45
+ const visibleConversations: ConversationItem[] = [];
46
+
47
+ for (const conversation of conversations) {
48
+ const latestMsg: MessageItem | null = conversation.latestMsg
49
+ ? JSON.parse(conversation.latestMsg)
50
+ : null;
51
+
52
+ if (latestMsg?.isInternal) continue;
53
+
54
+ visibleConversations.push(conversation);
55
+
56
+ if (
57
+ isShowFLashMessage &&
58
+ !isEmpty(conversation.latestMsg) &&
59
+ conversation.recvMsgOpt !== MessageReceiveOptType.NotNotify &&
60
+ latestMsg &&
61
+ oldMap[conversation.conversationID]?.latestMsgSendTime !==
62
+ conversation.latestMsgSendTime
63
+ ) {
57
64
  const lastMessageText = getLastMessageText({
58
65
  message: latestMsg,
59
66
  currentUserId,
@@ -73,7 +80,8 @@ export const useChatListener = () => {
73
80
  });
74
81
  }
75
82
  }
76
- useConversationStore.getState().updateConversations(conversations);
83
+
84
+ useConversationStore.getState().updateConversations(visibleConversations);
77
85
  },
78
86
  [currentUserId, isShowFLashMessage, onPressFlashMessage]
79
87
  );
@@ -97,6 +105,23 @@ export const useChatListener = () => {
97
105
  });
98
106
  }, []);
99
107
 
108
+ const OnGroupMemberInfoChanged = useCallback(
109
+ (member: GroupMemberItem) => {
110
+ const conversation = useConversationStore
111
+ .getState()
112
+ .getCurrentConversation();
113
+ if (
114
+ member?.groupID === conversation?.groupID &&
115
+ member?.userID === currentUserId
116
+ ) {
117
+ DeviceEventEmitter.emit(ChatEvent.GroupPermissionUpdated, {
118
+ permissions: member.permissions ?? [],
119
+ });
120
+ }
121
+ },
122
+ [currentUserId]
123
+ );
124
+
100
125
  const onMessageRevoked = useCallback((revokedInfo: RevokedInfo) => {
101
126
  markMessageRevoked(revokedInfo.clientMsgID);
102
127
  }, []);
@@ -128,8 +153,10 @@ export const useChatListener = () => {
128
153
  useConversationStore.getState().currentConversationId;
129
154
  const targetUserId = useConversationStore.getState().currentUserId;
130
155
  if (!conversationId && !targetUserId) return;
131
- const relevant = messages.filter((message) =>
132
- belongsToConversation(message, conversationId, targetUserId)
156
+ const relevant = messages.filter(
157
+ (message) =>
158
+ belongsToConversation(message, conversationId, targetUserId) &&
159
+ !message.isInternal
133
160
  );
134
161
 
135
162
  if (!relevant.length) return;
@@ -149,6 +176,10 @@ export const useChatListener = () => {
149
176
  // Group members
150
177
  OpenIMSDK.on(OpenIMEvent.OnGroupMemberAdded, onGroupMemberAdded);
151
178
  OpenIMSDK.on(OpenIMEvent.OnGroupMemberDeleted, onGroupMemberDeleted);
179
+ OpenIMSDK.on(
180
+ OpenIMEvent.OnGroupMemberInfoChanged,
181
+ OnGroupMemberInfoChanged
182
+ );
152
183
 
153
184
  // Message status
154
185
  OpenIMSDK.on(OpenIMEvent.SendMessageProgress, onSendMessageProgress);
@@ -168,6 +199,10 @@ export const useChatListener = () => {
168
199
  // Group members
169
200
  OpenIMSDK.off(OpenIMEvent.OnGroupMemberAdded, onGroupMemberAdded);
170
201
  OpenIMSDK.off(OpenIMEvent.OnGroupMemberDeleted, onGroupMemberDeleted);
202
+ OpenIMSDK.on(
203
+ OpenIMEvent.OnGroupMemberInfoChanged,
204
+ OnGroupMemberInfoChanged
205
+ );
171
206
 
172
207
  // Message status
173
208
  OpenIMSDK.off(OpenIMEvent.SendMessageProgress, onSendMessageProgress);
@@ -189,5 +224,6 @@ export const useChatListener = () => {
189
224
  onSendMessageProgress,
190
225
  onRecvNewMessages,
191
226
  onRecvOfflineNewMessages,
227
+ OnGroupMemberInfoChanged,
192
228
  ]);
193
229
  };
@@ -80,7 +80,11 @@ export const useRunFlow = () => {
80
80
  return res?.data?.data || undefined;
81
81
  },
82
82
  onSuccess: (data) => {
83
- setConverationFlowStep(data?.flowNextStep || undefined);
83
+ setConverationFlowStep(
84
+ data?.flowNextStep || undefined,
85
+ data?.isEnd,
86
+ data?.havingBotMessage
87
+ );
84
88
  },
85
89
  });
86
90
  };
@@ -10,7 +10,9 @@ import type {
10
10
  } from '../../types/chat';
11
11
  import type { BaseResponse } from '../../types/auth';
12
12
  import { PAGE_SIZE } from '../../constants';
13
- import { useMemo } from 'react';
13
+ import { useEffect, useMemo, useRef, useState } from 'react';
14
+ import { DeviceEventEmitter } from 'react-native';
15
+ import { ChatEvent, type MessageRevokedPayload } from '../../types/events';
14
16
 
15
17
  interface IUseSearchMessageProps {
16
18
  query: string;
@@ -25,7 +27,7 @@ export const useSearchMessage = ({
25
27
  pageSize = PAGE_SIZE,
26
28
  }: IUseSearchMessageProps) => {
27
29
  const { data, ...rest } = useInfiniteQuery({
28
- queryKey: messageQueryKeys.search(query, conversationId),
30
+ queryKey: [messageQueryKeys.search(query.trim(), conversationId), pageSize],
29
31
  queryFn: async ({ pageParam = 1 }) => {
30
32
  const params: ISearchMessagesRequest = {
31
33
  contentTypes: [
@@ -38,9 +40,10 @@ export const useSearchMessage = ({
38
40
  page: pageParam,
39
41
  pageSize: pageSize,
40
42
  applicationType,
41
- searchTerm: query,
43
+ searchTerm: query.trim(),
42
44
  conversationId,
43
45
  };
46
+ console.log('params', params);
44
47
  const res = await apiInstance?.post<BaseResponse<ISearchMessageItem[]>>(
45
48
  ENDPOINTS.chatService.searchMessages(),
46
49
  params
@@ -56,21 +59,49 @@ export const useSearchMessage = ({
56
59
  enabled: !!query && !!applicationType,
57
60
  });
58
61
 
59
- const { dataFlatten } = useMemo(() => {
60
- if (!data)
61
- return {
62
- dataFlatten: [],
63
- };
64
-
65
- const allItems =
62
+ const baseItems = useMemo<ISearchMessageItem[]>(() => {
63
+ if (!query.trim() || !data) return [];
64
+ return (
66
65
  data?.pages
67
66
  ?.flatMap?.((page) => page?.data)
68
- ?.filter((item) => item !== undefined) || [];
67
+ ?.filter((item) => item !== undefined) || []
68
+ );
69
+ }, [data, query]);
70
+
71
+ const [dataFlatten, setDataFlatten] =
72
+ useState<ISearchMessageItem[]>(baseItems);
73
+
74
+ // Sync khi baseItems thay đổi (query mới hoặc load more)
75
+ const prevBaseRef = useRef(baseItems);
76
+ if (prevBaseRef.current !== baseItems) {
77
+ prevBaseRef.current = baseItems;
78
+ setDataFlatten(baseItems);
79
+ }
69
80
 
70
- return {
71
- dataFlatten: allItems,
72
- };
73
- }, [data]);
81
+ useEffect(() => {
82
+ const sub = DeviceEventEmitter.addListener(
83
+ ChatEvent.MessageRevoked,
84
+ ({ clientMsgID }: MessageRevokedPayload) => {
85
+ setDataFlatten((prev) => {
86
+ const idx = prev.findIndex(
87
+ (item) => item.chatLog?.clientMsgID === clientMsgID
88
+ );
89
+ if (idx === -1) return prev;
90
+ const item = prev[idx]!;
91
+ const next = [...prev];
92
+ next[idx] = {
93
+ ...item,
94
+ chatLog: {
95
+ ...item.chatLog,
96
+ contentType: MessageType.RevokeMessage,
97
+ },
98
+ };
99
+ return next;
100
+ });
101
+ }
102
+ );
103
+ return () => sub.remove();
104
+ }, []);
74
105
 
75
106
  return {
76
107
  dataFlatten,
@@ -7,7 +7,12 @@ import type {
7
7
  OfflinePush,
8
8
  QuoteMsgParams,
9
9
  } from '@droppii/openim-rn-client-sdk';
10
- import { MessageStatus, MessageType } from '@droppii/openim-rn-client-sdk';
10
+ import {
11
+ GroupPermission,
12
+ MessageStatus,
13
+ MessageType,
14
+ SessionType,
15
+ } from '@droppii/openim-rn-client-sdk';
11
16
  import { extractUrls } from '../../utils/url';
12
17
  import OpenIMSDK from '@droppii/openim-rn-client-sdk';
13
18
  import {
@@ -28,6 +33,8 @@ import type { StickerItem } from '../../types/sticker';
28
33
  import { useQueryClient } from '@tanstack/react-query';
29
34
  import { stickerQueryKeys } from '../query-keys';
30
35
  import { getMessagePreview } from '../../utils/messageUtils';
36
+ import { UIUtils } from '../../utils/UIUtils';
37
+ import { trans } from '../../translation';
31
38
 
32
39
  const buildSendParams = (
33
40
  message: MessageItem,
@@ -45,7 +52,8 @@ export const useSendMessage = () => {
45
52
  const applicationType = useChatContext().applicationType;
46
53
  const pushNewMessage = useMessageStore((state) => state.pushNewMessage);
47
54
  const updateOneMessage = useMessageStore((state) => state.updateOneMessage);
48
- const { quotedMessage, setQuotedMessage } = useChatDetailContext();
55
+ const { quotedMessage, setQuotedMessage, groupPermissions } =
56
+ useChatDetailContext();
49
57
  const queryClient = useQueryClient();
50
58
 
51
59
  const dispatchSend = useCallback(
@@ -99,6 +107,16 @@ export const useSendMessage = () => {
99
107
  const recvID = currentConversation?.userID || targetUserId;
100
108
  const groupID = currentConversation?.groupID || targetGroupId;
101
109
  if (!recvID && !groupID) return;
110
+ if (
111
+ currentConversation?.conversationType === SessionType.Group &&
112
+ !groupPermissions?.includes(GroupPermission.SendMessage)
113
+ ) {
114
+ UIUtils.toast.open({
115
+ title: trans('chat:no_send_permission'),
116
+ theme: 'info',
117
+ });
118
+ return;
119
+ }
102
120
 
103
121
  const messageList: MessageItem[] = [];
104
122
 
@@ -174,6 +192,7 @@ export const useSendMessage = () => {
174
192
  quotedMessage,
175
193
  setQuotedMessage,
176
194
  queryClient,
195
+ groupPermissions,
177
196
  ]
178
197
  );
179
198