@sendbird/uikit-react-native 1.1.1 → 2.0.0-rc.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 (174) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/components/ChatFlatList.js +10 -8
  3. package/lib/commonjs/components/ChatFlatList.js.map +1 -1
  4. package/lib/commonjs/components/FileViewer.js +8 -3
  5. package/lib/commonjs/components/FileViewer.js.map +1 -1
  6. package/lib/commonjs/components/MessageRenderer/FileMessage/ImageFileMessage.js +47 -15
  7. package/lib/commonjs/components/MessageRenderer/FileMessage/ImageFileMessage.js.map +1 -1
  8. package/lib/commonjs/components/MessageRenderer/FileMessage/VideoFileMessage.js +51 -34
  9. package/lib/commonjs/components/MessageRenderer/FileMessage/VideoFileMessage.js.map +1 -1
  10. package/lib/commonjs/components/MessageRenderer/MessageIncomingSenderName.js +2 -1
  11. package/lib/commonjs/components/MessageRenderer/MessageIncomingSenderName.js.map +1 -1
  12. package/lib/commonjs/components/MessageRenderer/UserMessage/OpenGraphUserMessage.js +3 -1
  13. package/lib/commonjs/components/MessageRenderer/UserMessage/OpenGraphUserMessage.js.map +1 -1
  14. package/lib/commonjs/components/MessageRenderer/index.js +7 -2
  15. package/lib/commonjs/components/MessageRenderer/index.js.map +1 -1
  16. package/lib/commonjs/containers/SendbirdUIKitContainer.js +12 -15
  17. package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
  18. package/lib/commonjs/contexts/SendbirdChat.js +9 -9
  19. package/lib/commonjs/contexts/SendbirdChat.js.map +1 -1
  20. package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/SendInput.js +39 -6
  21. package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/SendInput.js.map +1 -1
  22. package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/index.js +4 -4
  23. package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/index.js.map +1 -1
  24. package/lib/commonjs/domain/groupChannel/types.js.map +1 -1
  25. package/lib/commonjs/domain/groupChannelList/component/GroupChannelListList.js +4 -2
  26. package/lib/commonjs/domain/groupChannelList/component/GroupChannelListList.js.map +1 -1
  27. package/lib/commonjs/domain/groupChannelSettings/component/GroupChannelSettingsInfo.js +1 -1
  28. package/lib/commonjs/domain/groupChannelSettings/component/GroupChannelSettingsInfo.js.map +1 -1
  29. package/lib/commonjs/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js +4 -2
  30. package/lib/commonjs/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js.map +1 -1
  31. package/lib/commonjs/domain/groupChannelSettings/module/moduleContext.js +44 -13
  32. package/lib/commonjs/domain/groupChannelSettings/module/moduleContext.js.map +1 -1
  33. package/lib/commonjs/domain/groupChannelUserList/types.js.map +1 -1
  34. package/lib/commonjs/fragments/createGroupChannelCreateFragment.js +7 -6
  35. package/lib/commonjs/fragments/createGroupChannelCreateFragment.js.map +1 -1
  36. package/lib/commonjs/fragments/createGroupChannelFragment.js +12 -12
  37. package/lib/commonjs/fragments/createGroupChannelFragment.js.map +1 -1
  38. package/lib/commonjs/fragments/createGroupChannelListFragment.js +1 -1
  39. package/lib/commonjs/fragments/createGroupChannelListFragment.js.map +1 -1
  40. package/lib/commonjs/fragments/createGroupChannelMembersFragment.js +4 -4
  41. package/lib/commonjs/fragments/createGroupChannelMembersFragment.js.map +1 -1
  42. package/lib/commonjs/hooks/useConnection.js +35 -34
  43. package/lib/commonjs/hooks/useConnection.js.map +1 -1
  44. package/lib/commonjs/hooks/usePushTokenRegistration.js +2 -2
  45. package/lib/commonjs/hooks/usePushTokenRegistration.js.map +1 -1
  46. package/lib/commonjs/index.js +10 -1
  47. package/lib/commonjs/index.js.map +1 -1
  48. package/lib/commonjs/libs/InternalLocalCacheStorage.js +8 -0
  49. package/lib/commonjs/libs/InternalLocalCacheStorage.js.map +1 -1
  50. package/lib/commonjs/libs/SBUError.js +41 -0
  51. package/lib/commonjs/libs/SBUError.js.map +1 -0
  52. package/lib/commonjs/libs/SBUUtils.js +20 -0
  53. package/lib/commonjs/libs/SBUUtils.js.map +1 -0
  54. package/lib/commonjs/localization/StringSet.type.js +6 -0
  55. package/lib/commonjs/localization/StringSet.type.js.map +1 -1
  56. package/lib/commonjs/platform/createFileService.expo.js +6 -4
  57. package/lib/commonjs/platform/createFileService.expo.js.map +1 -1
  58. package/lib/commonjs/platform/createFileService.native.js +18 -8
  59. package/lib/commonjs/platform/createFileService.native.js.map +1 -1
  60. package/lib/commonjs/platform/types.js +4 -0
  61. package/lib/commonjs/platform/types.js.map +1 -1
  62. package/lib/commonjs/version.js +1 -1
  63. package/lib/commonjs/version.js.map +1 -1
  64. package/lib/module/components/ChatFlatList.js +10 -8
  65. package/lib/module/components/ChatFlatList.js.map +1 -1
  66. package/lib/module/components/FileViewer.js +9 -4
  67. package/lib/module/components/FileViewer.js.map +1 -1
  68. package/lib/module/components/MessageRenderer/FileMessage/ImageFileMessage.js +48 -17
  69. package/lib/module/components/MessageRenderer/FileMessage/ImageFileMessage.js.map +1 -1
  70. package/lib/module/components/MessageRenderer/FileMessage/VideoFileMessage.js +52 -35
  71. package/lib/module/components/MessageRenderer/FileMessage/VideoFileMessage.js.map +1 -1
  72. package/lib/module/components/MessageRenderer/MessageIncomingSenderName.js +2 -1
  73. package/lib/module/components/MessageRenderer/MessageIncomingSenderName.js.map +1 -1
  74. package/lib/module/components/MessageRenderer/UserMessage/OpenGraphUserMessage.js +3 -1
  75. package/lib/module/components/MessageRenderer/UserMessage/OpenGraphUserMessage.js.map +1 -1
  76. package/lib/module/components/MessageRenderer/index.js +7 -2
  77. package/lib/module/components/MessageRenderer/index.js.map +1 -1
  78. package/lib/module/containers/SendbirdUIKitContainer.js +10 -15
  79. package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
  80. package/lib/module/contexts/SendbirdChat.js +10 -10
  81. package/lib/module/contexts/SendbirdChat.js.map +1 -1
  82. package/lib/module/domain/groupChannel/component/GroupChannelInput/SendInput.js +38 -7
  83. package/lib/module/domain/groupChannel/component/GroupChannelInput/SendInput.js.map +1 -1
  84. package/lib/module/domain/groupChannel/component/GroupChannelInput/index.js +5 -5
  85. package/lib/module/domain/groupChannel/component/GroupChannelInput/index.js.map +1 -1
  86. package/lib/module/domain/groupChannel/types.js.map +1 -1
  87. package/lib/module/domain/groupChannelList/component/GroupChannelListList.js +3 -2
  88. package/lib/module/domain/groupChannelList/component/GroupChannelListList.js.map +1 -1
  89. package/lib/module/domain/groupChannelSettings/component/GroupChannelSettingsInfo.js +1 -1
  90. package/lib/module/domain/groupChannelSettings/component/GroupChannelSettingsInfo.js.map +1 -1
  91. package/lib/module/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js +3 -2
  92. package/lib/module/domain/groupChannelSettings/component/GroupChannelSettingsMenu.js.map +1 -1
  93. package/lib/module/domain/groupChannelSettings/module/moduleContext.js +43 -14
  94. package/lib/module/domain/groupChannelSettings/module/moduleContext.js.map +1 -1
  95. package/lib/module/domain/groupChannelUserList/types.js.map +1 -1
  96. package/lib/module/fragments/createGroupChannelCreateFragment.js +7 -6
  97. package/lib/module/fragments/createGroupChannelCreateFragment.js.map +1 -1
  98. package/lib/module/fragments/createGroupChannelFragment.js +12 -12
  99. package/lib/module/fragments/createGroupChannelFragment.js.map +1 -1
  100. package/lib/module/fragments/createGroupChannelListFragment.js +1 -1
  101. package/lib/module/fragments/createGroupChannelListFragment.js.map +1 -1
  102. package/lib/module/fragments/createGroupChannelMembersFragment.js +4 -4
  103. package/lib/module/fragments/createGroupChannelMembersFragment.js.map +1 -1
  104. package/lib/module/hooks/useConnection.js +35 -35
  105. package/lib/module/hooks/useConnection.js.map +1 -1
  106. package/lib/module/hooks/usePushTokenRegistration.js +2 -2
  107. package/lib/module/hooks/usePushTokenRegistration.js.map +1 -1
  108. package/lib/module/index.js +1 -0
  109. package/lib/module/index.js.map +1 -1
  110. package/lib/module/libs/InternalLocalCacheStorage.js +7 -0
  111. package/lib/module/libs/InternalLocalCacheStorage.js.map +1 -1
  112. package/lib/module/libs/SBUError.js +32 -0
  113. package/lib/module/libs/SBUError.js.map +1 -0
  114. package/lib/module/libs/SBUUtils.js +10 -0
  115. package/lib/module/libs/SBUUtils.js.map +1 -0
  116. package/lib/module/localization/StringSet.type.js +6 -0
  117. package/lib/module/localization/StringSet.type.js.map +1 -1
  118. package/lib/module/platform/createFileService.expo.js +5 -4
  119. package/lib/module/platform/createFileService.expo.js.map +1 -1
  120. package/lib/module/platform/createFileService.native.js +18 -9
  121. package/lib/module/platform/createFileService.native.js.map +1 -1
  122. package/lib/module/platform/types.js +1 -1
  123. package/lib/module/platform/types.js.map +1 -1
  124. package/lib/module/version.js +1 -1
  125. package/lib/module/version.js.map +1 -1
  126. package/lib/typescript/src/components/MessageRenderer/UserMessage/OpenGraphUserMessage.d.ts +2 -2
  127. package/lib/typescript/src/components/MessageRenderer/index.d.ts +1 -1
  128. package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +1 -1
  129. package/lib/typescript/src/contexts/SendbirdChat.d.ts +1 -1
  130. package/lib/typescript/src/domain/groupChannel/component/GroupChannelInput/index.d.ts +3 -3
  131. package/lib/typescript/src/domain/groupChannel/component/GroupChannelMessageList.d.ts +6 -6
  132. package/lib/typescript/src/domain/groupChannel/types.d.ts +3 -3
  133. package/lib/typescript/src/domain/groupChannelUserList/types.d.ts +2 -2
  134. package/lib/typescript/src/hooks/useContext.d.ts +5 -5
  135. package/lib/typescript/src/index.d.ts +1 -0
  136. package/lib/typescript/src/libs/InternalLocalCacheStorage.d.ts +2 -0
  137. package/lib/typescript/src/libs/SBUError.d.ts +14 -0
  138. package/lib/typescript/src/libs/SBUUtils.d.ts +3 -0
  139. package/lib/typescript/src/localization/StringSet.type.d.ts +3 -0
  140. package/lib/typescript/src/platform/types.d.ts +2 -1
  141. package/lib/typescript/src/version.d.ts +1 -1
  142. package/package.json +8 -8
  143. package/src/components/ChatFlatList.tsx +5 -4
  144. package/src/components/FileViewer.tsx +12 -4
  145. package/src/components/MessageRenderer/FileMessage/ImageFileMessage.tsx +55 -12
  146. package/src/components/MessageRenderer/FileMessage/VideoFileMessage.tsx +38 -30
  147. package/src/components/MessageRenderer/MessageIncomingSenderName.tsx +1 -1
  148. package/src/components/MessageRenderer/UserMessage/OpenGraphUserMessage.tsx +5 -3
  149. package/src/components/MessageRenderer/index.tsx +5 -2
  150. package/src/containers/SendbirdUIKitContainer.tsx +13 -9
  151. package/src/contexts/SendbirdChat.tsx +18 -13
  152. package/src/domain/groupChannel/component/GroupChannelInput/SendInput.tsx +28 -4
  153. package/src/domain/groupChannel/component/GroupChannelInput/index.tsx +5 -5
  154. package/src/domain/groupChannel/types.ts +6 -6
  155. package/src/domain/groupChannelList/component/GroupChannelListList.tsx +3 -2
  156. package/src/domain/groupChannelSettings/component/GroupChannelSettingsInfo.tsx +1 -1
  157. package/src/domain/groupChannelSettings/component/GroupChannelSettingsMenu.tsx +3 -2
  158. package/src/domain/groupChannelSettings/module/moduleContext.tsx +33 -18
  159. package/src/domain/groupChannelUserList/types.ts +3 -3
  160. package/src/fragments/createGroupChannelCreateFragment.tsx +8 -7
  161. package/src/fragments/createGroupChannelFragment.tsx +4 -12
  162. package/src/fragments/createGroupChannelListFragment.tsx +1 -1
  163. package/src/fragments/createGroupChannelMembersFragment.tsx +4 -3
  164. package/src/hooks/useConnection.ts +40 -43
  165. package/src/hooks/usePushTokenRegistration.ts +2 -2
  166. package/src/index.ts +1 -0
  167. package/src/libs/InternalLocalCacheStorage.ts +5 -0
  168. package/src/libs/SBUError.ts +26 -0
  169. package/src/libs/SBUUtils.ts +9 -0
  170. package/src/localization/StringSet.type.ts +10 -0
  171. package/src/platform/createFileService.expo.ts +5 -4
  172. package/src/platform/createFileService.native.ts +17 -9
  173. package/src/platform/types.ts +3 -1
  174. package/src/version.ts +1 -1
