stream-chat-react-native-core 5.31.2-beta.3 → 5.32.0-beta.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 (235) hide show
  1. package/lib/commonjs/components/Channel/Channel.js +21 -20
  2. package/lib/commonjs/components/Channel/Channel.js.map +1 -1
  3. package/lib/commonjs/components/Chat/hooks/handleEventToSyncDB.js.map +1 -1
  4. package/lib/commonjs/components/Message/Message.js +9 -19
  5. package/lib/commonjs/components/Message/Message.js.map +1 -1
  6. package/lib/commonjs/components/Message/MessageSimple/MessageFooter.js +1 -2
  7. package/lib/commonjs/components/Message/MessageSimple/MessageFooter.js.map +1 -1
  8. package/lib/commonjs/components/Message/MessageSimple/ReactionList.js +54 -37
  9. package/lib/commonjs/components/Message/MessageSimple/ReactionList.js.map +1 -1
  10. package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js +6 -11
  11. package/lib/commonjs/components/Message/hooks/useCreateMessageContext.js.map +1 -1
  12. package/lib/commonjs/components/Message/hooks/useProcessReactions.js +90 -0
  13. package/lib/commonjs/components/Message/hooks/useProcessReactions.js.map +1 -0
  14. package/lib/commonjs/components/MessageOverlay/MessageOverlay.js +3 -12
  15. package/lib/commonjs/components/MessageOverlay/MessageOverlay.js.map +1 -1
  16. package/lib/commonjs/components/MessageOverlay/OverlayReactions.js +47 -143
  17. package/lib/commonjs/components/MessageOverlay/OverlayReactions.js.map +1 -1
  18. package/lib/commonjs/components/MessageOverlay/OverlayReactionsItem.js +166 -0
  19. package/lib/commonjs/components/MessageOverlay/OverlayReactionsItem.js.map +1 -0
  20. package/lib/commonjs/components/MessageOverlay/hooks/useFetchReactions.js +144 -0
  21. package/lib/commonjs/components/MessageOverlay/hooks/useFetchReactions.js.map +1 -0
  22. package/lib/commonjs/contexts/messageContext/MessageContext.js.map +1 -1
  23. package/lib/commonjs/contexts/themeContext/utils/theme.js +0 -1
  24. package/lib/commonjs/contexts/themeContext/utils/theme.js.map +1 -1
  25. package/lib/commonjs/i18n/en.json +81 -81
  26. package/lib/commonjs/i18n/es.json +81 -81
  27. package/lib/commonjs/i18n/fr.json +81 -81
  28. package/lib/commonjs/i18n/he.json +81 -81
  29. package/lib/commonjs/i18n/hi.json +81 -81
  30. package/lib/commonjs/i18n/it.json +81 -81
  31. package/lib/commonjs/i18n/ja.json +81 -81
  32. package/lib/commonjs/i18n/ko.json +81 -81
  33. package/lib/commonjs/i18n/nl.json +81 -81
  34. package/lib/commonjs/i18n/pt-br.json +83 -0
  35. package/lib/commonjs/i18n/ru.json +81 -81
  36. package/lib/commonjs/i18n/tr.json +81 -81
  37. package/lib/commonjs/mock-builders/generator/message.js +2 -0
  38. package/lib/commonjs/mock-builders/generator/message.js.map +1 -1
  39. package/lib/commonjs/store/QuickSqliteClient.js +1 -1
  40. package/lib/commonjs/store/apis/getReactions.js +17 -0
  41. package/lib/commonjs/store/apis/getReactions.js.map +1 -0
  42. package/lib/commonjs/store/apis/getReactionsforFilterSort.js +30 -0
  43. package/lib/commonjs/store/apis/getReactionsforFilterSort.js.map +1 -0
  44. package/lib/commonjs/store/apis/insertReaction.js +8 -1
  45. package/lib/commonjs/store/apis/insertReaction.js.map +1 -1
  46. package/lib/commonjs/store/apis/queries/selectReactionsForMessages.js +1 -1
  47. package/lib/commonjs/store/apis/queries/selectReactionsForMessages.js.map +1 -1
  48. package/lib/commonjs/store/apis/updateReaction.js +6 -6
  49. package/lib/commonjs/store/apis/updateReaction.js.map +1 -1
  50. package/lib/commonjs/store/mappers/mapMessageToStorable.js +5 -3
  51. package/lib/commonjs/store/mappers/mapMessageToStorable.js.map +1 -1
  52. package/lib/commonjs/store/mappers/mapStorableToMessage.js +5 -3
  53. package/lib/commonjs/store/mappers/mapStorableToMessage.js.map +1 -1
  54. package/lib/commonjs/store/schema.js +2 -1
  55. package/lib/commonjs/store/schema.js.map +1 -1
  56. package/lib/commonjs/utils/Streami18n.js +2 -2
  57. package/lib/commonjs/utils/Streami18n.js.map +1 -1
  58. package/lib/commonjs/utils/addReactionToLocalState.js +25 -13
  59. package/lib/commonjs/utils/addReactionToLocalState.js.map +1 -1
  60. package/lib/commonjs/utils/removeReactionFromLocalState.js +11 -3
  61. package/lib/commonjs/utils/removeReactionFromLocalState.js.map +1 -1
  62. package/lib/commonjs/utils/removeReservedFields.js +1 -1
  63. package/lib/commonjs/utils/removeReservedFields.js.map +1 -1
  64. package/lib/commonjs/utils/utils.js +19 -5
  65. package/lib/commonjs/utils/utils.js.map +1 -1
  66. package/lib/commonjs/version.json +1 -1
  67. package/lib/module/components/Channel/Channel.js +21 -20
  68. package/lib/module/components/Channel/Channel.js.map +1 -1
  69. package/lib/module/components/Chat/hooks/handleEventToSyncDB.js.map +1 -1
  70. package/lib/module/components/Message/Message.js +9 -19
  71. package/lib/module/components/Message/Message.js.map +1 -1
  72. package/lib/module/components/Message/MessageSimple/MessageFooter.js +1 -2
  73. package/lib/module/components/Message/MessageSimple/MessageFooter.js.map +1 -1
  74. package/lib/module/components/Message/MessageSimple/ReactionList.js +54 -37
  75. package/lib/module/components/Message/MessageSimple/ReactionList.js.map +1 -1
  76. package/lib/module/components/Message/hooks/useCreateMessageContext.js +6 -11
  77. package/lib/module/components/Message/hooks/useCreateMessageContext.js.map +1 -1
  78. package/lib/module/components/Message/hooks/useProcessReactions.js +90 -0
  79. package/lib/module/components/Message/hooks/useProcessReactions.js.map +1 -0
  80. package/lib/module/components/MessageOverlay/MessageOverlay.js +3 -12
  81. package/lib/module/components/MessageOverlay/MessageOverlay.js.map +1 -1
  82. package/lib/module/components/MessageOverlay/OverlayReactions.js +47 -143
  83. package/lib/module/components/MessageOverlay/OverlayReactions.js.map +1 -1
  84. package/lib/module/components/MessageOverlay/OverlayReactionsItem.js +166 -0
  85. package/lib/module/components/MessageOverlay/OverlayReactionsItem.js.map +1 -0
  86. package/lib/module/components/MessageOverlay/hooks/useFetchReactions.js +144 -0
  87. package/lib/module/components/MessageOverlay/hooks/useFetchReactions.js.map +1 -0
  88. package/lib/module/contexts/messageContext/MessageContext.js.map +1 -1
  89. package/lib/module/contexts/themeContext/utils/theme.js +0 -1
  90. package/lib/module/contexts/themeContext/utils/theme.js.map +1 -1
  91. package/lib/module/i18n/en.json +81 -81
  92. package/lib/module/i18n/es.json +81 -81
  93. package/lib/module/i18n/fr.json +81 -81
  94. package/lib/module/i18n/he.json +81 -81
  95. package/lib/module/i18n/hi.json +81 -81
  96. package/lib/module/i18n/it.json +81 -81
  97. package/lib/module/i18n/ja.json +81 -81
  98. package/lib/module/i18n/ko.json +81 -81
  99. package/lib/module/i18n/nl.json +81 -81
  100. package/lib/module/i18n/pt-br.json +83 -0
  101. package/lib/module/i18n/ru.json +81 -81
  102. package/lib/module/i18n/tr.json +81 -81
  103. package/lib/module/mock-builders/generator/message.js +2 -0
  104. package/lib/module/mock-builders/generator/message.js.map +1 -1
  105. package/lib/module/store/QuickSqliteClient.js +1 -1
  106. package/lib/module/store/apis/getReactions.js +17 -0
  107. package/lib/module/store/apis/getReactions.js.map +1 -0
  108. package/lib/module/store/apis/getReactionsforFilterSort.js +30 -0
  109. package/lib/module/store/apis/getReactionsforFilterSort.js.map +1 -0
  110. package/lib/module/store/apis/insertReaction.js +8 -1
  111. package/lib/module/store/apis/insertReaction.js.map +1 -1
  112. package/lib/module/store/apis/queries/selectReactionsForMessages.js +1 -1
  113. package/lib/module/store/apis/queries/selectReactionsForMessages.js.map +1 -1
  114. package/lib/module/store/apis/updateReaction.js +6 -6
  115. package/lib/module/store/apis/updateReaction.js.map +1 -1
  116. package/lib/module/store/mappers/mapMessageToStorable.js +5 -3
  117. package/lib/module/store/mappers/mapMessageToStorable.js.map +1 -1
  118. package/lib/module/store/mappers/mapStorableToMessage.js +5 -3
  119. package/lib/module/store/mappers/mapStorableToMessage.js.map +1 -1
  120. package/lib/module/store/schema.js +2 -1
  121. package/lib/module/store/schema.js.map +1 -1
  122. package/lib/module/utils/Streami18n.js +2 -2
  123. package/lib/module/utils/Streami18n.js.map +1 -1
  124. package/lib/module/utils/addReactionToLocalState.js +25 -13
  125. package/lib/module/utils/addReactionToLocalState.js.map +1 -1
  126. package/lib/module/utils/removeReactionFromLocalState.js +11 -3
  127. package/lib/module/utils/removeReactionFromLocalState.js.map +1 -1
  128. package/lib/module/utils/removeReservedFields.js +1 -1
  129. package/lib/module/utils/removeReservedFields.js.map +1 -1
  130. package/lib/module/utils/utils.js +19 -5
  131. package/lib/module/utils/utils.js.map +1 -1
  132. package/lib/module/version.json +1 -1
  133. package/lib/typescript/components/Channel/Channel.d.ts.map +1 -1
  134. package/lib/typescript/components/Channel/hooks/useCreateInputMessageInputContext.d.ts +2 -2
  135. package/lib/typescript/components/Chat/hooks/handleEventToSyncDB.d.ts.map +1 -1
  136. package/lib/typescript/components/Message/Message.d.ts.map +1 -1
  137. package/lib/typescript/components/Message/MessageSimple/ReactionList.d.ts +11 -3
  138. package/lib/typescript/components/Message/MessageSimple/ReactionList.d.ts.map +1 -1
  139. package/lib/typescript/components/Message/hooks/useCreateMessageContext.d.ts.map +1 -1
  140. package/lib/typescript/components/Message/hooks/useMessageActionHandlers.d.ts +1 -1
  141. package/lib/typescript/components/Message/hooks/useMessageActions.d.ts +1 -1
  142. package/lib/typescript/components/Message/hooks/useProcessReactions.d.ts +38 -0
  143. package/lib/typescript/components/Message/hooks/useProcessReactions.d.ts.map +1 -0
  144. package/lib/typescript/components/MessageOverlay/MessageOverlay.d.ts.map +1 -1
  145. package/lib/typescript/components/MessageOverlay/OverlayReactions.d.ts +2 -1
  146. package/lib/typescript/components/MessageOverlay/OverlayReactions.d.ts.map +1 -1
  147. package/lib/typescript/components/MessageOverlay/OverlayReactionsItem.d.ts +11 -0
  148. package/lib/typescript/components/MessageOverlay/OverlayReactionsItem.d.ts.map +1 -0
  149. package/lib/typescript/components/MessageOverlay/hooks/useFetchReactions.d.ts +14 -0
  150. package/lib/typescript/components/MessageOverlay/hooks/useFetchReactions.d.ts.map +1 -0
  151. package/lib/typescript/contexts/messageContext/MessageContext.d.ts +3 -6
  152. package/lib/typescript/contexts/messageContext/MessageContext.d.ts.map +1 -1
  153. package/lib/typescript/contexts/messageInputContext/MessageInputContext.d.ts +1 -1
  154. package/lib/typescript/contexts/themeContext/utils/theme.d.ts +0 -1
  155. package/lib/typescript/contexts/themeContext/utils/theme.d.ts.map +1 -1
  156. package/lib/typescript/i18n/en.json +81 -81
  157. package/lib/typescript/i18n/es.json +81 -81
  158. package/lib/typescript/i18n/fr.json +81 -81
  159. package/lib/typescript/i18n/he.json +81 -81
  160. package/lib/typescript/i18n/hi.json +81 -81
  161. package/lib/typescript/i18n/it.json +81 -81
  162. package/lib/typescript/i18n/ja.json +81 -81
  163. package/lib/typescript/i18n/ko.json +81 -81
  164. package/lib/typescript/i18n/nl.json +81 -81
  165. package/lib/typescript/i18n/pt-br.json +83 -0
  166. package/lib/typescript/i18n/ru.json +81 -81
  167. package/lib/typescript/i18n/tr.json +81 -81
  168. package/lib/typescript/store/apis/getReactions.d.ts +7 -0
  169. package/lib/typescript/store/apis/getReactions.d.ts.map +1 -0
  170. package/lib/typescript/store/apis/getReactionsforFilterSort.d.ts +14 -0
  171. package/lib/typescript/store/apis/getReactionsforFilterSort.d.ts.map +1 -0
  172. package/lib/typescript/store/apis/insertReaction.d.ts +3 -2
  173. package/lib/typescript/store/apis/insertReaction.d.ts.map +1 -1
  174. package/lib/typescript/store/apis/queries/selectReactionsForMessages.d.ts +4 -0
  175. package/lib/typescript/store/apis/queries/selectReactionsForMessages.d.ts.map +1 -1
  176. package/lib/typescript/store/apis/updateReaction.d.ts.map +1 -1
  177. package/lib/typescript/store/mappers/mapMessageToStorable.d.ts.map +1 -1
  178. package/lib/typescript/store/mappers/mapStorableToMessage.d.ts.map +1 -1
  179. package/lib/typescript/store/schema.d.ts +2 -1
  180. package/lib/typescript/store/schema.d.ts.map +1 -1
  181. package/lib/typescript/utils/Streami18n.d.ts +0 -5
  182. package/lib/typescript/utils/Streami18n.d.ts.map +1 -1
  183. package/lib/typescript/utils/addReactionToLocalState.d.ts.map +1 -1
  184. package/lib/typescript/utils/removeReactionFromLocalState.d.ts.map +1 -1
  185. package/lib/typescript/utils/removeReservedFields.d.ts.map +1 -1
  186. package/lib/typescript/utils/utils.d.ts +9 -3
  187. package/lib/typescript/utils/utils.d.ts.map +1 -1
  188. package/package.json +8 -9
  189. package/src/components/Channel/Channel.tsx +24 -34
  190. package/src/components/Chat/hooks/handleEventToSyncDB.ts +1 -2
  191. package/src/components/Message/Message.tsx +8 -26
  192. package/src/components/Message/MessageSimple/MessageFooter.tsx +1 -1
  193. package/src/components/Message/MessageSimple/ReactionList.tsx +72 -47
  194. package/src/components/Message/MessageSimple/__tests__/MessageContent.test.js +1 -1
  195. package/src/components/Message/hooks/useCreateMessageContext.ts +5 -10
  196. package/src/components/Message/hooks/useProcessReactions.ts +116 -0
  197. package/src/components/MessageOverlay/MessageOverlay.tsx +4 -17
  198. package/src/components/MessageOverlay/OverlayReactions.tsx +75 -176
  199. package/src/components/MessageOverlay/OverlayReactionsItem.tsx +188 -0
  200. package/src/components/MessageOverlay/hooks/useFetchReactions.ts +85 -0
  201. package/src/components/Thread/__tests__/__snapshots__/Thread.test.js.snap +139 -0
  202. package/src/contexts/messageContext/MessageContext.tsx +2 -6
  203. package/src/contexts/themeContext/utils/theme.ts +0 -2
  204. package/src/i18n/en.json +1 -1
  205. package/src/i18n/es.json +57 -57
  206. package/src/i18n/fr.json +57 -57
  207. package/src/i18n/he.json +57 -57
  208. package/src/i18n/hi.json +57 -57
  209. package/src/i18n/it.json +57 -57
  210. package/src/i18n/ja.json +57 -57
  211. package/src/i18n/ko.json +59 -59
  212. package/src/i18n/nl.json +57 -57
  213. package/src/i18n/pt-br.json +83 -0
  214. package/src/i18n/ru.json +57 -57
  215. package/src/i18n/tr.json +57 -57
  216. package/src/mock-builders/generator/message.js +2 -0
  217. package/src/store/QuickSqliteClient.ts +1 -1
  218. package/src/store/apis/getReactions.ts +21 -0
  219. package/src/store/apis/getReactionsforFilterSort.ts +43 -0
  220. package/src/store/apis/insertReaction.ts +15 -5
  221. package/src/store/apis/queries/selectReactionsForMessages.ts +5 -1
  222. package/src/store/apis/updateReaction.ts +6 -18
  223. package/src/store/mappers/mapMessageToStorable.ts +4 -2
  224. package/src/store/mappers/mapStorableToMessage.ts +12 -2
  225. package/src/store/schema.ts +4 -2
  226. package/src/utils/Streami18n.ts +1 -1
  227. package/src/utils/addReactionToLocalState.ts +33 -17
  228. package/src/utils/removeReactionFromLocalState.ts +22 -2
  229. package/src/utils/removeReservedFields.ts +2 -0
  230. package/src/utils/utils.ts +19 -7
  231. package/src/version.json +1 -1
  232. package/lib/commonjs/i18n/pt-BR.json +0 -83
  233. package/lib/module/i18n/pt-BR.json +0 -83
  234. package/lib/typescript/i18n/pt-BR.json +0 -83
  235. package/src/i18n/pt-BR.json +0 -83
