Skip to content

Commit b9afda6

Browse files
committed
feat: support mmkv storage and deprecate a async storage
1 parent 3836c10 commit b9afda6

File tree

20 files changed

+2087
-538
lines changed

20 files changed

+2087
-538
lines changed

docs-validation/1_introduction/SendYourFirstMessage.tsx

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -61,13 +61,15 @@ export const platformServices: SendbirdUIKitContainerProps['platformServices'] =
6161
* {@link https://sendbird.com/docs/chat/uikit/v3/react-native/introduction/send-first-message#2-get-started-3-step-5-wrap-your-app-in-sendbirduikitcontainer}
6262
* */
6363
import { SendbirdUIKitContainer } from '@sendbird/uikit-react-native';
64-
import AsyncStorage from '@react-native-async-storage/async-storage';
64+
import { MMKV } from 'react-native-mmkv';
65+
66+
const mmkv = new MMKV();
6567

6668
const App = () => {
6769
return (
6870
<SendbirdUIKitContainer
6971
appId={'APP_ID'}
70-
chatOptions={{ localCacheStorage: AsyncStorage }}
72+
chatOptions={{ localCacheStorage: mmkv }}
7173
platformServices={platformServices}
7274
>
7375
{/* Rest of your app */}
@@ -186,7 +188,7 @@ const App2 = () => {
186188
return (
187189
<SendbirdUIKitContainer
188190
appId={'APP_ID'}
189-
chatOptions={{ localCacheStorage: AsyncStorage }}
191+
chatOptions={{ localCacheStorage: mmkv }}
190192
platformServices={platformServices}
191193
>
192194
<Navigation />

docs-validation/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@
99
},
1010
"dependencies": {
1111
"@bam.tech/react-native-image-resizer": "^3.0.4",
12-
"@react-native-async-storage/async-storage": "^1.15.17",
1312
"@react-native-camera-roll/camera-roll": "^5.4.0",
1413
"@react-native-clipboard/clipboard": "^1.8.5",
1514
"@react-native-firebase/messaging": "^14.7.0",
1615
"@react-navigation/native": "^6.0.6",
1716
"@react-navigation/native-stack": "^6.7.0",
18-
"@sendbird/chat": "^4.10.7",
17+
"@sendbird/chat": "^4.12.8",
1918
"react": "17.0.2",
2019
"react-native": "0.67.5",
2120
"react-native-create-thumbnail": "^1.5.1",
2221
"react-native-document-picker": "^8.0.0",
2322
"react-native-file-access": "^2.5.0",
2423
"react-native-image-picker": "^4.7.3",
24+
"react-native-mmkv": "^2.0.0",
2525
"react-native-permissions": "^3.6.0",
2626
"react-native-safe-area-context": "^3.3.2",
2727
"react-native-video": "^5.2.0"

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@
9898
]
9999
},
100100
"resolutions": {
101-
"@sendbird/chat": "4.11.3",
101+
"@sendbird/chat": "4.12.8",
102102
"@types/react": "^18",
103103
"@types/react-native": "^0.67"
104104
}

packages/uikit-chat-hooks/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@
5555
"typescript": "5.2.2"
5656
},
5757
"peerDependencies": {
58-
"@sendbird/chat": "^4.10.7",
58+
"@sendbird/chat": "^4.12.8",
5959
"react": ">=16.13.1"
6060
},
6161
"react-native-builder-bob": {

packages/uikit-react-native/README.md

Lines changed: 11 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -46,16 +46,15 @@ UIKit for React-Native can be installed through either `yarn` or `npm`
4646

4747
**Install dependencies**
4848

49-
> Note: If you are using `react-native` version `0.72` or higher, you don't need to install `@sendbird/react-native-scrollview-enhancer`.
49+
> Note: If you are using `react-native` version `0.71` or lower, you should install `@sendbird/react-native-scrollview-enhancer`.
5050
5151
```sh
5252
npm install @sendbird/uikit-react-native \
5353
@sendbird/chat \
54-
@sendbird/react-native-scrollview-enhancer \
5554
date-fns \
5655
react-native-safe-area-context \
5756
@react-native-community/netinfo \
58-
@react-native-async-storage/async-storage
57+
react-native-mmkv
5958
```
6059

6160
**Linking native modules**
@@ -116,7 +115,7 @@ const App = () => {
116115
<SendbirdUIKitContainer
117116
appId={'APP_ID'}
118117
chatOptions={{
119-
localCacheStorage: AsyncStorage,
118+
localCacheStorage: MMKV,
120119
}}
121120
platformServices={{
122121
file: FileService,
@@ -257,45 +256,30 @@ const expoPlatformServices = {
257256
You can implement Local caching easily.
258257

259258
```shell
260-
npm i @react-native-async-storage/async-storage
259+
npm i react-native-mmkv
261260
npx pod-install
262261
```
263262

264263
```tsx
265-
import AsyncStorage from '@react-native-async-storage/async-storage';
264+
import { MMKV } from 'react-native-mmkv';
266265

267266
import { SendbirdUIKitContainer } from '@sendbird/uikit-react-native';
268267

268+
const mmkv = new MMKV();
269269
const App = () => {
270-
return <SendbirdUIKitContainer chatOptions={{ localCacheStorage: AsyncStorage }}>{/* ... */}</SendbirdUIKitContainer>;
270+
return <SendbirdUIKitContainer chatOptions={{ localCacheStorage: mmkv }}>{/* ... */}</SendbirdUIKitContainer>;
271271
};
272272
```
273273

274-
Or you can use storage you are using instead of `AsyncStorage` (e.g. [`react-native-mmkv`](https://github.com/mrousavy/react-native-mmkv))
274+
Or you can use `AsyncStorage` instead of `MMKV`, but it has been deprecated.
275275

276276
```tsx
277-
import { MMKV } from 'react-native-mmkv';
277+
import { AsyncStorage } from '@react-native-async-storage/async-storage';
278278

279-
import { LocalCacheStorage, SendbirdUIKitContainer } from '@sendbird/uikit-react-native';
280-
281-
const mmkvStorage = new MMKV();
282-
const localCacheStorage: LocalCacheStorage = {
283-
async getAllKeys() {
284-
return mmkvStorage.getAllKeys();
285-
},
286-
async setItem(key: string, value: string) {
287-
return mmkvStorage.set(key, value);
288-
},
289-
async getItem(key: string) {
290-
return mmkvStorage.getString(key) ?? null;
291-
},
292-
async removeItem(key: string) {
293-
return mmkvStorage.delete(key);
294-
},
295-
};
279+
import { SendbirdUIKitContainer } from '@sendbird/uikit-react-native';
296280

297281
const App = () => {
298-
return <SendbirdUIKitContainer chatOptions={{ localCacheStorage }}>{/* ... */}</SendbirdUIKitContainer>;
282+
return <SendbirdUIKitContainer chatOptions={{ localCacheStorage: AsyncStorage }}>{/* ... */}</SendbirdUIKitContainer>;
299283
};
300284
```
301285

packages/uikit-react-native/package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
"react-native-document-picker": "^8.0.0",
9898
"react-native-file-access": "^2.5.0",
9999
"react-native-image-picker": "^4.7.1",
100+
"react-native-mmkv": "2.5.1",
100101
"react-native-permissions": "^3.6.0",
101102
"react-native-safe-area-context": "^3.3.2",
102103
"react-native-video": "^5.2.0",
@@ -108,7 +109,7 @@
108109
"@react-native-clipboard/clipboard": ">=1.8.5",
109110
"@react-native-community/netinfo": ">=9.3.0",
110111
"@react-native-firebase/messaging": ">=14.4.0",
111-
"@sendbird/chat": "^4.10.7",
112+
"@sendbird/chat": "^4.12.8",
112113
"@sendbird/react-native-scrollview-enhancer": "*",
113114
"date-fns": ">=2.28.0",
114115
"expo-av": ">=12.0.4",
@@ -126,6 +127,7 @@
126127
"react-native-document-picker": ">=8.0.0",
127128
"react-native-file-access": ">=2.4.3",
128129
"react-native-image-picker": ">=4.7.1",
130+
"react-native-mmkv": "^2.0.0",
129131
"react-native-permissions": ">=3.6.0",
130132
"react-native-safe-area-context": ">=3.3.2",
131133
"react-native-video": ">=5.2.0"

packages/uikit-react-native/src/containers/SendbirdUIKitContainer.tsx

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,17 @@ import {
1515
UIKitThemeProvider,
1616
} from '@sendbird/uikit-react-native-foundation';
1717
import { SBUConfig, UIKitConfigProvider } from '@sendbird/uikit-tools';
18-
import type {
18+
import {
19+
Logger,
20+
NOOP,
1921
PartialDeep,
2022
SendbirdChatSDK,
2123
SendbirdGroupChannel,
2224
SendbirdGroupChannelCreateParams,
2325
SendbirdMember,
2426
SendbirdUser,
27+
useIsFirstMount,
2528
} from '@sendbird/uikit-utils';
26-
import { NOOP, useIsFirstMount } from '@sendbird/uikit-utils';
2729

2830
import { LocalizationContext, LocalizationProvider } from '../contexts/LocalizationCtx';
2931
import { PlatformServiceProvider } from '../contexts/PlatformServiceCtx';
@@ -49,7 +51,7 @@ import type {
4951
PlayerServiceInterface,
5052
RecorderServiceInterface,
5153
} from '../platform/types';
52-
import type { ErrorBoundaryProps, LocalCacheStorage } from '../types';
54+
import { ErrorBoundaryProps, LocalCacheStorage } from '../types';
5355
import VERSION from '../version';
5456
import InternalErrorBoundaryContainer from './InternalErrorBoundaryContainer';
5557

@@ -78,13 +80,13 @@ const chatOmitKeys = [
7880
'appVersion',
7981
'localCacheEnabled',
8082
'useAsyncStorageStore',
83+
'useMMKVStorageStore',
8184
] as const;
8285
function sanitizeChatOptions<T extends Record<string, unknown>>(chatOptions: T): T {
8386
const opts = { ...chatOptions };
8487
chatOmitKeys.forEach((key) => delete opts[key]);
8588
return opts;
8689
}
87-
8890
export type SendbirdUIKitContainerProps = React.PropsWithChildren<{
8991
appId: string;
9092
platformServices: {
@@ -95,11 +97,11 @@ export type SendbirdUIKitContainerProps = React.PropsWithChildren<{
9597
player: PlayerServiceInterface;
9698
recorder: RecorderServiceInterface;
9799
};
98-
chatOptions: {
99-
localCacheStorage: LocalCacheStorage;
100-
onInitialized?: (sdkInstance: SendbirdChatSDK) => SendbirdChatSDK;
101-
} & Partial<ChatOmittedInitParams> &
102-
Partial<ChatRelatedFeaturesInUIKit>;
100+
chatOptions: Partial<ChatOmittedInitParams> &
101+
Partial<ChatRelatedFeaturesInUIKit> & {
102+
onInitialized?: (sdkInstance: SendbirdChatSDK) => SendbirdChatSDK;
103+
localCacheStorage: LocalCacheStorage;
104+
};
103105
uikitOptions?: PartialDeep<{
104106
common: SBUConfig['common'];
105107
groupChannel: Omit<SBUConfig['groupChannel']['channel'], UnimplementedFeatures> & {
@@ -163,6 +165,10 @@ const SendbirdUIKitContainer = (props: SendbirdUIKitContainerProps) => {
163165

164166
if (!chatOptions.localCacheStorage) {
165167
throw new Error('SendbirdUIKitContainer: chatOptions.localCacheStorage is required');
168+
} else if ('getItem' in chatOptions.localCacheStorage) {
169+
Logger.warn(
170+
'SendbirdUIKitContainer: localCacheStorage for `AsyncStorage` is deprecated. Please use `MMKV` instead.',
171+
);
166172
}
167173

168174
const defaultStringSet = localization?.stringSet ?? StringSetEn;
@@ -172,7 +178,7 @@ const SendbirdUIKitContainer = (props: SendbirdUIKitContainerProps) => {
172178

173179
const [internalStorage] = useState(() => new InternalLocalCacheStorage(chatOptions.localCacheStorage));
174180
const [sdkInstance, setSdkInstance] = useState<SendbirdChatSDK>(() => {
175-
const sendbird = initializeSendbird(appId, { internalStorage, ...sanitizeChatOptions(chatOptions) });
181+
const sendbird = initializeSendbird(appId, sanitizeChatOptions(chatOptions));
176182
unsubscribes.current = sendbird.unsubscribes;
177183
return sendbird.chatSDK;
178184
});
@@ -183,7 +189,7 @@ const SendbirdUIKitContainer = (props: SendbirdUIKitContainerProps) => {
183189

184190
useLayoutEffect(() => {
185191
if (!isFirstMount) {
186-
const sendbird = initializeSendbird(appId, { internalStorage, ...sanitizeChatOptions(chatOptions) });
192+
const sendbird = initializeSendbird(appId, sanitizeChatOptions(chatOptions));
187193
setSdkInstance(sendbird.chatSDK);
188194
unsubscribes.current = sendbird.unsubscribes;
189195
}
@@ -287,21 +293,23 @@ const SendbirdUIKitContainer = (props: SendbirdUIKitContainerProps) => {
287293
};
288294

289295
interface InitOptions extends ChatOmittedInitParams {
290-
internalStorage: InternalLocalCacheStorage;
296+
localCacheStorage: LocalCacheStorage;
291297
onInitialized?: (sdk: SendbirdChatSDK) => SendbirdChatSDK;
292298
}
293299
const initializeSendbird = (appId: string, options: InitOptions) => {
294300
let chatSDK: SendbirdChatSDK;
295301
const unsubscribes: Array<() => void> = [];
296-
const { internalStorage, onInitialized, ...chatInitParams } = options;
302+
const { localCacheStorage, onInitialized, ...chatInitParams } = options;
297303

304+
const isMMKVStorage = 'getString' in localCacheStorage;
298305
chatSDK = SendbirdChat.init({
299306
...chatInitParams,
300307
appId,
301308
newInstance: true,
302309
modules: [new GroupChannelModule(), new OpenChannelModule()],
303310
localCacheEnabled: true,
304-
useAsyncStorageStore: internalStorage as never,
311+
useMMKVStorageStore: isMMKVStorage ? (localCacheStorage as never) : undefined,
312+
useAsyncStorageStore: !isMMKVStorage ? (localCacheStorage as never) : undefined,
305313
});
306314

307315
if (onInitialized) {

packages/uikit-react-native/src/libs/EmojiManager.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import type { SendbirdEmoji, SendbirdEmojiCategory, SendbirdEmojiContainer } from '@sendbird/uikit-utils';
22

3-
import type { LocalCacheStorage } from '../types';
3+
import type { AsyncLocalCacheStorage } from '../types';
44
import InternalLocalCacheStorage from './InternalLocalCacheStorage';
55

6-
class MemoryStorage implements LocalCacheStorage {
6+
class MemoryStorage implements AsyncLocalCacheStorage {
77
_data: Record<string, string> = {};
88

99
async getAllKeys(): Promise<readonly string[] | string[]> {

0 commit comments

Comments
 (0)