@sendbird/uikit-react-native 2.2.0 → 2.3.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.
- package/README.md +42 -17
- package/lib/commonjs/components/FileViewer.js +2 -5
- package/lib/commonjs/components/FileViewer.js.map +1 -1
- package/lib/commonjs/components/MessageRenderer/FileMessage/ImageFileMessage.js +1 -1
- package/lib/commonjs/components/MessageRenderer/FileMessage/ImageFileMessage.js.map +1 -1
- package/lib/commonjs/components/MessageRenderer/FileMessage/VideoFileMessage.js +1 -1
- package/lib/commonjs/components/MessageRenderer/FileMessage/VideoFileMessage.js.map +1 -1
- package/lib/commonjs/components/MessageRenderer/FileMessage/index.js +1 -6
- package/lib/commonjs/components/MessageRenderer/FileMessage/index.js.map +1 -1
- package/lib/commonjs/components/MessageRenderer/UserMessage/BaseUserMessage.js +2 -2
- package/lib/commonjs/components/MessageRenderer/UserMessage/BaseUserMessage.js.map +1 -1
- package/lib/commonjs/components/MessageRenderer/UserMessage/OpenGraphUserMessage.js +5 -3
- package/lib/commonjs/components/MessageRenderer/UserMessage/OpenGraphUserMessage.js.map +1 -1
- package/lib/commonjs/containers/SendbirdUIKitContainer.js +14 -3
- package/lib/commonjs/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/commonjs/contexts/PlatformServiceCtx.js.map +1 -1
- package/lib/commonjs/contexts/SendbirdChatCtx.js +10 -14
- package/lib/commonjs/contexts/SendbirdChatCtx.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/SendInput.js +68 -13
- package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/SendInput.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/index.js +1 -0
- package/lib/commonjs/domain/groupChannel/component/GroupChannelInput/index.js.map +1 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js +3 -1
- package/lib/commonjs/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/commonjs/domain/groupChannelSettings/module/moduleContext.js +2 -2
- package/lib/commonjs/domain/groupChannelSettings/module/moduleContext.js.map +1 -1
- package/lib/commonjs/fragments/createGroupChannelListFragment.js +4 -14
- package/lib/commonjs/fragments/createGroupChannelListFragment.js.map +1 -1
- package/lib/commonjs/hooks/useKeyboardStatus.js +13 -9
- package/lib/commonjs/hooks/useKeyboardStatus.js.map +1 -1
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/libs/ImageCompressionConfig.js +38 -0
- package/lib/commonjs/libs/ImageCompressionConfig.js.map +1 -0
- package/lib/commonjs/libs/SBUUtils.js +27 -0
- package/lib/commonjs/libs/SBUUtils.js.map +1 -1
- package/lib/commonjs/localization/StringSet.type.js +3 -0
- package/lib/commonjs/localization/StringSet.type.js.map +1 -1
- package/lib/commonjs/platform/createMediaService.expo.js +35 -1
- package/lib/commonjs/platform/createMediaService.expo.js.map +1 -1
- package/lib/commonjs/platform/createMediaService.native.js +41 -6
- package/lib/commonjs/platform/createMediaService.native.js.map +1 -1
- package/lib/commonjs/platform/dynamicModule.js +9 -57
- package/lib/commonjs/platform/dynamicModule.js.map +1 -1
- package/lib/commonjs/platform/types.js.map +1 -1
- package/lib/commonjs/version.js +1 -1
- package/lib/commonjs/version.js.map +1 -1
- package/lib/module/components/FileViewer.js +2 -5
- package/lib/module/components/FileViewer.js.map +1 -1
- package/lib/module/components/MessageRenderer/FileMessage/ImageFileMessage.js +1 -1
- package/lib/module/components/MessageRenderer/FileMessage/ImageFileMessage.js.map +1 -1
- package/lib/module/components/MessageRenderer/FileMessage/VideoFileMessage.js +1 -1
- package/lib/module/components/MessageRenderer/FileMessage/VideoFileMessage.js.map +1 -1
- package/lib/module/components/MessageRenderer/FileMessage/index.js +1 -5
- package/lib/module/components/MessageRenderer/FileMessage/index.js.map +1 -1
- package/lib/module/components/MessageRenderer/UserMessage/BaseUserMessage.js +2 -2
- package/lib/module/components/MessageRenderer/UserMessage/BaseUserMessage.js.map +1 -1
- package/lib/module/components/MessageRenderer/UserMessage/OpenGraphUserMessage.js +4 -4
- package/lib/module/components/MessageRenderer/UserMessage/OpenGraphUserMessage.js.map +1 -1
- package/lib/module/containers/SendbirdUIKitContainer.js +13 -3
- package/lib/module/containers/SendbirdUIKitContainer.js.map +1 -1
- package/lib/module/contexts/PlatformServiceCtx.js.map +1 -1
- package/lib/module/contexts/SendbirdChatCtx.js +12 -14
- package/lib/module/contexts/SendbirdChatCtx.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelInput/SendInput.js +69 -14
- package/lib/module/domain/groupChannel/component/GroupChannelInput/SendInput.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelInput/index.js +1 -0
- package/lib/module/domain/groupChannel/component/GroupChannelInput/index.js.map +1 -1
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js +3 -2
- package/lib/module/domain/groupChannel/component/GroupChannelMessageList.js.map +1 -1
- package/lib/module/domain/groupChannelSettings/module/moduleContext.js +2 -2
- package/lib/module/domain/groupChannelSettings/module/moduleContext.js.map +1 -1
- package/lib/module/fragments/createGroupChannelListFragment.js +5 -9
- package/lib/module/fragments/createGroupChannelListFragment.js.map +1 -1
- package/lib/module/hooks/useKeyboardStatus.js +12 -9
- package/lib/module/hooks/useKeyboardStatus.js.map +1 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/libs/ImageCompressionConfig.js +30 -0
- package/lib/module/libs/ImageCompressionConfig.js.map +1 -0
- package/lib/module/libs/SBUUtils.js +26 -1
- package/lib/module/libs/SBUUtils.js.map +1 -1
- package/lib/module/localization/StringSet.type.js +3 -0
- package/lib/module/localization/StringSet.type.js.map +1 -1
- package/lib/module/platform/createMediaService.expo.js +33 -1
- package/lib/module/platform/createMediaService.expo.js.map +1 -1
- package/lib/module/platform/createMediaService.native.js +38 -5
- package/lib/module/platform/createMediaService.native.js.map +1 -1
- package/lib/module/platform/dynamicModule.js +10 -56
- package/lib/module/platform/dynamicModule.js.map +1 -1
- package/lib/module/platform/types.js.map +1 -1
- package/lib/module/version.js +1 -1
- package/lib/module/version.js.map +1 -1
- package/lib/typescript/src/containers/SendbirdUIKitContainer.d.ts +10 -7
- package/lib/typescript/src/contexts/PlatformServiceCtx.d.ts +8 -2
- package/lib/typescript/src/contexts/SendbirdChatCtx.d.ts +8 -3
- package/lib/typescript/src/hooks/useContext.d.ts +2 -29
- package/lib/typescript/src/index.d.ts +1 -1
- package/lib/typescript/src/libs/ImageCompressionConfig.d.ts +16 -0
- package/lib/typescript/src/libs/SBUUtils.d.ts +6 -0
- package/lib/typescript/src/localization/StringSet.type.d.ts +3 -0
- package/lib/typescript/src/platform/createMediaService.expo.d.ts +5 -1
- package/lib/typescript/src/platform/createMediaService.native.d.ts +7 -5
- package/lib/typescript/src/platform/dynamicModule.d.ts +7 -12
- package/lib/typescript/src/platform/types.d.ts +28 -3
- package/lib/typescript/src/version.d.ts +1 -1
- package/package.json +15 -5
- package/src/components/FileViewer.tsx +2 -5
- package/src/components/MessageRenderer/FileMessage/ImageFileMessage.tsx +6 -1
- package/src/components/MessageRenderer/FileMessage/VideoFileMessage.tsx +1 -1
- package/src/components/MessageRenderer/FileMessage/index.tsx +1 -4
- package/src/components/MessageRenderer/UserMessage/BaseUserMessage.tsx +2 -2
- package/src/components/MessageRenderer/UserMessage/OpenGraphUserMessage.tsx +4 -4
- package/src/containers/SendbirdUIKitContainer.tsx +25 -6
- package/src/contexts/PlatformServiceCtx.tsx +9 -2
- package/src/contexts/SendbirdChatCtx.tsx +22 -19
- package/src/domain/groupChannel/component/GroupChannelInput/SendInput.tsx +82 -14
- package/src/domain/groupChannel/component/GroupChannelInput/index.tsx +1 -0
- package/src/domain/groupChannel/component/GroupChannelMessageList.tsx +3 -2
- package/src/domain/groupChannelSettings/module/moduleContext.tsx +8 -2
- package/src/fragments/createGroupChannelListFragment.tsx +5 -9
- package/src/hooks/useKeyboardStatus.ts +10 -5
- package/src/index.ts +1 -0
- package/src/libs/ImageCompressionConfig.ts +31 -0
- package/src/libs/SBUUtils.ts +28 -1
- package/src/localization/StringSet.type.ts +7 -0
- package/src/platform/createMediaService.expo.tsx +24 -1
- package/src/platform/createMediaService.native.tsx +31 -9
- package/src/platform/dynamicModule.ts +17 -59
- package/src/platform/types.ts +29 -7
- package/src/version.ts +1 -1
- package/lib/commonjs/utils/common.js +0 -19
- package/lib/commonjs/utils/common.js.map +0 -1
- package/lib/module/utils/common.js +0 -7
- package/lib/module/utils/common.js.map +0 -1
- package/lib/typescript/src/utils/common.d.ts +0 -1
- package/src/utils/common.ts +0 -8
|
@@ -30,6 +30,8 @@ import type { UIKitFeaturesInSendbirdChatContext } from '../contexts/SendbirdCha
|
|
|
30
30
|
import { SendbirdChatProvider } from '../contexts/SendbirdChatCtx';
|
|
31
31
|
import { UserProfileProvider } from '../contexts/UserProfileCtx';
|
|
32
32
|
import EmojiManager from '../libs/EmojiManager';
|
|
33
|
+
import type { ImageCompressionConfigInterface } from '../libs/ImageCompressionConfig';
|
|
34
|
+
import ImageCompressionConfig from '../libs/ImageCompressionConfig';
|
|
33
35
|
import InternalLocalCacheStorage from '../libs/InternalLocalCacheStorage';
|
|
34
36
|
import MentionConfig, { MentionConfigInterface } from '../libs/MentionConfig';
|
|
35
37
|
import MentionManager from '../libs/MentionManager';
|
|
@@ -57,6 +59,7 @@ export const SendbirdUIKit = Object.freeze({
|
|
|
57
59
|
CHANNEL_LIST_MESSAGE_RECEIPT_STATUS: false,
|
|
58
60
|
USE_USER_ID_FOR_NICKNAME: false,
|
|
59
61
|
USER_MENTION: false,
|
|
62
|
+
IMAGE_COMPRESSION: true,
|
|
60
63
|
},
|
|
61
64
|
});
|
|
62
65
|
|
|
@@ -66,7 +69,7 @@ export type SendbirdUIKitContainerProps = React.PropsWithChildren<{
|
|
|
66
69
|
file: FileServiceInterface;
|
|
67
70
|
notification: NotificationServiceInterface;
|
|
68
71
|
clipboard: ClipboardServiceInterface;
|
|
69
|
-
media
|
|
72
|
+
media: MediaServiceInterface;
|
|
70
73
|
};
|
|
71
74
|
chatOptions?: {
|
|
72
75
|
localCacheStorage?: LocalCacheStorage;
|
|
@@ -82,6 +85,10 @@ export type SendbirdUIKitContainerProps = React.PropsWithChildren<{
|
|
|
82
85
|
defaultHeaderHeight?: number;
|
|
83
86
|
HeaderComponent?: HeaderStyleContextType['HeaderComponent'];
|
|
84
87
|
};
|
|
88
|
+
errorBoundary?: {
|
|
89
|
+
onError?: (props: ErrorBoundaryProps) => void;
|
|
90
|
+
ErrorInfoComponent?: (props: ErrorBoundaryProps) => JSX.Element;
|
|
91
|
+
};
|
|
85
92
|
toast?: {
|
|
86
93
|
dismissTimeout?: number;
|
|
87
94
|
};
|
|
@@ -93,10 +100,7 @@ export type SendbirdUIKitContainerProps = React.PropsWithChildren<{
|
|
|
93
100
|
) => SendbirdGroupChannelCreateParams | Promise<SendbirdGroupChannelCreateParams>;
|
|
94
101
|
};
|
|
95
102
|
userMention?: Pick<Partial<MentionConfigInterface>, 'mentionLimit' | 'suggestionLimit' | 'debounceMills'>;
|
|
96
|
-
|
|
97
|
-
onError?: (props: ErrorBoundaryProps) => void;
|
|
98
|
-
ErrorInfoComponent?: (props: ErrorBoundaryProps) => JSX.Element;
|
|
99
|
-
};
|
|
103
|
+
imageCompression?: Partial<ImageCompressionConfigInterface>;
|
|
100
104
|
}>;
|
|
101
105
|
|
|
102
106
|
const SendbirdUIKitContainer = ({
|
|
@@ -106,10 +110,11 @@ const SendbirdUIKitContainer = ({
|
|
|
106
110
|
platformServices,
|
|
107
111
|
localization,
|
|
108
112
|
styles,
|
|
113
|
+
errorBoundary,
|
|
109
114
|
toast,
|
|
110
115
|
userProfile,
|
|
111
116
|
userMention,
|
|
112
|
-
|
|
117
|
+
imageCompression,
|
|
113
118
|
}: SendbirdUIKitContainerProps) => {
|
|
114
119
|
const defaultStringSet = localization?.stringSet ?? StringSetEn;
|
|
115
120
|
|
|
@@ -125,7 +130,9 @@ const SendbirdUIKitContainer = ({
|
|
|
125
130
|
unsubscribes.current = sendbird.unsubscribes;
|
|
126
131
|
return sendbird.chatSDK;
|
|
127
132
|
});
|
|
133
|
+
|
|
128
134
|
const emojiManager = useMemo(() => new EmojiManager(internalStorage), [internalStorage]);
|
|
135
|
+
|
|
129
136
|
const mentionManager = useMemo(() => {
|
|
130
137
|
const config = new MentionConfig({
|
|
131
138
|
mentionLimit: userMention?.mentionLimit || MentionConfig.DEFAULT.MENTION_LIMIT,
|
|
@@ -137,6 +144,16 @@ const SendbirdUIKitContainer = ({
|
|
|
137
144
|
return new MentionManager(config, chatOptions?.enableUserMention ?? SendbirdUIKit.DEFAULT.USER_MENTION);
|
|
138
145
|
}, [userMention?.mentionLimit, userMention?.suggestionLimit, userMention?.debounceMills]);
|
|
139
146
|
|
|
147
|
+
const imageCompressionConfig = useMemo(
|
|
148
|
+
() =>
|
|
149
|
+
new ImageCompressionConfig({
|
|
150
|
+
compressionRate: imageCompression?.compressionRate || ImageCompressionConfig.DEFAULT.COMPRESSION_RATE,
|
|
151
|
+
width: imageCompression?.width,
|
|
152
|
+
height: imageCompression?.height,
|
|
153
|
+
}),
|
|
154
|
+
[imageCompression?.compressionRate, imageCompression?.width, imageCompression?.height],
|
|
155
|
+
);
|
|
156
|
+
|
|
140
157
|
useLayoutEffect(() => {
|
|
141
158
|
if (!isFirstMount) {
|
|
142
159
|
const sendbird = initializeSendbird(appId, internalStorage, chatOptions?.onInitialized);
|
|
@@ -161,6 +178,7 @@ const SendbirdUIKitContainer = ({
|
|
|
161
178
|
sdkInstance={sdkInstance}
|
|
162
179
|
emojiManager={emojiManager}
|
|
163
180
|
mentionManager={mentionManager}
|
|
181
|
+
imageCompressionConfig={imageCompressionConfig}
|
|
164
182
|
enableAutoPushTokenRegistration={
|
|
165
183
|
chatOptions?.enableAutoPushTokenRegistration ?? SendbirdUIKit.DEFAULT.AUTO_PUSH_TOKEN_REGISTRATION
|
|
166
184
|
}
|
|
@@ -175,6 +193,7 @@ const SendbirdUIKitContainer = ({
|
|
|
175
193
|
chatOptions?.enableUseUserIdForNickname ?? SendbirdUIKit.DEFAULT.USE_USER_ID_FOR_NICKNAME
|
|
176
194
|
}
|
|
177
195
|
enableUserMention={chatOptions?.enableUserMention ?? SendbirdUIKit.DEFAULT.USER_MENTION}
|
|
196
|
+
enableImageCompression={chatOptions?.enableImageCompression ?? SendbirdUIKit.DEFAULT.IMAGE_COMPRESSION}
|
|
178
197
|
>
|
|
179
198
|
<LocalizationProvider stringSet={defaultStringSet}>
|
|
180
199
|
<PlatformServiceProvider
|
|
@@ -11,10 +11,17 @@ type Props = React.PropsWithChildren<{
|
|
|
11
11
|
fileService: FileServiceInterface;
|
|
12
12
|
clipboardService: ClipboardServiceInterface;
|
|
13
13
|
notificationService: NotificationServiceInterface;
|
|
14
|
-
mediaService
|
|
14
|
+
mediaService: MediaServiceInterface;
|
|
15
15
|
}>;
|
|
16
16
|
|
|
17
|
-
export
|
|
17
|
+
export type PlatformServiceContextType = {
|
|
18
|
+
fileService: FileServiceInterface;
|
|
19
|
+
clipboardService: ClipboardServiceInterface;
|
|
20
|
+
notificationService: NotificationServiceInterface;
|
|
21
|
+
mediaService: MediaServiceInterface;
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
export const PlatformServiceContext = React.createContext<PlatformServiceContextType | null>(null);
|
|
18
25
|
export const PlatformServiceProvider = ({
|
|
19
26
|
children,
|
|
20
27
|
fileService,
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import React, { useCallback,
|
|
2
|
-
import { AppState, AppStateStatus } from 'react-native';
|
|
1
|
+
import React, { useCallback, useState } from 'react';
|
|
3
2
|
|
|
4
3
|
import { useAppFeatures } from '@sendbird/uikit-chat-hooks';
|
|
5
4
|
import type {
|
|
@@ -8,9 +7,10 @@ import type {
|
|
|
8
7
|
SendbirdUser,
|
|
9
8
|
SendbirdUserUpdateParams,
|
|
10
9
|
} from '@sendbird/uikit-utils';
|
|
11
|
-
import { confirmAndMarkAsDelivered, useForceUpdate } from '@sendbird/uikit-utils';
|
|
10
|
+
import { confirmAndMarkAsDelivered, useAppState, useForceUpdate } from '@sendbird/uikit-utils';
|
|
12
11
|
|
|
13
12
|
import type EmojiManager from '../libs/EmojiManager';
|
|
13
|
+
import type ImageCompressionConfig from '../libs/ImageCompressionConfig';
|
|
14
14
|
import type MentionManager from '../libs/MentionManager';
|
|
15
15
|
import type { FileType } from '../platform/types';
|
|
16
16
|
|
|
@@ -20,18 +20,21 @@ export interface UIKitFeaturesInSendbirdChatContext {
|
|
|
20
20
|
enableChannelListMessageReceiptStatus: boolean;
|
|
21
21
|
enableUseUserIdForNickname: boolean;
|
|
22
22
|
enableUserMention: boolean;
|
|
23
|
+
enableImageCompression: boolean;
|
|
23
24
|
}
|
|
24
25
|
|
|
25
26
|
interface Props extends UIKitFeaturesInSendbirdChatContext, React.PropsWithChildren {
|
|
26
27
|
sdkInstance: SendbirdChatSDK;
|
|
27
28
|
emojiManager: EmojiManager;
|
|
28
29
|
mentionManager: MentionManager;
|
|
30
|
+
imageCompressionConfig: ImageCompressionConfig;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
|
-
type
|
|
33
|
+
export type SendbirdChatContextType = {
|
|
32
34
|
sdk: SendbirdChatSDK;
|
|
33
35
|
emojiManager: EmojiManager;
|
|
34
36
|
mentionManager: MentionManager;
|
|
37
|
+
imageCompressionConfig: ImageCompressionConfig;
|
|
35
38
|
currentUser?: SendbirdUser;
|
|
36
39
|
setCurrentUser: React.Dispatch<React.SetStateAction<SendbirdUser | undefined>>;
|
|
37
40
|
|
|
@@ -46,6 +49,7 @@ type Context = {
|
|
|
46
49
|
channelListMessageReceiptStatusEnabled: boolean;
|
|
47
50
|
useUserIdForNicknameEnabled: boolean;
|
|
48
51
|
userMentionEnabled: boolean;
|
|
52
|
+
imageCompressionEnabled: boolean;
|
|
49
53
|
|
|
50
54
|
// Sendbird application features
|
|
51
55
|
deliveryReceiptEnabled: boolean;
|
|
@@ -55,29 +59,31 @@ type Context = {
|
|
|
55
59
|
};
|
|
56
60
|
};
|
|
57
61
|
|
|
58
|
-
export const SendbirdChatContext = React.createContext<
|
|
62
|
+
export const SendbirdChatContext = React.createContext<SendbirdChatContextType | null>(null);
|
|
59
63
|
export const SendbirdChatProvider = ({
|
|
60
64
|
children,
|
|
61
65
|
sdkInstance,
|
|
62
66
|
emojiManager,
|
|
63
67
|
mentionManager,
|
|
68
|
+
imageCompressionConfig,
|
|
64
69
|
enableAutoPushTokenRegistration,
|
|
65
70
|
enableChannelListMessageReceiptStatus,
|
|
66
71
|
enableChannelListTypingIndicator,
|
|
67
72
|
enableUseUserIdForNickname,
|
|
68
73
|
enableUserMention,
|
|
74
|
+
enableImageCompression,
|
|
69
75
|
}: Props) => {
|
|
70
76
|
const [currentUser, _setCurrentUser] = useState<SendbirdUser>();
|
|
71
77
|
const forceUpdate = useForceUpdate();
|
|
72
78
|
const appFeatures = useAppFeatures(sdkInstance);
|
|
73
79
|
|
|
74
|
-
const setCurrentUser:
|
|
80
|
+
const setCurrentUser: SendbirdChatContextType['setCurrentUser'] = useCallback((user) => {
|
|
75
81
|
// NOTE: Sendbird SDK handle User object is always same object, so force update after setCurrentUser
|
|
76
82
|
_setCurrentUser(user);
|
|
77
83
|
forceUpdate();
|
|
78
84
|
}, []);
|
|
79
85
|
|
|
80
|
-
const updateCurrentUserInfo:
|
|
86
|
+
const updateCurrentUserInfo: SendbirdChatContextType['updateCurrentUserInfo'] = useCallback(
|
|
81
87
|
async (nickname, profile) => {
|
|
82
88
|
let user = currentUser;
|
|
83
89
|
|
|
@@ -109,28 +115,24 @@ export const SendbirdChatProvider = ({
|
|
|
109
115
|
[sdkInstance, currentUser, setCurrentUser],
|
|
110
116
|
);
|
|
111
117
|
|
|
112
|
-
const markAsDeliveredWithChannel:
|
|
118
|
+
const markAsDeliveredWithChannel: SendbirdChatContextType['markAsDeliveredWithChannel'] = useCallback(
|
|
113
119
|
(channel: SendbirdGroupChannel) => {
|
|
114
120
|
if (appFeatures.deliveryReceiptEnabled) confirmAndMarkAsDelivered([channel]);
|
|
115
121
|
},
|
|
116
122
|
[sdkInstance, appFeatures.deliveryReceiptEnabled],
|
|
117
123
|
);
|
|
118
124
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
};
|
|
125
|
+
useAppState('change', (status) => {
|
|
126
|
+
// 'active' | 'background' | 'inactive' | 'unknown' | 'extension';
|
|
127
|
+
if (status === 'active') sdkInstance.connectionState === 'CLOSED' && sdkInstance.setForegroundState();
|
|
128
|
+
else if (status === 'background') sdkInstance.connectionState === 'OPEN' && sdkInstance.setBackgroundState();
|
|
129
|
+
});
|
|
125
130
|
|
|
126
|
-
|
|
127
|
-
return () => subscriber.remove();
|
|
128
|
-
}, [sdkInstance]);
|
|
129
|
-
|
|
130
|
-
const value: Context = {
|
|
131
|
+
const value: SendbirdChatContextType = {
|
|
131
132
|
sdk: sdkInstance,
|
|
132
133
|
emojiManager,
|
|
133
134
|
mentionManager,
|
|
135
|
+
imageCompressionConfig,
|
|
134
136
|
currentUser,
|
|
135
137
|
setCurrentUser,
|
|
136
138
|
|
|
@@ -144,6 +146,7 @@ export const SendbirdChatProvider = ({
|
|
|
144
146
|
channelListMessageReceiptStatusEnabled: enableChannelListMessageReceiptStatus,
|
|
145
147
|
useUserIdForNicknameEnabled: enableUseUserIdForNickname,
|
|
146
148
|
userMentionEnabled: enableUserMention,
|
|
149
|
+
imageCompressionEnabled: enableImageCompression,
|
|
147
150
|
},
|
|
148
151
|
};
|
|
149
152
|
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
useToast,
|
|
19
19
|
useUIKitTheme,
|
|
20
20
|
} from '@sendbird/uikit-react-native-foundation';
|
|
21
|
-
import { conditionChaining } from '@sendbird/uikit-utils';
|
|
21
|
+
import { conditionChaining, isImage, shouldCompressImage } from '@sendbird/uikit-utils';
|
|
22
22
|
|
|
23
23
|
import { useLocalization, usePlatformService, useSendbirdChat } from '../../../../hooks/useContext';
|
|
24
24
|
import SBUError from '../../../../libs/SBUError';
|
|
@@ -49,9 +49,9 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
49
49
|
},
|
|
50
50
|
ref,
|
|
51
51
|
) {
|
|
52
|
-
const { mentionManager } = useSendbirdChat();
|
|
52
|
+
const { mentionManager, imageCompressionConfig, features } = useSendbirdChat();
|
|
53
53
|
const { STRINGS } = useLocalization();
|
|
54
|
-
const { fileService } = usePlatformService();
|
|
54
|
+
const { fileService, mediaService } = usePlatformService();
|
|
55
55
|
const { colors } = useUIKitTheme();
|
|
56
56
|
const { openSheet } = useBottomSheet();
|
|
57
57
|
const { alert } = useAlert();
|
|
@@ -75,13 +75,16 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
75
75
|
title: STRINGS.GROUP_CHANNEL.DIALOG_ATTACHMENT_CAMERA,
|
|
76
76
|
icon: 'camera',
|
|
77
77
|
onPress: async () => {
|
|
78
|
-
const
|
|
78
|
+
const mediaFile = await fileService.openCamera({
|
|
79
79
|
mediaType: 'all',
|
|
80
80
|
onOpenFailure: (error) => {
|
|
81
81
|
if (error.code === SBUError.CODE.ERR_PERMISSIONS_DENIED) {
|
|
82
82
|
alert({
|
|
83
83
|
title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
|
|
84
|
-
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
|
|
84
|
+
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
|
|
85
|
+
STRINGS.LABELS.PERMISSION_CAMERA,
|
|
86
|
+
STRINGS.LABELS.PERMISSION_APP_NAME,
|
|
87
|
+
),
|
|
85
88
|
buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
|
|
86
89
|
});
|
|
87
90
|
} else {
|
|
@@ -90,8 +93,28 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
90
93
|
},
|
|
91
94
|
});
|
|
92
95
|
|
|
93
|
-
if (
|
|
94
|
-
|
|
96
|
+
if (mediaFile) {
|
|
97
|
+
// Image compression
|
|
98
|
+
if (
|
|
99
|
+
isImage(mediaFile.uri, mediaFile.type) &&
|
|
100
|
+
shouldCompressImage(mediaFile.uri, features.imageCompressionEnabled)
|
|
101
|
+
) {
|
|
102
|
+
await SBUUtils.safeRun(async () => {
|
|
103
|
+
const compressed = await mediaService.compressImage({
|
|
104
|
+
uri: mediaFile.uri,
|
|
105
|
+
maxWidth: imageCompressionConfig.width,
|
|
106
|
+
maxHeight: imageCompressionConfig.height,
|
|
107
|
+
compressionRate: imageCompressionConfig.compressionRate,
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
if (compressed) {
|
|
111
|
+
mediaFile.uri = compressed.uri;
|
|
112
|
+
mediaFile.size = compressed.size;
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
onSendFileMessage(mediaFile).catch(() => toast.show(STRINGS.TOAST.SEND_MSG_ERROR, 'error'));
|
|
95
118
|
}
|
|
96
119
|
},
|
|
97
120
|
},
|
|
@@ -99,14 +122,17 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
99
122
|
title: STRINGS.GROUP_CHANNEL.DIALOG_ATTACHMENT_PHOTO_LIBRARY,
|
|
100
123
|
icon: 'photo',
|
|
101
124
|
onPress: async () => {
|
|
102
|
-
const
|
|
125
|
+
const mediaFiles = await fileService.openMediaLibrary({
|
|
103
126
|
selectionLimit: 1,
|
|
104
127
|
mediaType: 'all',
|
|
105
128
|
onOpenFailure: (error) => {
|
|
106
129
|
if (error.code === SBUError.CODE.ERR_PERMISSIONS_DENIED) {
|
|
107
130
|
alert({
|
|
108
131
|
title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
|
|
109
|
-
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
|
|
132
|
+
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
|
|
133
|
+
STRINGS.LABELS.PERMISSION_DEVICE_STORAGE,
|
|
134
|
+
STRINGS.LABELS.PERMISSION_APP_NAME,
|
|
135
|
+
),
|
|
110
136
|
buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
|
|
111
137
|
});
|
|
112
138
|
} else {
|
|
@@ -115,8 +141,30 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
115
141
|
},
|
|
116
142
|
});
|
|
117
143
|
|
|
118
|
-
if (
|
|
119
|
-
|
|
144
|
+
if (mediaFiles && mediaFiles[0]) {
|
|
145
|
+
const mediaFile = mediaFiles[0];
|
|
146
|
+
|
|
147
|
+
// Image compression
|
|
148
|
+
if (
|
|
149
|
+
isImage(mediaFile.uri, mediaFile.type) &&
|
|
150
|
+
shouldCompressImage(mediaFile.uri, features.imageCompressionEnabled)
|
|
151
|
+
) {
|
|
152
|
+
await SBUUtils.safeRun(async () => {
|
|
153
|
+
const compressed = await mediaService.compressImage({
|
|
154
|
+
uri: mediaFile.uri,
|
|
155
|
+
maxWidth: imageCompressionConfig.width,
|
|
156
|
+
maxHeight: imageCompressionConfig.height,
|
|
157
|
+
compressionRate: imageCompressionConfig.compressionRate,
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
if (compressed) {
|
|
161
|
+
mediaFile.uri = compressed.uri;
|
|
162
|
+
mediaFile.size = compressed.size;
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
onSendFileMessage(mediaFiles[0]).catch(() => toast.show(STRINGS.TOAST.SEND_MSG_ERROR, 'error'));
|
|
120
168
|
}
|
|
121
169
|
},
|
|
122
170
|
},
|
|
@@ -124,12 +172,32 @@ const SendInput = forwardRef<RNTextInput, SendInputProps>(function SendInput(
|
|
|
124
172
|
title: STRINGS.GROUP_CHANNEL.DIALOG_ATTACHMENT_FILES,
|
|
125
173
|
icon: 'document',
|
|
126
174
|
onPress: async () => {
|
|
127
|
-
const
|
|
175
|
+
const documentFile = await fileService.openDocument({
|
|
128
176
|
onOpenFailure: () => toast.show(STRINGS.TOAST.OPEN_FILES_ERROR, 'error'),
|
|
129
177
|
});
|
|
130
178
|
|
|
131
|
-
if (
|
|
132
|
-
|
|
179
|
+
if (documentFile) {
|
|
180
|
+
// Image compression
|
|
181
|
+
if (
|
|
182
|
+
isImage(documentFile.uri, documentFile.type) &&
|
|
183
|
+
shouldCompressImage(documentFile.uri, features.imageCompressionEnabled)
|
|
184
|
+
) {
|
|
185
|
+
await SBUUtils.safeRun(async () => {
|
|
186
|
+
const compressed = await mediaService.compressImage({
|
|
187
|
+
uri: documentFile.uri,
|
|
188
|
+
maxWidth: imageCompressionConfig.width,
|
|
189
|
+
maxHeight: imageCompressionConfig.height,
|
|
190
|
+
compressionRate: imageCompressionConfig.compressionRate,
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
if (compressed) {
|
|
194
|
+
documentFile.uri = compressed.uri;
|
|
195
|
+
documentFile.size = compressed.size;
|
|
196
|
+
}
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
onSendFileMessage(documentFile).catch(() => toast.show(STRINGS.TOAST.SEND_MSG_ERROR, 'error'));
|
|
133
201
|
}
|
|
134
202
|
},
|
|
135
203
|
},
|
|
@@ -24,6 +24,7 @@ const KEYBOARD_AVOID_VIEW_BEHAVIOR = Platform.select({ ios: 'padding' as const,
|
|
|
24
24
|
|
|
25
25
|
// FIXME(iOS): Dynamic style does not work properly when typing the CJK. (https://github.com/facebook/react-native/issues/26107)
|
|
26
26
|
// To workaround temporarily, change the key for re-mount the component.
|
|
27
|
+
// -> This will affect to keyboard blur when add/remove first mentioned user.
|
|
27
28
|
const GET_INPUT_KEY = (shouldReset: boolean) => (shouldReset ? 'uikit-input-clear' : 'uikit-input');
|
|
28
29
|
|
|
29
30
|
// TODO: Refactor 'Edit' mode to clearly
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import React, { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
|
2
|
-
import {
|
|
2
|
+
import { ListRenderItem, Platform, View } from 'react-native';
|
|
3
3
|
import { useSafeAreaInsets } from 'react-native-safe-area-context';
|
|
4
4
|
|
|
5
5
|
import type { BottomSheetItem } from '@sendbird/uikit-react-native-foundation';
|
|
@@ -29,6 +29,7 @@ import ChatFlatList from '../../../components/ChatFlatList';
|
|
|
29
29
|
import { ReactionAddons } from '../../../components/ReactionAddons';
|
|
30
30
|
import { DEPRECATION_WARNING } from '../../../constants';
|
|
31
31
|
import { useLocalization, usePlatformService, useSendbirdChat } from '../../../hooks/useContext';
|
|
32
|
+
import SBUUtils from '../../../libs/SBUUtils';
|
|
32
33
|
import { GroupChannelContexts } from '../module/moduleContext';
|
|
33
34
|
import type { GroupChannelProps } from '../types';
|
|
34
35
|
|
|
@@ -281,7 +282,7 @@ const useGetMessagePressActions = ({
|
|
|
281
282
|
break;
|
|
282
283
|
}
|
|
283
284
|
default: {
|
|
284
|
-
response.onPress = () =>
|
|
285
|
+
response.onPress = () => SBUUtils.openURL(msg.url);
|
|
285
286
|
break;
|
|
286
287
|
}
|
|
287
288
|
}
|
|
@@ -84,7 +84,10 @@ export const GroupChannelSettingsContextsProvider: GroupChannelSettingsModule['P
|
|
|
84
84
|
if (error.code === SBUError.CODE.ERR_PERMISSIONS_DENIED) {
|
|
85
85
|
alert({
|
|
86
86
|
title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
|
|
87
|
-
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
|
|
87
|
+
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
|
|
88
|
+
STRINGS.LABELS.PERMISSION_CAMERA,
|
|
89
|
+
STRINGS.LABELS.PERMISSION_APP_NAME,
|
|
90
|
+
),
|
|
88
91
|
buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
|
|
89
92
|
});
|
|
90
93
|
} else {
|
|
@@ -107,7 +110,10 @@ export const GroupChannelSettingsContextsProvider: GroupChannelSettingsModule['P
|
|
|
107
110
|
if (error.code === SBUError.CODE.ERR_PERMISSIONS_DENIED) {
|
|
108
111
|
alert({
|
|
109
112
|
title: STRINGS.DIALOG.ALERT_PERMISSIONS_TITLE,
|
|
110
|
-
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
|
|
113
|
+
message: STRINGS.DIALOG.ALERT_PERMISSIONS_MESSAGE(
|
|
114
|
+
STRINGS.LABELS.PERMISSION_DEVICE_STORAGE,
|
|
115
|
+
STRINGS.LABELS.PERMISSION_APP_NAME,
|
|
116
|
+
),
|
|
111
117
|
buttons: [{ text: STRINGS.DIALOG.ALERT_PERMISSIONS_OK, onPress: () => SBUUtils.openSettings() }],
|
|
112
118
|
});
|
|
113
119
|
} else {
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import { AppState } from 'react-native';
|
|
1
|
+
import React from 'react';
|
|
3
2
|
|
|
4
3
|
import { useGroupChannelList } from '@sendbird/uikit-chat-hooks';
|
|
5
|
-
import { PASS, useFreshCallback } from '@sendbird/uikit-utils';
|
|
4
|
+
import { PASS, useAppState, useFreshCallback } from '@sendbird/uikit-utils';
|
|
6
5
|
|
|
7
6
|
import StatusComposition from '../components/StatusComposition';
|
|
8
7
|
import GroupChannelPreviewContainer from '../containers/GroupChannelPreviewContainer';
|
|
@@ -34,12 +33,9 @@ const createGroupChannelListFragment = (initModule?: Partial<GroupChannelListMod
|
|
|
34
33
|
});
|
|
35
34
|
|
|
36
35
|
if (features.deliveryReceiptEnabled) {
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
});
|
|
41
|
-
return () => listener.remove();
|
|
42
|
-
}, []);
|
|
36
|
+
useAppState('change', (status) => {
|
|
37
|
+
if (status === 'active') groupChannels.forEach(markAsDeliveredWithChannel);
|
|
38
|
+
});
|
|
43
39
|
}
|
|
44
40
|
|
|
45
41
|
const _renderGroupChannelPreview: GroupChannelListProps['List']['renderGroupChannelPreview'] = useFreshCallback(
|
|
@@ -9,9 +9,14 @@ type KeyboardEvents = {
|
|
|
9
9
|
hideEvent: KeyboardEventName;
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
let isLayoutAnimationConfigured = false;
|
|
13
|
+
|
|
12
14
|
const configureNextLayoutAnimation = (event: KeyboardEvent) => {
|
|
13
|
-
|
|
14
|
-
LayoutAnimation.
|
|
15
|
+
if (isLayoutAnimationConfigured) return;
|
|
16
|
+
const config = LayoutAnimation.create(event.duration, event.easing, LayoutAnimation.Properties.scaleY);
|
|
17
|
+
isLayoutAnimationConfigured = true;
|
|
18
|
+
const onEnd = () => (isLayoutAnimationConfigured = false);
|
|
19
|
+
LayoutAnimation.configureNext(config, onEnd, onEnd);
|
|
15
20
|
};
|
|
16
21
|
|
|
17
22
|
const { showEvent, hideEvent } = Platform.select<KeyboardEvents>({
|
|
@@ -34,12 +39,12 @@ const useKeyboardStatus = () => {
|
|
|
34
39
|
setKeyboardStatus({ visible: true, height, bottomSpace });
|
|
35
40
|
}),
|
|
36
41
|
|
|
37
|
-
Keyboard.addListener(hideEvent, (
|
|
42
|
+
Keyboard.addListener(hideEvent, () => {
|
|
38
43
|
const height = 0;
|
|
39
44
|
const bottomSpace = Platform.select({ default: height });
|
|
40
|
-
const nextLayoutAnimation = Platform.select({ ios: configureNextLayoutAnimation, default: NOOP });
|
|
45
|
+
// const nextLayoutAnimation = Platform.select({ ios: configureNextLayoutAnimation, default: NOOP });
|
|
41
46
|
|
|
42
|
-
nextLayoutAnimation(event);
|
|
47
|
+
// nextLayoutAnimation(event);
|
|
43
48
|
setKeyboardStatus({ visible: false, height, bottomSpace });
|
|
44
49
|
}),
|
|
45
50
|
];
|
package/src/index.ts
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Logger } from '@sendbird/uikit-utils';
|
|
2
|
+
|
|
3
|
+
export interface ImageCompressionConfigInterface {
|
|
4
|
+
compressionRate: number;
|
|
5
|
+
width?: number;
|
|
6
|
+
height?: number;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
class ImageCompressionConfig {
|
|
10
|
+
static DEFAULT = {
|
|
11
|
+
COMPRESSION_RATE: 0.7,
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
constructor(private _config: ImageCompressionConfigInterface) {
|
|
15
|
+
if (_config.compressionRate > 1) Logger.warn('Compression rate must be in the range of 0.0 - 1.0');
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get compressionRate() {
|
|
19
|
+
return Math.min(Math.max(0, this._config.compressionRate), 1);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get width() {
|
|
23
|
+
return this._config.width;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
get height() {
|
|
27
|
+
return this._config.height;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export default ImageCompressionConfig;
|
package/src/libs/SBUUtils.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
import { Linking, Platform } from 'react-native';
|
|
1
|
+
import { Image, Linking, Platform } from 'react-native';
|
|
2
|
+
|
|
3
|
+
import { Logger } from '@sendbird/uikit-utils';
|
|
2
4
|
|
|
3
5
|
export default class SBUUtils {
|
|
4
6
|
static openSettings() {
|
|
@@ -6,4 +8,29 @@ export default class SBUUtils {
|
|
|
6
8
|
if (Platform.OS === 'ios') Linking.openURL('App-Prefs:root');
|
|
7
9
|
});
|
|
8
10
|
}
|
|
11
|
+
|
|
12
|
+
static openURL(url: string) {
|
|
13
|
+
const targetUrl = url.startsWith('http') ? url : 'https://' + url;
|
|
14
|
+
Linking.openURL(targetUrl).catch((err) => Logger.warn('Cannot open url', err));
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
static getImageSize(uri: string): Promise<{ width: number; height: number }> {
|
|
18
|
+
return new Promise((resolve, reject) => {
|
|
19
|
+
Image.getSize(
|
|
20
|
+
uri,
|
|
21
|
+
(width, height) => {
|
|
22
|
+
resolve({ width, height });
|
|
23
|
+
},
|
|
24
|
+
(error) => {
|
|
25
|
+
reject(error);
|
|
26
|
+
},
|
|
27
|
+
);
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
static async safeRun(callback: () => Promise<void>) {
|
|
32
|
+
try {
|
|
33
|
+
await callback();
|
|
34
|
+
} catch (e) {}
|
|
35
|
+
}
|
|
9
36
|
}
|
|
@@ -169,6 +169,10 @@ export interface StringSet {
|
|
|
169
169
|
};
|
|
170
170
|
// UI
|
|
171
171
|
LABELS: {
|
|
172
|
+
PERMISSION_APP_NAME: string;
|
|
173
|
+
PERMISSION_CAMERA: string;
|
|
174
|
+
PERMISSION_DEVICE_STORAGE: string;
|
|
175
|
+
|
|
172
176
|
USER_NO_NAME: string;
|
|
173
177
|
CHANNEL_NO_MEMBERS: string;
|
|
174
178
|
TYPING_INDICATOR_TYPINGS: (users: SendbirdUser[]) => string | undefined;
|
|
@@ -391,6 +395,9 @@ export const createBaseStringSet = ({ dateLocale, overrides }: StringSetCreateOp
|
|
|
391
395
|
...overrides?.GROUP_CHANNEL_INVITE,
|
|
392
396
|
},
|
|
393
397
|
LABELS: {
|
|
398
|
+
PERMISSION_APP_NAME: 'Application',
|
|
399
|
+
PERMISSION_CAMERA: 'camera',
|
|
400
|
+
PERMISSION_DEVICE_STORAGE: 'device storage',
|
|
394
401
|
USER_NO_NAME,
|
|
395
402
|
CHANNEL_NO_MEMBERS,
|
|
396
403
|
TYPING_INDICATOR_TYPINGS: (users, NO_NAME = USER_NO_NAME) => {
|