@sendbird/uikit-react-native 1.0.2 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (172) hide show
  1. package/README.md +7 -7
  2. package/lib/commonjs/SendbirdUIKitContainer.js +5 -2
  3. package/lib/commonjs/SendbirdUIKitContainer.js.map +1 -1
  4. package/lib/commonjs/components/FileViewer.js +326 -0
  5. package/lib/commonjs/components/FileViewer.js.map +1 -0
  6. package/lib/commonjs/components/GroupChannelPreviewContainer.js +180 -0
  7. package/lib/commonjs/components/GroupChannelPreviewContainer.js.map +1 -0
  8. package/lib/commonjs/components/MessageRenderer/FileMessage/VideoFileMessage.js +116 -0
  9. package/lib/commonjs/components/MessageRenderer/FileMessage/VideoFileMessage.js.map +1 -0
  10. package/lib/commonjs/components/MessageRenderer/FileMessage/index.js +8 -0
  11. package/lib/commonjs/components/MessageRenderer/FileMessage/index.js.map +1 -1
  12. package/lib/commonjs/components/MessageRenderer/MessageOutgoingStatus.js +15 -24
  13. package/lib/commonjs/components/MessageRenderer/MessageOutgoingStatus.js.map +1 -1
  14. package/lib/commonjs/components/SBUPressable.js +45 -0
  15. package/lib/commonjs/components/SBUPressable.js.map +1 -0
  16. package/lib/commonjs/components/UserActionBar.js +1 -3
  17. package/lib/commonjs/components/UserActionBar.js.map +1 -1
  18. package/lib/commonjs/components/UserSelectableBar.js +1 -3
  19. package/lib/commonjs/components/UserSelectableBar.js.map +1 -1
  20. package/lib/commonjs/constants.js +7 -1
  21. package/lib/commonjs/constants.js.map +1 -1
  22. package/lib/commonjs/contexts/PlatformService.js +4 -2
  23. package/lib/commonjs/contexts/PlatformService.js.map +1 -1
  24. package/lib/commonjs/contexts/SendbirdChat.js +6 -2
  25. package/lib/commonjs/contexts/SendbirdChat.js.map +1 -1
  26. package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/SendInput.js +1 -1
  27. package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/SendInput.js.map +1 -1
  28. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +30 -7
  29. package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  30. package/lib/commonjs/domain/groupChannel/module/moduleContext.js +2 -3
  31. package/lib/commonjs/domain/groupChannel/module/moduleContext.js.map +1 -1
  32. package/lib/commonjs/domain/groupChannel/types.js.map +1 -1
  33. package/lib/commonjs/domain/groupChannelList/types.js.map +1 -1
  34. package/lib/commonjs/domain/groupChannelSettings/module/moduleContext.js +1 -1
  35. package/lib/commonjs/domain/groupChannelSettings/module/moduleContext.js.map +1 -1
  36. package/lib/commonjs/fragments/createGroupChannelCreateFragment.js +3 -7
  37. package/lib/commonjs/fragments/createGroupChannelCreateFragment.js.map +1 -1
  38. package/lib/commonjs/fragments/createGroupChannelFragment.js +13 -11
  39. package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
  40. package/lib/commonjs/fragments/createGroupChannelListFragment.js +7 -37
  41. package/lib/commonjs/fragments/createGroupChannelListFragment.js.map +1 -1
  42. package/lib/commonjs/fragments/createGroupChannelMembersFragment.js +1 -1
  43. package/lib/commonjs/fragments/createGroupChannelMembersFragment.js.map +1 -1
  44. package/lib/commonjs/hooks/useContext.js.map +1 -1
  45. package/lib/commonjs/index.js +29 -2
  46. package/lib/commonjs/index.js.map +1 -1
  47. package/lib/commonjs/localization/StringSet.type.js +8 -0
  48. package/lib/commonjs/localization/StringSet.type.js.map +1 -1
  49. package/lib/commonjs/platform/createFileService.expo.js +21 -2
  50. package/lib/commonjs/platform/createFileService.expo.js.map +1 -1
  51. package/lib/commonjs/platform/createFileService.native.js +20 -3
  52. package/lib/commonjs/platform/createFileService.native.js.map +1 -1
  53. package/lib/commonjs/platform/createMediaService.expo.js +64 -0
  54. package/lib/commonjs/platform/createMediaService.expo.js.map +1 -0
  55. package/lib/commonjs/platform/createMediaService.native.js +67 -0
  56. package/lib/commonjs/platform/createMediaService.native.js.map +1 -0
  57. package/lib/commonjs/platform/createNotificationService.expo.js.map +1 -1
  58. package/lib/commonjs/platform/types.js.map +1 -1
  59. package/lib/commonjs/version.js +1 -1
  60. package/lib/commonjs/version.js.map +1 -1
  61. package/lib/module/SendbirdUIKitContainer.js +5 -2
  62. package/lib/module/SendbirdUIKitContainer.js.map +1 -1
  63. package/lib/module/components/FileViewer.js +304 -0
  64. package/lib/module/components/FileViewer.js.map +1 -0
  65. package/lib/module/components/GroupChannelPreviewContainer.js +158 -0
  66. package/lib/module/components/GroupChannelPreviewContainer.js.map +1 -0
  67. package/lib/module/components/MessageRenderer/FileMessage/VideoFileMessage.js +100 -0
  68. package/lib/module/components/MessageRenderer/FileMessage/VideoFileMessage.js.map +1 -0
  69. package/lib/module/components/MessageRenderer/FileMessage/index.js +6 -0
  70. package/lib/module/components/MessageRenderer/FileMessage/index.js.map +1 -1
  71. package/lib/module/components/MessageRenderer/MessageOutgoingStatus.js +17 -26
  72. package/lib/module/components/MessageRenderer/MessageOutgoingStatus.js.map +1 -1
  73. package/lib/module/components/SBUPressable.js +33 -0
  74. package/lib/module/components/SBUPressable.js.map +1 -0
  75. package/lib/module/components/UserActionBar.js +1 -1
  76. package/lib/module/components/UserActionBar.js.map +1 -1
  77. package/lib/module/components/UserSelectableBar.js +1 -1
  78. package/lib/module/components/UserSelectableBar.js.map +1 -1
  79. package/lib/module/constants.js +5 -0
  80. package/lib/module/constants.js.map +1 -1
  81. package/lib/module/contexts/PlatformService.js +4 -2
  82. package/lib/module/contexts/PlatformService.js.map +1 -1
  83. package/lib/module/contexts/SendbirdChat.js +6 -2
  84. package/lib/module/contexts/SendbirdChat.js.map +1 -1
  85. package/lib/module/domain/groupChannel/component/GroupChannelInput/SendInput.js +1 -1
  86. package/lib/module/domain/groupChannel/component/GroupChannelInput/SendInput.js.map +1 -1
  87. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +28 -7
  88. package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
  89. package/lib/module/domain/groupChannel/module/moduleContext.js +2 -3
  90. package/lib/module/domain/groupChannel/module/moduleContext.js.map +1 -1
  91. package/lib/module/domain/groupChannel/types.js.map +1 -1
  92. package/lib/module/domain/groupChannelList/types.js.map +1 -1
  93. package/lib/module/domain/groupChannelSettings/module/moduleContext.js +1 -1
  94. package/lib/module/domain/groupChannelSettings/module/moduleContext.js.map +1 -1
  95. package/lib/module/fragments/createGroupChannelCreateFragment.js +4 -4
  96. package/lib/module/fragments/createGroupChannelCreateFragment.js.map +1 -1
  97. package/lib/module/fragments/createGroupChannelFragment.js +15 -13
  98. package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
  99. package/lib/module/fragments/createGroupChannelListFragment.js +11 -38
  100. package/lib/module/fragments/createGroupChannelListFragment.js.map +1 -1
  101. package/lib/module/fragments/createGroupChannelMembersFragment.js +1 -1
  102. package/lib/module/fragments/createGroupChannelMembersFragment.js.map +1 -1
  103. package/lib/module/hooks/useContext.js.map +1 -1
  104. package/lib/module/index.js +4 -1
  105. package/lib/module/index.js.map +1 -1
  106. package/lib/module/localization/StringSet.type.js +8 -0
  107. package/lib/module/localization/StringSet.type.js.map +1 -1
  108. package/lib/module/platform/createFileService.expo.js +21 -2
  109. package/lib/module/platform/createFileService.expo.js.map +1 -1
  110. package/lib/module/platform/createFileService.native.js +20 -3
  111. package/lib/module/platform/createFileService.native.js.map +1 -1
  112. package/lib/module/platform/createMediaService.expo.js +54 -0
  113. package/lib/module/platform/createMediaService.expo.js.map +1 -0
  114. package/lib/module/platform/createMediaService.native.js +57 -0
  115. package/lib/module/platform/createMediaService.native.js.map +1 -0
  116. package/lib/module/platform/createNotificationService.expo.js.map +1 -1
  117. package/lib/module/platform/types.js.map +1 -1
  118. package/lib/module/version.js +1 -1
  119. package/lib/module/version.js.map +1 -1
  120. package/lib/typescript/src/SendbirdUIKitContainer.d.ts +7 -3
  121. package/lib/typescript/src/components/FileViewer.d.ts +12 -0
  122. package/lib/typescript/src/components/GroupChannelPreviewContainer.d.ts +8 -0
  123. package/lib/typescript/src/components/MessageRenderer/FileMessage/VideoFileMessage.d.ts +3 -0
  124. package/lib/typescript/src/components/SBUPressable.d.ts +18 -0
  125. package/lib/typescript/src/components/UserActionBar.d.ts +2 -3
  126. package/lib/typescript/src/components/UserSelectableBar.d.ts +2 -3
  127. package/lib/typescript/src/constants.d.ts +5 -0
  128. package/lib/typescript/src/contexts/PlatformService.d.ts +3 -2
  129. package/lib/typescript/src/contexts/SendbirdChat.d.ts +5 -1
  130. package/lib/typescript/src/domain/groupChannel/component/GroupChannelMessageList.d.ts +3 -2
  131. package/lib/typescript/src/domain/groupChannel/types.d.ts +6 -2
  132. package/lib/typescript/src/hooks/useContext.d.ts +7 -5
  133. package/lib/typescript/src/index.d.ts +3 -0
  134. package/lib/typescript/src/localization/StringSet.type.d.ts +4 -0
  135. package/lib/typescript/src/platform/createMediaService.expo.d.ts +9 -0
  136. package/lib/typescript/src/platform/createMediaService.native.d.ts +9 -0
  137. package/lib/typescript/src/platform/createNotificationService.expo.d.ts +1 -1
  138. package/lib/typescript/src/platform/types.d.ts +20 -1
  139. package/lib/typescript/src/version.d.ts +1 -1
  140. package/package.json +14 -5
  141. package/src/SendbirdUIKitContainer.tsx +14 -2
  142. package/src/components/FileViewer.tsx +284 -0
  143. package/src/components/GroupChannelPreviewContainer.tsx +134 -0
  144. package/src/components/MessageRenderer/FileMessage/VideoFileMessage.tsx +91 -0
  145. package/src/components/MessageRenderer/FileMessage/index.tsx +6 -0
  146. package/src/components/MessageRenderer/MessageOutgoingStatus.tsx +25 -32
  147. package/src/components/SBUPressable.tsx +40 -0
  148. package/src/components/UserActionBar.tsx +1 -1
  149. package/src/components/UserSelectableBar.tsx +1 -1
  150. package/src/constants.ts +5 -0
  151. package/src/contexts/PlatformService.tsx +15 -3
  152. package/src/contexts/SendbirdChat.tsx +13 -5
  153. package/src/domain/groupChannel/component/GroupChannelInput/SendInput.tsx +1 -1
  154. package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +23 -6
  155. package/src/domain/groupChannel/module/moduleContext.tsx +6 -13
  156. package/src/domain/groupChannel/types.ts +8 -2
  157. package/src/domain/groupChannelList/types.ts +1 -0
  158. package/src/domain/groupChannelSettings/module/moduleContext.tsx +5 -10
  159. package/src/fragments/createGroupChannelCreateFragment.tsx +38 -41
  160. package/src/fragments/createGroupChannelFragment.tsx +23 -33
  161. package/src/fragments/createGroupChannelListFragment.tsx +10 -32
  162. package/src/fragments/createGroupChannelMembersFragment.tsx +34 -39
  163. package/src/hooks/useContext.ts +3 -5
  164. package/src/index.ts +5 -1
  165. package/src/localization/StringSet.type.ts +8 -0
  166. package/src/platform/createFileService.expo.ts +17 -2
  167. package/src/platform/createFileService.native.ts +16 -3
  168. package/src/platform/createMediaService.expo.tsx +30 -0
  169. package/src/platform/createMediaService.native.tsx +37 -0
  170. package/src/platform/createNotificationService.expo.ts +1 -1
  171. package/src/platform/types.ts +26 -1
  172. package/src/version.ts +1 -1