@@ -73,30 +73,22 @@ const createGroupChannelFragment = (initModule?: Partial<GroupChannelModule>): G
73
73
  );
74
74
 
75
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);
76
+ const processedParams = await onBeforeSendFileMessage({ file });
79
77
  await sendFileMessage(processedParams);
80
78
  });
81
79
  const onSendUserMessage: GroupChannelProps['Input']['onSendUserMessage'] = useFreshCallback(async (text) => {
82
- const params = new sdk.UserMessageParams();
83
- params.message = text;
84
- const processedParams = await onBeforeSendUserMessage(params);
80
+ const processedParams = await onBeforeSendUserMessage({ message: text });
85
81
  await sendUserMessage(processedParams);
86
82
  });
87
83
  const onUpdateFileMessage: GroupChannelProps['Input']['onUpdateFileMessage'] = useFreshCallback(
88
84
  async (editedFile, message) => {
89
- const params = new sdk.FileMessageParams();
90
- params.file = editedFile;
91
- const processedParams = await onBeforeSendFileMessage(params);
85
+ const processedParams = await onBeforeSendFileMessage({ file: editedFile });
92
86
  await updateFileMessage(message.messageId, processedParams);
93
87
  },
94
88
  );
95
89
  const onUpdateUserMessage: GroupChannelProps['Input']['onUpdateUserMessage'] = useFreshCallback(
96
90
  async (editedText, message) => {
97
- const params = new sdk.UserMessageParams();
98
- params.message = editedText;
99
- const processedParams = await onBeforeSendUserMessage(params);
91
+ const processedParams = await onBeforeSendUserMessage({ message: editedText });
100
92
  await updateUserMessage(message.messageId, processedParams);
101
93
  },
102
94
  );