@@ -1,8 +1,13 @@
1
- import React from 'react';
1
+ import React, { useMemo } from 'react';
2
2
  import { StyleSheet, Text, useWindowDimensions, View, ViewStyle } from 'react-native';
3
3
  import { FlatList } from 'react-native-gesture-handler';
4
4
  import Animated, { interpolate, useAnimatedStyle, useSharedValue } from 'react-native-reanimated';
5
- import Svg, { Circle } from 'react-native-svg';
5
+
6
+ import { ReactionSortBase } from 'stream-chat';
7
+
8
+ import { useFetchReactions } from './hooks/useFetchReactions';
9
+
10
+ import { OverlayReactionsItem } from './OverlayReactionsItem';
6
11
 
7
12
  import type { Alignment } from '../../contexts/messageContext/MessageContext';
8
13
  import type { MessageOverlayContextValue } from '../../contexts/messageOverlayContext/MessageOverlayContext';
@@ -12,7 +17,6 @@ import {
12
17
  LoveReaction,
13
18
  ThumbsDownReaction,
14
19
  ThumbsUpReaction,
15
- Unknown,
16
20
  WutReaction,
17
21
  } from '../../icons';
18
22
 
@@ -23,21 +27,6 @@ const styles = StyleSheet.create({
23
27
  avatarContainer: {
24
28
  padding: 8,
25
29
  },
26
- avatarInnerContainer: {
27
- alignSelf: 'center',
28
- },
29
- avatarName: {
30
- flex: 1,
31
- fontSize: 12,
32
- fontWeight: '700',
33
- paddingTop: 6,
34
- textAlign: 'center',
35
- },
36
- avatarNameContainer: {
37
- alignItems: 'center',
38
- flexDirection: 'row',
39
- flexGrow: 1,
40
- },
41
30
  container: {
42
31
  alignItems: 'center',
43
32
  borderRadius: 16,
@@ -52,18 +41,6 @@ const styles = StyleSheet.create({
52
41
  alignItems: 'center',
53
42
  paddingBottom: 12,
54
43
  },
55
- reactionBubble: {
56
- alignItems: 'center',
57
- borderRadius: 24,
58
- justifyContent: 'center',
59
- position: 'absolute',
60
- },
61
- reactionBubbleBackground: {
62
- borderRadius: 24,
63
- height: 24,
64
- position: 'absolute',
65
- width: 24,
66
- },
67
44
  title: {
68
45
  fontSize: 16,
69
46
  fontWeight: '700',
@@ -109,58 +86,62 @@ export type Reaction = {
109
86
  export type OverlayReactionsProps<
110
87
  StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
111
88
  > = Pick<MessageOverlayContextValue<StreamChatGenerics>, 'OverlayReactionsAvatar'> & {
112
- reactions: Reaction[];
113
89
  showScreen: Animated.SharedValue<number>;
114
90
  title: string;
115
91
  alignment?: Alignment;
92
+ messageId?: string;
93
+ reactions?: Reaction[];
116
94
  supportedReactions?: ReactionData[];
117
95
  };
118
96
 
119
- type ReactionIconProps = Pick<Reaction, 'type'> & {
120
- pathFill: string;
121
- size: number;
122
- supportedReactions: ReactionData[];
123
- };
124
-
125
- const ReactionIcon = ({ pathFill, size, supportedReactions, type }: ReactionIconProps) => {
126
- const Icon = supportedReactions.find((reaction) => reaction.type === type)?.Icon || Unknown;
127
- return <Icon height={size} pathFill={pathFill} width={size} />;
97
+ const sort: ReactionSortBase = {
98
+ created_at: -1,
128
99
  };
129
100
 
130
101
  /**
131
102
  * OverlayReactions - A high level component which implements all the logic required for message overlay reactions
132
103
  */
133
104
  export const OverlayReactions = (props: OverlayReactionsProps) => {
105
+ const [itemHeight, setItemHeight] = React.useState(0);
134
106
  const {
135
107
  alignment: overlayAlignment,
108
+ messageId,
136
109
  OverlayReactionsAvatar,
137
- reactions,
110
+ reactions: propReactions,
138
111
  showScreen,
139
112
  supportedReactions = reactionData,
140
113
  title,
141
114
  } = props;
142
115
  const layoutHeight = useSharedValue(0);
143
116
  const layoutWidth = useSharedValue(0);
144
-
145
- const [itemHeight, setItemHeight] = React.useState(0);
117
+ const {
118
+ loading,
119
+ loadNextPage,
120
+ reactions: fetchedReactions,
121
+ } = useFetchReactions({
122
+ messageId,
123
+ sort,
124
+ });
125
+
126
+ const reactions = useMemo(
127
+ () =>
128
+ propReactions ||
129
+ (fetchedReactions.map((reaction) => ({
130
+ alignment: 'left',
131
+ id: reaction.user?.id,
132
+ image: reaction.user?.image,
133
+ name: reaction.user?.name,
134
+ type: reaction.type,
135
+ })) as Reaction[]),
136
+ [propReactions, fetchedReactions],
137
+ );
146
138
 
147
139
  const {
148
140
  theme: {
149
- colors: { accent_blue, black, grey_gainsboro, white },
141
+ colors: { black, white },
150
142
  overlay: {
151
143
  padding: overlayPadding,
152
- reactions: {
153
- avatarContainer,
154
- avatarName,
155
- avatarSize,
156
- container,
157
- flatListContainer,
158
- radius,
159
- reactionBubble,
160
- reactionBubbleBackground,
161
- reactionBubbleBorderRadius,
162
- title: titleStyle,
163
- },
144
+ reactions: { avatarContainer, avatarSize, container, flatListContainer, title: titleStyle },
164
145
  },
165
146
  },
166
147
  } = useTheme();
@@ -185,100 +166,13 @@ export const OverlayReactions = (props: OverlayReactionsProps) => {
185
166
  (avatarSize + (Number(avatarContainer.padding || 0) || styles.avatarContainer.padding) * 2),
186
167
  );
187
168
 
188
- const renderItem = ({ item }: { item: Reaction }) => {
189
- const { alignment = 'left', name, type } = item;
190
- const x = avatarSize / 2 - (avatarSize / (radius * 4)) * (alignment === 'left' ? 1 : -1);
191
- const y = avatarSize - radius;
192
-
193
- const left =
194
- alignment === 'left'
195
- ? x -
196
- (Number(reactionBubbleBackground.width || 0) || styles.reactionBubbleBackground.width) +
197
- radius
198
- : x - radius;
199
- const top =
200
- y -
201
- radius -
202
- (Number(reactionBubbleBackground.height || 0) || styles.reactionBubbleBackground.height);
203
-
204
- return (
205
- <View style={[styles.avatarContainer, avatarContainer]}>
206
- <View style={styles.avatarInnerContainer}>
207
- <OverlayReactionsAvatar reaction={item} size={avatarSize} />
208
- <View style={[StyleSheet.absoluteFill]}>
209
- <Svg>
210
- <Circle
211
- cx={x - (radius * 2 - radius / 4) * (alignment === 'left' ? 1 : -1)}
212
- cy={y - radius * 2 - radius / 4}
213
- fill={alignment === 'left' ? grey_gainsboro : white}
214
- r={radius * 2}
215
- stroke={alignment === 'left' ? white : grey_gainsboro}
216
- strokeWidth={radius / 2}
217
- />
218
- <Circle
219
- cx={x}
220
- cy={y}
221
- fill={alignment === 'left' ? grey_gainsboro : white}
222
- r={radius}
223
- stroke={alignment === 'left' ? white : grey_gainsboro}
224
- strokeWidth={radius / 2}
225
- />
226
- </Svg>
227
- <View
228
- style={[
229
- styles.reactionBubbleBackground,
230
- {
231
- backgroundColor: alignment === 'left' ? grey_gainsboro : white,
232
- borderColor: alignment === 'left' ? white : grey_gainsboro,
233
- borderWidth: radius / 2,
234
- left,
235
- top,
236
- },
237
- reactionBubbleBackground,
238
- ]}
239
- />
240
- <View style={[StyleSheet.absoluteFill]}>
241
- <Svg>
242
- <Circle
243
- cx={x - (radius * 2 - radius / 4) * (alignment === 'left' ? 1 : -1)}
244
- cy={y - radius * 2 - radius / 4}
245
- fill={alignment === 'left' ? grey_gainsboro : white}
246
- r={radius * 2 - radius / 2}
247
- />
248
- </Svg>
249
- </View>
250
- <View
251
- style={[
252
- styles.reactionBubble,
253
- {
254
- backgroundColor: alignment === 'left' ? grey_gainsboro : white,
255
- height:
256
- (reactionBubbleBorderRadius || styles.reactionBubble.borderRadius) - radius / 2,
257
- left,
258
- top,
259
- width:
260
- (reactionBubbleBorderRadius || styles.reactionBubble.borderRadius) - radius / 2,
261
- },
262
- reactionBubble,
263
- ]}
264
- >
265
- <ReactionIcon
266
- pathFill={accent_blue}
267
- size={(reactionBubbleBorderRadius || styles.reactionBubble.borderRadius) / 2}
268
- supportedReactions={supportedReactions}
269
- type={type}
270
- />
271
- </View>
272
- </View>
273
- </View>
274
- <View style={styles.avatarNameContainer}>
275
- <Text numberOfLines={2} style={[styles.avatarName, { color: black }, avatarName]}>
276
- {name}
277
- </Text>
278
- </View>
279
- </View>
280
- );
281
- };
169
+ const renderItem = ({ item }: { item: Reaction }) => (
170
+ <OverlayReactionsItem
171
+ OverlayReactionsAvatar={OverlayReactionsAvatar}
172
+ reaction={item}
173
+ supportedReactions={supportedReactions}
174
+ />
175
+ );
282
176
 
283
177
  const showScreenStyle = useAnimatedStyle<ViewStyle>(
284
178
  () => ({
@@ -316,33 +210,38 @@ export const OverlayReactions = (props: OverlayReactionsProps) => {
316
210
  ]}
317
211
  >
318
212
  <Text style={[styles.title, { color: black }, titleStyle]}>{title}</Text>
319
- <FlatList
320
- contentContainerStyle={styles.flatListContentContainer}
321
- data={filteredReactions}
322
- key={numColumns}
323
- keyExtractor={({ name }, index) => `${name}_${index}`}
324
- numColumns={numColumns}
325
- renderItem={renderItem}
326
- scrollEnabled={filteredReactions.length / numColumns > 1}
327
- style={[
328
- styles.flatListContainer,
329
- flatListContainer,
330
- {
331
- // we show the item height plus a little extra to tease for scrolling if there are more than one row
332
- maxHeight:
333
- itemHeight + (filteredReactions.length / numColumns > 1 ? itemHeight / 4 : 8),
334
- },
335
- ]}
336
- />
213
+ {!loading && (
214
+ <FlatList
215
+ contentContainerStyle={styles.flatListContentContainer}
216
+ data={filteredReactions}
217
+ key={numColumns}
218
+ keyExtractor={({ id, name }, index) => `${name}${id}_${index}`}
219
+ numColumns={numColumns}
220
+ onEndReached={loadNextPage}
221
+ renderItem={renderItem}
222
+ scrollEnabled={filteredReactions.length / numColumns > 1}
223
+ style={[
224
+ styles.flatListContainer,
225
+ flatListContainer,
226
+ {
227
+ // we show the item height plus a little extra to tease for scrolling if there are more than one row
228
+ maxHeight:
229
+ itemHeight + (filteredReactions.length / numColumns > 1 ? itemHeight / 4 : 8),
230
+ },
231
+ ]}
232
+ />
233
+ )}
337
234
  {/* The below view is unseen by the user, we use it to compute the height that the item must be */}
338
- <View
339
- onLayout={({ nativeEvent: { layout } }) => {
340
- setItemHeight(layout.height);
341
- }}
342
- style={[styles.unseenItemContainer, styles.flatListContentContainer]}
343
- >
344
- {renderItem({ item: filteredReactions[0] })}
345
- </View>
235
+ {!loading && (
236
+ <View
237
+ onLayout={({ nativeEvent: { layout } }) => {
238
+ setItemHeight(layout.height);
239
+ }}
240
+ style={[styles.unseenItemContainer, styles.flatListContentContainer]}
241
+ >
242
+ {renderItem({ item: filteredReactions[0] })}
243
+ </View>
244
+ )}
346
245
  </Animated.View>
347
246
  </>
348
247
  );
@@ -0,0 +1,188 @@
1
+ import React from 'react';
2
+
3
+ import { StyleSheet, Text, View } from 'react-native';
4
+ import Svg, { Circle } from 'react-native-svg';
5
+
6
+ import { ReactionResponse } from 'stream-chat';
7
+
8
+ import { Reaction } from './OverlayReactions';
9
+
10
+ import { useChatContext } from '../../contexts/chatContext/ChatContext';
11
+ import type { MessageOverlayContextValue } from '../../contexts/messageOverlayContext/MessageOverlayContext';
12
+ import { useTheme } from '../../contexts/themeContext/ThemeContext';
13
+ import { Unknown } from '../../icons';
14
+
15
+ import type { DefaultStreamChatGenerics } from '../../types/types';
16
+ import { ReactionData } from '../../utils/utils';
17
+
18
+ export type OverlayReactionsItemProps<
19
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
20
+ > = Pick<MessageOverlayContextValue<StreamChatGenerics>, 'OverlayReactionsAvatar'> & {
21
+ reaction: Reaction;
22
+ supportedReactions: ReactionData[];
23
+ };
24
+
25
+ type ReactionIconProps<
26
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
27
+ > = Pick<ReactionResponse<StreamChatGenerics>, 'type'> & {
28
+ pathFill: string;
29
+ size: number;
30
+ supportedReactions: ReactionData[];
31
+ };
32
+
33
+ const ReactionIcon = ({ pathFill, size, supportedReactions, type }: ReactionIconProps) => {
34
+ const Icon = supportedReactions.find((reaction) => reaction.type === type)?.Icon || Unknown;
35
+ return <Icon height={size} pathFill={pathFill} width={size} />;
36
+ };
37
+
38
+ export const OverlayReactionsItem = <
39
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
40
+ >({
41
+ OverlayReactionsAvatar,
42
+ reaction,
43
+ supportedReactions,
44
+ }: OverlayReactionsItemProps<StreamChatGenerics>) => {
45
+ const { id, name, type } = reaction;
46
+ const {
47
+ theme: {
48
+ colors: { accent_blue, black, grey_gainsboro, white },
49
+ overlay: {
50
+ reactions: {
51
+ avatarContainer,
52
+ avatarName,
53
+ avatarSize,
54
+ radius,
55
+ reactionBubble,
56
+ reactionBubbleBackground,
57
+ reactionBubbleBorderRadius,
58
+ },
59
+ },
60
+ },
61
+ } = useTheme();
62
+ const { client } = useChatContext();
63
+ const alignment = client.userID && client.userID === id ? 'right' : 'left';
64
+ const x = avatarSize / 2 - (avatarSize / (radius * 4)) * (alignment === 'left' ? 1 : -1);
65
+ const y = avatarSize - radius;
66
+
67
+ const left =
68
+ alignment === 'left'
69
+ ? x -
70
+ (Number(reactionBubbleBackground.width || 0) || styles.reactionBubbleBackground.width) +
71
+ radius
72
+ : x - radius;
73
+ const top =
74
+ y -
75
+ radius -
76
+ (Number(reactionBubbleBackground.height || 0) || styles.reactionBubbleBackground.height);
77
+
78
+ return (
79
+ <View style={[styles.avatarContainer, avatarContainer]}>
80
+ <View style={styles.avatarInnerContainer}>
81
+ <OverlayReactionsAvatar reaction={reaction} size={avatarSize} />
82
+ <View style={[StyleSheet.absoluteFill]}>
83
+ <Svg>
84
+ <Circle
85
+ cx={x - (radius * 2 - radius / 4) * (alignment === 'left' ? 1 : -1)}
86
+ cy={y - radius * 2 - radius / 4}
87
+ fill={alignment === 'left' ? grey_gainsboro : white}
88
+ r={radius * 2}
89
+ stroke={alignment === 'left' ? white : grey_gainsboro}
90
+ strokeWidth={radius / 2}
91
+ />
92
+ <Circle
93
+ cx={x}
94
+ cy={y}
95
+ fill={alignment === 'left' ? grey_gainsboro : white}
96
+ r={radius}
97
+ stroke={alignment === 'left' ? white : grey_gainsboro}
98
+ strokeWidth={radius / 2}
99
+ />
100
+ </Svg>
101
+ <View
102
+ style={[
103
+ styles.reactionBubbleBackground,
104
+ {
105
+ backgroundColor: alignment === 'left' ? grey_gainsboro : white,
106
+ borderColor: alignment === 'left' ? white : grey_gainsboro,
107
+ borderWidth: radius / 2,
108
+ left,
109
+ top,
110
+ },
111
+ reactionBubbleBackground,
112
+ ]}
113
+ />
114
+ <View style={[StyleSheet.absoluteFill]}>
115
+ <Svg>
116
+ <Circle
117
+ cx={x - (radius * 2 - radius / 4) * (alignment === 'left' ? 1 : -1)}
118
+ cy={y - radius * 2 - radius / 4}
119
+ fill={alignment === 'left' ? grey_gainsboro : white}
120
+ r={radius * 2 - radius / 2}
121
+ />
122
+ </Svg>
123
+ </View>
124
+ <View
125
+ style={[
126
+ styles.reactionBubble,
127
+ {
128
+ backgroundColor: alignment === 'left' ? grey_gainsboro : white,
129
+ height:
130
+ (reactionBubbleBorderRadius || styles.reactionBubble.borderRadius) - radius / 2,
131
+ left,
132
+ top,
133
+ width:
134
+ (reactionBubbleBorderRadius || styles.reactionBubble.borderRadius) - radius / 2,
135
+ },
136
+ reactionBubble,
137
+ ]}
138
+ >
139
+ <ReactionIcon
140
+ pathFill={accent_blue}
141
+ size={(reactionBubbleBorderRadius || styles.reactionBubble.borderRadius) / 2}
142
+ supportedReactions={supportedReactions}
143
+ type={type}
144
+ />
145
+ </View>
146
+ </View>
147
+ </View>
148
+ <View style={styles.avatarNameContainer}>
149
+ <Text numberOfLines={2} style={[styles.avatarName, { color: black }, avatarName]}>
150
+ {name}
151
+ </Text>
152
+ </View>
153
+ </View>
154
+ );
155
+ };
156
+
157
+ const styles = StyleSheet.create({
158
+ avatarContainer: {
159
+ padding: 8,
160
+ },
161
+ avatarInnerContainer: {
162
+ alignSelf: 'center',
163
+ },
164
+ avatarName: {
165
+ flex: 1,
166
+ fontSize: 12,
167
+ fontWeight: '700',
168
+ paddingTop: 6,
169
+ textAlign: 'center',
170
+ },
171
+ avatarNameContainer: {
172
+ alignItems: 'center',
173
+ flexDirection: 'row',
174
+ flexGrow: 1,
175
+ },
176
+ reactionBubble: {
177
+ alignItems: 'center',
178
+ borderRadius: 24,
179
+ justifyContent: 'center',
180
+ position: 'absolute',
181
+ },
182
+ reactionBubbleBackground: {
183
+ borderRadius: 24,
184
+ height: 24,
185
+ position: 'absolute',
186
+ width: 24,
187
+ },
188
+ });
@@ -0,0 +1,85 @@
1
+ import { useCallback, useEffect, useMemo, useState } from 'react';
2
+
3
+ import { ReactionResponse, ReactionSort } from 'stream-chat';
4
+
5
+ import { useChatContext } from '../../../contexts/chatContext/ChatContext';
6
+ import { getReactionsForFilterSort } from '../../../store/apis/getReactionsforFilterSort';
7
+ import { DefaultStreamChatGenerics } from '../../../types/types';
8
+
9
+ export type UseFetchReactionParams<
10
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
11
+ > = {
12
+ limit?: number;
13
+ messageId?: string;
14
+ reactionType?: string;
15
+ sort?: ReactionSort<StreamChatGenerics>;
16
+ };
17
+
18
+ export const useFetchReactions = <
19
+ StreamChatGenerics extends DefaultStreamChatGenerics = DefaultStreamChatGenerics,
20
+ >({
21
+ limit = 25,
22
+ messageId,
23
+ reactionType,
24
+ sort,
25
+ }: UseFetchReactionParams) => {
26
+ const [reactions, setReactions] = useState<ReactionResponse<StreamChatGenerics>[]>([]);
27
+ const [loading, setLoading] = useState(true);
28
+ const [next, setNext] = useState<string | undefined>(undefined);
29
+
30
+ const { client, enableOfflineSupport } = useChatContext();
31
+
32
+ const sortString = useMemo(() => JSON.stringify(sort), [sort]);
33
+
34
+ const fetchReactions = useCallback(async () => {
35
+ const loadOfflineReactions = () => {
36
+ if (!messageId) return;
37
+ const reactionsFromDB = getReactionsForFilterSort({
38
+ currentMessageId: messageId,
39
+ filters: reactionType ? { type: reactionType } : {},
40
+ sort,
41
+ });
42
+ if (reactionsFromDB) {
43
+ setReactions(reactionsFromDB);
44
+ setLoading(false);
45
+ }
46
+ };
47
+
48
+ const loadOnlineReactions = async () => {
49
+ if (!messageId) return;
50
+ const response = await client.queryReactions(
51
+ messageId,
52
+ reactionType ? { type: reactionType } : {},
53
+ sort,
54
+ { limit, next },
55
+ );
56
+ if (response) {
57
+ setNext(response.next);
58
+ setReactions((prevReactions) => [...prevReactions, ...response.reactions]);
59
+ setLoading(false);
60
+ }
61
+ };
62
+
63
+ try {
64
+ if (enableOfflineSupport) {
65
+ loadOfflineReactions();
66
+ } else {
67
+ await loadOnlineReactions();
68
+ }
69
+ } catch (error) {
70
+ console.log('Error fetching reactions: ', error);
71
+ }
72
+ }, [client, messageId, reactionType, sortString, next, enableOfflineSupport]);
73
+
74
+ const loadNextPage = useCallback(async () => {
75
+ if (next) {
76
+ await fetchReactions();
77
+ }
78
+ }, [fetchReactions]);
79
+
80
+ useEffect(() => {
81
+ fetchReactions();
82
+ }, [messageId, reactionType, sortString]);
83
+
84
+ return { loading, loadNextPage, reactions };
85
+ };