@@ -1,17 +1,29 @@
1
1
  import React from 'react';
2
2
 
3
- import type { ClipboardServiceInterface, FileServiceInterface, NotificationServiceInterface } from '../platform/types';
3
+ import type {
4
+ ClipboardServiceInterface,
5
+ FileServiceInterface,
6
+ MediaServiceInterface,
7
+ NotificationServiceInterface,
8
+ } from '../platform/types';
4
9
 
5
10
  type Props = React.PropsWithChildren<{
6
11
  fileService: FileServiceInterface;
7
12
  clipboardService: ClipboardServiceInterface;
8
13
  notificationService: NotificationServiceInterface;
14
+ mediaService?: MediaServiceInterface;
9
15
  }>;
10
16
 
11
17
  export const PlatformServiceContext = React.createContext<Props | null>(null);
12
- export const PlatformServiceProvider = ({ children, fileService, clipboardService, notificationService }: Props) => {
18
+ export const PlatformServiceProvider = ({
19
+ children,
20
+ fileService,
21
+ clipboardService,
22
+ notificationService,
23
+ mediaService,
24
+ }: Props) => {
13
25
  return (
14
- <PlatformServiceContext.Provider value={{ fileService, clipboardService, notificationService }}>
26
+ <PlatformServiceContext.Provider value={{ fileService, clipboardService, notificationService, mediaService }}>
15
27
  {children}
16
28
  </PlatformServiceContext.Provider>
17
29
  );
@@ -11,8 +11,8 @@ type Props = React.PropsWithChildren<{
11
11
  sdkInstance: SendbirdChatSDK;
12
12
 
13
13
  enableAutoPushTokenRegistration: boolean;
14
- // enableChannelListTypingIndicator: boolean;
15
- // enableChannelListMessageReceiptStatus: boolean;
14
+ enableChannelListTypingIndicator: boolean;
15
+ enableChannelListMessageReceiptStatus: boolean;
16
16
  }>;
17
17
 
18
18
  type Context = {
@@ -27,8 +27,8 @@ type Context = {
27
27
  features: {
28
28
  // UIKit features
29
29
  autoPushTokenRegistrationEnabled: boolean;
30
- // channelListTypingIndicatorEnabled: boolean;
31
- // channelListMessageReceiptStateEnabled: boolean;
30
+ channelListTypingIndicatorEnabled: boolean;
31
+ channelListMessageReceiptStatusEnabled: boolean;
32
32
 
33
33
  // Sendbird application features
34
34
  deliveryReceiptEnabled: boolean;
@@ -39,7 +39,13 @@ type Context = {
39
39
  };
40
40
 
41
41
  export const SendbirdChatContext = React.createContext<Context | null>(null);
42
- export const SendbirdChatProvider = ({ children, sdkInstance, enableAutoPushTokenRegistration }: Props) => {
42
+ export const SendbirdChatProvider = ({
43
+ children,
44
+ sdkInstance,
45
+ enableAutoPushTokenRegistration,
46
+ enableChannelListMessageReceiptStatus,
47
+ enableChannelListTypingIndicator,
48
+ }: Props) => {
43
49
  const [currentUser, _setCurrentUser] = useState<SendbirdUser>();
44
50
  const forceUpdate = useForceUpdate();
45
51
  const appFeatures = useAppFeatures(sdkInstance);
@@ -103,6 +109,8 @@ export const SendbirdChatProvider = ({ children, sdkInstance, enableAutoPushToke
103
109
  features: {
104
110
  ...appFeatures,
105
111
  autoPushTokenRegistrationEnabled: enableAutoPushTokenRegistration,
112
+ channelListTypingIndicatorEnabled: enableChannelListTypingIndicator,
113
+ channelListMessageReceiptStatusEnabled: enableChannelListMessageReceiptStatus,
106
114
  },
107
115
  };
108
116
 
@@ -38,7 +38,7 @@ const SendInput = ({ onSendUserMessage, onSendFileMessage, text, setText, disabl
38
38
  icon: 'camera',
39
39
  onPress: async () => {
40
40
  const photo = await fileService.openCamera({
41
- mediaType: 'photo',
41
+ mediaType: 'all',
42
42
  onOpenFailureWithToastMessage: () => toast.show(STRINGS.TOAST.OPEN_CAMERA_ERROR, 'error'),
43
43
  });
44
44
 
@@ -19,11 +19,13 @@ import {
19
19
  getFileType,
20
20
  isMyMessage,
21
21
  messageKeyExtractor,
22
+ toMegabyte,
22
23
  useFreshCallback,
23
24
  } from '@sendbird/uikit-utils';
24
25
 
25
26
  import type { ChatFlatListRef } from '../../../components/ChatFlatList';
26
27
  import ChatFlatList from '../../../components/ChatFlatList';
28
+ import { DEPRECATION_WARNING } from '../../../constants';
27
29
  import { useLocalization, usePlatformService } from '../../../hooks/useContext';
28
30
  import { GroupChannelContexts } from '../module/moduleContext';
29
31
  import type { GroupChannelProps } from '../types';
@@ -44,6 +46,7 @@ const GroupChannelMessageList = ({
44
46
  onResendFailedMessage,
45
47
  onDeleteMessage,
46
48
  onPressImageMessage,
49
+ onPressMediaMessage,
47
50
  flatListProps,
48
51
  enableMessageGrouping,
49
52
  }: GroupChannelProps['MessageList']) => {
@@ -56,6 +59,7 @@ const GroupChannelMessageList = ({
56
59
  const getMessagePressActions = useGetMessagePressActions({
57
60
  onDeleteMessage,
58
61
  onPressImageMessage,
62
+ onPressMediaMessage,
59
63
  currentUserId,
60
64
  onResendFailedMessage,
61
65
  });
@@ -135,15 +139,15 @@ const GroupChannelMessageList = ({
135
139
  };
136
140
 
137
141
  type HandleableMessage = SendbirdUserMessage | SendbirdFileMessage;
138
- const toMegabyte = (byte: number) => byte / 1024 / 1024;
139
142
  const useGetMessagePressActions = ({
140
143
  onPressImageMessage,
144
+ onPressMediaMessage,
141
145
  onDeleteMessage,
142
146
  onResendFailedMessage,
143
147
  currentUserId,
144
148
  }: Pick<
145
149
  GroupChannelProps['MessageList'],
146
- 'onDeleteMessage' | 'onResendFailedMessage' | 'onPressImageMessage' | 'currentUserId'
150
+ 'onDeleteMessage' | 'onResendFailedMessage' | 'currentUserId' | 'onPressImageMessage' | 'onPressMediaMessage'
147
151
  >) => {
148
152
  const { colors } = useUIKitTheme();
149
153
  const { STRINGS } = useLocalization();
@@ -253,10 +257,23 @@ const useGetMessagePressActions = ({
253
257
  }
254
258
 
255
259
  const fileType = getFileType(msg.type || getFileExtension(msg.name));
256
- if (fileType === 'image') {
257
- response.onPress = () => onPressImageMessage?.(msg, getAvailableUriFromFileMessage(msg));
258
- } else {
259
- response.onPress = () => Linking.openURL(msg.url).catch();
260
+ switch (fileType) {
261
+ case 'image':
262
+ case 'video':
263
+ case 'audio': {
264
+ response.onPress = () => {
265
+ if (onPressImageMessage && fileType === 'image') {
266
+ Logger.warn(DEPRECATION_WARNING.GROUP_CHANNEL.ON_PRESS_IMAGE_MESSAGE);
267
+ onPressImageMessage(msg, getAvailableUriFromFileMessage(msg));
268
+ }
269
+ onPressMediaMessage?.(msg, () => onDeleteMessage(msg), getAvailableUriFromFileMessage(msg));
270
+ };
271
+ break;
272
+ }
273
+ default: {
274
+ response.onPress = () => Linking.openURL(msg.url).catch();
275
+ break;
276
+ }
260
277
  }
261
278
  }
262
279
 
@@ -41,20 +41,13 @@ export const GroupChannelContextsProvider: GroupChannelModule['Provider'] = ({
41
41
  const [typingUsers, setTypingUsers] = useState<SendbirdUser[]>([]);
42
42
  const [editMessage, setEditMessage] = useState<SendbirdUserMessage | SendbirdFileMessage>();
43
43
 
44
- useChannelHandler(
45
- sdk,
46
- `GroupChannelContextsProvider_${id}`,
47
- {
48
- onTypingStatusUpdated(eventChannel) {
49
- if (isDifferentChannel(channel, eventChannel)) return;
50
- if (!enableTypingIndicator) return;
51
-
52
- const usersWithoutMe = eventChannel.getTypingUsers().filter((u) => u.userId !== currentUser?.userId);
53
- setTypingUsers(usersWithoutMe);
54
- },
44
+ useChannelHandler(sdk, `GroupChannelContextsProvider_${id}`, {
45
+ onTypingStatusUpdated(eventChannel) {
46
+ if (isDifferentChannel(channel, eventChannel)) return;
47
+ if (!enableTypingIndicator) return;
48
+ setTypingUsers(eventChannel.getTypingUsers());
55
49
  },
56
- [channel, currentUser?.userId, enableTypingIndicator],
57
- );
50
+ });
58
51
 
59
52
  return (
60
53
  <ProviderLayout>
@@ -28,7 +28,7 @@ export interface GroupChannelProps {
28
28
  onBeforeSendUserMessage?: (
29
29
  params: SendbirdUserMessageParams,
30
30
  ) => SendbirdUserMessageParams | Promise<SendbirdUserMessageParams>;
31
- onPressImageMessage?: GroupChannelProps['MessageList']['onPressImageMessage'];
31
+ onPressMediaMessage?: GroupChannelProps['MessageList']['onPressMediaMessage'];
32
32
 
33
33
  renderMessage?: GroupChannelProps['MessageList']['renderMessage'];
34
34
  renderNewMessagesButton?: GroupChannelProps['MessageList']['renderNewMessagesButton'];
@@ -42,6 +42,9 @@ export interface GroupChannelProps {
42
42
  sortComparator?: UseGroupChannelMessagesOptions['sortComparator'];
43
43
  collectionCreator?: UseGroupChannelMessagesOptions['collectionCreator'];
44
44
  queryCreator?: UseGroupChannelMessagesOptions['queryCreator'];
45
+
46
+ /** @deprecated `onPressImageMessage` is deprecated, please use `onPressMediaMessage` instead **/
47
+ onPressImageMessage?: GroupChannelProps['MessageList']['onPressImageMessage'];
45
48
  };
46
49
  Header: {
47
50
  onPressHeaderLeft: () => void;
@@ -59,7 +62,7 @@ export interface GroupChannelProps {
59
62
 
60
63
  onResendFailedMessage: (failedMessage: SendbirdUserMessage | SendbirdFileMessage) => Promise<void>;
61
64
  onDeleteMessage: (message: SendbirdUserMessage | SendbirdFileMessage) => Promise<void>;
62
- onPressImageMessage?: (message: SendbirdFileMessage, uri: string) => void;
65
+ onPressMediaMessage?: (message: SendbirdFileMessage, deleteMessage: () => Promise<void>, uri: string) => void;
63
66
 
64
67
  renderMessage: (props: {
65
68
  message: SendbirdMessage;
@@ -81,6 +84,9 @@ export interface GroupChannelProps {
81
84
  onPress: () => void;
82
85
  }>;
83
86
  flatListProps?: Omit<FlatListProps<SendbirdMessage>, 'data' | 'renderItem'>;
87
+
88
+ /** @deprecated `onPressImageMessage` is deprecated, please use `onPressMediaMessage` instead **/
89
+ onPressImageMessage?: (message: SendbirdFileMessage, uri: string) => void;
84
90
  };
85
91
  Input: {
86
92
  channel: SendbirdGroupChannel;
@@ -42,6 +42,7 @@ export interface GroupChannelListProps {
42
42
  groupChannels: SendbirdGroupChannel[];
43
43
  /** Method to render GroupChannel preview **/
44
44
  renderGroupChannelPreview: (
45
+ // FIXME/BREAKING: Changed to props object
45
46
  channel: SendbirdGroupChannel,
46
47
  onLongPressChannel: () => void,
47
48
  ) => React.ReactElement | null;
@@ -41,16 +41,11 @@ export const GroupChannelSettingsContextsProvider: GroupChannelSettingsModule['P
41
41
  forceUpdate();
42
42
  };
43
43
 
44
- useChannelHandler(
45
- sdk,
46
- `${HOOK_NAME}_${uniqId}`,
47
- {
48
- onChannelChanged: onChannelChanged,
49
- onChannelFrozen: onChannelChanged,
50
- onChannelUnfrozen: onChannelChanged,
51
- },
52
- [activeChannel],
53
- );
44
+ useChannelHandler(sdk, `${HOOK_NAME}_${uniqId}`, {
45
+ onChannelChanged: onChannelChanged,
46
+ onChannelFrozen: onChannelChanged,
47
+ onChannelUnfrozen: onChannelChanged,
48
+ });
54
49
 
55
50
  const toast = useToast();
56
51
  const { openSheet } = useBottomSheet();
@@ -1,8 +1,8 @@
1
- import React, { useCallback } from 'react';
1
+ import React from 'react';
2
2
  import { TouchableOpacity } from 'react-native';
3
3
 
4
4
  import { useUserList } from '@sendbird/uikit-chat-hooks';
5
- import { Logger, PASS, SendbirdUser } from '@sendbird/uikit-utils';
5
+ import { Logger, PASS, SendbirdUser, useFreshCallback } from '@sendbird/uikit-utils';
6
6
 
7
7
  import StatusComposition from '../components/StatusComposition';
8
8
  import UserSelectableBar from '../components/UserSelectableBar';
@@ -50,45 +50,42 @@ const createGroupChannelCreateFragment = <UserType,>(
50
50
  sortComparator,
51
51
  });
52
52
 
53
- const _renderUser: NonNullable<typeof renderUser> = useCallback(
54
- (user, selectedUsers, setSelectedUsers) => {
55
- if (queryCreator && !renderUser) {
56
- throw new Error('You should provide "renderUser" when providing "queryCreator"');
57
- }
58
- if (renderUser) return renderUser(user, selectedUsers, setSelectedUsers);
59
-
60
- const sbUser = user as unknown as SendbirdUser;
61
- const sbSelectedUsers = selectedUsers as unknown as SendbirdUser[];
62
- const sbSetSelectedUsers = setSelectedUsers as unknown as React.Dispatch<React.SetStateAction<SendbirdUser[]>>;
63
-
64
- const isMe = sbUser.userId === currentUser?.userId;
65
- if (isMe) return null;
66
-
67
- const userIdx = sbSelectedUsers.findIndex((u) => u.userId === sbUser.userId);
68
- const isSelected = userIdx > -1;
69
-
70
- return (
71
- <TouchableOpacity
72
- activeOpacity={0.7}
73
- onPress={() => {
74
- sbSetSelectedUsers(([...draft]) => {
75
- if (isSelected) draft.splice(userIdx, 1);
76
- else draft.push(sbUser);
77
- return draft;
78
- });
79
- }}
80
- >
81
- <UserSelectableBar
82
- uri={sbUser.profileUrl}
83
- name={sbUser.nickname || STRINGS.LABELS.USER_NO_NAME}
84
- selected={isSelected}
85
- disabled={false}
86
- />
87
- </TouchableOpacity>
88
- );
89
- },
90
- [renderUser, queryCreator],
91
- );
53
+ const _renderUser: NonNullable<typeof renderUser> = useFreshCallback((user, selectedUsers, setSelectedUsers) => {
54
+ if (queryCreator && !renderUser) {
55
+ throw new Error('You should provide "renderUser" when providing "queryCreator"');
56
+ }
57
+ if (renderUser) return renderUser(user, selectedUsers, setSelectedUsers);
58
+
59
+ const sbUser = user as unknown as SendbirdUser;
60
+ const sbSelectedUsers = selectedUsers as unknown as SendbirdUser[];
61
+ const sbSetSelectedUsers = setSelectedUsers as unknown as React.Dispatch<React.SetStateAction<SendbirdUser[]>>;
62
+
63
+ const isMe = sbUser.userId === currentUser?.userId;
64
+ if (isMe) return null;
65
+
66
+ const userIdx = sbSelectedUsers.findIndex((u) => u.userId === sbUser.userId);
67
+ const isSelected = userIdx > -1;
68
+
69
+ return (
70
+ <TouchableOpacity
71
+ activeOpacity={0.7}
72
+ onPress={() => {
73
+ sbSetSelectedUsers(([...draft]) => {
74
+ if (isSelected) draft.splice(userIdx, 1);
75
+ else draft.push(sbUser);
76
+ return draft;
77
+ });
78
+ }}
79
+ >
80
+ <UserSelectableBar
81
+ uri={sbUser.profileUrl}
82
+ name={sbUser.nickname || STRINGS.LABELS.USER_NO_NAME}
83
+ selected={isSelected}
84
+ disabled={false}
85
+ />
86
+ </TouchableOpacity>
87
+ );
88
+ });
92
89
 
93
90
  return (
94
91
  <UserListModule.Provider
@@ -1,7 +1,7 @@
1
- import React, { useCallback, useMemo } from 'react';
1
+ import React, { useMemo } from 'react';
2
2
 
3
3
  import { useGroupChannelMessages } from '@sendbird/uikit-chat-hooks';
4
- import { NOOP, PASS, messageComparator } from '@sendbird/uikit-utils';
4
+ import { NOOP, PASS, messageComparator, useFreshCallback } from '@sendbird/uikit-utils';
5
5
 
6
6
  import MessageRenderer from '../components/MessageRenderer';
7
7
  import NewMessagesButton from '../components/NewMessagesButton';
@@ -22,7 +22,8 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
22
22
  enableTypingIndicator = true,
23
23
  onPressHeaderLeft = NOOP,
24
24
  onPressHeaderRight = NOOP,
25
- onPressImageMessage = NOOP,
25
+ onPressImageMessage,
26
+ onPressMediaMessage = NOOP,
26
27
  onChannelDeleted = NOOP,
27
28
  onBeforeSendFileMessage = PASS,
28
29
  onBeforeSendUserMessage = PASS,
@@ -57,13 +58,10 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
57
58
  enableCollectionWithoutLocalCache: true,
58
59
  });
59
60
 
60
- const _renderMessage: GroupChannelProps['MessageList']['renderMessage'] = useCallback(
61
- (props) => {
62
- if (renderMessage) return renderMessage(props);
63
- return <MessageRenderer {...props} />;
64
- },
65
- [renderMessage],
66
- );
61
+ const _renderMessage: GroupChannelProps['MessageList']['renderMessage'] = useFreshCallback((props) => {
62
+ if (renderMessage) return renderMessage(props);
63
+ return <MessageRenderer {...props} />;
64
+ });
67
65
 
68
66
  const memoizedFlatListProps = useMemo(
69
67
  () => ({
@@ -74,42 +72,33 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
74
72
  [loading, flatListProps],
75
73
  );
76
74
 
77
- const onSendFileMessage: GroupChannelProps['Input']['onSendFileMessage'] = useCallback(
78
- async (file) => {
79
- const params = new sdk.FileMessageParams();
80
- params.file = file;
81
- const processedParams = await onBeforeSendFileMessage(params);
82
- await sendFileMessage(processedParams);
83
- },
84
- [sdk, sendFileMessage, onBeforeSendFileMessage],
85
- );
86
-
87
- const onSendUserMessage: GroupChannelProps['Input']['onSendUserMessage'] = useCallback(
88
- async (text) => {
89
- const params = new sdk.UserMessageParams();
90
- params.message = text;
91
- const processedParams = await onBeforeSendUserMessage(params);
92
- await sendUserMessage(processedParams);
93
- },
94
- [sdk, sendUserMessage, onBeforeSendUserMessage],
95
- );
96
- const onUpdateFileMessage: GroupChannelProps['Input']['onUpdateFileMessage'] = useCallback(
75
+ const onSendFileMessage: GroupChannelProps['Input']['onSendFileMessage'] = useFreshCallback(async (file) => {
76
+ const params = new sdk.FileMessageParams();
77
+ params.file = file;
78
+ const processedParams = await onBeforeSendFileMessage(params);
79
+ await sendFileMessage(processedParams);
80
+ });
81
+ const onSendUserMessage: GroupChannelProps['Input']['onSendUserMessage'] = useFreshCallback(async (text) => {
82
+ const params = new sdk.UserMessageParams();
83
+ params.message = text;
84
+ const processedParams = await onBeforeSendUserMessage(params);
85
+ await sendUserMessage(processedParams);
86
+ });
87
+ const onUpdateFileMessage: GroupChannelProps['Input']['onUpdateFileMessage'] = useFreshCallback(
97
88
  async (editedFile, message) => {
98
89
  const params = new sdk.FileMessageParams();
99
90
  params.file = editedFile;
100
91
  const processedParams = await onBeforeSendFileMessage(params);
101
92
  await updateFileMessage(message.messageId, processedParams);
102
93
  },
103
- [sdk, updateFileMessage, onBeforeSendFileMessage],
104
94
  );
105
- const onUpdateUserMessage: GroupChannelProps['Input']['onUpdateUserMessage'] = useCallback(
95
+ const onUpdateUserMessage: GroupChannelProps['Input']['onUpdateUserMessage'] = useFreshCallback(
106
96
  async (editedText, message) => {
107
97
  const params = new sdk.UserMessageParams();
108
98
  params.message = editedText;
109
99
  const processedParams = await onBeforeSendUserMessage(params);
110
100
  await updateUserMessage(message.messageId, processedParams);
111
101
  },
112
- [sdk, updateUserMessage, onBeforeSendUserMessage],
113
102
  );
114
103
 
115
104
  return (
@@ -135,6 +124,7 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
135
124
  onResendFailedMessage={resendMessage}
136
125
  onDeleteMessage={deleteMessage}
137
126
  onPressImageMessage={onPressImageMessage}
127
+ onPressMediaMessage={onPressMediaMessage}
138
128
  flatListProps={memoizedFlatListProps}
139
129
  />
140
130
  <GroupChannelModule.Input
@@ -1,22 +1,19 @@
1
- import React, { useCallback, useEffect } from 'react';
2
- import { AppState, Pressable } from 'react-native';
1
+ import React, { useEffect } from 'react';
2
+ import { AppState } from 'react-native';
3
3
 
4
4
  import { useGroupChannelList } from '@sendbird/uikit-chat-hooks';
5
- import { GroupChannelPreview } from '@sendbird/uikit-react-native-foundation';
6
- import { Logger, PASS, channelComparator, getFileExtension, getFileType } from '@sendbird/uikit-utils';
5
+ import { Logger, PASS, channelComparator, useFreshCallback } from '@sendbird/uikit-utils';
7
6
 
8
- import ChannelCover from '../components/ChannelCover';
7
+ import GroupChannelPreviewContainer from '../components/GroupChannelPreviewContainer';
9
8
  import StatusComposition from '../components/StatusComposition';
10
- import { DEFAULT_LONG_PRESS_DELAY } from '../constants';
11
9
  import createGroupChannelListModule from '../domain/groupChannelList/module/createGroupChannelListModule';
12
10
  import type {
13
11
  GroupChannelListFragment,
14
12
  GroupChannelListModule,
15
13
  GroupChannelListProps,
16
14
  } from '../domain/groupChannelList/types';
17
- import { useLocalization, useSendbirdChat } from '../hooks/useContext';
15
+ import { useSendbirdChat } from '../hooks/useContext';
18
16
 
19
- const iconMapper = { audio: 'file-audio', image: 'photo', video: 'play', file: 'file-document' } as const;
20
17
  const createGroupChannelListFragment = (initModule?: Partial<GroupChannelListModule>): GroupChannelListFragment => {
21
18
  const GroupChannelListModule = createGroupChannelListModule(initModule);
22
19
  return ({
@@ -31,7 +28,6 @@ const createGroupChannelListFragment = (initModule?: Partial<GroupChannelListMod
31
28
  menuItemCreator = PASS,
32
29
  }) => {
33
30
  const { sdk, currentUser, features, markAsDeliveredWithChannel } = useSendbirdChat();
34
- const { STRINGS } = useLocalization();
35
31
  const { groupChannels, next, loading } = useGroupChannelList(sdk, currentUser?.userId, {
36
32
  queryCreator,
37
33
  sortComparator,
@@ -47,35 +43,17 @@ const createGroupChannelListFragment = (initModule?: Partial<GroupChannelListMod
47
43
  }, []);
48
44
  }
49
45
 
50
- const _renderGroupChannelPreview: GroupChannelListProps['List']['renderGroupChannelPreview'] = useCallback(
46
+ const _renderGroupChannelPreview: GroupChannelListProps['List']['renderGroupChannelPreview'] = useFreshCallback(
51
47
  (channel, onLongPressChannel) => {
52
48
  if (renderGroupChannelPreview) return renderGroupChannelPreview(channel, onLongPressChannel);
53
49
  return (
54
- <Pressable
50
+ <GroupChannelPreviewContainer
51
+ channel={channel}
55
52
  onPress={() => onPressChannel(channel)}
56
- onLongPress={onLongPressChannel}
57
- delayLongPress={DEFAULT_LONG_PRESS_DELAY}
58
- >
59
- <GroupChannelPreview
60
- customCover={<ChannelCover channel={channel} size={56} />}
61
- coverUrl={channel.coverUrl}
62
- title={STRINGS.GROUP_CHANNEL_LIST.CHANNEL_PREVIEW_TITLE(currentUser?.userId ?? '', channel)}
63
- titleCaption={STRINGS.GROUP_CHANNEL_LIST.CHANNEL_PREVIEW_TITLE_CAPTION(channel)}
64
- body={STRINGS.GROUP_CHANNEL_LIST.CHANNEL_PREVIEW_BODY(channel)}
65
- badgeCount={channel.unreadMessageCount}
66
- bodyIcon={
67
- channel.lastMessage?.isFileMessage()
68
- ? iconMapper[getFileType(channel.lastMessage.type || getFileExtension(channel.lastMessage.name))]
69
- : undefined
70
- }
71
- frozen={channel.isFrozen}
72
- notificationOff={channel.myPushTriggerOption === 'off'}
73
- memberCount={channel.memberCount > 2 ? channel.memberCount : undefined}
74
- />
75
- </Pressable>
53
+ onLongPress={() => onLongPressChannel()}
54
+ />
76
55
  );
77
56
  },
78
- [STRINGS, onPressChannel, currentUser?.userId],
79
57
  );
80
58
 
81
59
  if (!currentUser) {
@@ -26,46 +26,41 @@ const createGroupChannelMembersFragment = (
26
26
 
27
27
  const { STRINGS } = useLocalization();
28
28
 
29
- useChannelHandler(
30
- sdk,
31
- `${name}_${uniqId}`,
32
- {
33
- onUserEntered(channel) {
34
- if (channel.url === activeChannel.url) forceUpdate();
35
- },
36
- onUserLeft(channel) {
37
- if (channel.url === activeChannel.url) forceUpdate();
38
- },
39
- onUserJoined(channel) {
40
- if (channel.url === activeChannel.url) forceUpdate();
41
- },
42
- onUserUnmuted(channel) {
43
- if (channel.url === activeChannel.url) forceUpdate();
44
- },
45
- onUserUnbanned(channel) {
46
- if (channel.url === activeChannel.url) forceUpdate();
47
- },
48
- onUserBanned(channel) {
49
- if (channel.url === activeChannel.url) forceUpdate();
50
- },
51
- onUserMuted(channel) {
52
- if (channel.url === activeChannel.url) forceUpdate();
53
- },
54
- onChannelMemberCountChanged(channels) {
55
- if (channels.find((c) => c.url === channel.url)) forceUpdate();
56
- },
57
- onChannelChanged(channel) {
58
- if (channel.url === activeChannel.url) forceUpdate();
59
- },
60
- onChannelFrozen(channel) {
61
- if (channel.url === activeChannel.url) forceUpdate();
62
- },
63
- onChannelUnfrozen(channel) {
64
- if (channel.url === activeChannel.url) forceUpdate();
65
- },
29
+ useChannelHandler(sdk, `${name}_${uniqId}`, {
30
+ onUserEntered(channel) {
31
+ if (channel.url === activeChannel.url) forceUpdate();
66
32
  },
67
- [activeChannel],
68
- );
33
+ onUserLeft(channel) {
34
+ if (channel.url === activeChannel.url) forceUpdate();
35
+ },
36
+ onUserJoined(channel) {
37
+ if (channel.url === activeChannel.url) forceUpdate();
38
+ },
39
+ onUserUnmuted(channel) {
40
+ if (channel.url === activeChannel.url) forceUpdate();
41
+ },
42
+ onUserUnbanned(channel) {
43
+ if (channel.url === activeChannel.url) forceUpdate();
44
+ },
45
+ onUserBanned(channel) {
46
+ if (channel.url === activeChannel.url) forceUpdate();
47
+ },
48
+ onUserMuted(channel) {
49
+ if (channel.url === activeChannel.url) forceUpdate();
50
+ },
51
+ onChannelMemberCountChanged(channels) {
52
+ if (channels.find((c) => c.url === channel.url)) forceUpdate();
53
+ },
54
+ onChannelChanged(channel) {
55
+ if (channel.url === activeChannel.url) forceUpdate();
56
+ },
57
+ onChannelFrozen(channel) {
58
+ if (channel.url === activeChannel.url) forceUpdate();
59
+ },
60
+ onChannelUnfrozen(channel) {
61
+ if (channel.url === activeChannel.url) forceUpdate();
62
+ },
63
+ });
69
64
 
70
65
  const _renderUser: NonNullable<typeof renderUser> = useCallback(
71
66
  (user, selectedUsers, setSelectedUsers) => {
@@ -1,13 +1,11 @@
1
- import React, { useContext } from 'react';
1
+ import { useContext } from 'react';
2
2
 
3
- import { LocalizationContext, LocalizationContextType } from '../contexts/Localization';
3
+ import { LocalizationContext } from '../contexts/Localization';
4
4
  import { PlatformServiceContext } from '../contexts/PlatformService';
5
5
  import { SendbirdChatContext } from '../contexts/SendbirdChat';
6
6
 
7
7
  export const useLocalization = () => {
8
- const value = useContext<LocalizationContextType | null>(
9
- LocalizationContext as React.Context<LocalizationContextType | null>,
10
- );
8
+ const value = useContext(LocalizationContext);
11
9
  if (!value) throw new Error('LocalizationContext is not provided');
12
10
  return value;
13
11
  };