@@ -57,7 +57,7 @@ const createGroupChannelListFragment = (initModule?: Partial<GroupChannelListMod
57
57
  );
58
58
 
59
59
  if (!currentUser) {
60
- Logger.warn('Cannot render GroupChannelListFragment, User is not connected');
60
+ Logger.warn('Cannot render GroupChannelListFragment, please connect using `useConnection()` hook first');
61
61
  return null;
62
62
  }
63
63
 
@@ -27,9 +27,10 @@ const createGroupChannelMembersFragment = (
27
27
  const { STRINGS } = useLocalization();
28
28
 
29
29
  useChannelHandler(sdk, `${name}_${uniqId}`, {
30
- onUserEntered(channel) {
31
- if (channel.url === activeChannel.url) forceUpdate();
32
- },
30
+ // Note: Removed from v4
31
+ // onUserEntered(channel) {
32
+ // if (channel.url === activeChannel.url) forceUpdate();
33
+ // },
33
34
  onUserLeft(channel) {
34
35
  if (channel.url === activeChannel.url) forceUpdate();
35
36
  },
@@ -1,13 +1,12 @@
1
1
  import { useCallback } from 'react';
2
- import type Sendbird from 'sendbird';
3
2
 
4
- import { Logger, SendbirdUser } from '@sendbird/uikit-utils';
3
+ import { Logger, SendbirdError, SendbirdUser } from '@sendbird/uikit-utils';
5
4
 
6
5
  import { useSendbirdChat } from './useContext';
7
6
  import usePushTokenRegistration from './usePushTokenRegistration';
8
7
 
9
8
  type ConnectOptions = { nickname?: string; accessToken?: string };
10
- const cacheStrictCodes = [400300, 400301, 400302, 400310];
9
+ const cacheRestrictCodes = [400300, 400301, 400302, 400310];
11
10
 
12
11
  const useConnection = () => {
13
12
  const { sdk, setCurrentUser, features } = useSendbirdChat();
@@ -15,48 +14,47 @@ const useConnection = () => {
15
14
 
16
15
  const connect = useCallback(
17
16
  async (userId: string, opts?: ConnectOptions): Promise<SendbirdUser> => {
18
- return new Promise((resolve, reject) => {
19
- const callback: Sendbird.userCallback = async (user, error) => {
20
- if (error && sdk.isCacheEnabled && cacheStrictCodes.some((code) => error.code === code)) {
21
- Logger.warn('[useConnection]', 'connect failure', error.message, error.code);
17
+ try {
18
+ Logger.debug('[useConnection]', 'connect start:', userId);
19
+ let user = await sdk.connect(userId, opts?.accessToken);
20
+
21
+ if (opts?.nickname) {
22
+ Logger.debug('[useConnection]', 'nickname-sync start:', opts.nickname);
23
+ await sdk
24
+ .updateCurrentUserInfo({ nickname: opts.nickname })
25
+ .then((updatedUser) => (user = updatedUser))
26
+ .catch((e) => Logger.warn('[useConnection]', 'nickname-sync failure', e));
27
+ }
28
+
29
+ if (features.autoPushTokenRegistrationEnabled) {
30
+ Logger.debug('[useConnection]', 'autoPushTokenRegistration enabled, register for current user');
31
+ await registerPushTokenForCurrentUser().catch((e) => {
32
+ Logger.warn('[useConnection]', 'autoPushToken Registration failure', e);
33
+ });
34
+ }
35
+
36
+ Logger.debug('[useConnection]', 'connected! (online)');
37
+ setCurrentUser(user);
38
+
39
+ return user;
40
+ } catch (e) {
41
+ const error = e as unknown as SendbirdError;
42
+
43
+ if (sdk.isCacheEnabled) {
44
+ if (cacheRestrictCodes.some((code) => error.code === code)) {
45
+ Logger.warn('[useConnection]', 'offline connect restricted', error.message, error.code);
22
46
  Logger.warn('[useConnection]', 'clear cached-data');
23
47
  await sdk.clearCachedData().catch((e) => Logger.warn('[useConnection]', 'clear cached-data failure', e));
24
- return reject(error);
25
- }
26
-
27
- if (user) {
28
- let _user = user;
29
-
30
- if (opts?.nickname) {
31
- Logger.debug('[useConnection]', 'nickname-sync start:', opts.nickname);
32
- await sdk
33
- .updateCurrentUserInfo(opts.nickname, sdk.currentUser.profileUrl)
34
- .then((updatedUser) => (_user = updatedUser))
35
- .catch((e) => Logger.warn('[useConnection]', 'nickname-sync failure', e));
36
- }
37
-
38
- if (features.autoPushTokenRegistrationEnabled) {
39
- Logger.debug('[useConnection]', 'autoPushTokenRegistration enabled, register for current user');
40
- await registerPushTokenForCurrentUser().catch((e) => {
41
- Logger.warn('[useConnection]', 'autoPushToken Registration failure', e);
42
- });
43
- }
44
-
45
- Logger.debug('[useConnection]', 'connected!');
46
- setCurrentUser(_user);
47
- return resolve(_user);
48
+ } else if (sdk.currentUser) {
49
+ Logger.debug('[useConnection]', 'connected! (offline)');
50
+ setCurrentUser(sdk.currentUser);
51
+ return sdk.currentUser;
48
52
  }
53
+ }
49
54
 
50
- if (error) {
51
- Logger.warn('[useConnection]', 'connect failure', error.message, error.code);
52
- return reject(error);
53
- }
54
- };
55
-
56
- Logger.debug('[useConnection]', 'connect start:', userId);
57
- if (opts?.accessToken) sdk.connect(userId, opts.accessToken, callback);
58
- else sdk.connect(userId, callback);
59
- });
55
+ Logger.warn('[useConnection]', 'connect failure', error.message, error.code);
56
+ throw error;
57
+ }
60
58
  },
61
59
  [sdk, registerPushTokenForCurrentUser, features.autoPushTokenRegistrationEnabled],
62
60
  );
@@ -71,8 +69,7 @@ const useConnection = () => {
71
69
  });
72
70
  }
73
71
 
74
- await sdk.disconnect();
75
- setCurrentUser(undefined);
72
+ await sdk.disconnect().then(() => setCurrentUser(undefined));
76
73
  Logger.debug('[useConnection]', 'disconnected!');
77
74
  }, [sdk, unregisterPushTokenForCurrentUser, features.autoPushTokenRegistrationEnabled]);
78
75
 
@@ -14,11 +14,11 @@ const usePushTokenRegistration = () => {
14
14
  return [
15
15
  Platform.select({
16
16
  ios: (token: string) => sdk.registerAPNSPushTokenForCurrentUser(token),
17
- default: (token: string) => sdk.registerGCMPushTokenForCurrentUser(token),
17
+ default: (token: string) => sdk.registerFCMPushTokenForCurrentUser(token),
18
18
  }),
19
19
  Platform.select({
20
20
  ios: (token: string) => sdk.unregisterAPNSPushTokenForCurrentUser(token),
21
- default: (token: string) => sdk.unregisterGCMPushTokenForCurrentUser(token),
21
+ default: (token: string) => sdk.unregisterFCMPushTokenForCurrentUser(token),
22
22
  }),
23
23
  Platform.select({
24
24
  ios: notificationService.getAPNSToken,
package/src/index.ts CHANGED
@@ -101,6 +101,7 @@ export {
101
101
  SendbirdUIKit,
102
102
  SendbirdUIKitContainerProps,
103
103
  } from './containers/SendbirdUIKitContainer';
104
+ export { default as SBUError } from './libs/SBUError';
104
105
 
105
106
  export * from './types';
106
107
 
@@ -1,3 +1,5 @@
1
+ import { ASYNC_NOOP } from '@sendbird/uikit-utils';
2
+
1
3
  import type { KeyValuePairGet, KeyValuePairSet, LocalCacheStorage } from '../types';
2
4
 
3
5
  export default class InternalLocalCacheStorage implements LocalCacheStorage {
@@ -42,4 +44,7 @@ export default class InternalLocalCacheStorage implements LocalCacheStorage {
42
44
  await Promise.all(keyValuePairs.map(([key, value]) => this.storage.setItem(key, value)));
43
45
  }
44
46
  }
47
+
48
+ clear = ASYNC_NOOP;
49
+ flushGetRequests = ASYNC_NOOP;
45
50
  }
@@ -0,0 +1,26 @@
1
+ enum SBUErrorCode {
2
+ ERR_UNKNOWN = 90000000,
3
+
4
+ // Platform service - 91001000 ~
5
+ ERR_PERMISSIONS_DENIED = 91001000,
6
+ ERR_DEVICE_UNAVAILABLE,
7
+ }
8
+
9
+ export default class SBUError extends Error {
10
+ static CODE = SBUErrorCode;
11
+
12
+ static get UNKNOWN() {
13
+ return new SBUError(SBUErrorCode.ERR_UNKNOWN);
14
+ }
15
+
16
+ static get PERMISSIONS_DENIED() {
17
+ return new SBUError(SBUErrorCode.ERR_PERMISSIONS_DENIED);
18
+ }
19
+ static get DEVICE_UNAVAILABLE() {
20
+ return new SBUError(SBUErrorCode.ERR_DEVICE_UNAVAILABLE);
21
+ }
22
+
23
+ constructor(public code: SBUErrorCode, message?: string) {
24
+ super(message);
25
+ }
26
+ }
@@ -0,0 +1,9 @@
1
+ import { Linking, Platform } from 'react-native';
2
+
3
+ export default class SBUUtils {
4
+ static openSettings() {
5
+ Linking.openSettings().catch(() => {
6
+ if (Platform.OS === 'ios') Linking.openURL('App-Prefs:root');
7
+ });
8
+ }
9
+ }
@@ -149,6 +149,11 @@ export interface StringSet {
149
149
  };
150
150
  DIALOG: {
151
151
  ALERT_DEFAULT_OK: string;
152
+
153
+ ALERT_PERMISSIONS_TITLE: string;
154
+ ALERT_PERMISSIONS_MESSAGE: (permission: string, appName: string) => string;
155
+ ALERT_PERMISSIONS_OK: string;
156
+
152
157
  PROMPT_DEFAULT_OK: string;
153
158
  PROMPT_DEFAULT_CANCEL: string;
154
159
  PROMPT_DEFAULT_PLACEHOLDER: string;
@@ -316,6 +321,11 @@ export const createBaseStringSet = ({ dateLocale, overrides }: StringSetCreateOp
316
321
  },
317
322
  DIALOG: {
318
323
  ALERT_DEFAULT_OK: 'OK',
324
+ ALERT_PERMISSIONS_TITLE: 'Allow permission',
325
+ ALERT_PERMISSIONS_MESSAGE: (permission, appName = 'Application') => {
326
+ return `${appName} need permission to access your ${permission}. Go to Settings to allow access`;
327
+ },
328
+ ALERT_PERMISSIONS_OK: 'SETTINGS',
319
329
  PROMPT_DEFAULT_OK: 'Submit',
320
330
  PROMPT_DEFAULT_CANCEL: 'Cancel',
321
331
  PROMPT_DEFAULT_PLACEHOLDER: 'Enter',
@@ -5,6 +5,7 @@ import type * as ExpoMediaLibrary from 'expo-media-library';
5
5
 
6
6
  import { getFileExtension, getFileType } from '@sendbird/uikit-utils';
7
7
 
8
+ import SBUError from '../libs/SBUError';
8
9
  import type { ExpoMediaLibraryPermissionResponse, ExpoPermissionResponse } from '../utils/expoPermissionGranted';
9
10
  import expoPermissionGranted from '../utils/expoPermissionGranted';
10
11
  import fileTypeGuard from '../utils/fileTypeGuard';
@@ -55,7 +56,7 @@ const createExpoFileService = ({
55
56
  if (!hasPermission) {
56
57
  const granted = await this.requestCameraPermission();
57
58
  if (!granted) {
58
- options?.onOpenFailureWithToastMessage?.();
59
+ options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);
59
60
  return null;
60
61
  }
61
62
  }
@@ -89,7 +90,7 @@ const createExpoFileService = ({
89
90
  if (!hasPermission) {
90
91
  const granted = await this.requestMediaLibraryPermission('read');
91
92
  if (!granted) {
92
- options?.onOpenFailureWithToastMessage?.();
93
+ options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);
93
94
  return null;
94
95
  }
95
96
  }
@@ -123,8 +124,8 @@ const createExpoFileService = ({
123
124
  if (response.type === 'cancel') return null;
124
125
  const { mimeType, uri, size, name } = response;
125
126
  return fileTypeGuard({ uri, size, name, type: mimeType });
126
- } catch {
127
- options?.onOpenFailureWithToastMessage?.();
127
+ } catch (e) {
128
+ options?.onOpenFailure?.(SBUError.UNKNOWN, e);
128
129
  return null;
129
130
  }
130
131
  }
@@ -6,8 +6,9 @@ import type * as ImagePicker from 'react-native-image-picker';
6
6
  import type * as Permissions from 'react-native-permissions';
7
7
  import type { Permission } from 'react-native-permissions';
8
8
 
9
- import { getFileExtension, getFileType } from '@sendbird/uikit-utils';
9
+ import { getFileExtension, getFileType, normalizeFileName } from '@sendbird/uikit-utils';
10
10
 
11
+ import SBUError from '../libs/SBUError';
11
12
  import fileTypeGuard from '../utils/fileTypeGuard';
12
13
  import nativePermissionGranted from '../utils/nativePermissionGranted';
13
14
  import type {
@@ -87,12 +88,13 @@ const createNativeFileService = ({
87
88
  if (!hasPermission) {
88
89
  const granted = await this.requestCameraPermission();
89
90
  if (!granted) {
90
- options?.onOpenFailureWithToastMessage?.();
91
+ options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);
91
92
  return null;
92
93
  }
93
94
  }
94
95
 
95
96
  const response = await imagePickerModule.launchCamera({
97
+ presentationStyle: 'fullScreen',
96
98
  cameraType: options?.cameraType ?? 'back',
97
99
  mediaType: (() => {
98
100
  switch (options?.mediaType) {
@@ -109,7 +111,7 @@ const createNativeFileService = ({
109
111
  });
110
112
  if (response.didCancel) return null;
111
113
  if (response.errorCode === 'camera_unavailable') {
112
- options?.onOpenFailureWithToastMessage?.();
114
+ options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));
113
115
  return null;
114
116
  }
115
117
 
@@ -126,12 +128,13 @@ const createNativeFileService = ({
126
128
  if (!hasPermission) {
127
129
  const granted = await this.requestMediaLibraryPermission();
128
130
  if (!granted) {
129
- options?.onOpenFailureWithToastMessage?.();
131
+ options?.onOpenFailure?.(SBUError.PERMISSIONS_DENIED);
130
132
  return null;
131
133
  }
132
134
  }
133
135
 
134
136
  const response = await imagePickerModule.launchImageLibrary({
137
+ presentationStyle: 'fullScreen',
135
138
  selectionLimit,
136
139
  mediaType: (() => {
137
140
  switch (options?.mediaType) {
@@ -148,7 +151,7 @@ const createNativeFileService = ({
148
151
  });
149
152
  if (response.didCancel) return null;
150
153
  if (response.errorCode === 'camera_unavailable') {
151
- options?.onOpenFailureWithToastMessage?.();
154
+ options?.onOpenFailure?.(SBUError.DEVICE_UNAVAILABLE, new Error(response.errorMessage));
152
155
  return null;
153
156
  }
154
157
 
@@ -162,7 +165,7 @@ const createNativeFileService = ({
162
165
  return fileTypeGuard({ uri, size, name, type });
163
166
  } catch (e) {
164
167
  if (!documentPickerModule.isCancel(e) && documentPickerModule.isInProgress(e)) {
165
- options?.onOpenFailureWithToastMessage?.();
168
+ options?.onOpenFailure?.(SBUError.UNKNOWN, e);
166
169
  }
167
170
  return null;
168
171
  }
@@ -186,13 +189,18 @@ const createNativeFileService = ({
186
189
  await fsModule.FileSystem.fetch(options.fileUrl, { path: downloadPath });
187
190
  const fileType = getFileType(getFileExtension(options.fileUrl));
188
191
 
189
- if (Platform.OS === 'ios' && fileType.match(/image|video/)) {
190
- await mediaLibraryModule.save(downloadPath);
192
+ if (Platform.OS === 'ios' && (fileType === 'image' || fileType === 'video')) {
193
+ const type = ({ 'image': 'photo', 'video': 'video' } as const)[fileType];
194
+ await mediaLibraryModule.save(downloadPath, { type });
191
195
  }
192
196
 
193
197
  if (Platform.OS === 'android') {
194
198
  const dirType = { 'file': 'downloads', 'audio': 'audio', 'image': 'images', 'video': 'video' } as const;
195
- await fsModule.FileSystem.cpExternal(downloadPath, options.fileName, dirType[fileType]);
199
+ await fsModule.FileSystem.cpExternal(
200
+ downloadPath,
201
+ normalizeFileName(options.fileName, getFileExtension(options.fileUrl)),
202
+ dirType[fileType],
203
+ );
196
204
  }
197
205
  return downloadPath;
198
206
  }
@@ -1,3 +1,5 @@
1
+ import type SBUError from '../libs/SBUError';
2
+
1
3
  export type Unsubscribe = () => void | undefined;
2
4
  export type DownloadedPath = string;
3
5
  export type FilePickerResponse = FileType | null;
@@ -23,7 +25,7 @@ export interface ClipboardServiceInterface {
23
25
  export interface FileServiceInterface extends FilePickerServiceInterface, FileSystemServiceInterface {}
24
26
 
25
27
  export interface OpenResultListener {
26
- onOpenFailureWithToastMessage?: () => void;
28
+ onOpenFailure?: (error: SBUError, originError?: unknown) => void;
27
29
  }
28
30
  export interface OpenMediaLibraryOptions extends OpenResultListener {
29
31
  selectionLimit?: number;
package/src/version.ts CHANGED
@@ -1,2 +1,2 @@
1
- const VERSION = '1.1.1';
1
+ const VERSION = '2.0.0-rc.0';
2
2
  export default VERSION;