diff --git a/.storybook/preview.tsx b/.storybook/preview.tsx
index 1cd9a07cd..d08cce149 100644
--- a/.storybook/preview.tsx
+++ b/.storybook/preview.tsx
@@ -1,6 +1,6 @@
import React from 'react';
import type { Preview } from '@storybook/react';
-import { SendbirdSdkContext } from '../src/lib/SendbirdSdkContext';
+import { SendbirdContext } from '../src/lib/Sendbird/context/SendbirdContext';
import '../src/lib/index.scss';
import './index.css';
@@ -28,9 +28,9 @@ const preview: Preview = {
decorators: [
(Story) => (
-
+
{Story()}
-
+
),
],
diff --git a/apps/testing/src/utils/paramsBuilder.ts b/apps/testing/src/utils/paramsBuilder.ts
index 66fab5531..fc190f9af 100644
--- a/apps/testing/src/utils/paramsBuilder.ts
+++ b/apps/testing/src/utils/paramsBuilder.ts
@@ -1,4 +1,4 @@
-import { UIKitOptions } from '../../../../src/lib/types.ts';
+import { UIKitOptions } from '../../../../src/lib/Sendbird/types';
import { useSearchParams } from 'react-router-dom';
export interface InitialParams {
diff --git a/rollup.module-exports.mjs b/rollup.module-exports.mjs
index bea9e1cc5..9c1756795 100644
--- a/rollup.module-exports.mjs
+++ b/rollup.module-exports.mjs
@@ -10,10 +10,11 @@ export default {
App: 'src/modules/App/index.tsx',
// SendbirdProvider
- SendbirdProvider: 'src/lib/Sendbird.tsx',
+ SendbirdProvider: 'src/lib/Sendbird/index.tsx',
sendbirdSelectors: 'src/lib/selectors.ts',
- useSendbirdStateContext: 'src/hooks/useSendbirdStateContext.tsx',
- withSendbird: 'src/lib/SendbirdSdkContext.tsx',
+ // TODO: Support below legacy exports
+ // useSendbirdStateContext: 'src/hooks/useSendbirdStateContext.tsx',
+ // withSendbird: 'src/lib/SendbirdSdkContext.tsx',
// Voice message
'VoiceRecorder/context': 'src/hooks/VoiceRecorder/index.tsx',
diff --git a/src/hooks/VoicePlayer/index.tsx b/src/hooks/VoicePlayer/index.tsx
index 598528242..de644ec80 100644
--- a/src/hooks/VoicePlayer/index.tsx
+++ b/src/hooks/VoicePlayer/index.tsx
@@ -19,8 +19,8 @@ import {
VOICE_PLAYER_AUDIO_ID,
VOICE_PLAYER_ROOT_ID,
} from '../../utils/consts';
-import useSendbirdStateContext from '../useSendbirdStateContext';
import { getParsedVoiceAudioFileInfo } from './utils';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
// VoicePlayerProvider interface
export interface VoicePlayerProps {
@@ -64,7 +64,8 @@ export const VoicePlayerProvider = ({
currentPlayer,
audioStorage,
} = voicePlayerStore;
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const { logger } = config;
const stop = (text = '') => {
diff --git a/src/hooks/VoiceRecorder/index.tsx b/src/hooks/VoiceRecorder/index.tsx
index 84681b9ca..217877f5d 100644
--- a/src/hooks/VoiceRecorder/index.tsx
+++ b/src/hooks/VoiceRecorder/index.tsx
@@ -8,9 +8,9 @@ import {
VOICE_MESSAGE_MIME_TYPE,
VOICE_RECORDER_AUDIO_BIT_RATE,
} from '../../utils/consts';
-import useSendbirdStateContext from '../useSendbirdStateContext';
import { type WebAudioUtils } from './WebAudioUtils';
import { noop } from '../../utils/utils';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
// Input props of VoiceRecorder
export interface VoiceRecorderProps {
@@ -37,7 +37,8 @@ const Context = createContext({
export const VoiceRecorderProvider = (props: VoiceRecorderProps): React.ReactElement => {
const { children } = props;
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const { logger, groupChannel } = config;
const [mediaRecorder, setMediaRecorder] = useState(null);
const [isRecordable, setIsRecordable] = useState(false);
diff --git a/src/hooks/VoiceRecorder/useVoiceRecorder.tsx b/src/hooks/VoiceRecorder/useVoiceRecorder.tsx
index 50533cabf..e317b1c2a 100644
--- a/src/hooks/VoiceRecorder/useVoiceRecorder.tsx
+++ b/src/hooks/VoiceRecorder/useVoiceRecorder.tsx
@@ -1,7 +1,7 @@
import { useCallback, useEffect, useRef, useState } from 'react';
import { VoiceRecorderEventHandler, useVoiceRecorderContext } from '.';
-import useSendbirdStateContext from '../useSendbirdStateContext';
import { noop } from '../../utils/utils';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
// export interface UseVoiceRecorderProps extends VoiceRecorderEventHandler {
// /**
@@ -31,7 +31,8 @@ export const useVoiceRecorder = ({
onRecordingStarted = noop,
onRecordingEnded = noop,
}: VoiceRecorderEventHandler): UseVoiceRecorderContext => {
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const { voiceRecord } = config;
const maxRecordingTime = voiceRecord.maxRecordingTime;
const voiceRecorder = useVoiceRecorderContext();
diff --git a/src/hooks/useSendbirdStateContext.tsx b/src/hooks/useSendbirdStateContext.tsx
deleted file mode 100644
index 591fd8f66..000000000
--- a/src/hooks/useSendbirdStateContext.tsx
+++ /dev/null
@@ -1,22 +0,0 @@
-/**
- * Example:
- * const MyComponent = () => {
- * const context = useSendbirdStateContext();
- * const sdk = sendbirdSelectors.getSdk(context);
- * return (...
);
- * }
- */
-import { useContext } from 'react';
-
-import { SendbirdSdkContext } from '../lib/SendbirdSdkContext';
-import { SendBirdState } from '../lib/types';
-
-const NO_CONTEXT_ERROR = 'No sendbird state value available. Make sure you are rendering `` at the top of your app.';
-
-export function useSendbirdStateContext(): SendBirdState {
- const context = useContext(SendbirdSdkContext);
- if (!context) throw new Error(NO_CONTEXT_ERROR);
- return context;
-}
-
-export default useSendbirdStateContext;
diff --git a/src/index.ts b/src/index.ts
index 14dd7e661..16bf960d2 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -15,11 +15,11 @@ export { default as MessageSearch } from './modules/MessageSearch';
// HOC for using ui-kit state
// withBird(MyCustomComponent) will give the sendbird state as props to MyCustomComponent
-export { default as withSendBird } from './lib/SendbirdSdkContext';
+export { withSendBird } from './lib/Sendbird/index';
+export { useSendbirdStateContext } from './lib/Sendbird/context/hooks/useSendbirdStateContext';
export { default as sendbirdSelectors } from './lib/selectors';
// for legacy parity, slowly remove
export { default as sendBirdSelectors } from './lib/selectors';
-export { default as useSendbirdStateContext } from './hooks/useSendbirdStateContext';
// Public enum included in AppProps
export { TypingIndicatorType } from './types';
diff --git a/src/lib/MediaQueryContext.tsx b/src/lib/MediaQueryContext.tsx
index 5c59fe9e0..20eb8163e 100644
--- a/src/lib/MediaQueryContext.tsx
+++ b/src/lib/MediaQueryContext.tsx
@@ -1,5 +1,5 @@
import React, { useEffect, useState } from 'react';
-import type { Logger } from './SendbirdState';
+import type { Logger } from './Sendbird/types';
const DEFAULT_MOBILE = false;
// const DEFAULT_MOBILE = '768px';
diff --git a/src/lib/Sendbird.tsx b/src/lib/Sendbird.tsx
deleted file mode 100644
index a2eadf6b2..000000000
--- a/src/lib/Sendbird.tsx
+++ /dev/null
@@ -1,436 +0,0 @@
-import './index.scss';
-import './__experimental__typography.scss';
-
-import React, { useEffect, useMemo, useReducer, useState } from 'react';
-import { GroupChannel } from '@sendbird/chat/groupChannel';
-import { UIKitConfigProvider, useUIKitConfig } from '@sendbird/uikit-tools';
-
-import { SendbirdSdkContext } from './SendbirdSdkContext';
-
-import useTheme from './hooks/useTheme';
-
-import sdkReducers from './dux/sdk/reducers';
-import userReducers from './dux/user/reducers';
-import appInfoReducers from './dux/appInfo/reducers';
-
-import sdkInitialState from './dux/sdk/initialState';
-import userInitialState from './dux/user/initialState';
-import appInfoInitialState from './dux/appInfo/initialState';
-
-import useOnlineStatus from './hooks/useOnlineStatus';
-import useConnect from './hooks/useConnect';
-import { LoggerFactory, LogLevel } from './Logger';
-import pubSubFactory from './pubSub/index';
-
-import { VoiceMessageProvider } from './VoiceMessageProvider';
-import { LocalizationProvider } from './LocalizationContext';
-import { MediaQueryProvider, useMediaQueryContext } from './MediaQueryContext';
-import getStringSet, { StringSet } from '../ui/Label/stringSet';
-import {
- DEFAULT_MULTIPLE_FILES_MESSAGE_LIMIT,
- DEFAULT_UPLOAD_SIZE_LIMIT,
- VOICE_RECORDER_DEFAULT_MAX,
- VOICE_RECORDER_DEFAULT_MIN,
-} from '../utils/consts';
-import { uikitConfigMapper } from './utils/uikitConfigMapper';
-
-import { useMarkAsReadScheduler } from './hooks/useMarkAsReadScheduler';
-import { ConfigureSessionTypes } from './hooks/useConnect/types';
-import { useMarkAsDeliveredScheduler } from './hooks/useMarkAsDeliveredScheduler';
-import { getCaseResolvedReplyType } from './utils/resolvedReplyType';
-import { useUnmount } from '../hooks/useUnmount';
-import { disconnectSdk } from './hooks/useConnect/disconnectSdk';
-import {
- UIKitOptions,
- CommonUIKitConfigProps,
- SendbirdChatInitParams,
- CustomExtensionParams,
- SBUEventHandlers,
- SendbirdProviderUtils,
-} from './types';
-import { GlobalModalProvider, ModalRoot } from '../hooks/useModal';
-import { HTMLTextDirection, RenderUserProfileProps, UserListQuery } from '../types';
-import PUBSUB_TOPICS, { SBUGlobalPubSub, SBUGlobalPubSubTopicPayloadUnion } from './pubSub/topics';
-import { EmojiManager } from './emojiManager';
-import { uikitConfigStorage } from './utils/uikitConfigStorage';
-import useMessageTemplateUtils from './hooks/useMessageTemplateUtils';
-import { EmojiReactionListRoot, MenuRoot } from '../ui/ContextMenu';
-import useHTMLTextDirection from '../hooks/useHTMLTextDirection';
-
-export { useSendbirdStateContext } from '../hooks/useSendbirdStateContext';
-
-interface VoiceRecordOptions {
- maxRecordingTime?: number;
- minRecordingTime?: number;
-}
-
-export type ImageCompressionOutputFormatType = 'preserve' | 'png' | 'jpeg';
-export interface ImageCompressionOptions {
- compressionRate?: number;
- resizingWidth?: number | string;
- resizingHeight?: number | string;
- outputFormat?: ImageCompressionOutputFormatType;
-}
-
-export interface SendbirdConfig {
- logLevel?: string | Array;
- pubSub?: SBUGlobalPubSub;
- userMention?: {
- maxMentionCount?: number;
- maxSuggestionCount?: number;
- };
- isREMUnitEnabled?: boolean;
-}
-
-export interface SendbirdProviderProps extends CommonUIKitConfigProps, React.PropsWithChildren {
- appId: string;
- userId: string;
- accessToken?: string;
- customApiHost?: string;
- customWebSocketHost?: string;
- configureSession?: ConfigureSessionTypes;
- theme?: 'light' | 'dark';
- config?: SendbirdConfig;
- nickname?: string;
- colorSet?: Record;
- stringSet?: Partial;
- dateLocale?: Locale;
- profileUrl?: string;
- voiceRecord?: VoiceRecordOptions;
- userListQuery?: () => UserListQuery;
- imageCompression?: ImageCompressionOptions;
- allowProfileEdit?: boolean;
- disableMarkAsDelivered?: boolean;
- breakpoint?: string | boolean;
- htmlTextDirection?: HTMLTextDirection;
- forceLeftToRightMessageLayout?: boolean;
- uikitOptions?: UIKitOptions;
- isUserIdUsedForNickname?: boolean;
- sdkInitParams?: SendbirdChatInitParams;
- customExtensionParams?: CustomExtensionParams;
- isMultipleFilesMessageEnabled?: boolean;
- // UserProfile
- renderUserProfile?: (props: RenderUserProfileProps) => React.ReactElement;
- onStartDirectMessage?: (channel: GroupChannel) => void;
- /**
- * @deprecated Please use `onStartDirectMessage` instead. It's renamed.
- */
- onUserProfileMessage?: (channel: GroupChannel) => void;
-
- // Customer provided callbacks
- eventHandlers?: SBUEventHandlers;
-}
-
-export function SendbirdProvider(props: SendbirdProviderProps) {
- const localConfigs: UIKitOptions = uikitConfigMapper({
- legacyConfig: {
- replyType: props.replyType,
- isMentionEnabled: props.isMentionEnabled,
- isReactionEnabled: props.isReactionEnabled,
- disableUserProfile: props.disableUserProfile,
- isVoiceMessageEnabled: props.isVoiceMessageEnabled,
- isTypingIndicatorEnabledOnChannelList: props.isTypingIndicatorEnabledOnChannelList,
- isMessageReceiptStatusEnabledOnChannelList: props.isMessageReceiptStatusEnabledOnChannelList,
- showSearchIcon: props.showSearchIcon,
- },
- uikitOptions: props.uikitOptions,
- });
-
- return (
-
-
-
- );
-}
-const SendbirdSDK = ({
- appId,
- userId,
- children,
- accessToken,
- customApiHost,
- customWebSocketHost,
- configureSession,
- theme = 'light',
- config = {},
- nickname = '',
- colorSet,
- stringSet,
- dateLocale,
- profileUrl = '',
- voiceRecord,
- userListQuery,
- imageCompression = {},
- allowProfileEdit = false,
- disableMarkAsDelivered = false,
- renderUserProfile,
- onUserProfileMessage: _onUserProfileMessage,
- onStartDirectMessage: _onStartDirectMessage,
- breakpoint = false,
- isUserIdUsedForNickname = true,
- sdkInitParams,
- customExtensionParams,
- isMultipleFilesMessageEnabled = false,
- eventHandlers,
- htmlTextDirection = 'ltr',
- forceLeftToRightMessageLayout = false,
-}: SendbirdProviderProps): React.ReactElement => {
- const onStartDirectMessage = _onStartDirectMessage ?? _onUserProfileMessage;
- const { logLevel = '', userMention = {}, isREMUnitEnabled = false, pubSub: customPubSub } = config;
- const { isMobile } = useMediaQueryContext();
- const [logger, setLogger] = useState(LoggerFactory(logLevel as LogLevel));
- const [pubSub] = useState(() => customPubSub ?? pubSubFactory());
- const [sdkStore, sdkDispatcher] = useReducer(sdkReducers, sdkInitialState);
- const [userStore, userDispatcher] = useReducer(userReducers, userInitialState);
- const [appInfoStore, appInfoDispatcher] = useReducer(appInfoReducers, appInfoInitialState);
-
- const { configs, configsWithAppAttr, initDashboardConfigs } = useUIKitConfig();
-
- const sdkInitialized = sdkStore.initialized;
- const sdk = sdkStore?.sdk;
- const { uploadSizeLimit, multipleFilesMessageFileCountLimit } = sdk?.appInfo ?? {};
-
- useTheme(colorSet);
-
- const { getCachedTemplate, updateMessageTemplatesInfo, initializeMessageTemplatesInfo } = useMessageTemplateUtils({
- sdk,
- logger,
- appInfoStore,
- appInfoDispatcher,
- });
-
- const utils: SendbirdProviderUtils = {
- updateMessageTemplatesInfo,
- getCachedTemplate,
- };
-
- const reconnect = useConnect(
- {
- appId,
- userId,
- accessToken,
- isUserIdUsedForNickname,
- isMobile,
- },
- {
- logger,
- nickname,
- profileUrl,
- configureSession,
- customApiHost,
- customWebSocketHost,
- sdkInitParams,
- customExtensionParams,
- sdk,
- sdkDispatcher,
- userDispatcher,
- appInfoDispatcher,
- initDashboardConfigs,
- eventHandlers,
- initializeMessageTemplatesInfo,
- },
- );
-
- useUnmount(() => {
- if (typeof sdk.disconnect === 'function') {
- disconnectSdk({
- logger,
- sdkDispatcher,
- userDispatcher,
- sdk,
- });
- }
- }, [sdk.disconnectWebSocket]);
-
- // to create a pubsub to communicate between parent and child
- useEffect(() => {
- setLogger(LoggerFactory(logLevel as LogLevel));
- }, [logLevel]);
-
- // should move to reducer
- const [currentTheme, setCurrentTheme] = useState(theme);
- useEffect(() => {
- setCurrentTheme(theme);
- }, [theme]);
-
- useEffect(() => {
- const body = document.querySelector('body');
- body?.classList.remove('sendbird-experimental__rem__units');
- if (isREMUnitEnabled) {
- body?.classList.add('sendbird-experimental__rem__units');
- }
- }, [isREMUnitEnabled]);
- // add-remove theme from body
- useEffect(() => {
- logger.info('Setup theme', `Theme: ${currentTheme}`);
- try {
- const body = document.querySelector('body');
- body?.classList.remove('sendbird-theme--light');
- body?.classList.remove('sendbird-theme--dark');
- body?.classList.add(`sendbird-theme--${currentTheme || 'light'}`);
- logger.info('Finish setup theme');
- // eslint-disable-next-line no-empty
- } catch (e) {
- logger.warning('Setup theme failed', `${e}`);
- }
- return () => {
- try {
- const body = document.querySelector('body');
- body?.classList.remove('sendbird-theme--light');
- body?.classList.remove('sendbird-theme--dark');
- // eslint-disable-next-line no-empty
- } catch { }
- };
- }, [currentTheme]);
-
- useHTMLTextDirection(htmlTextDirection);
-
- const isOnline = useOnlineStatus(sdkStore.sdk, logger);
-
- const markAsReadScheduler = useMarkAsReadScheduler({ isConnected: isOnline }, { logger });
- const markAsDeliveredScheduler = useMarkAsDeliveredScheduler({ isConnected: isOnline }, { logger });
-
- const localeStringSet = React.useMemo(() => {
- return { ...getStringSet('en'), ...stringSet };
- }, [stringSet]);
-
- /**
- * Feature Configuration - TODO
- * This will be moved into the UIKitConfigProvider, aftering Dashboard applies
- */
- const uikitMultipleFilesMessageLimit = useMemo(() => {
- return Math.min(DEFAULT_MULTIPLE_FILES_MESSAGE_LIMIT, multipleFilesMessageFileCountLimit ?? Number.MAX_SAFE_INTEGER);
- }, [multipleFilesMessageFileCountLimit]);
-
- // Emoji Manager
- const emojiManager = useMemo(() => {
- return new EmojiManager({
- sdk,
- logger,
- });
- }, [sdkStore.initialized]);
-
- return (
-
-
-
-
- {children}
-
-
-
- {/* Roots */}
-
-
-
-
- );
-};
-
-export default SendbirdProvider;
diff --git a/src/lib/Sendbird/MIGRATION_GUIDE.md b/src/lib/Sendbird/MIGRATION_GUIDE.md
new file mode 100644
index 000000000..8e85eb71e
--- /dev/null
+++ b/src/lib/Sendbird/MIGRATION_GUIDE.md
@@ -0,0 +1,27 @@
+# SendbirdProvider interface change
+
+## What has been changed?
+
+### Dispatchers are removed
+
+There were `sdkDispatcher`, `userDispatcher`, `appInfoDispatcher` and `reconnect` in the `SendbirdSdkContext`.
+so you could get them like below
+
+```tsx
+const { dispatchers } = useSendbirdSdkContext();
+const { sdkDispatcher, userDispatcher, appInfoDispatcher, reconnect } = dispatchers;
+```
+
+Now these context are removed, so you can't get the `dispatchers` from now on.
+
+### Actions are added!
+
+However, you don't have to worry! We replace them with `actions`.
+```tsx
+const { actions } = useSendbirdSdkContext();
+```
+
+This is a replacement of `dispatchers`. For example, `connect` replace the `reconnect` of `dispatchers`.
+```tsx
+actions.connect();
+```
diff --git a/src/lib/Sendbird/README.md b/src/lib/Sendbird/README.md
new file mode 100644
index 000000000..3968d4abf
--- /dev/null
+++ b/src/lib/Sendbird/README.md
@@ -0,0 +1,25 @@
+# SendbirdProvider
+
+## How to use SendbirdProvider?
+
+#### Import
+Import `SendbirdProvider` and `useSendbirdStateContext`.
+```tsx
+import { SendbirdProvider, useSendbirdStateContext } from '@sendbird/uikit-react';
+```
+
+#### Example
+```tsx
+const MyComponent = () => {
+ const context = useSendbirdStateContext();
+ // Use the context
+ return ({/* Fill components */}
);
+};
+const MyApp = () => {
+ return (
+
+
+
+ );
+};
+```
diff --git a/src/lib/Sendbird/__experimental__typography.scss b/src/lib/Sendbird/__experimental__typography.scss
new file mode 100644
index 000000000..c55ad2bca
--- /dev/null
+++ b/src/lib/Sendbird/__experimental__typography.scss
@@ -0,0 +1,110 @@
+// We are tyring to move font size into "rem" units for accesibility
+// todo: make this default in @sendbird/uikit@v4
+
+// assuming @fontsize = 16px
+// about rem https://www.joshwcomeau.com/css/surprising-truth-about-pixels-and-accessibility/#rems
+.sendbird-experimental__rem__units {
+ // typography
+ .sendbird-label--h-1 {
+ font-size: 1.25rem;
+ }
+
+ .sendbird-label--h-2 {
+ font-size: 1.125rem;
+ }
+
+ .sendbird-label--subtitle-1 {
+ font-size: 1rem;
+ }
+
+ .sendbird-label--subtitle-2 {
+ font-size: .875rem;
+ }
+
+ .sendbird-label--body-1 {
+ font-size: .875rem;
+ }
+
+ .sendbird-label--body-2 {
+ font-size: .75rem;
+ }
+
+ .sendbird-label--button-1 {
+ font-size: .875rem;
+ }
+
+ .sendbird-label--button-2 {
+ font-size: .875rem;
+ }
+
+ .sendbird-label--caption-1 {
+ font-size: .875rem;
+ }
+
+ .sendbird-label--caption-2 {
+ font-size: .75rem;
+ }
+
+ .sendbird-label--caption-3 {
+ font-size: .75rem;
+ }
+
+ // message search
+ .sendbird-message-search-pannel {
+ .sendbird-message-search-pannel__input__container__input-area {
+ font-size: .875rem;
+ }
+ }
+
+ // checkbox
+ .sendbird-checkbox {
+ font-size: 1.375rem;
+ }
+
+ .sendbird-mention-user-label {
+ font-size: .875rem;
+ &.purple {
+ font-size: 1.125rem;
+ }
+ }
+
+ // message input
+ .sendbird-message-input {
+ .sendbird-message-input--textarea,
+ .sendbird-message-input--placeholder {
+ font-size: .875rem;
+ }
+ }
+
+ // input
+ .sendbird-input {
+ .sendbird-input__input,
+ .sendbird-input__placeholder {
+ font-size: .875rem;
+ }
+ }
+
+ // tooltip
+ .sendbird-tooltip {
+ &__text {
+ font-size: .75rem;
+ }
+ }
+
+ // quote-message
+ .sendbird-quote-message {
+ .sendbird-quote-message__replied-to {
+ .sendbird-quote-message__replied-to__text {
+ font-size: .75rem;
+ }
+ }
+ .sendbird-quote-message__replied-message {
+ .sendbird-quote-message__replied-message__text-message {
+ font-size: .75rem;
+ }
+ }
+ .sendbird-quote-message__replied-message__file-message {
+ font-size: .75rem;
+ }
+ }
+}
diff --git a/src/lib/Sendbird/context/SendbirdContext.tsx b/src/lib/Sendbird/context/SendbirdContext.tsx
new file mode 100644
index 000000000..21d1bfa13
--- /dev/null
+++ b/src/lib/Sendbird/context/SendbirdContext.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { createStore } from '../../../utils/storeManager';
+import { initialState } from './initialState';
+import { SendbirdState } from '../types';
+import { useStore } from '../../../hooks/useStore';
+
+/**
+ * SendbirdContext
+ */
+export const SendbirdContext = React.createContext> | null>(null);
+
+/**
+ * Create store for Sendbird context
+ */
+export const createSendbirdContextStore = () => createStore(initialState);
+
+/**
+ * A specialized hook for Ssendbird state management
+ * @returns {ReturnType>}
+ */
+export const useSendbirdStore = () => {
+ return useStore(SendbirdContext, state => state, initialState);
+};
diff --git a/src/lib/Sendbird/context/SendbirdProvider.tsx b/src/lib/Sendbird/context/SendbirdProvider.tsx
new file mode 100644
index 000000000..b992665e6
--- /dev/null
+++ b/src/lib/Sendbird/context/SendbirdProvider.tsx
@@ -0,0 +1,403 @@
+/* External libraries */
+import React, { ReactElement, useEffect, useMemo, useRef, useState } from 'react';
+import { useUIKitConfig } from '@sendbird/uikit-tools';
+
+/* Types */
+import type { ImageCompressionOptions, SendbirdProviderProps, SendbirdStateConfig } from '../types';
+
+/* Providers */
+import VoiceMessageProvider from '../../VoiceMessageProvider';
+import { MediaQueryProvider, useMediaQueryContext } from '../../MediaQueryContext';
+import { LocalizationProvider } from '../../LocalizationContext';
+import { GlobalModalProvider, ModalRoot } from '../../../hooks/useModal';
+
+/* Managers */
+import { LoggerFactory, type LogLevel } from '../../Logger';
+import pubSubFactory from '../../pubSub';
+import { EmojiManager } from '../../emojiManager';
+import PUBSUB_TOPICS, { SBUGlobalPubSubTopicPayloadUnion } from '../../pubSub/topics';
+
+/* Hooks */
+import useTheme from '../../hooks/useTheme';
+import useMessageTemplateUtils from '../../hooks/useMessageTemplateUtils';
+import { useUnmount } from '../../../hooks/useUnmount';
+import useHTMLTextDirection from '../../../hooks/useHTMLTextDirection';
+import useOnlineStatus from '../../hooks/useOnlineStatus';
+import { useMarkAsReadScheduler } from '../../hooks/useMarkAsReadScheduler';
+import { useMarkAsDeliveredScheduler } from '../../hooks/useMarkAsDeliveredScheduler';
+
+/* Utils */
+import getStringSet from '../../../ui/Label/stringSet';
+import { getCaseResolvedReplyType } from '../../utils/resolvedReplyType';
+import { DEFAULT_MULTIPLE_FILES_MESSAGE_LIMIT, DEFAULT_UPLOAD_SIZE_LIMIT, VOICE_RECORDER_DEFAULT_MAX, VOICE_RECORDER_DEFAULT_MIN } from '../../../utils/consts';
+import { EmojiReactionListRoot, MenuRoot } from '../../../ui/ContextMenu';
+
+import useSendbird from './hooks/useSendbird';
+import { SendbirdContext, useSendbirdStore } from './SendbirdContext';
+import { createStore } from '../../../utils/storeManager';
+import { initialState } from './initialState';
+
+/**
+ * SendbirdContext - Manager
+ */
+const SendbirdContextManager = ({
+ appId,
+ userId,
+ accessToken,
+ customApiHost,
+ customWebSocketHost,
+ configureSession,
+ theme = 'light',
+ config = {},
+ nickname = '',
+ colorSet,
+ profileUrl = '',
+ voiceRecord,
+ userListQuery,
+ imageCompression = {},
+ allowProfileEdit = false,
+ disableMarkAsDelivered = false,
+ renderUserProfile,
+ onUserProfileMessage: _onUserProfileMessage,
+ onStartDirectMessage: _onStartDirectMessage,
+ isUserIdUsedForNickname = true,
+ sdkInitParams,
+ customExtensionParams,
+ isMultipleFilesMessageEnabled = false,
+ eventHandlers,
+ htmlTextDirection = 'ltr',
+ forceLeftToRightMessageLayout = false,
+}: SendbirdProviderProps): ReactElement => {
+ const onStartDirectMessage = _onStartDirectMessage ?? _onUserProfileMessage;
+ const { logLevel = '', userMention = {}, isREMUnitEnabled = false, pubSub: customPubSub } = config;
+ const { isMobile } = useMediaQueryContext();
+ const [logger, setLogger] = useState(LoggerFactory(logLevel as LogLevel));
+ const [pubSub] = useState(customPubSub ?? pubSubFactory());
+
+ const { state, updateState } = useSendbirdStore();
+ const { actions } = useSendbird();
+ const { sdkStore, appInfoStore } = state.stores;
+
+ const { configs, configsWithAppAttr, initDashboardConfigs } = useUIKitConfig();
+
+ const sdkInitialized = sdkStore.initialized;
+ const sdk = sdkStore?.sdk;
+ const { uploadSizeLimit, multipleFilesMessageFileCountLimit } = sdk?.appInfo ?? {};
+
+ useTheme(colorSet);
+
+ const { getCachedTemplate, updateMessageTemplatesInfo, initializeMessageTemplatesInfo } = useMessageTemplateUtils({
+ sdk,
+ logger,
+ appInfoStore,
+ actions,
+ });
+
+ // Reconnect when necessary
+ useEffect(() => {
+ actions.connect({
+ appId,
+ userId,
+ accessToken,
+ isUserIdUsedForNickname,
+ isMobile,
+ logger,
+ nickname,
+ profileUrl,
+ configureSession,
+ customApiHost,
+ customWebSocketHost,
+ sdkInitParams,
+ customExtensionParams,
+ initDashboardConfigs,
+ eventHandlers,
+ initializeMessageTemplatesInfo,
+ });
+ }, [appId, userId]);
+
+ // Disconnect on unmount
+ useUnmount(() => {
+ actions.disconnect({ logger });
+ });
+
+ // to create a pubsub to communicate between parent and child
+ useEffect(() => {
+ setLogger(LoggerFactory(logLevel as LogLevel));
+ }, [logLevel]);
+
+ // should move to reducer
+ const [currentTheme, setCurrentTheme] = useState(theme);
+ useEffect(() => {
+ setCurrentTheme(theme);
+ }, [theme]);
+
+ useEffect(() => {
+ const body = document.querySelector('body');
+ body?.classList.remove('sendbird-experimental__rem__units');
+ if (isREMUnitEnabled) {
+ body?.classList.add('sendbird-experimental__rem__units');
+ }
+ }, [isREMUnitEnabled]);
+ // add-remove theme from body
+ useEffect(() => {
+ logger.info('Setup theme', `Theme: ${currentTheme}`);
+ try {
+ const body = document.querySelector('body');
+ body?.classList.remove('sendbird-theme--light');
+ body?.classList.remove('sendbird-theme--dark');
+ body?.classList.add(`sendbird-theme--${currentTheme || 'light'}`);
+ logger.info('Finish setup theme');
+ // eslint-disable-next-line no-empty
+ } catch (e) {
+ logger.warning('Setup theme failed', `${e}`);
+ }
+ return () => {
+ try {
+ const body = document.querySelector('body');
+ body?.classList.remove('sendbird-theme--light');
+ body?.classList.remove('sendbird-theme--dark');
+ // eslint-disable-next-line no-empty
+ } catch { }
+ };
+ }, [currentTheme]);
+
+ useHTMLTextDirection(htmlTextDirection);
+
+ const isOnline = useOnlineStatus(sdkStore.sdk, logger);
+
+ const markAsReadScheduler = useMarkAsReadScheduler({ isConnected: isOnline }, { logger });
+ const markAsDeliveredScheduler = useMarkAsDeliveredScheduler({ isConnected: isOnline }, { logger });
+
+ /**
+ * Feature Configuration - TODO
+ * This will be moved into the UIKitConfigProvider, aftering Dashboard applies
+ */
+ const uikitMultipleFilesMessageLimit = useMemo(() => {
+ return Math.min(DEFAULT_MULTIPLE_FILES_MESSAGE_LIMIT, multipleFilesMessageFileCountLimit ?? Number.MAX_SAFE_INTEGER);
+ }, [multipleFilesMessageFileCountLimit]);
+
+ // Emoji Manager
+ const emojiManager = useMemo(() => {
+ return new EmojiManager({
+ sdk,
+ logger,
+ });
+ }, [sdkStore.initialized]);
+
+ const uikitConfigs = useMemo(() => ({
+ common: {
+ enableUsingDefaultUserProfile: configs.common.enableUsingDefaultUserProfile,
+ },
+ groupChannel: {
+ enableOgtag: sdkInitialized && configsWithAppAttr(sdk).groupChannel.channel.enableOgtag,
+ enableTypingIndicator: configs.groupChannel.channel.enableTypingIndicator,
+ enableReactions: sdkInitialized && configsWithAppAttr(sdk).groupChannel.channel.enableReactions,
+ enableMention: configs.groupChannel.channel.enableMention,
+ replyType: configs.groupChannel.channel.replyType,
+ threadReplySelectType: configs.groupChannel.channel.threadReplySelectType,
+ enableVoiceMessage: configs.groupChannel.channel.enableVoiceMessage,
+ enableDocument: configs.groupChannel.channel.input.enableDocument,
+ typingIndicatorTypes: configs.groupChannel.channel.typingIndicatorTypes,
+ enableFeedback: configs.groupChannel.channel.enableFeedback,
+ enableSuggestedReplies: configs.groupChannel.channel.enableSuggestedReplies,
+ showSuggestedRepliesFor: configs.groupChannel.channel.showSuggestedRepliesFor,
+ suggestedRepliesDirection: configs.groupChannel.channel.suggestedRepliesDirection,
+ enableMarkdownForUserMessage: configs.groupChannel.channel.enableMarkdownForUserMessage,
+ enableFormTypeMessage: configs.groupChannel.channel.enableFormTypeMessage,
+ enableReactionsSupergroup: sdkInitialized && configsWithAppAttr(sdk).groupChannel.channel.enableReactionsSupergroup as never,
+ },
+ groupChannelList: {
+ enableTypingIndicator: configs.groupChannel.channelList.enableTypingIndicator,
+ enableMessageReceiptStatus: configs.groupChannel.channelList.enableMessageReceiptStatus,
+ },
+ groupChannelSettings: {
+ enableMessageSearch: sdkInitialized && configsWithAppAttr(sdk).groupChannel.setting.enableMessageSearch,
+ },
+ openChannel: {
+ enableOgtag: sdkInitialized && configsWithAppAttr(sdk).openChannel.channel.enableOgtag,
+ enableDocument: configs.openChannel.channel.input.enableDocument,
+ },
+ }), [
+ sdkInitialized,
+ configs.common,
+ configs.groupChannel.channel,
+ configs.groupChannel.channelList,
+ configs.groupChannel.setting,
+ configs.openChannel.channel,
+ ]);
+ const storeState = useMemo(() => ({
+ stores: {
+ sdkStore: state.stores.sdkStore,
+ userStore: state.stores.userStore,
+ appInfoStore: state.stores.appInfoStore,
+ },
+ }), [
+ state.stores.sdkStore,
+ state.stores.userStore,
+ state.stores.appInfoStore,
+ ]);
+ const uikitUploadSizeLimit = useMemo(() => (uploadSizeLimit ?? DEFAULT_UPLOAD_SIZE_LIMIT), [uploadSizeLimit, DEFAULT_UPLOAD_SIZE_LIMIT]);
+ const configImageCompression = useMemo(() => ({
+ compressionRate: 0.7,
+ outputFormat: 'preserve',
+ ...imageCompression,
+ }), [imageCompression]);
+ const configVoiceRecord = useMemo(() => ({
+ maxRecordingTime: voiceRecord?.maxRecordingTime ?? VOICE_RECORDER_DEFAULT_MAX,
+ minRecordingTime: voiceRecord?.minRecordingTime ?? VOICE_RECORDER_DEFAULT_MIN,
+ }), [
+ voiceRecord?.maxRecordingTime,
+ voiceRecord?.minRecordingTime,
+ ]);
+ const configUserMention = useMemo(() => ({
+ maxMentionCount: userMention?.maxMentionCount || 10,
+ maxSuggestionCount: userMention?.maxSuggestionCount || 15,
+ }), [
+ userMention?.maxMentionCount,
+ userMention?.maxSuggestionCount,
+ ]);
+ const deprecatedConfigs = useMemo(() => ({
+ disableUserProfile: !configs.common.enableUsingDefaultUserProfile,
+ isReactionEnabled: sdkInitialized && configsWithAppAttr(sdk).groupChannel.channel.enableReactions,
+ isMentionEnabled: configs.groupChannel.channel.enableMention,
+ isVoiceMessageEnabled: configs.groupChannel.channel.enableVoiceMessage,
+ replyType: getCaseResolvedReplyType(configs.groupChannel.channel.replyType).upperCase,
+ isTypingIndicatorEnabledOnChannelList: configs.groupChannel.channelList.enableTypingIndicator,
+ isMessageReceiptStatusEnabledOnChannelList: configs.groupChannel.channelList.enableMessageReceiptStatus,
+ showSearchIcon: sdkInitialized && configsWithAppAttr(sdk).groupChannel.setting.enableMessageSearch,
+ }), [
+ sdkInitialized,
+ configsWithAppAttr,
+ configs.common.enableUsingDefaultUserProfile,
+ configs.groupChannel.channel.enableReactions,
+ configs.groupChannel.channel.enableMention,
+ configs.groupChannel.channel.enableVoiceMessage,
+ configs.groupChannel.channel.replyType,
+ configs.groupChannel.channelList.enableTypingIndicator,
+ configs.groupChannel.channelList.enableMessageReceiptStatus,
+ configs.groupChannel.setting.enableMessageSearch,
+ ]);
+ const configState = useMemo>(() => ({
+ config: {
+ disableMarkAsDelivered,
+ renderUserProfile,
+ onStartDirectMessage,
+ onUserProfileMessage: onStartDirectMessage, // legacy of onStartDirectMessage
+ allowProfileEdit,
+ isOnline,
+ userId,
+ appId,
+ accessToken,
+ theme: currentTheme,
+ setCurrentTheme,
+ setCurrenttheme: setCurrentTheme, // deprecated: typo
+ isMultipleFilesMessageEnabled,
+ uikitMultipleFilesMessageLimit,
+ logger,
+ pubSub,
+ userListQuery,
+ htmlTextDirection,
+ forceLeftToRightMessageLayout,
+ markAsReadScheduler,
+ markAsDeliveredScheduler,
+ uikitUploadSizeLimit,
+ imageCompression: configImageCompression,
+ voiceRecord: configVoiceRecord,
+ userMention: configUserMention,
+ // Remote configs set from dashboard by UIKit feature configuration
+ ...uikitConfigs,
+ ...deprecatedConfigs,
+ },
+ }), [
+ disableMarkAsDelivered,
+ renderUserProfile,
+ onStartDirectMessage,
+ allowProfileEdit,
+ isOnline,
+ userId,
+ appId,
+ accessToken,
+ currentTheme,
+ setCurrentTheme,
+ isMultipleFilesMessageEnabled,
+ uikitMultipleFilesMessageLimit,
+ logger,
+ pubSub,
+ userListQuery,
+ htmlTextDirection,
+ forceLeftToRightMessageLayout,
+ markAsReadScheduler,
+ markAsDeliveredScheduler,
+ uikitUploadSizeLimit,
+ configImageCompression,
+ configVoiceRecord,
+ configUserMention,
+ uikitConfigs,
+ deprecatedConfigs,
+ ]);
+ const utilsState = useMemo(() => ({
+ utils: {
+ updateMessageTemplatesInfo,
+ getCachedTemplate,
+ },
+ }), [
+ updateMessageTemplatesInfo,
+ getCachedTemplate,
+ ]);
+
+ useEffect(() => {
+ updateState({
+ ...storeState,
+ ...utilsState,
+ ...configState,
+ eventHandlers,
+ emojiManager,
+ });
+ }, [
+ storeState,
+ configState,
+ eventHandlers,
+ emojiManager,
+ utilsState,
+ ]);
+
+ return null;
+};
+
+const InternalSendbirdProvider = ({ children, stringSet, breakpoint, dateLocale }) => {
+ const storeRef = useRef(createStore(initialState));
+ const localeStringSet = useMemo(() => {
+ return { ...getStringSet('en'), ...stringSet };
+ }, [stringSet]);
+
+ return (
+
+
+
+
+
+ {children}
+
+
+
+
+ {/* Roots */}
+
+
+
+
+ );
+};
+
+export const SendbirdContextProvider = (props: SendbirdProviderProps) => {
+ const { children } = props;
+
+ return (
+
+
+ {children}
+
+ );
+};
+
+export default SendbirdContextProvider;
diff --git a/src/lib/Sendbird/context/hooks/useSendbird.tsx b/src/lib/Sendbird/context/hooks/useSendbird.tsx
new file mode 100644
index 000000000..908242fe3
--- /dev/null
+++ b/src/lib/Sendbird/context/hooks/useSendbird.tsx
@@ -0,0 +1,232 @@
+import { useContext, useMemo, useSyncExternalStore } from 'react';
+import { SendbirdError, User } from '@sendbird/chat';
+
+import { SendbirdContext } from '../SendbirdContext';
+import { LoggerInterface } from '../../../Logger';
+import { MessageTemplatesInfo, SendbirdState, WaitingTemplateKeyData } from '../../types';
+import { initSDK, setupSDK, updateAppInfoStore, updateSdkStore, updateUserStore } from '../../utils';
+
+const NO_CONTEXT_ERROR = 'No sendbird state value available. Make sure you are rendering `` at the top of your app.';
+export const useSendbird = () => {
+ const store = useContext(SendbirdContext);
+ if (!store) throw new Error(NO_CONTEXT_ERROR);
+
+ const state = useSyncExternalStore(store.subscribe, store.getState);
+ const actions = useMemo(() => ({
+ /* Example: How to set the state basically */
+ // exampleAction: () => {
+ // store.setState((state): SendbirdState => ({
+ // ...state,
+ // example: true,
+ // })),
+ // },
+
+ /* AppInfo */
+ initMessageTemplateInfo: ({ payload }: { payload: MessageTemplatesInfo }) => {
+ store.setState((state): SendbirdState => (
+ updateAppInfoStore(state, {
+ messageTemplatesInfo: payload,
+ waitingTemplateKeysMap: {},
+ })
+ ));
+ },
+ upsertMessageTemplates: ({ payload }) => {
+ const appInfoStore = state.stores.appInfoStore;
+ const templatesInfo = appInfoStore.messageTemplatesInfo;
+ if (!templatesInfo) return state; // Not initialized. Ignore.
+
+ const waitingTemplateKeysMap = { ...appInfoStore.waitingTemplateKeysMap };
+ payload.forEach((templatesMapData) => {
+ const { key, template } = templatesMapData;
+ templatesInfo.templatesMap[key] = template;
+ delete waitingTemplateKeysMap[key];
+ });
+ store.setState((state): SendbirdState => (
+ updateAppInfoStore(state, {
+ waitingTemplateKeysMap,
+ messageTemplatesInfo: templatesInfo,
+ })
+ ));
+ },
+ upsertWaitingTemplateKeys: ({ payload }) => {
+ const appInfoStore = state.stores.appInfoStore;
+ const { keys, requestedAt } = payload;
+ const waitingTemplateKeysMap = { ...appInfoStore.waitingTemplateKeysMap };
+ keys.forEach((key) => {
+ waitingTemplateKeysMap[key] = {
+ erroredMessageIds: waitingTemplateKeysMap[key]?.erroredMessageIds ?? [],
+ requestedAt,
+ };
+ });
+ store.setState((state): SendbirdState => (
+ updateAppInfoStore(state, {
+ waitingTemplateKeysMap,
+ })
+ ));
+ },
+ markErrorWaitingTemplateKeys: ({ payload }) => {
+ const appInfoStore = state.stores.appInfoStore;
+ const { keys, messageId } = payload;
+ const waitingTemplateKeysMap = { ...appInfoStore.waitingTemplateKeysMap };
+ keys.forEach((key) => {
+ const waitingTemplateKeyData: WaitingTemplateKeyData | undefined = waitingTemplateKeysMap[key];
+ if (waitingTemplateKeyData && waitingTemplateKeyData.erroredMessageIds.indexOf(messageId) === -1) {
+ waitingTemplateKeyData.erroredMessageIds.push(messageId);
+ }
+ });
+ store.setState((state): SendbirdState => (
+ updateAppInfoStore(state, {
+ waitingTemplateKeysMap,
+ })
+ ));
+ },
+
+ /* SDK */
+ setSdkLoading: (payload) => {
+ store.setState((state): SendbirdState => (
+ updateSdkStore(state, {
+ initialized: false,
+ loading: payload,
+ })
+ ));
+ },
+ sdkError: () => {
+ store.setState((state): SendbirdState => (
+ updateSdkStore(state, {
+ initialized: false,
+ loading: false,
+ error: true,
+ })
+ ));
+ },
+ initSdk: (payload) => {
+ store.setState((state): SendbirdState => (
+ updateSdkStore(state, {
+ sdk: payload,
+ initialized: true,
+ loading: false,
+ error: false,
+ })
+ ));
+ },
+ resetSdk: () => {
+ store.setState((state): SendbirdState => (
+ updateSdkStore(state, {
+ sdk: null,
+ initialized: false,
+ loading: false,
+ error: false,
+ })
+ ));
+ },
+
+ /* User */
+ initUser: (payload) => {
+ store.setState((state): SendbirdState => (
+ updateUserStore(state, {
+ initialized: true,
+ loading: false,
+ user: payload,
+ })
+ ));
+ },
+ resetUser: () => {
+ store.setState((state): SendbirdState => (
+ updateUserStore(state, {
+ initialized: false,
+ loading: false,
+ user: null,
+ })
+ ));
+ },
+ updateUserInfo: (payload: User) => {
+ store.setState((state): SendbirdState => (
+ updateUserStore(state, {
+ user: payload,
+ })
+ ));
+ },
+
+ /* Connection */
+ connect: async (params) => {
+ const {
+ logger,
+ userId,
+ appId,
+ accessToken,
+ nickname,
+ profileUrl,
+ isMobile,
+ sdkInitParams,
+ customApiHost,
+ customWebSocketHost,
+ customExtensionParams,
+ eventHandlers,
+ initializeMessageTemplatesInfo,
+ configureSession,
+ initDashboardConfigs,
+ } = params;
+
+ // clean up previous ws connection
+ await actions.disconnect({ logger });
+
+ const sdk = initSDK({
+ appId,
+ customApiHost,
+ customWebSocketHost,
+ sdkInitParams,
+ });
+
+ setupSDK(sdk, {
+ logger,
+ isMobile,
+ customExtensionParams,
+ sessionHandler: configureSession ? configureSession(sdk) : undefined,
+ });
+
+ actions.setSdkLoading(true);
+
+ try {
+ const user = await sdk.connect(userId, accessToken);
+ actions.initUser(user);
+
+ if (nickname || profileUrl) {
+ await sdk.updateCurrentUserInfo({
+ nickname: nickname || user.nickname || '',
+ profileUrl: profileUrl || user.profileUrl,
+ });
+ }
+
+ await initializeMessageTemplatesInfo?.(sdk);
+ await initDashboardConfigs?.(sdk);
+
+ actions.initSdk(sdk);
+
+ eventHandlers?.connection?.onConnected?.(user);
+ } catch (error) {
+ const sendbirdError = error as SendbirdError;
+ actions.resetSdk();
+ actions.resetUser();
+ logger.error?.('SendbirdProvider | useSendbird/connect failed', sendbirdError);
+ eventHandlers?.connection?.onFailed?.(sendbirdError);
+ }
+ },
+ disconnect: async ({ logger }: { logger: LoggerInterface }) => {
+ actions.setSdkLoading(true);
+
+ const sdk = state.stores.sdkStore.sdk;
+
+ if (sdk?.disconnectWebSocket) {
+ await sdk.disconnectWebSocket();
+ }
+
+ actions.resetSdk();
+ actions.resetUser();
+ logger.info?.('SendbirdProvider | useSendbird/disconnect completed');
+ },
+ }), [store]);
+
+ return { state, actions };
+};
+
+export default useSendbird;
diff --git a/src/lib/Sendbird/context/hooks/useSendbirdStateContext.tsx b/src/lib/Sendbird/context/hooks/useSendbirdStateContext.tsx
new file mode 100644
index 000000000..145a10472
--- /dev/null
+++ b/src/lib/Sendbird/context/hooks/useSendbirdStateContext.tsx
@@ -0,0 +1,12 @@
+import { SendbirdState } from '../../types';
+import useSendbird from './useSendbird';
+
+// NOTE: Do not use this hook internally.
+// This hook is exported to support backward compatibility.
+// Keep this function for backward compatibility.
+export function useSendbirdStateContext(): SendbirdState {
+ const { state, actions } = useSendbird();
+ return { ...state, ...actions };
+}
+
+export default useSendbirdStateContext;
diff --git a/src/lib/Sendbird/context/initialState.ts b/src/lib/Sendbird/context/initialState.ts
new file mode 100644
index 000000000..74812b544
--- /dev/null
+++ b/src/lib/Sendbird/context/initialState.ts
@@ -0,0 +1,133 @@
+import type { SendbirdState, SendbirdStateConfig, ReplyType, SendbirdStateStore, SdkStore } from '../types';
+import {
+ DEFAULT_MULTIPLE_FILES_MESSAGE_LIMIT,
+ DEFAULT_UPLOAD_SIZE_LIMIT,
+} from '../../../utils/consts';
+import { User } from '@sendbird/chat';
+
+/**
+ * Config
+ */
+const deprecatedConfig = {
+ onUserProfileMessage: undefined,
+ disableUserProfile: false,
+ isReactionEnabled: true,
+ isMentionEnabled: false,
+ isVoiceMessageEnabled: true,
+ replyType: 'NONE' as ReplyType,
+ showSearchIcon: true,
+ isTypingIndicatorEnabledOnChannelList: false,
+ isMessageReceiptStatusEnabledOnChannelList: false,
+ setCurrenttheme: () => {},
+};
+const config: SendbirdStateConfig = {
+ ...deprecatedConfig,
+ // Connection
+ appId: '',
+ userId: '',
+ accessToken: undefined,
+ theme: 'light',
+ isOnline: false,
+ // High level options
+ allowProfileEdit: true,
+ forceLeftToRightMessageLayout: false,
+ disableMarkAsDelivered: false,
+ isMultipleFilesMessageEnabled: false,
+ htmlTextDirection: 'ltr',
+ uikitUploadSizeLimit: DEFAULT_UPLOAD_SIZE_LIMIT,
+ uikitMultipleFilesMessageLimit: DEFAULT_MULTIPLE_FILES_MESSAGE_LIMIT,
+ imageCompression: undefined,
+ voiceRecord: undefined,
+ userMention: undefined,
+ // Functions
+ renderUserProfile: undefined,
+ onStartDirectMessage: undefined,
+ setCurrentTheme: undefined,
+ userListQuery: undefined,
+ // Utils
+ pubSub: undefined,
+ logger: undefined,
+ markAsReadScheduler: undefined,
+ markAsDeliveredScheduler: undefined,
+ // UIKit Configs
+ common: {
+ enableUsingDefaultUserProfile: false,
+ },
+ groupChannel: {
+ enableOgtag: true,
+ enableTypingIndicator: true,
+ enableReactions: true,
+ enableMention: false,
+ replyType: 'none',
+ threadReplySelectType: 'thread',
+ enableVoiceMessage: true,
+ typingIndicatorTypes: undefined,
+ enableDocument: false,
+ enableFeedback: false,
+ enableSuggestedReplies: false,
+ showSuggestedRepliesFor: 'all_messages',
+ suggestedRepliesDirection: 'vertical',
+ enableMarkdownForUserMessage: false,
+ enableFormTypeMessage: false,
+ enableReactionsSupergroup: undefined as never, // @deprecated
+ },
+ groupChannelList: {
+ enableTypingIndicator: false,
+ enableMessageReceiptStatus: false,
+ },
+ groupChannelSettings: {
+ enableMessageSearch: false,
+ },
+ openChannel: {
+ enableOgtag: true,
+ enableDocument: false,
+ },
+};
+
+/**
+ * Stores
+ */
+const stores: SendbirdStateStore = {
+ sdkStore: {
+ sdk: {} as SdkStore['sdk'],
+ initialized: false,
+ loading: false,
+ error: undefined,
+ },
+ userStore: {
+ user: {} as User,
+ initialized: false,
+ loading: false,
+ },
+ appInfoStore: {
+ messageTemplatesInfo: undefined,
+ waitingTemplateKeysMap: {},
+ },
+};
+
+export const initialState: SendbirdState = {
+ config,
+ stores,
+ emojiManager: undefined,
+ eventHandlers: {
+ reaction: {
+ onPressUserProfile: () => {},
+ },
+ connection: {
+ onConnected: () => {},
+ onFailed: () => {},
+ },
+ modal: {
+ onMounted: () => {},
+ },
+ message: {
+ onSendMessageFailed: () => {},
+ onUpdateMessageFailed: () => {},
+ onFileUploadFailed: () => {},
+ },
+ },
+ utils: {
+ updateMessageTemplatesInfo: () => new Promise(() => {}),
+ getCachedTemplate: () => null,
+ },
+};
diff --git a/src/lib/Sendbird/index.scss b/src/lib/Sendbird/index.scss
new file mode 100644
index 000000000..99ebdc01f
--- /dev/null
+++ b/src/lib/Sendbird/index.scss
@@ -0,0 +1,6 @@
+// Too keep all the important CSS to boot and makes sure things arent repeated
+@import url('https://fonts.googleapis.com/css?family=Open+Sans:400,600,700&display=swap');
+@import '../../styles/light-theme';
+@import '../../styles/dark-theme';
+@import '../../styles/misc-colors';
+@import '../../styles/postcss-rtl';
diff --git a/src/lib/Sendbird/index.tsx b/src/lib/Sendbird/index.tsx
new file mode 100644
index 000000000..ef8d1fe57
--- /dev/null
+++ b/src/lib/Sendbird/index.tsx
@@ -0,0 +1,82 @@
+import React from 'react';
+import './index.scss';
+import './__experimental__typography.scss';
+
+import { UIKitConfigProvider } from '@sendbird/uikit-tools';
+
+import type { SendbirdProviderProps, UIKitOptions } from './types';
+import { uikitConfigMapper } from '../utils/uikitConfigMapper';
+import { uikitConfigStorage } from '../utils/uikitConfigStorage';
+import { SendbirdContextProvider } from './context/SendbirdProvider';
+import useSendbird from './context/hooks/useSendbird';
+
+export type { SendbirdProviderProps } from './types';
+
+// For Exportation
+export const SendbirdProvider = (props: SendbirdProviderProps) => {
+ const localConfigs: UIKitOptions = uikitConfigMapper({
+ legacyConfig: {
+ replyType: props.replyType,
+ isMentionEnabled: props.isMentionEnabled,
+ isReactionEnabled: props.isReactionEnabled,
+ disableUserProfile: props.disableUserProfile,
+ isVoiceMessageEnabled: props.isVoiceMessageEnabled,
+ isTypingIndicatorEnabledOnChannelList: props.isTypingIndicatorEnabledOnChannelList,
+ isMessageReceiptStatusEnabledOnChannelList: props.isMessageReceiptStatusEnabledOnChannelList,
+ showSearchIcon: props.showSearchIcon,
+ },
+ uikitOptions: props.uikitOptions,
+ });
+
+ return (
+
+
+
+ );
+};
+
+type ContextAwareComponentType = {
+ (props: any): JSX.Element;
+ displayName: string;
+};
+type PropsType = Record;
+const withSendbirdContext = (OriginalComponent: any, mapStoreToProps: (props: any) => PropsType): ContextAwareComponentType => {
+ const ContextAwareComponent = (props) => {
+ const { state, actions } = useSendbird();
+ const context = { ...state, ...actions };
+ if (mapStoreToProps && typeof mapStoreToProps !== 'function') {
+ // eslint-disable-next-line no-console
+ console.warn('Second parameter to withSendbirdContext must be a pure function');
+ }
+ const mergedProps = (mapStoreToProps && typeof mapStoreToProps === 'function')
+ ? { ...mapStoreToProps(context), ...props }
+ : { ...context, ...props };
+ return <>
+
+ >;
+ };
+
+ const componentName = OriginalComponent.displayName || OriginalComponent.name || 'Component';
+ ContextAwareComponent.displayName = `SendbirdAware${componentName}`;
+
+ return ContextAwareComponent;
+};
+/**
+ * @deprecated This function is deprecated. Use `useSendbirdStateContext` instead.
+ * */
+export const withSendBird = withSendbirdContext;
+
+export default SendbirdProvider;
diff --git a/src/lib/Sendbird/types.ts b/src/lib/Sendbird/types.ts
new file mode 100644
index 000000000..5e1bf9854
--- /dev/null
+++ b/src/lib/Sendbird/types.ts
@@ -0,0 +1,439 @@
+// src/lib/Sendbird/types.ts
+
+import React, { MutableRefObject } from 'react';
+import type SendbirdChat from '@sendbird/chat';
+import type {
+ User,
+ SendbirdChatParams,
+ SendbirdError,
+ SessionHandler,
+} from '@sendbird/chat';
+import type {
+ GroupChannel,
+ GroupChannelCreateParams,
+ GroupChannelModule,
+ Member,
+ SendbirdGroupChat,
+} from '@sendbird/chat/groupChannel';
+import type {
+ OpenChannel,
+ OpenChannelCreateParams,
+ OpenChannelModule,
+ SendbirdOpenChat,
+} from '@sendbird/chat/openChannel';
+import type {
+ FileMessageCreateParams,
+ UserMessage,
+ UserMessageCreateParams,
+ UserMessageUpdateParams,
+} from '@sendbird/chat/message';
+import { Module, ModuleNamespaces } from '@sendbird/chat/lib/__definition';
+import { SBUConfig } from '@sendbird/uikit-tools';
+
+import { PartialDeep } from '../../utils/typeHelpers/partialDeep';
+import { CoreMessageType } from '../../utils';
+import { LoggerInterface } from '../Logger';
+import { MarkAsReadSchedulerType } from '../hooks/useMarkAsReadScheduler';
+import { MarkAsDeliveredSchedulerType } from '../hooks/useMarkAsDeliveredScheduler';
+import { SBUGlobalPubSub } from '../pubSub/topics';
+import { EmojiManager } from '../emojiManager';
+import { StringSet } from '../../ui/Label/stringSet';
+
+/* -------------------------------------------------------------------------- */
+/* Legacy */
+/* -------------------------------------------------------------------------- */
+
+export type ReplyType = 'NONE' | 'QUOTE_REPLY' | 'THREAD';
+export type ConfigureSessionTypes = (sdk: SendbirdChat | SendbirdGroupChat | SendbirdOpenChat) => SessionHandler;
+// Sendbird state dispatcher
+export type CustomUseReducerDispatcher = React.Dispatch<{
+ type: string;
+ payload: any;
+}>;
+
+/* -------------------------------------------------------------------------- */
+/* Common Types */
+/* -------------------------------------------------------------------------- */
+
+// Image compression settings
+export type ImageCompressionOutputFormatType = 'preserve' | 'png' | 'jpeg';
+
+export interface ImageCompressionOptions {
+ compressionRate?: number;
+ resizingWidth?: number | string;
+ resizingHeight?: number | string;
+ outputFormat?: ImageCompressionOutputFormatType;
+}
+
+// Logger type
+export type Logger = LoggerInterface;
+
+// Roles for a user in a channel
+export const Role = {
+ OPERATOR: 'operator',
+ NONE: 'none',
+} as const;
+
+export type RoleType = typeof Role[keyof typeof Role];
+
+export type HTMLTextDirection = 'ltr' | 'rtl';
+
+export interface RenderUserProfileProps {
+ user: User | Member;
+ currentUserId: string;
+ close(): void;
+ avatarRef: MutableRefObject;
+}
+
+export interface UserListQuery {
+ hasNext?: boolean;
+ next(): Promise>;
+ get isLoading(): boolean;
+}
+
+/* -------------------------------------------------------------------------- */
+/* Stores */
+/* -------------------------------------------------------------------------- */
+
+// AppInfo
+export interface MessageTemplatesInfo {
+ token: string; // This server-side token gets updated on every CRUD operation on message template table.
+ templatesMap: Record;
+}
+
+export interface WaitingTemplateKeyData {
+ requestedAt: number;
+ erroredMessageIds: number[];
+}
+
+export type ProcessedMessageTemplate = {
+ version: number;
+ uiTemplate: string; // This is stringified ui_template.body.items
+ colorVariables?: Record;
+};
+
+export interface AppInfoStateType {
+ messageTemplatesInfo?: MessageTemplatesInfo;
+ /**
+ * This represents template keys that are currently waiting for its fetch response.
+ * Whenever initialized, request succeeds or fails, it needs to be updated.
+ */
+ waitingTemplateKeysMap: Record;
+}
+
+/* -------------------------------------------------------------------------- */
+/* Event Handlers Types */
+/* -------------------------------------------------------------------------- */
+
+export interface SBUEventHandlers {
+ reaction?: {
+ onPressUserProfile?(member: User): void;
+ };
+ connection?: {
+ onConnected?(user: User): void;
+ onFailed?(error: SendbirdError): void;
+ };
+ modal?: {
+ onMounted?(params: { id: string; close(): void }): void | (() => void);
+ };
+ message?: {
+ onSendMessageFailed?: (message: CoreMessageType, error: unknown) => void;
+ onUpdateMessageFailed?: (message: CoreMessageType, error: unknown) => void;
+ onFileUploadFailed?: (error: unknown) => void;
+ };
+}
+
+/* -------------------------------------------------------------------------- */
+/* Sendbird State Types */
+/* -------------------------------------------------------------------------- */
+
+interface VoiceRecordOptions {
+ maxRecordingTime?: number;
+ minRecordingTime?: number;
+}
+
+export interface SendbirdConfig {
+ logLevel?: string | Array;
+ pubSub?: SBUGlobalPubSub;
+ userMention?: {
+ maxMentionCount?: number;
+ maxSuggestionCount?: number;
+ };
+ isREMUnitEnabled?: boolean;
+}
+
+export interface CommonUIKitConfigProps {
+ /** @deprecated Please use `uikitOptions.common.enableUsingDefaultUserProfile` instead * */
+ disableUserProfile?: boolean;
+ /** @deprecated Please use `uikitOptions.groupChannel.replyType` instead * */
+ replyType?: 'NONE' | 'QUOTE_REPLY' | 'THREAD';
+ /** @deprecated Please use `uikitOptions.groupChannel.enableReactions` instead * */
+ isReactionEnabled?: boolean;
+ /** @deprecated Please use `uikitOptions.groupChannel.enableMention` instead * */
+ isMentionEnabled?: boolean;
+ /** @deprecated Please use `uikitOptions.groupChannel.enableVoiceMessage` instead * */
+ isVoiceMessageEnabled?: boolean;
+ /** @deprecated Please use `uikitOptions.groupChannelList.enableTypingIndicator` instead * */
+ isTypingIndicatorEnabledOnChannelList?: boolean;
+ /** @deprecated Please use `uikitOptions.groupChannelList.enableMessageReceiptStatus` instead * */
+ isMessageReceiptStatusEnabledOnChannelList?: boolean;
+ /** @deprecated Please use `uikitOptions.groupChannelSettings.enableMessageSearch` instead * */
+ showSearchIcon?: boolean;
+}
+export type SendbirdChatInitParams = Omit, 'appId'>;
+export type CustomExtensionParams = Record;
+
+export type UIKitOptions = PartialDeep<{
+ common: SBUConfig['common'];
+ groupChannel: SBUConfig['groupChannel']['channel'];
+ groupChannelList: SBUConfig['groupChannel']['channelList'];
+ groupChannelSettings: SBUConfig['groupChannel']['setting'];
+ openChannel: SBUConfig['openChannel']['channel'];
+}>;
+
+export interface SendbirdProviderProps extends CommonUIKitConfigProps, React.PropsWithChildren {
+ appId: string;
+ userId: string;
+ accessToken?: string;
+ customApiHost?: string;
+ customWebSocketHost?: string;
+ configureSession?: ConfigureSessionTypes;
+ theme?: 'light' | 'dark';
+ config?: SendbirdConfig;
+ nickname?: string;
+ colorSet?: Record;
+ stringSet?: Partial;
+ dateLocale?: Locale;
+ profileUrl?: string;
+ voiceRecord?: VoiceRecordOptions;
+ userListQuery?: () => UserListQuery;
+ imageCompression?: ImageCompressionOptions;
+ allowProfileEdit?: boolean;
+ disableMarkAsDelivered?: boolean;
+ breakpoint?: string | boolean;
+ htmlTextDirection?: HTMLTextDirection;
+ forceLeftToRightMessageLayout?: boolean;
+ uikitOptions?: UIKitOptions;
+ isUserIdUsedForNickname?: boolean;
+ sdkInitParams?: SendbirdChatInitParams;
+ customExtensionParams?: CustomExtensionParams;
+ isMultipleFilesMessageEnabled?: boolean;
+ // UserProfile
+ renderUserProfile?: (props: RenderUserProfileProps) => React.ReactElement;
+ onStartDirectMessage?: (channel: GroupChannel) => void;
+ /**
+ * @deprecated Please use `onStartDirectMessage` instead. It's renamed.
+ */
+ onUserProfileMessage?: (channel: GroupChannel) => void;
+
+ // Customer provided callbacks
+ eventHandlers?: SBUEventHandlers;
+}
+
+export interface SendbirdStateConfig {
+ renderUserProfile?: (props: RenderUserProfileProps) => React.ReactElement;
+ onStartDirectMessage?: (props: GroupChannel) => void;
+ allowProfileEdit: boolean;
+ isOnline: boolean;
+ userId: string;
+ appId: string;
+ accessToken?: string;
+ theme: string;
+ htmlTextDirection: HTMLTextDirection;
+ forceLeftToRightMessageLayout: boolean;
+ pubSub: SBUGlobalPubSub;
+ logger: Logger;
+ setCurrentTheme: (theme: 'light' | 'dark') => void;
+ userListQuery?: () => UserListQuery;
+ uikitUploadSizeLimit: number;
+ uikitMultipleFilesMessageLimit: number;
+ voiceRecord: {
+ maxRecordingTime: number;
+ minRecordingTime: number;
+ };
+ userMention: {
+ maxMentionCount: number,
+ maxSuggestionCount: number,
+ };
+ imageCompression: ImageCompressionOptions;
+ markAsReadScheduler: MarkAsReadSchedulerType;
+ markAsDeliveredScheduler: MarkAsDeliveredSchedulerType;
+ disableMarkAsDelivered: boolean;
+ isMultipleFilesMessageEnabled: boolean;
+ // Remote configs set from dashboard by UIKit feature configuration
+ common: {
+ enableUsingDefaultUserProfile: SBUConfig['common']['enableUsingDefaultUserProfile'];
+ },
+ groupChannel: {
+ enableOgtag: SBUConfig['groupChannel']['channel']['enableOgtag'];
+ enableTypingIndicator: SBUConfig['groupChannel']['channel']['enableTypingIndicator'];
+ enableReactions: SBUConfig['groupChannel']['channel']['enableReactions'];
+ enableMention: SBUConfig['groupChannel']['channel']['enableMention'];
+ replyType: SBUConfig['groupChannel']['channel']['replyType'];
+ threadReplySelectType: SBUConfig['groupChannel']['channel']['threadReplySelectType'];
+ enableVoiceMessage: SBUConfig['groupChannel']['channel']['enableVoiceMessage'];
+ typingIndicatorTypes: SBUConfig['groupChannel']['channel']['typingIndicatorTypes'];
+ enableDocument: SBUConfig['groupChannel']['channel']['input']['enableDocument'];
+ enableFeedback: SBUConfig['groupChannel']['channel']['enableFeedback'];
+ enableSuggestedReplies: SBUConfig['groupChannel']['channel']['enableSuggestedReplies'];
+ showSuggestedRepliesFor: SBUConfig['groupChannel']['channel']['showSuggestedRepliesFor'];
+ suggestedRepliesDirection: SBUConfig['groupChannel']['channel']['suggestedRepliesDirection'];
+ enableMarkdownForUserMessage: SBUConfig['groupChannel']['channel']['enableMarkdownForUserMessage'];
+ enableFormTypeMessage: SBUConfig['groupChannel']['channel']['enableFormTypeMessage'];
+ /**
+ * @deprecated Currently, this feature is turned off by default. If you wish to use this feature, contact us: {@link https://dashboard.sendbird.com/settings/contact_us?category=feedback_and_feature_requests&product=UIKit}
+ */
+ enableReactionsSupergroup: never;
+ },
+ groupChannelList: {
+ enableTypingIndicator: SBUConfig['groupChannel']['channelList']['enableTypingIndicator'];
+ enableMessageReceiptStatus: SBUConfig['groupChannel']['channelList']['enableMessageReceiptStatus'];
+ },
+ groupChannelSettings: {
+ enableMessageSearch: SBUConfig['groupChannel']['setting']['enableMessageSearch'];
+ },
+ openChannel: {
+ enableOgtag: SBUConfig['openChannel']['channel']['enableOgtag'];
+ enableDocument: SBUConfig['openChannel']['channel']['input']['enableDocument'];
+ },
+ /**
+ * @deprecated Please use `onStartDirectMessage` instead. It's renamed.
+ */
+ onUserProfileMessage?: (props: GroupChannel) => void;
+ /**
+ * @deprecated Please use `!config.common.enableUsingDefaultUserProfile` instead.
+ * Note that you should use the negation of `config.common.enableUsingDefaultUserProfile`
+ * to replace `disableUserProfile`.
+ */
+ disableUserProfile: boolean;
+ /** @deprecated Please use `config.groupChannel.enableReactions` instead * */
+ isReactionEnabled: boolean;
+ /** @deprecated Please use `config.groupChannel.enableMention` instead * */
+ isMentionEnabled: boolean;
+ /** @deprecated Please use `config.groupChannel.enableVoiceMessage` instead * */
+ isVoiceMessageEnabled?: boolean;
+ /** @deprecated Please use `config.groupChannel.replyType` instead * */
+ replyType: ReplyType;
+ /** @deprecated Please use `config.groupChannelSettings.enableMessageSearch` instead * */
+ showSearchIcon?: boolean;
+ /** @deprecated Please use `config.groupChannelList.enableTypingIndicator` instead * */
+ isTypingIndicatorEnabledOnChannelList?: boolean;
+ /** @deprecated Please use `config.groupChannelList.enableMessageReceiptStatus` instead * */
+ isMessageReceiptStatusEnabledOnChannelList?: boolean;
+ /** @deprecated Please use setCurrentTheme instead * */
+ setCurrenttheme: (theme: 'light' | 'dark') => void;
+}
+
+export type SendbirdChatType = SendbirdChat & ModuleNamespaces<[GroupChannelModule, OpenChannelModule]>;
+
+export interface SdkStore {
+ error: boolean;
+ initialized: boolean;
+ loading: boolean;
+ sdk: SendbirdChat & ModuleNamespaces<[GroupChannelModule, OpenChannelModule]>;
+}
+
+export interface UserStore {
+ initialized: boolean;
+ loading: boolean;
+ user: User;
+}
+
+export interface AppInfoStore {
+ messageTemplatesInfo?: MessageTemplatesInfo;
+ /**
+ * This represents template keys that are currently waiting for its fetch response.
+ * Whenever initialized, request succeeds or fails, it needs to be updated.
+ */
+ waitingTemplateKeysMap: Record;
+}
+
+export interface SendbirdStateStore {
+ sdkStore: SdkStore;
+ userStore: UserStore;
+ appInfoStore: AppInfoStore;
+}
+
+export type SendbirdState = {
+ config: SendbirdStateConfig;
+ stores: SendbirdStateStore;
+ // dispatchers: {
+ // sdkDispatcher: React.Dispatch,
+ // userDispatcher: React.Dispatch,
+ // appInfoDispatcher: React.Dispatch,
+ // reconnect: ReconnectType,
+ // },
+ // Customer provided callbacks
+ eventHandlers?: SBUEventHandlers;
+ emojiManager: EmojiManager;
+ utils: SendbirdProviderUtils;
+};
+
+/* -------------------------------------------------------------------------- */
+/* Utility Types */
+/* -------------------------------------------------------------------------- */
+
+export interface SendbirdProviderUtils {
+ updateMessageTemplatesInfo: (
+ templateKeys: string[],
+ messageId: number,
+ createdAt: number
+ ) => Promise;
+ getCachedTemplate: (key: string) => ProcessedMessageTemplate | null;
+}
+
+// Selectors for state access
+export interface sendbirdSelectorsInterface {
+ getSdk: (store: SendbirdState) => SendbirdChat | undefined;
+ getConnect: (store: SendbirdState) => (userId: string, accessToken?: string) => Promise;
+ getDisconnect: (store: SendbirdState) => () => Promise;
+ getUpdateUserInfo: (
+ store: SendbirdState
+ ) => (nickName: string, profileUrl?: string) => Promise;
+ getCreateGroupChannel: (
+ store: SendbirdState
+ ) => (channelParams: GroupChannelCreateParams) => Promise;
+ getCreateOpenChannel: (
+ store: SendbirdState
+ ) => (channelParams: OpenChannelCreateParams) => Promise;
+ getGetGroupChannel: (
+ store: SendbirdState
+ ) => (channelUrl: string, isSelected?: boolean) => Promise;
+ getGetOpenChannel: (
+ store: SendbirdState
+ ) => (channelUrl: string) => Promise;
+ getLeaveGroupChannel: (
+ store: SendbirdState
+ ) => (channel: GroupChannel) => Promise;
+ getEnterOpenChannel: (
+ store: SendbirdState
+ ) => (channel: OpenChannel) => Promise;
+ getExitOpenChannel: (
+ store: SendbirdState
+ ) => (channel: OpenChannel) => Promise;
+ getFreezeChannel: (
+ store: SendbirdState
+ ) => (channel: GroupChannel | OpenChannel) => Promise;
+ getUnFreezeChannel: (
+ store: SendbirdState
+ ) => (channel: GroupChannel | OpenChannel) => Promise;
+ getSendUserMessage: (
+ store: SendbirdState
+ ) => (
+ channel: GroupChannel | OpenChannel,
+ userMessageParams: UserMessageCreateParams
+ ) => any; // Replace with specific type
+ getSendFileMessage: (
+ store: SendbirdState
+ ) => (
+ channel: GroupChannel | OpenChannel,
+ fileMessageParams: FileMessageCreateParams
+ ) => any; // Replace with specific type
+ getUpdateUserMessage: (
+ store: SendbirdState
+ ) => (
+ channel: GroupChannel | OpenChannel,
+ messageId: string | number,
+ params: UserMessageUpdateParams
+ ) => Promise;
+}
diff --git a/src/lib/Sendbird/utils.ts b/src/lib/Sendbird/utils.ts
new file mode 100644
index 000000000..c708e1aaf
--- /dev/null
+++ b/src/lib/Sendbird/utils.ts
@@ -0,0 +1,93 @@
+import SendbirdChat, { DeviceOsPlatform, SendbirdChatWith, SendbirdPlatform, SendbirdProduct, SessionHandler } from '@sendbird/chat';
+import { GroupChannelModule } from '@sendbird/chat/groupChannel';
+import { OpenChannelModule } from '@sendbird/chat/openChannel';
+
+import type { AppInfoStore, CustomExtensionParams, SdkStore, SendbirdState, UserStore } from './types';
+import { LoggerInterface } from '../Logger';
+
+type UpdateAppInfoStoreType = (state: SendbirdState, payload: AppInfoStore) => SendbirdState;
+export const updateAppInfoStore: UpdateAppInfoStoreType = (state, payload) => {
+ return {
+ ...state,
+ stores: {
+ ...state.stores,
+ appInfoStore: {
+ ...state.stores.appInfoStore,
+ ...payload,
+ },
+ },
+ };
+};
+type UpdateSdkStoreType = (state: SendbirdState, payload: Partial) => SendbirdState;
+export const updateSdkStore: UpdateSdkStoreType = (state, payload) => {
+ return {
+ ...state,
+ stores: {
+ ...state.stores,
+ sdkStore: {
+ ...state.stores.sdkStore,
+ ...payload,
+ },
+ },
+ };
+};
+type UpdateUserStoreType = (state: SendbirdState, payload: Partial) => SendbirdState;
+export const updateUserStore: UpdateUserStoreType = (state, payload) => {
+ return {
+ ...state,
+ stores: {
+ ...state.stores,
+ userStore: {
+ ...state.stores.userStore,
+ ...payload,
+ },
+ },
+ };
+};
+
+export function initSDK({
+ appId,
+ customApiHost,
+ customWebSocketHost,
+ sdkInitParams = {},
+}: {
+ appId: string;
+ customApiHost?: string;
+ customWebSocketHost?: string;
+ sdkInitParams?: Record;
+}) {
+ const params = Object.assign(sdkInitParams, {
+ appId,
+ modules: [new GroupChannelModule(), new OpenChannelModule()],
+ // newInstance: isNewApp,
+ localCacheEnabled: true,
+ });
+
+ if (customApiHost) params.customApiHost = customApiHost;
+ if (customWebSocketHost) params.customWebSocketHost = customWebSocketHost;
+ return SendbirdChat.init(params);
+}
+
+const APP_VERSION_STRING = '__react_dev_mode__';
+/**
+ * Sets up the Sendbird SDK after initialization.
+ * Configures necessary settings, adds extensions, sets the platform, and configures the session handler if provided.
+ */
+export function setupSDK(
+ sdk: SendbirdChatWith<[GroupChannelModule, OpenChannelModule]>,
+ params: { logger: LoggerInterface; sessionHandler?: SessionHandler; isMobile?: boolean; customExtensionParams?: CustomExtensionParams },
+) {
+ const { logger, sessionHandler, isMobile, customExtensionParams } = params;
+
+ logger.info?.('SendbirdProvider | useConnect/setupConnection/setVersion', { version: APP_VERSION_STRING });
+ sdk.addExtension('sb_uikit', APP_VERSION_STRING);
+ sdk.addSendbirdExtensions(
+ [{ product: SendbirdProduct.UIKIT_CHAT, version: APP_VERSION_STRING, platform: SendbirdPlatform?.JS }],
+ { platform: isMobile ? DeviceOsPlatform.MOBILE_WEB : DeviceOsPlatform.WEB },
+ customExtensionParams,
+ );
+ if (sessionHandler) {
+ logger.info?.('SendbirdProvider | useConnect/setupConnection/configureSession', sessionHandler);
+ sdk.setSessionHandler(sessionHandler);
+ }
+}
diff --git a/src/lib/SendbirdSdkContext.tsx b/src/lib/SendbirdSdkContext.tsx
deleted file mode 100644
index bd3b867b7..000000000
--- a/src/lib/SendbirdSdkContext.tsx
+++ /dev/null
@@ -1,36 +0,0 @@
-import React from 'react';
-import type { SendBirdState } from './types';
-
-type ContextAwareComponentType = {
- (props: any): JSX.Element;
- displayName: string;
-};
-
-export const SendbirdSdkContext = React.createContext(null);
-
-/**
- * @deprecated This function is deprecated. Use `useSendbirdStateContext` instead.
- * */
-const withSendbirdContext = (OriginalComponent: any, mapStoreToProps: Record): ContextAwareComponentType => {
- const ContextAwareComponent = (props: any) => (
-
- {(context) => {
- if (mapStoreToProps && typeof mapStoreToProps !== 'function') {
- // eslint-disable-next-line no-console
- console.warn('Second parameter to withSendbirdContext must be a pure function');
- }
- const mergedProps = (mapStoreToProps && typeof mapStoreToProps === 'function')
- ? { ...mapStoreToProps(context), ...props }
- : { ...context, ...props };
- return ;
- }}
-
- );
-
- const componentName = OriginalComponent.displayName || OriginalComponent.name || 'Component';
- ContextAwareComponent.displayName = `SendbirdAware${componentName}`;
-
- return ContextAwareComponent;
-};
-
-export default withSendbirdContext;
diff --git a/src/lib/SendbirdState.tsx b/src/lib/SendbirdState.tsx
deleted file mode 100644
index 11b79baba..000000000
--- a/src/lib/SendbirdState.tsx
+++ /dev/null
@@ -1,9 +0,0 @@
-import { Dispatch } from 'react';
-import { LoggerInterface } from './Logger';
-
-export type CustomUseReducerDispatcher = Dispatch<{
- type: string;
- payload: any;
-}>;
-
-export type Logger = LoggerInterface;
diff --git a/src/lib/UserProfileContext.tsx b/src/lib/UserProfileContext.tsx
index 92f5d4104..eaf82aa94 100644
--- a/src/lib/UserProfileContext.tsx
+++ b/src/lib/UserProfileContext.tsx
@@ -1,7 +1,7 @@
import React, { useContext } from 'react';
import type { GroupChannel } from '@sendbird/chat/groupChannel';
import type { RenderUserProfileProps } from '../types';
-import useSendbirdStateContext from '../hooks/useSendbirdStateContext';
+import useSendbird from './Sendbird/context/hooks/useSendbird';
interface UserProfileContextInterface {
isOpenChannel: boolean;
@@ -44,7 +44,8 @@ export const UserProfileProvider = ({
onStartDirectMessage: _onStartDirectMessage,
children,
}: UserProfileProviderProps) => {
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const onStartDirectMessage = _onStartDirectMessage ?? _onUserProfileMessage ?? config.onStartDirectMessage;
return (
diff --git a/src/lib/dux/appInfo/actionTypes.ts b/src/lib/dux/appInfo/actionTypes.ts
deleted file mode 100644
index f90c4ebdc..000000000
--- a/src/lib/dux/appInfo/actionTypes.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { CreateAction } from '../../../utils/typeHelpers/reducers/createAction';
-import { MessageTemplatesInfo, ProcessedMessageTemplate } from './initialState';
-
-export const APP_INFO_ACTIONS = {
- INITIALIZE_MESSAGE_TEMPLATES_INFO: 'INITIALIZE_MESSAGE_TEMPLATES_INFO',
- UPSERT_MESSAGE_TEMPLATES: 'UPSERT_MESSAGE_TEMPLATES',
- UPSERT_WAITING_TEMPLATE_KEYS: 'UPSERT_WAITING_TEMPLATE_KEYS',
- MARK_ERROR_WAITING_TEMPLATE_KEYS: 'MARK_ERROR_WAITING_TEMPLATE_KEYS',
-} as const;
-
-export type TemplatesMapData = {
- key: string;
- template: ProcessedMessageTemplate;
-};
-
-type APP_INFO_PAYLOAD_TYPES = {
- [APP_INFO_ACTIONS.INITIALIZE_MESSAGE_TEMPLATES_INFO]: MessageTemplatesInfo,
- [APP_INFO_ACTIONS.UPSERT_MESSAGE_TEMPLATES]: TemplatesMapData[],
- [APP_INFO_ACTIONS.UPSERT_WAITING_TEMPLATE_KEYS]: { keys: string[], requestedAt: number },
- [APP_INFO_ACTIONS.MARK_ERROR_WAITING_TEMPLATE_KEYS]: { keys: string[], messageId: number },
-};
-
-export type AppInfoActionTypes = CreateAction;
diff --git a/src/lib/dux/appInfo/initialState.ts b/src/lib/dux/appInfo/initialState.ts
deleted file mode 100644
index 54b99449b..000000000
--- a/src/lib/dux/appInfo/initialState.ts
+++ /dev/null
@@ -1,30 +0,0 @@
-export type ProcessedMessageTemplate = {
- version: number;
- uiTemplate: string; // This is stringified ui_template.body.items
- colorVariables?: Record;
-};
-
-export interface MessageTemplatesInfo {
- token: string; // This server-side token gets updated on every CRUD operation on message template table.
- templatesMap: Record;
-}
-
-export interface WaitingTemplateKeyData {
- requestedAt: number;
- erroredMessageIds: number[];
-}
-
-export interface AppInfoStateType {
- messageTemplatesInfo?: MessageTemplatesInfo;
- /**
- * This represents template keys that are currently waiting for its fetch response.
- * Whenever initialized, request succeeds or fails, it needs to be updated.
- */
- waitingTemplateKeysMap: Record;
-}
-
-const initialState: AppInfoStateType = {
- waitingTemplateKeysMap: {},
-};
-
-export default initialState;
diff --git a/src/lib/dux/appInfo/reducers.ts b/src/lib/dux/appInfo/reducers.ts
deleted file mode 100644
index 3494608c6..000000000
--- a/src/lib/dux/appInfo/reducers.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-import { match } from 'ts-pattern';
-import { AppInfoStateType, WaitingTemplateKeyData } from './initialState';
-import { APP_INFO_ACTIONS, AppInfoActionTypes } from './actionTypes';
-
-export default function reducer(state: AppInfoStateType, action: AppInfoActionTypes): AppInfoStateType {
- return match(action)
- .with(
- { type: APP_INFO_ACTIONS.INITIALIZE_MESSAGE_TEMPLATES_INFO },
- ({ payload }) => {
- return {
- messageTemplatesInfo: payload,
- waitingTemplateKeysMap: {},
- };
- })
- .with(
- { type: APP_INFO_ACTIONS.UPSERT_MESSAGE_TEMPLATES },
- ({ payload }) => {
- const templatesInfo = state.messageTemplatesInfo;
- if (!templatesInfo) return state; // Not initialized. Ignore.
-
- const waitingTemplateKeysMap = { ...state.waitingTemplateKeysMap };
- payload.forEach((templatesMapData) => {
- const { key, template } = templatesMapData;
- templatesInfo.templatesMap[key] = template;
- delete waitingTemplateKeysMap[key];
- });
- return {
- ...state,
- waitingTemplateKeysMap,
- messageTemplatesInfo: templatesInfo,
- };
- })
- .with(
- { type: APP_INFO_ACTIONS.UPSERT_WAITING_TEMPLATE_KEYS },
- ({ payload }) => {
- const { keys, requestedAt } = payload;
- const waitingTemplateKeysMap = { ...state.waitingTemplateKeysMap };
- keys.forEach((key) => {
- waitingTemplateKeysMap[key] = {
- erroredMessageIds: waitingTemplateKeysMap[key]?.erroredMessageIds ?? [],
- requestedAt,
- };
- });
- return {
- ...state,
- waitingTemplateKeysMap,
- };
- })
- .with(
- { type: APP_INFO_ACTIONS.MARK_ERROR_WAITING_TEMPLATE_KEYS },
- ({ payload }) => {
- const { keys, messageId } = payload;
- const waitingTemplateKeysMap = { ...state.waitingTemplateKeysMap };
- keys.forEach((key) => {
- const waitingTemplateKeyData: WaitingTemplateKeyData | undefined = waitingTemplateKeysMap[key];
- if (waitingTemplateKeyData && waitingTemplateKeyData.erroredMessageIds.indexOf(messageId) === -1) {
- waitingTemplateKeyData.erroredMessageIds.push(messageId);
- }
- });
- return {
- ...state,
- waitingTemplateKeysMap,
- };
- })
- .otherwise(() => {
- return state;
- });
-}
diff --git a/src/lib/dux/appInfo/utils.ts b/src/lib/dux/appInfo/utils.ts
deleted file mode 100644
index ea1ce6f4c..000000000
--- a/src/lib/dux/appInfo/utils.ts
+++ /dev/null
@@ -1,23 +0,0 @@
-import { ProcessedMessageTemplate } from './initialState';
-import { SendbirdMessageTemplate } from '../../../ui/TemplateMessageItemBody/types';
-
-/**
- * Takes JSON parsed template and then returns processed message template for storing it in global state.
- */
-export const getProcessedTemplate = (parsedTemplate: SendbirdMessageTemplate): ProcessedMessageTemplate => {
- return {
- version: Number(parsedTemplate.ui_template.version),
- uiTemplate: JSON.stringify(parsedTemplate.ui_template.body.items),
- colorVariables: parsedTemplate.color_variables,
- };
-};
-
-export const getProcessedTemplatesMap = (
- parsedTemplates: SendbirdMessageTemplate[],
-): Record => {
- const processedTemplates = {};
- parsedTemplates.forEach((template) => {
- processedTemplates[template.key] = getProcessedTemplate(template);
- });
- return processedTemplates;
-};
diff --git a/src/lib/dux/sdk/actionTypes.ts b/src/lib/dux/sdk/actionTypes.ts
deleted file mode 100644
index 2b416c0d3..000000000
--- a/src/lib/dux/sdk/actionTypes.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { CreateAction } from '../../../utils/typeHelpers/reducers/createAction';
-import { SdkStoreStateType } from './initialState';
-
-export const SDK_ACTIONS = {
- INIT_SDK: 'INIT_SDK',
- SET_SDK_LOADING: 'SET_SDK_LOADING',
- RESET_SDK: 'RESET_SDK',
- SDK_ERROR: 'SDK_ERROR',
-} as const;
-
-type SDK_PAYLOAD_TYPES = {
- [SDK_ACTIONS.SET_SDK_LOADING]: boolean,
- [SDK_ACTIONS.INIT_SDK]: SdkStoreStateType['sdk'],
- [SDK_ACTIONS.SDK_ERROR]: null,
- [SDK_ACTIONS.RESET_SDK]: null,
-};
-
-export type SdkActionTypes = CreateAction;
diff --git a/src/lib/dux/sdk/initialState.ts b/src/lib/dux/sdk/initialState.ts
deleted file mode 100644
index fc9e50eb9..000000000
--- a/src/lib/dux/sdk/initialState.ts
+++ /dev/null
@@ -1,17 +0,0 @@
-import { SdkStore } from '../../types';
-
-export interface SdkStoreStateType {
- initialized: SdkStore['initialized']
- loading: SdkStore['loading']
- sdk: SdkStore['sdk'],
- error: SdkStore['error'];
-}
-
-const initialState: SdkStoreStateType = {
- initialized: false,
- loading: false,
- sdk: {} as SdkStore['sdk'],
- error: false,
-};
-
-export default initialState;
diff --git a/src/lib/dux/sdk/reducers.ts b/src/lib/dux/sdk/reducers.ts
deleted file mode 100644
index 443226e9a..000000000
--- a/src/lib/dux/sdk/reducers.ts
+++ /dev/null
@@ -1,36 +0,0 @@
-import { match } from 'ts-pattern';
-import { SdkActionTypes, SDK_ACTIONS } from './actionTypes';
-import initialState, { SdkStoreStateType } from './initialState';
-
-export default function reducer(state: SdkStoreStateType, action: SdkActionTypes): SdkStoreStateType {
- return match(action)
- .with({ type: SDK_ACTIONS.SET_SDK_LOADING }, ({ payload }) => {
- return {
- ...state,
- initialized: false,
- loading: payload,
- };
- })
- .with({ type: SDK_ACTIONS.SDK_ERROR }, () => {
- return {
- ...state,
- initialized: false,
- loading: false,
- error: true,
- };
- })
- .with({ type: SDK_ACTIONS.INIT_SDK }, ({ payload }) => {
- return {
- sdk: payload,
- initialized: true,
- loading: false,
- error: false,
- };
- })
- .with({ type: SDK_ACTIONS.RESET_SDK }, () => {
- return initialState;
- })
- .otherwise(() => {
- return state;
- });
-}
diff --git a/src/lib/dux/user/actionTypes.ts b/src/lib/dux/user/actionTypes.ts
deleted file mode 100644
index 85e4c762f..000000000
--- a/src/lib/dux/user/actionTypes.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { User } from '@sendbird/chat';
-import { CreateAction } from '../../../utils/typeHelpers/reducers/createAction';
-
-export const USER_ACTIONS = {
- INIT_USER: 'INIT_USER',
- RESET_USER: 'RESET_USER',
- UPDATE_USER_INFO: 'UPDATE_USER_INFO',
-} as const;
-
-type USER_PAYLOAD_TYPES = {
- [USER_ACTIONS.INIT_USER]: User,
- [USER_ACTIONS.RESET_USER]: null,
- [USER_ACTIONS.UPDATE_USER_INFO]: User,
-};
-
-export type UserActionTypes = CreateAction;
diff --git a/src/lib/dux/user/initialState.ts b/src/lib/dux/user/initialState.ts
deleted file mode 100644
index af5da7577..000000000
--- a/src/lib/dux/user/initialState.ts
+++ /dev/null
@@ -1,15 +0,0 @@
-import { User } from '@sendbird/chat';
-
-export interface UserStoreStateType {
- initialized: boolean;
- loading: boolean;
- user: User;
-}
-
-const initialState: UserStoreStateType = {
- initialized: false,
- loading: false,
- user: {} as User,
-};
-
-export default initialState;
diff --git a/src/lib/dux/user/reducers.ts b/src/lib/dux/user/reducers.ts
deleted file mode 100644
index 27bea4de5..000000000
--- a/src/lib/dux/user/reducers.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-import { match } from 'ts-pattern';
-import { UserActionTypes, USER_ACTIONS } from './actionTypes';
-import initialState, { UserStoreStateType } from './initialState';
-
-export default function reducer(state: UserStoreStateType, action: UserActionTypes): UserStoreStateType {
- return match(action)
- .with({ type: USER_ACTIONS.INIT_USER }, ({ payload }) => {
- return {
- initialized: true,
- loading: false,
- user: payload,
- };
- })
- .with({ type: USER_ACTIONS.RESET_USER }, () => {
- return initialState;
- })
- .with({ type: USER_ACTIONS.UPDATE_USER_INFO }, ({ payload }) => {
- return {
- ...state,
- user: payload,
- };
- })
- .otherwise(() => {
- return state;
- });
-}
diff --git a/src/lib/emojiManager.tsx b/src/lib/emojiManager.tsx
index cc9a2c664..1c51a3cd3 100644
--- a/src/lib/emojiManager.tsx
+++ b/src/lib/emojiManager.tsx
@@ -12,8 +12,7 @@
*/
import type { Emoji, EmojiCategory, EmojiContainer } from '@sendbird/chat';
-import type { SendbirdChatType } from './types';
-import { Logger } from './SendbirdState';
+import type { SendbirdChatType, Logger } from './Sendbird/types';
import { match } from 'ts-pattern';
import { Reaction } from '@sendbird/chat/message';
diff --git a/src/lib/hooks/__tests__/schedulerFactory.spec.ts b/src/lib/hooks/__tests__/schedulerFactory.spec.ts
index 4d5b6405d..4d17f4a31 100644
--- a/src/lib/hooks/__tests__/schedulerFactory.spec.ts
+++ b/src/lib/hooks/__tests__/schedulerFactory.spec.ts
@@ -2,7 +2,7 @@ import { GroupChannel } from '@sendbird/chat/groupChannel';
import { schedulerFactory } from '../schedulerFactory';
import { LoggerFactory } from '../../Logger';
-import { Logger } from '../../SendbirdState';
+import type { Logger } from '../../Sendbird/types';
jest.useFakeTimers();
jest.spyOn(global, 'setInterval');
diff --git a/src/lib/hooks/__tests__/useMarkAsDeliveredScheduler.spec.ts b/src/lib/hooks/__tests__/useMarkAsDeliveredScheduler.spec.ts
index 5c93304a3..ca42115eb 100644
--- a/src/lib/hooks/__tests__/useMarkAsDeliveredScheduler.spec.ts
+++ b/src/lib/hooks/__tests__/useMarkAsDeliveredScheduler.spec.ts
@@ -3,7 +3,7 @@ import { GroupChannel } from '@sendbird/chat/groupChannel';
import { useMarkAsDeliveredScheduler } from '../useMarkAsDeliveredScheduler';
import { LoggerFactory } from '../../Logger';
-import { Logger } from '../../SendbirdState';
+import type { Logger } from '../../Sendbird/types';
jest.useFakeTimers();
diff --git a/src/lib/hooks/__tests__/useMarkAsReadScheduler.spec.ts b/src/lib/hooks/__tests__/useMarkAsReadScheduler.spec.ts
index 64fa42ddd..9c4e6e92b 100644
--- a/src/lib/hooks/__tests__/useMarkAsReadScheduler.spec.ts
+++ b/src/lib/hooks/__tests__/useMarkAsReadScheduler.spec.ts
@@ -3,7 +3,7 @@ import { GroupChannel } from '@sendbird/chat/groupChannel';
import { useMarkAsReadScheduler } from '../useMarkAsReadScheduler';
import { LoggerFactory } from '../../Logger';
-import { Logger } from '../../SendbirdState';
+import type { Logger } from '../../Sendbird/types';
const logger = LoggerFactory('all') as Logger;
describe('useMarkAsReadScheduler', () => {
diff --git a/src/lib/hooks/schedulerFactory.ts b/src/lib/hooks/schedulerFactory.ts
index aa923618a..7ce2f32f9 100644
--- a/src/lib/hooks/schedulerFactory.ts
+++ b/src/lib/hooks/schedulerFactory.ts
@@ -1,5 +1,5 @@
import { GroupChannel } from '@sendbird/chat/groupChannel';
-import { Logger } from '../SendbirdState';
+import type { Logger } from '../Sendbird/types';
const TIMEOUT = 2000;
diff --git a/src/lib/hooks/useConnect/__test__/data.mocks.ts b/src/lib/hooks/useConnect/__test__/data.mocks.ts
deleted file mode 100644
index 9bc5579c9..000000000
--- a/src/lib/hooks/useConnect/__test__/data.mocks.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { User } from '@sendbird/chat';
-import { LoggerFactory } from '../../../Logger';
-import { ConnectTypes, DisconnectSdkTypes, SetupConnectionTypes, StaticTypes, TriggerTypes } from '../types';
-
-export const mockUser = {
- userId: 'test-user-id',
- nickname: 'test-nickname',
- profileUrl: 'test-profile-url',
-} as unknown as User;
-
-export const mockUser2 = {
- userId: 'test-user-id2',
- nickname: 'test-nickname2',
- profileUrl: 'test-profile-url2',
-} as unknown as User;
-
-export const mockSdk = {
- connect: jest.fn().mockImplementation((userId) => {
- if (userId === mockUser2.userId) {
- return Promise.resolve(mockUser2);
- }
- if (userId === mockUser.userId) {
- return Promise.resolve(mockUser);
- }
- if (userId?.length > 0) {
- return Promise.resolve({ userId: userId });
- }
- return Promise.reject();
- }),
- disconnect: jest.fn().mockImplementation(() => Promise.resolve(true)),
- disconnectWebSocket: jest.fn().mockImplementation(() => Promise.resolve(true)),
- updateCurrentUserInfo: jest.fn().mockImplementation((user) => Promise.resolve(user)),
- setSessionHandler: jest.fn(),
- addExtension: jest.fn(),
- addSendbirdExtensions: jest.fn(),
- getUIKitConfiguration: jest.fn().mockImplementation(() => Promise.resolve({})),
-} as unknown as ConnectTypes['sdk'];
-
-export const mockSdkDispatcher = jest.fn() as unknown as ConnectTypes['sdkDispatcher'];
-export const mockUserDispatcher = jest.fn() as unknown as ConnectTypes['userDispatcher'];
-export const mockAppInfoDispatcher = jest.fn() as unknown as ConnectTypes['appInfoDispatcher'];
-export const mockInitDashboardConfigs = jest.fn().mockImplementation(() => Promise.resolve({})) as unknown as ConnectTypes['initDashboardConfigs'];
-
-export const defaultStaticParams: StaticTypes = {
- nickname: 'test-nickname',
- profileUrl: 'test-profile-url',
- sdk: mockSdk,
- logger: LoggerFactory('all'),
- sdkDispatcher: mockSdkDispatcher,
- userDispatcher: mockUserDispatcher,
- appInfoDispatcher: mockAppInfoDispatcher,
- initDashboardConfigs: mockInitDashboardConfigs,
- initializeMessageTemplatesInfo: jest.fn().mockImplementation(() => Promise.resolve()),
-};
-
-export const defaultTriggerParams: TriggerTypes = {
- userId: 'test-user-id',
- appId: 'test-app-id',
- accessToken: 'test-access-token',
-};
-
-export const defaultConnectParams: ConnectTypes = {
- ...defaultStaticParams,
- ...defaultTriggerParams,
-};
-
-export const defaultSetupConnectionParams: SetupConnectionTypes = {
- ...defaultConnectParams,
-};
-
-export const defaultDisconnectSdkParams: DisconnectSdkTypes = {
- sdkDispatcher: mockSdkDispatcher,
- userDispatcher: mockUserDispatcher,
- sdk: mockSdk,
- logger: LoggerFactory('all'),
-};
-
-export function generateDisconnectSdkParams(overrides?: Partial): DisconnectSdkTypes {
- return {
- ...defaultDisconnectSdkParams,
- ...overrides,
- };
-}
-
-export function generateSetUpConnectionParams(overrides?: Partial): SetupConnectionTypes {
- return {
- ...defaultSetupConnectionParams,
- ...overrides,
- };
-}
diff --git a/src/lib/hooks/useConnect/__test__/disconnectSdk.spec.ts b/src/lib/hooks/useConnect/__test__/disconnectSdk.spec.ts
deleted file mode 100644
index 9f66cfa56..000000000
--- a/src/lib/hooks/useConnect/__test__/disconnectSdk.spec.ts
+++ /dev/null
@@ -1,29 +0,0 @@
-import { SDK_ACTIONS } from '../../../dux/sdk/actionTypes';
-import { USER_ACTIONS } from '../../../dux/user/actionTypes';
-import { disconnectSdk } from '../disconnectSdk';
-import { generateDisconnectSdkParams } from './data.mocks';
-
-describe('useConnect/disconnectSdk', () => {
- it('should call disconnectSdk when there is proper SDK', async () => {
- // setup
- const disconnectProps = generateDisconnectSdkParams();
- const mockDisconnect = disconnectProps.sdk.disconnectWebSocket as jest.Mock;
-
- // execute
- await disconnectSdk(disconnectProps);
-
- // verify
- expect(disconnectProps.sdkDispatcher).toHaveBeenCalledBefore(mockDisconnect);
- expect(disconnectProps.sdkDispatcher).toBeCalledWith({ type: SDK_ACTIONS.SET_SDK_LOADING, payload: true });
- expect(disconnectProps.sdk.disconnectWebSocket).toHaveBeenCalled();
- expect(disconnectProps.sdkDispatcher).toBeCalledWith({ type: SDK_ACTIONS.RESET_SDK });
- expect(disconnectProps.userDispatcher).toBeCalledWith({ type: USER_ACTIONS.RESET_USER });
- });
-
- it('should not call disconnectSdk when there is no SDK', async () => {
- const disconnectProps = generateDisconnectSdkParams({ sdk: undefined });
- await disconnectSdk(disconnectProps);
- expect(disconnectProps.sdkDispatcher).toBeCalledWith({ type: SDK_ACTIONS.SET_SDK_LOADING, payload: true });
- expect(disconnectProps.sdkDispatcher).not.toBeCalledWith({ type: SDK_ACTIONS.RESET_SDK });
- });
-});
diff --git a/src/lib/hooks/useConnect/__test__/setupConnection.spec.ts b/src/lib/hooks/useConnect/__test__/setupConnection.spec.ts
deleted file mode 100644
index 514d869c1..000000000
--- a/src/lib/hooks/useConnect/__test__/setupConnection.spec.ts
+++ /dev/null
@@ -1,268 +0,0 @@
-/* eslint-disable @typescript-eslint/no-var-requires */
-/* eslint-disable global-require */
-import { SDK_ACTIONS } from '../../../dux/sdk/actionTypes';
-import { USER_ACTIONS } from '../../../dux/user/actionTypes';
-import { getMissingParamError, setUpConnection, initSDK, getConnectSbError } from '../setupConnection';
-import { SetupConnectionTypes } from '../types';
-import { generateSetUpConnectionParams, mockSdk, mockUser, mockUser2 } from './data.mocks';
-import { SendbirdError } from '@sendbird/chat';
-
-// todo: combine after mock-sdk is implemented
-jest.mock('@sendbird/chat', () => {
- const originalModule = jest.requireActual('@sendbird/chat');
- return {
- init: jest.fn(() => mockSdk),
- ...originalModule,
- };
-});
-
-describe('useConnect/setupConnection', () => {
- it('should call SDK_ERROR when there is no appId', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const params = { ...setUpConnectionProps, appId: undefined };
- const errorMessage = getMissingParamError({ userId: params.userId, appId: params.appId });
-
- await expect(setUpConnection(params as unknown as SetupConnectionTypes)).rejects.toMatch(errorMessage);
-
- expect(mockSdk.connect).not.toBeCalledWith({ type: SDK_ACTIONS.SET_SDK_LOADING, payload: true });
- expect(setUpConnectionProps.sdkDispatcher).toBeCalledWith({ type: SDK_ACTIONS.SDK_ERROR });
- });
-
- it('should call SDK_ERROR when there is no userId', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const params = { ...setUpConnectionProps, userId: undefined };
- const errorMessage = getMissingParamError({ userId: params.userId, appId: params.appId });
-
- await expect(setUpConnection(params as unknown as SetupConnectionTypes)).rejects.toMatch(errorMessage);
-
- expect(setUpConnectionProps.sdkDispatcher).toHaveBeenCalledWith({ type: SDK_ACTIONS.SET_SDK_LOADING, payload: true });
- expect(mockSdk.connect).not.toBeCalledWith({ type: SDK_ACTIONS.SET_SDK_LOADING, payload: true });
- expect(setUpConnectionProps.sdkDispatcher).toBeCalledWith({ type: SDK_ACTIONS.SDK_ERROR });
- });
-
- it('should replace nickname with userId when isUserIdUsedForNickname is true', async () => {
- const newUser = {
- userId: 'new-userid',
- nickname: '',
- profileUrl: 'new-user-profile-url',
- };
- const setUpConnectionProps = generateSetUpConnectionParams();
- await setUpConnection({
- ...setUpConnectionProps,
- ...newUser,
- isUserIdUsedForNickname: true,
- });
-
- const updatedUser = { nickname: newUser.userId, profileUrl: newUser.profileUrl };
- expect(mockSdk.updateCurrentUserInfo).toHaveBeenCalledWith(updatedUser);
- expect(setUpConnectionProps.userDispatcher).toHaveBeenCalledWith({
- type: USER_ACTIONS.UPDATE_USER_INFO,
- payload: updatedUser,
- });
- });
-
- it('should not replace nickname with userId when isUserIdUsedForNickname is false', async () => {
- const newUser = {
- userId: 'new-userid',
- nickname: '',
- profileUrl: 'new-user-profile-url',
- };
- const setUpConnectionProps = generateSetUpConnectionParams();
- await setUpConnection({
- ...setUpConnectionProps,
- ...newUser,
- isUserIdUsedForNickname: false,
- });
-
- const updatedUser = { nickname: '', profileUrl: newUser.profileUrl };
- expect(mockSdk.updateCurrentUserInfo).toHaveBeenCalledWith(updatedUser);
- expect(setUpConnectionProps.userDispatcher).toHaveBeenCalledWith({
- type: USER_ACTIONS.UPDATE_USER_INFO,
- payload: updatedUser,
- });
- });
-
- it('should call setUpConnection when there is proper SDK', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- await setUpConnection(setUpConnectionProps);
- expect(setUpConnectionProps.sdkDispatcher).toHaveBeenNthCalledWith(1, {
- type: SDK_ACTIONS.SET_SDK_LOADING,
- payload: true,
- });
- expect(mockSdk.connect).toHaveBeenCalledWith(setUpConnectionProps.userId, setUpConnectionProps.accessToken);
- expect(setUpConnectionProps.sdkDispatcher).toHaveBeenNthCalledWith(2, {
- type: SDK_ACTIONS.INIT_SDK,
- payload: mockSdk,
- });
- expect(setUpConnectionProps.userDispatcher).toHaveBeenCalledOnceWith({
- type: USER_ACTIONS.INIT_USER,
- payload: mockUser,
- });
- });
-
- it('should call connect with only userId when there is no access token', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const params = { ...setUpConnectionProps, accessToken: undefined };
- await setUpConnection(params);
- expect(mockSdk.connect).toHaveBeenCalledWith(mockUser.userId, undefined);
- });
-
- it('should call connect with userId & access token', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const params = { ...setUpConnectionProps, accessToken: setUpConnectionProps.accessToken };
- await setUpConnection(params);
- expect(mockSdk.connect).toHaveBeenCalledWith(mockUser.userId, setUpConnectionProps.accessToken);
- });
-
- it('should call configureSession if provided', async () => {
- const configureSession = jest.fn().mockImplementation(() => 'mock_session');
- const setUpConnectionProps = generateSetUpConnectionParams();
- await setUpConnection({ ...setUpConnectionProps, configureSession });
- expect(configureSession).toHaveBeenCalledWith(mockSdk);
- });
-
- it('should call updateCurrentUserInfo when', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const newNickname = 'newNickname';
- const newprofileUrl = 'newprofileUrl';
- await setUpConnection({
- ...setUpConnectionProps,
- userId: mockUser2.userId,
- nickname: newNickname,
- profileUrl: newprofileUrl,
- });
- expect(mockSdk.updateCurrentUserInfo).toHaveBeenCalledWith({ nickname: 'newNickname', profileUrl: 'newprofileUrl' });
- expect(setUpConnectionProps.userDispatcher).toHaveBeenCalledWith({
- type: USER_ACTIONS.INIT_USER,
- payload: {
- nickname: 'test-nickname2',
- profileUrl: 'test-profile-url2',
- userId: 'test-user-id2',
- },
- });
- });
-
- it('should call connectCbError if connection fails', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- setUpConnectionProps.userId = '';
- const errorMessage = getMissingParamError({
- userId: '',
- appId: setUpConnectionProps.appId,
- });
-
- await expect(setUpConnection(setUpConnectionProps)).rejects.toMatch(errorMessage);
-
- expect(setUpConnectionProps.sdkDispatcher).toHaveBeenCalledWith({
- type: SDK_ACTIONS.SDK_ERROR,
- });
- });
-
- it('should call onConnectionFailed callback when connection fails', async () => {
- const onConnectionFailed = jest.fn();
- const setUpConnectionProps = generateSetUpConnectionParams();
- setUpConnectionProps.eventHandlers = { connection: { onFailed: onConnectionFailed } };
-
- const error = new Error('test-error');
- // @ts-expect-error
- mockSdk.connect.mockRejectedValueOnce(error);
- const expected = getConnectSbError(error as SendbirdError);
- // // Ensure that the onConnectionFailed callback is called with the correct error message
- await expect(setUpConnection(setUpConnectionProps)).rejects.toStrictEqual(expected);
- // Ensure that onConnectionFailed callback is called with the expected error object
- expect(onConnectionFailed).toHaveBeenCalledWith(error);
- });
-
- it('should call onConnected callback when connection succeeded', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- setUpConnectionProps.eventHandlers = { connection: { onConnected: jest.fn() } };
-
- const user = { userId: 'test-user-id', nickname: 'test-nickname', profileUrl: 'test-profile-url' };
- // @ts-expect-error
- mockSdk.connect.mockResolvedValueOnce(user);
-
- await expect(setUpConnection(setUpConnectionProps)).resolves.toStrictEqual(undefined);
- expect(setUpConnectionProps.eventHandlers.connection.onConnected).toHaveBeenCalledWith(user);
- });
-});
-
-describe('useConnect/setupConnection/initSDK', () => {
- it('should call init with correct appId', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const { appId, customApiHost, customWebSocketHost } = setUpConnectionProps;
- const newSdk = initSDK({ appId, customApiHost, customWebSocketHost });
- // @ts-ignore
- expect(require('@sendbird/chat').init).toBeCalledWith({
- appId,
- newInstance: false,
- localCacheEnabled: true,
- modules: [
- // @ts-ignore
- new (require('@sendbird/chat/groupChannel').GroupChannelModule)(),
- // @ts-ignore
- new (require('@sendbird/chat/openChannel').OpenChannelModule)(),
- ],
- });
- expect(newSdk).toEqual(mockSdk);
- });
-
- it('should call init with correct customApiHost & customWebSocketHost', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const { appId, customApiHost, customWebSocketHost } = setUpConnectionProps;
- const newSdk = initSDK({ appId, customApiHost, customWebSocketHost });
- // @ts-ignore
- expect(require('@sendbird/chat').init).toBeCalledWith({
- appId,
- newInstance: false,
- localCacheEnabled: true,
- modules: [
- // @ts-ignore
- new (require('@sendbird/chat/groupChannel').GroupChannelModule)(),
- // @ts-ignore
- new (require('@sendbird/chat/openChannel').OpenChannelModule)(),
- ],
- customApiHost,
- customWebSocketHost,
- });
- expect(newSdk).toEqual(mockSdk);
- });
-
- it('should call init with sdkInitParams', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const { appId, sdkInitParams } = setUpConnectionProps;
- const newSdk = initSDK({ appId, sdkInitParams });
- // @ts-ignore
- expect(require('@sendbird/chat').init).toBeCalledWith({
- appId,
- newInstance: false,
- localCacheEnabled: true,
- modules: [
- // @ts-ignore
- new (require('@sendbird/chat/groupChannel').GroupChannelModule)(),
- // @ts-ignore
- new (require('@sendbird/chat/openChannel').OpenChannelModule)(),
- ],
- sdkInitParams,
- });
- expect(newSdk).toEqual(mockSdk);
- });
-
- it('should call init with customExtensionParams', async () => {
- const setUpConnectionProps = generateSetUpConnectionParams();
- const { appId, customExtensionParams } = setUpConnectionProps;
- const newSdk = initSDK({ appId, customExtensionParams });
- // @ts-ignore
- expect(require('@sendbird/chat').init).toBeCalledWith({
- appId,
- newInstance: false,
- localCacheEnabled: true,
- modules: [
- // @ts-ignore
- new (require('@sendbird/chat/groupChannel').GroupChannelModule)(),
- // @ts-ignore
- new (require('@sendbird/chat/openChannel').OpenChannelModule)(),
- ],
- customExtensionParams,
- });
- expect(newSdk).toEqual(mockSdk);
- });
-});
diff --git a/src/lib/hooks/useConnect/connect.ts b/src/lib/hooks/useConnect/connect.ts
deleted file mode 100644
index d22ca7c05..000000000
--- a/src/lib/hooks/useConnect/connect.ts
+++ /dev/null
@@ -1,56 +0,0 @@
-import { disconnectSdk } from './disconnectSdk';
-import { setUpConnection } from './setupConnection';
-import { ConnectTypes } from './types';
-
-export async function connect({
- logger,
- sdkDispatcher,
- userDispatcher,
- appInfoDispatcher,
- initDashboardConfigs,
- userId,
- appId,
- isNewApp = false,
- customApiHost,
- customWebSocketHost,
- configureSession,
- nickname,
- profileUrl,
- accessToken,
- sdk,
- sdkInitParams,
- customExtensionParams,
- isMobile,
- eventHandlers,
- isUserIdUsedForNickname,
- initializeMessageTemplatesInfo,
-}: ConnectTypes): Promise {
- await disconnectSdk({
- logger,
- sdkDispatcher,
- userDispatcher,
- sdk,
- });
- await setUpConnection({
- logger,
- sdkDispatcher,
- userDispatcher,
- appInfoDispatcher,
- initDashboardConfigs,
- userId,
- appId,
- isNewApp,
- customApiHost,
- customWebSocketHost,
- configureSession,
- nickname,
- profileUrl,
- accessToken,
- sdkInitParams,
- customExtensionParams,
- isMobile,
- eventHandlers,
- isUserIdUsedForNickname,
- initializeMessageTemplatesInfo,
- });
-}
diff --git a/src/lib/hooks/useConnect/disconnectSdk.ts b/src/lib/hooks/useConnect/disconnectSdk.ts
deleted file mode 100644
index 210a24bbf..000000000
--- a/src/lib/hooks/useConnect/disconnectSdk.ts
+++ /dev/null
@@ -1,25 +0,0 @@
-import { SDK_ACTIONS } from '../../dux/sdk/actionTypes';
-import { USER_ACTIONS } from '../../dux/user/actionTypes';
-import { DisconnectSdkTypes } from './types';
-
-export async function disconnectSdk({
- sdkDispatcher,
- userDispatcher,
- sdk,
-}: DisconnectSdkTypes): Promise {
- return new Promise((resolve) => {
- sdkDispatcher({ type: SDK_ACTIONS.SET_SDK_LOADING, payload: true });
- if (sdk?.disconnectWebSocket) {
- sdk.disconnectWebSocket()
- .then(() => {
- sdkDispatcher({ type: SDK_ACTIONS.RESET_SDK });
- userDispatcher({ type: USER_ACTIONS.RESET_USER });
- })
- .finally(() => {
- resolve(true);
- });
- } else {
- resolve(true);
- }
- });
-}
diff --git a/src/lib/hooks/useConnect/index.ts b/src/lib/hooks/useConnect/index.ts
deleted file mode 100644
index 8b7c6ff10..000000000
--- a/src/lib/hooks/useConnect/index.ts
+++ /dev/null
@@ -1,100 +0,0 @@
-import { useCallback, useEffect, useRef } from 'react';
-
-import { ReconnectType, StaticTypes, TriggerTypes } from './types';
-import { connect } from './connect';
-
-export default function useConnect(triggerTypes: TriggerTypes, staticTypes: StaticTypes): ReconnectType {
- const { userId, appId, accessToken, isMobile, isUserIdUsedForNickname } = triggerTypes;
- const {
- logger,
- nickname,
- profileUrl,
- configureSession,
- customApiHost,
- customWebSocketHost,
- sdk,
- sdkDispatcher,
- userDispatcher,
- appInfoDispatcher,
- initDashboardConfigs,
- sdkInitParams,
- customExtensionParams,
- eventHandlers,
- initializeMessageTemplatesInfo,
- } = staticTypes;
-
- // Note: This is a workaround to prevent the creation of multiple SDK instances when React strict mode is enabled.
- const connectDeps = useRef<{ appId: string, userId: string }>({
- appId: '',
- userId: '',
- });
-
- useEffect(() => {
- logger?.info?.('SendbirdProvider | useConnect/useEffect', { userId, appId, accessToken });
-
- const isNewApp = connectDeps.current.appId !== appId;
- if (connectDeps.current.appId === appId && connectDeps.current.userId === userId) {
- return;
- } else {
- connectDeps.current = { appId, userId };
- }
-
- connect({
- userId,
- appId,
- isNewApp,
- accessToken,
- logger,
- nickname,
- profileUrl,
- configureSession,
- customApiHost,
- customWebSocketHost,
- sdk,
- sdkDispatcher,
- userDispatcher,
- appInfoDispatcher,
- initDashboardConfigs,
- isUserIdUsedForNickname,
- sdkInitParams,
- customExtensionParams,
- isMobile,
- eventHandlers,
- initializeMessageTemplatesInfo,
- }).catch(error => {
- logger?.error?.('SendbirdProvider | useConnect/useEffect', error);
- });
- }, [userId, appId]);
-
- const reconnect = useCallback(async () => {
- logger?.info?.('SendbirdProvider | useConnect/reconnect/useCallback', { sdk });
-
- try {
- await connect({
- userId,
- appId,
- accessToken,
- logger,
- nickname,
- profileUrl,
- configureSession,
- customApiHost,
- customWebSocketHost,
- sdk,
- sdkDispatcher,
- userDispatcher,
- appInfoDispatcher,
- initDashboardConfigs,
- isUserIdUsedForNickname,
- sdkInitParams,
- customExtensionParams,
- isMobile,
- eventHandlers,
- initializeMessageTemplatesInfo,
- });
- } catch (error) {
- logger?.error?.('SendbirdProvider | useConnect/reconnect/useCallback', error);
- }
- }, [sdk]);
- return reconnect;
-}
diff --git a/src/lib/hooks/useConnect/setupConnection.ts b/src/lib/hooks/useConnect/setupConnection.ts
deleted file mode 100644
index 1872aac25..000000000
--- a/src/lib/hooks/useConnect/setupConnection.ts
+++ /dev/null
@@ -1,238 +0,0 @@
-import SendbirdChat, {
- DeviceOsPlatform,
- SendbirdChatWith,
- SendbirdError,
- SendbirdErrorCode,
- SendbirdPlatform,
- SendbirdProduct,
- SessionHandler,
- User,
-} from '@sendbird/chat';
-import { OpenChannelModule } from '@sendbird/chat/openChannel';
-import { GroupChannelModule } from '@sendbird/chat/groupChannel';
-
-import { SDK_ACTIONS } from '../../dux/sdk/actionTypes';
-import { USER_ACTIONS } from '../../dux/user/actionTypes';
-
-import { isTextuallyNull } from '../../../utils';
-
-import { SetupConnectionTypes } from './types';
-import { CustomExtensionParams, SendbirdChatInitParams } from '../../types';
-import { LoggerInterface } from '../../Logger';
-
-const APP_VERSION_STRING = '__react_dev_mode__';
-
-const { INIT_SDK, SET_SDK_LOADING, RESET_SDK, SDK_ERROR } = SDK_ACTIONS;
-const { INIT_USER, UPDATE_USER_INFO, RESET_USER } = USER_ACTIONS;
-
-export function getMissingParamError({ userId, appId }: { userId?: string; appId?: string }): string {
- return `SendbirdProvider | useConnect/setupConnection/Connection failed UserId: ${userId} or appId: ${appId} missing`;
-}
-export function getConnectSbError(error?: SendbirdError): string {
- return `SendbirdProvider | useConnect/setupConnection/Connection failed. ${error?.code || ''} ${error?.message || ''}`;
-}
-
-export async function setUpConnection({
- logger,
- sdkDispatcher,
- userDispatcher,
- initDashboardConfigs,
- userId,
- appId,
- isNewApp,
- customApiHost,
- customWebSocketHost,
- configureSession,
- nickname,
- profileUrl,
- accessToken,
- isUserIdUsedForNickname,
- sdkInitParams,
- customExtensionParams,
- isMobile = false,
- eventHandlers,
- initializeMessageTemplatesInfo,
-}: SetupConnectionTypes): Promise {
- logger.info?.('SendbirdProvider | useConnect/setupConnection/init', { userId, appId });
- sdkDispatcher({ type: SET_SDK_LOADING, payload: true });
-
- if (!userId || !appId) {
- const errorMessage = getMissingParamError({ userId, appId });
- logger.error?.(errorMessage);
- sdkDispatcher({ type: SDK_ERROR });
- return Promise.reject(errorMessage);
- }
-
- return new Promise((resolve, reject) => {
- logger.info?.(`SendbirdProvider | useConnect/setupConnection/connect connecting using ${accessToken ?? userId}`);
-
- const sdk = initSDK({ appId, customApiHost, customWebSocketHost, isNewApp, sdkInitParams });
- const sessionHandler = typeof configureSession === 'function' ? configureSession(sdk) : undefined;
- setupSDK(sdk, { logger, sessionHandler, customExtensionParams, isMobile });
-
- sdk
- .connect(userId, accessToken)
- .then((user) => onConnected(user))
- .catch(async (error) => {
- // NOTE: The part that connects via the SDK must be callable directly by the customer.
- // we should refactor this in next major version.
- if (shouldRetryWithValidSessionToken(error) && sessionHandler) {
- try {
- const sessionToken = await new Promise(sessionHandler.onSessionTokenRequired);
- if (sessionToken) {
- logger.info?.(
- `SendbirdProvider | useConnect/setupConnection/connect retry connect with valid session token: ${sessionToken.slice(0, 10) + '...'}`,
- );
- const user = await sdk.connect(userId, sessionToken);
- return onConnected(user);
- }
- } catch (error) {
- // NOTE: Filter out the error from `onSessionTokenRequired`.
- if (error instanceof SendbirdError) {
- // connect in offline mode
- // if (sdk.isCacheEnabled && sdk.currentUser) return onConnected(sdk.currentUser);
- return onConnectFailed(error);
- }
- }
- }
-
- return onConnectFailed(error);
- });
-
- const onConnected = async (user: User) => {
- logger.info?.('SendbirdProvider | useConnect/setupConnection/onConnected', user);
- sdkDispatcher({ type: INIT_SDK, payload: sdk });
- userDispatcher({ type: INIT_USER, payload: user });
-
- try {
- await initializeMessageTemplatesInfo(sdk);
- } catch (error) {
- logger.error?.('SendbirdProvider | useConnect/setupConnection/upsertMessageTemplateListInLocalStorage failed', { error });
- }
-
- try {
- await initDashboardConfigs(sdk);
- logger.info?.('SendbirdProvider | useConnect/setupConnection/getUIKitConfiguration success');
- } catch (error) {
- logger.error?.('SendbirdProvider | useConnect/setupConnection/getUIKitConfiguration failed', { error });
- }
-
- try {
- // use nickname/profileUrl if provided or set userID as nickname
- if ((nickname !== user.nickname || profileUrl !== user.profileUrl) && !(isTextuallyNull(nickname) && isTextuallyNull(profileUrl))) {
- logger.info?.('SendbirdProvider | useConnect/setupConnection/updateCurrentUserInfo', { nickname, profileUrl });
- const updateParams = {
- nickname: nickname || user.nickname || (isUserIdUsedForNickname ? user.userId : ''),
- profileUrl: profileUrl || user.profileUrl,
- };
-
- const updatedUser = await sdk.updateCurrentUserInfo(updateParams);
- logger.info?.('SendbirdProvider | useConnect/setupConnection/updateCurrentUserInfo success', updateParams);
- userDispatcher({ type: UPDATE_USER_INFO, payload: updatedUser });
- }
- } catch {
- // NO-OP
- }
-
- resolve();
- eventHandlers?.connection?.onConnected?.(user);
- };
-
- const onConnectFailed = async (e: SendbirdError) => {
- if (sdk.isCacheEnabled && shouldClearCache(e)) {
- logger.error?.(`SendbirdProvider | useConnect/setupConnection/connect clear cache [${e.code}/${e.message}]`);
- await sdk.clearCachedData();
- }
-
- const errorMessage = getConnectSbError(e);
- logger.error?.(errorMessage, { e, appId, userId });
- userDispatcher({ type: RESET_USER });
- sdkDispatcher({ type: RESET_SDK });
- sdkDispatcher({ type: SDK_ERROR });
-
- reject(errorMessage);
- eventHandlers?.connection?.onFailed?.(e);
- };
- });
-}
-
-/**
- * Initializes the Sendbird SDK with the provided parameters.
- * */
-export function initSDK({
- appId,
- isNewApp = false,
- customApiHost,
- customWebSocketHost,
- sdkInitParams = {},
-}: {
- appId: string;
- isNewApp?: boolean;
- customApiHost?: string;
- customWebSocketHost?: string;
- sdkInitParams?: SendbirdChatInitParams;
- customExtensionParams?: CustomExtensionParams;
-}) {
- const params = Object.assign(sdkInitParams, {
- appId,
- modules: [new GroupChannelModule(), new OpenChannelModule()],
- newInstance: isNewApp,
- localCacheEnabled: true,
- });
-
- if (customApiHost) params.customApiHost = customApiHost;
- if (customWebSocketHost) params.customWebSocketHost = customWebSocketHost;
- return SendbirdChat.init(params);
-}
-
-/**
- * Sets up the Sendbird SDK after initialization.
- * Configures necessary settings, adds extensions, sets the platform, and configures the session handler if provided.
- */
-function setupSDK(
- sdk: SendbirdChatWith<[GroupChannelModule, OpenChannelModule]>,
- params: { logger: LoggerInterface; sessionHandler?: SessionHandler; isMobile?: boolean; customExtensionParams?: CustomExtensionParams },
-) {
- const { logger, sessionHandler, isMobile, customExtensionParams } = params;
-
- logger.info?.('SendbirdProvider | useConnect/setupConnection/setVersion', { version: APP_VERSION_STRING });
- sdk.addExtension('sb_uikit', APP_VERSION_STRING);
- sdk.addSendbirdExtensions(
- [{ product: SendbirdProduct.UIKIT_CHAT, version: APP_VERSION_STRING, platform: SendbirdPlatform?.JS }],
- { platform: isMobile ? DeviceOsPlatform.MOBILE_WEB : DeviceOsPlatform.WEB },
- customExtensionParams,
- );
- if (sessionHandler) {
- logger.info?.('SendbirdProvider | useConnect/setupConnection/configureSession', sessionHandler);
- sdk.setSessionHandler(sessionHandler);
- }
-}
-
-function shouldClearCache(error: unknown): error is SendbirdError {
- if (!(error instanceof SendbirdError)) return false;
-
- return [
- SendbirdErrorCode.USER_AUTH_DEACTIVATED,
- SendbirdErrorCode.USER_AUTH_DELETED_OR_NOT_FOUND,
- SendbirdErrorCode.SESSION_TOKEN_EXPIRED,
- SendbirdErrorCode.SESSION_REVOKED,
- ].includes(error.code);
-}
-
-function shouldRetryWithValidSessionToken(error: unknown): error is SendbirdError {
- if (!(error instanceof SendbirdError)) return false;
-
- return [
- SendbirdErrorCode.SESSION_TOKEN_EXPIRED,
- /**
- * Note: INVALID_TOKEN has been added arbitrarily due to legacy constraints
- *
- * In the useEffect of the useConnect hook, authentication is being performed
- * but changes of the `accessToken` is not being detected.
- * `disconnectSdk` is called when connect is called redundantly for the same user ID, causing issues, so `accessToken` has been excluded form the deps.
- *
- * In case the `accessToken` is missed, an additional attempt to connect is made
- * */
- SendbirdErrorCode.INVALID_TOKEN,
- ].includes(error.code);
-}
diff --git a/src/lib/hooks/useConnect/types.ts b/src/lib/hooks/useConnect/types.ts
deleted file mode 100644
index 0217cc7d1..000000000
--- a/src/lib/hooks/useConnect/types.ts
+++ /dev/null
@@ -1,58 +0,0 @@
-import SendbirdChat, { SessionHandler } from '@sendbird/chat';
-import { SendbirdGroupChat } from '@sendbird/chat/groupChannel';
-import { SendbirdOpenChat } from '@sendbird/chat/openChannel';
-
-import { SdkActionTypes } from '../../dux/sdk/actionTypes';
-import { UserActionTypes } from '../../dux/user/actionTypes';
-
-import { Logger } from '../../SendbirdState';
-
-import { SendbirdChatInitParams, CustomExtensionParams, SBUEventHandlers } from '../../types';
-import { AppInfoActionTypes } from '../../dux/appInfo/actionTypes';
-
-export type SdkDispatcher = React.Dispatch;
-export type UserDispatcher = React.Dispatch;
-export type AppInfoDispatcher = React.Dispatch;
-
-export type TriggerTypes = {
- userId: string;
- appId: string;
- // todo: doulbe check this type before merge
- accessToken?: string;
- isUserIdUsedForNickname?: boolean;
- isNewApp?: boolean;
- isMobile?: boolean;
-};
-
-export type ConfigureSessionTypes = (sdk: SendbirdChat | SendbirdGroupChat | SendbirdOpenChat) => SessionHandler;
-
-export type StaticTypes = {
- nickname: string;
- profileUrl: string;
- configureSession?: ConfigureSessionTypes;
- customApiHost?: string;
- customWebSocketHost?: string;
- sdk: SendbirdChat;
- logger: Logger;
- sdkDispatcher: SdkDispatcher;
- userDispatcher: UserDispatcher;
- appInfoDispatcher: AppInfoDispatcher;
- initDashboardConfigs: (sdk: SendbirdChat) => Promise;
- sdkInitParams?: SendbirdChatInitParams;
- customExtensionParams?: CustomExtensionParams;
- eventHandlers?: SBUEventHandlers;
- initializeMessageTemplatesInfo: (sdk: SendbirdChat) => Promise;
-};
-
-export type ConnectTypes = TriggerTypes & StaticTypes;
-
-export type SetupConnectionTypes = Omit;
-
-export type DisconnectSdkTypes = {
- sdkDispatcher: SdkDispatcher;
- userDispatcher: UserDispatcher;
- sdk: SendbirdChat;
- logger: Logger;
-};
-
-export type ReconnectType = () => void;
diff --git a/src/lib/hooks/useMarkAsDeliveredScheduler.ts b/src/lib/hooks/useMarkAsDeliveredScheduler.ts
index 15253787d..8881a5cdf 100644
--- a/src/lib/hooks/useMarkAsDeliveredScheduler.ts
+++ b/src/lib/hooks/useMarkAsDeliveredScheduler.ts
@@ -2,7 +2,7 @@ import { useEffect, useMemo } from 'react';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { schedulerFactory } from './schedulerFactory';
-import { Logger } from '../SendbirdState';
+import { Logger } from '../Sendbird/types';
import { useUnmount } from '../../hooks/useUnmount';
export type MarkAsDeliveredSchedulerType = {
@@ -30,7 +30,7 @@ export function useMarkAsDeliveredScheduler({
try {
await channel.markAsDelivered();
} catch (error) {
- logger.warning('Channel: Mark as delivered failed', { channel, error });
+ logger?.warning('Channel: Mark as delivered failed', { channel, error });
}
},
}), []);
diff --git a/src/lib/hooks/useMarkAsReadScheduler.ts b/src/lib/hooks/useMarkAsReadScheduler.ts
index f0d31bd96..3bd9c8cc7 100644
--- a/src/lib/hooks/useMarkAsReadScheduler.ts
+++ b/src/lib/hooks/useMarkAsReadScheduler.ts
@@ -2,7 +2,7 @@ import { useEffect, useMemo } from 'react';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { schedulerFactory } from './schedulerFactory';
-import { Logger } from '../SendbirdState';
+import type { Logger } from '../Sendbird/types';
import { useUnmount } from '../../hooks/useUnmount';
export type MarkAsReadSchedulerType = {
diff --git a/src/lib/hooks/useMessageTemplateUtils.ts b/src/lib/hooks/useMessageTemplateUtils.ts
index e0a6fef40..50907bfcc 100644
--- a/src/lib/hooks/useMessageTemplateUtils.ts
+++ b/src/lib/hooks/useMessageTemplateUtils.ts
@@ -1,19 +1,39 @@
-import React from 'react';
-import { AppInfoStateType, MessageTemplatesInfo, ProcessedMessageTemplate } from '../dux/appInfo/initialState';
-import { SendbirdMessageTemplate } from '../../ui/TemplateMessageItemBody/types';
-import { getProcessedTemplate, getProcessedTemplatesMap } from '../dux/appInfo/utils';
import SendbirdChat from '@sendbird/chat';
-import { APP_INFO_ACTIONS, AppInfoActionTypes } from '../dux/appInfo/actionTypes';
+import { AppInfoStateType, MessageTemplatesInfo, ProcessedMessageTemplate } from '../Sendbird/types';
+import { SendbirdMessageTemplate } from '../../ui/TemplateMessageItemBody/types';
import { CACHED_MESSAGE_TEMPLATES_KEY, CACHED_MESSAGE_TEMPLATES_TOKEN_KEY } from '../../utils/consts';
import { LoggerInterface } from '../Logger';
+import useSendbird from '../Sendbird/context/hooks/useSendbird';
+import { useCallback } from 'react';
const MESSAGE_TEMPLATES_FETCH_LIMIT = 20;
+/**
+ * Takes JSON parsed template and then returns processed message template for storing it in global state.
+ */
+export const getProcessedTemplate = (parsedTemplate: SendbirdMessageTemplate): ProcessedMessageTemplate => {
+ return {
+ version: Number(parsedTemplate.ui_template.version),
+ uiTemplate: JSON.stringify(parsedTemplate.ui_template.body.items),
+ colorVariables: parsedTemplate.color_variables,
+ };
+};
+
+export const getProcessedTemplatesMap = (
+ parsedTemplates: SendbirdMessageTemplate[],
+): Record => {
+ const processedTemplates = {};
+ parsedTemplates.forEach((template) => {
+ processedTemplates[template.key] = getProcessedTemplate(template);
+ });
+ return processedTemplates;
+};
+
interface UseMessageTemplateUtilsProps {
sdk: SendbirdChat,
logger: LoggerInterface,
appInfoStore: AppInfoStateType,
- appInfoDispatcher: React.Dispatch,
+ actions: ReturnType['actions'],
}
export interface UseMessageTemplateUtilsWrapper {
@@ -22,22 +42,15 @@ export interface UseMessageTemplateUtilsWrapper {
initializeMessageTemplatesInfo: (readySdk: SendbirdChat) => Promise;
}
-const {
- INITIALIZE_MESSAGE_TEMPLATES_INFO,
- UPSERT_MESSAGE_TEMPLATES,
- UPSERT_WAITING_TEMPLATE_KEYS,
- MARK_ERROR_WAITING_TEMPLATE_KEYS,
-} = APP_INFO_ACTIONS;
-
export default function useMessageTemplateUtils({
sdk,
logger,
appInfoStore,
- appInfoDispatcher,
+ actions,
}: UseMessageTemplateUtilsProps): UseMessageTemplateUtilsWrapper {
const messageTemplatesInfo: MessageTemplatesInfo | undefined = appInfoStore?.messageTemplatesInfo;
- const getCachedTemplate = (key: string): ProcessedMessageTemplate | null => {
+ const getCachedTemplate = useCallback((key: string): ProcessedMessageTemplate | null => {
if (!messageTemplatesInfo) return null;
let cachedTemplate: ProcessedMessageTemplate | null = null;
@@ -46,7 +59,7 @@ export default function useMessageTemplateUtils({
cachedTemplate = cachedMessageTemplates[key] ?? null;
}
return cachedTemplate;
- };
+ }, [appInfoStore?.messageTemplatesInfo]);
/**
* Fetches a single message template by given key and then
@@ -107,7 +120,7 @@ export default function useMessageTemplateUtils({
token: sdkMessageTemplateToken,
templatesMap: getProcessedTemplatesMap(parsedTemplates),
};
- appInfoDispatcher({ type: INITIALIZE_MESSAGE_TEMPLATES_INFO, payload: newMessageTemplatesInfo });
+ actions.initMessageTemplateInfo({ payload: newMessageTemplatesInfo });
localStorage.setItem(CACHED_MESSAGE_TEMPLATES_TOKEN_KEY, sdkMessageTemplateToken);
localStorage.setItem(CACHED_MESSAGE_TEMPLATES_KEY, JSON.stringify(parsedTemplates));
} else if (
@@ -120,7 +133,7 @@ export default function useMessageTemplateUtils({
token: sdkMessageTemplateToken,
templatesMap: getProcessedTemplatesMap(parsedTemplates),
};
- appInfoDispatcher({ type: INITIALIZE_MESSAGE_TEMPLATES_INFO, payload: newMessageTemplatesInfo });
+ actions.initMessageTemplateInfo({ payload: newMessageTemplatesInfo });
}
};
@@ -128,72 +141,64 @@ export default function useMessageTemplateUtils({
* If given message is a template message with template key and if the key does not exist in the cache,
* update the cache by fetching the template.
*/
- const updateMessageTemplatesInfo = async (
+ const updateMessageTemplatesInfo = useCallback(async (
templateKeys: string[],
messageId: number,
requestedAt: number,
): Promise => {
- if (appInfoDispatcher) {
- appInfoDispatcher({
- type: UPSERT_WAITING_TEMPLATE_KEYS,
- payload: {
+ actions.upsertWaitingTemplateKeys({ keys: templateKeys, requestedAt } as any);
+ const newParsedTemplates: SendbirdMessageTemplate[] | null = [];
+ try {
+ let hasMore = true;
+ let token = null;
+ while (hasMore) {
+ const result = await sdk.message.getMessageTemplatesByToken(token, {
keys: templateKeys,
- requestedAt,
- },
- });
- const newParsedTemplates: SendbirdMessageTemplate[] | null = [];
- try {
- let hasMore = true;
- let token = null;
- while (hasMore) {
- const result = await sdk.message.getMessageTemplatesByToken(token, {
- keys: templateKeys,
- });
- result.templates.forEach((newTemplate) => {
- newParsedTemplates.push(JSON.parse(newTemplate.template));
- });
- hasMore = result.hasMore;
- token = result.token;
- }
- } catch (e) {
- logger?.error?.('Sendbird | fetchProcessedMessageTemplates failed', e, templateKeys);
+ });
+ result.templates.forEach((newTemplate) => {
+ newParsedTemplates.push(JSON.parse(newTemplate.template));
+ });
+ hasMore = result.hasMore;
+ token = result.token;
}
- if (newParsedTemplates.length > 0) {
- // Update cache
- const cachedMessageTemplates: string | null = localStorage.getItem(CACHED_MESSAGE_TEMPLATES_KEY);
- if (cachedMessageTemplates) {
- const parsedTemplates: SendbirdMessageTemplate[] = JSON.parse(cachedMessageTemplates);
- const existingKeys = parsedTemplates.map((parsedTemplate) => parsedTemplate.key);
- newParsedTemplates.forEach((newParsedTemplate) => {
- if (!existingKeys.includes(newParsedTemplate.key)) {
- parsedTemplates.push(newParsedTemplate);
- }
- });
- localStorage.setItem(CACHED_MESSAGE_TEMPLATES_KEY, JSON.stringify(parsedTemplates));
- } else {
- localStorage.setItem(CACHED_MESSAGE_TEMPLATES_KEY, JSON.stringify([newParsedTemplates]));
- }
- // Update memory
- appInfoDispatcher({
- type: UPSERT_MESSAGE_TEMPLATES,
- payload: newParsedTemplates.map((newParsedTemplate) => {
- return {
- key: newParsedTemplate.key,
- template: getProcessedTemplate(newParsedTemplate),
- };
- }),
+ } catch (e) {
+ logger?.error?.('Sendbird | fetchProcessedMessageTemplates failed', e, templateKeys);
+ }
+ if (newParsedTemplates.length > 0) {
+ // Update cache
+ const cachedMessageTemplates: string | null = localStorage.getItem(CACHED_MESSAGE_TEMPLATES_KEY);
+ if (cachedMessageTemplates) {
+ const parsedTemplates: SendbirdMessageTemplate[] = JSON.parse(cachedMessageTemplates);
+ const existingKeys = parsedTemplates.map((parsedTemplate) => parsedTemplate.key);
+ newParsedTemplates.forEach((newParsedTemplate) => {
+ if (!existingKeys.includes(newParsedTemplate.key)) {
+ parsedTemplates.push(newParsedTemplate);
+ }
});
+ localStorage.setItem(CACHED_MESSAGE_TEMPLATES_KEY, JSON.stringify(parsedTemplates));
} else {
- appInfoDispatcher({
- type: MARK_ERROR_WAITING_TEMPLATE_KEYS,
- payload: {
- keys: templateKeys,
- messageId,
- },
- });
+ localStorage.setItem(CACHED_MESSAGE_TEMPLATES_KEY, JSON.stringify([newParsedTemplates]));
}
+ // Update memory
+ actions.upsertMessageTemplates({
+ payload: newParsedTemplates.map((newParsedTemplate) => {
+ return {
+ key: newParsedTemplate.key,
+ template: getProcessedTemplate(newParsedTemplate),
+ };
+ }),
+ } as any);
+ } else {
+ actions.markErrorWaitingTemplateKeys({
+ keys: templateKeys,
+ messageId,
+ } as any);
}
- };
+ }, [
+ actions.upsertMessageTemplates,
+ actions.upsertWaitingTemplateKeys,
+ sdk.message?.getMessageTemplatesByToken,
+ ]);
return {
getCachedTemplate,
updateMessageTemplatesInfo,
diff --git a/src/lib/selectors.ts b/src/lib/selectors.ts
index 6f33e11b9..d46826a81 100644
--- a/src/lib/selectors.ts
+++ b/src/lib/selectors.ts
@@ -11,10 +11,10 @@ import { FileMessage, FileMessageCreateParams, SendableMessage, UserMessageUpdat
import {
SdkStore,
- SendBirdState,
- SendBirdStateConfig,
- SendBirdStateStore,
-} from './types';
+ SendbirdState,
+ SendbirdStateConfig,
+ SendbirdStateStore,
+} from './Sendbird/types';
import { noop } from '../utils/utils';
import { SendableMessageType } from '../utils';
import { PublishingModuleType } from '../modules/internalInterfaces';
@@ -58,9 +58,9 @@ import { PublishingModuleType } from '../modules/internalInterfaces';
/**
* const sdk = selectors.getSdk(state);
*/
-export const getSdk = (state: SendBirdState) => {
+export const getSdk = (state: SendbirdState) => {
const { stores = {} } = state;
- const { sdkStore = {} } = stores as SendBirdStateStore;
+ const { sdkStore = {} } = stores as SendbirdStateStore;
const { sdk } = sdkStore as SdkStore;
return sdk;
};
@@ -68,9 +68,9 @@ export const getSdk = (state: SendBirdState) => {
/**
* const pubSub = selectors.getPubSub(state);
*/
-export const getPubSub = (state: SendBirdState) => {
+export const getPubSub = (state: SendbirdState) => {
const { config = {} } = state;
- const { pubSub } = config as SendBirdStateConfig;
+ const { pubSub } = config as SendbirdStateConfig;
return pubSub;
};
@@ -82,7 +82,7 @@ export const getPubSub = (state: SendBirdState) => {
* .then((user) => {})
* .catch((error) => {})
*/
-export const getConnect = (state: SendBirdState) => (
+export const getConnect = (state: SendbirdState) => (
(userId: string, accessToken?: string): Promise => (
new Promise((resolve, reject) => {
const sdk = getSdk(state);
@@ -111,7 +111,7 @@ export const getConnect = (state: SendBirdState) => (
* .then(() => {})
* .catch((error) => {})
*/
-export const getDisconnect = (state: SendBirdState) => (
+export const getDisconnect = (state: SendbirdState) => (
(): Promise => (
new Promise((resolve, reject) => {
const sdk = getSdk(state);
@@ -134,7 +134,7 @@ export const getDisconnect = (state: SendBirdState) => (
* .then((user) => {})
* .catch((error) => {})
*/
-export const getUpdateUserInfo = (state: SendBirdState) => (
+export const getUpdateUserInfo = (state: SendbirdState) => (
(nickname: string, profileUrl?: string): Promise => (
new Promise((resolve, reject) => {
const sdk = getSdk(state);
@@ -163,7 +163,7 @@ export const getUpdateUserInfo = (state: SendBirdState) => (
* .then((channel) => {})
* .catch((error) => {})
*/
-export const getCreateGroupChannel = (state: SendBirdState) => (
+export const getCreateGroupChannel = (state: SendbirdState) => (
(params: GroupChannelCreateParams): Promise => (
new Promise((resolve, reject) => {
const sdk = getSdk(state);
@@ -196,7 +196,7 @@ export const getCreateGroupChannel = (state: SendBirdState) => (
* .then((channel) => {})
* .catch((error) => {})
*/
-export const getCreateOpenChannel = (state: SendBirdState) => (
+export const getCreateOpenChannel = (state: SendbirdState) => (
(params: OpenChannelCreateParams): Promise => (
new Promise((resolve, reject) => {
const sdk = getSdk(state);
@@ -230,7 +230,7 @@ export const getCreateOpenChannel = (state: SendBirdState) => (
* })
* .catch((error) => {})
*/
-export const getGetGroupChannel = (state: SendBirdState) => (
+export const getGetGroupChannel = (state: SendbirdState) => (
(channelUrl: string): Promise => (
new Promise((resolve, reject) => {
const sdk = getSdk(state);
@@ -264,7 +264,7 @@ export const getGetGroupChannel = (state: SendBirdState) => (
* })
* .catch((error) => {})
*/
-export const getGetOpenChannel = (state: SendBirdState) => (
+export const getGetOpenChannel = (state: SendbirdState) => (
(channelUrl: string): Promise => (
new Promise((resolve, reject) => {
const sdk = getSdk(state);
@@ -294,7 +294,7 @@ export const getGetOpenChannel = (state: SendBirdState) => (
* .then((channel) => {})
* .catch((error) => {})
*/
-export const getLeaveGroupChannel = (state: SendBirdState) => (
+export const getLeaveGroupChannel = (state: SendbirdState) => (
(channelUrl: string): Promise => (
new Promise((resolve, reject) => {
getGetGroupChannel(state)?.(channelUrl)
@@ -317,7 +317,7 @@ export const getLeaveGroupChannel = (state: SendBirdState) => (
* .then((channel) => {})
* .catch((error) => {})
*/
-export const getEnterOpenChannel = (state: SendBirdState) => (
+export const getEnterOpenChannel = (state: SendbirdState) => (
(channelUrl: string): Promise => (
new Promise((resolve, reject) => {
getGetOpenChannel(state)?.(channelUrl)
@@ -340,7 +340,7 @@ export const getEnterOpenChannel = (state: SendBirdState) => (
* .then((channel) => {})
* .catch((error) => {})
*/
-export const getExitOpenChannel = (state: SendBirdState) => (
+export const getExitOpenChannel = (state: SendbirdState) => (
(channelUrl: string): Promise => (
new Promise((resolve, reject) => {
getGetOpenChannel(state)?.(channelUrl)
@@ -462,7 +462,7 @@ export class UikitMessageHandler {
* .onSucceeded((message) => {})
*/
-export const getSendUserMessage = (state: SendBirdState, publishingModules: PublishingModuleType[] = []) => (
+export const getSendUserMessage = (state: SendbirdState, publishingModules: PublishingModuleType[] = []) => (
(channel: GroupChannel | OpenChannel, params: UserMessageCreateParams): UikitMessageHandler => {
const handler = new UikitMessageHandler();
const pubSub = getPubSub(state);
@@ -502,7 +502,7 @@ export const getSendUserMessage = (state: SendBirdState, publishingModules: Publ
* .onFailed((error, message) => {})
* .onSucceeded((message) => {})
*/
-export const getSendFileMessage = (state: SendBirdState, publishingModules: PublishingModuleType[] = []) => (
+export const getSendFileMessage = (state: SendbirdState, publishingModules: PublishingModuleType[] = []) => (
(channel: GroupChannel | OpenChannel, params: FileMessageCreateParams): UikitMessageHandler => {
const handler = new UikitMessageHandler();
const pubSub = getPubSub(state);
@@ -542,7 +542,7 @@ export const getSendFileMessage = (state: SendBirdState, publishingModules: Publ
* .then((message) => {})
* .catch((error) => {})
*/
-export const getUpdateUserMessage = (state: SendBirdState, publishingModules: PublishingModuleType[] = []) => (
+export const getUpdateUserMessage = (state: SendbirdState, publishingModules: PublishingModuleType[] = []) => (
(channel: GroupChannel | OpenChannel, messageId: number, params: UserMessageUpdateParams): Promise => (
new Promise((resolve, reject) => {
const pubSub = getPubSub(state);
@@ -570,7 +570,7 @@ export const getUpdateUserMessage = (state: SendBirdState, publishingModules: Pu
* .then((message) => {})
* .catch((error) => {})
*/
-// const getUpdateFileMessage = (state: SendBirdState) => (
+// const getUpdateFileMessage = (state: SendbirdState) => (
// (channel: GroupChannel | OpenChannel, messageId: number, params: FileMessageUpdateParams) => (
// new Promise((resolve, reject) => {
// const pubSub = getPubSub(state);
@@ -596,7 +596,7 @@ export const getUpdateUserMessage = (state: SendBirdState, publishingModules: Pu
* .then((deletedMessage) => {})
* .catch((error) => {})
*/
-export const getDeleteMessage = (state: SendBirdState) => (
+export const getDeleteMessage = (state: SendbirdState) => (
(channel: GroupChannel | OpenChannel, message: SendableMessageType): Promise => (
new Promise((resolve, reject) => {
const pubSub = getPubSub(state);
@@ -623,7 +623,7 @@ export const getDeleteMessage = (state: SendBirdState) => (
* .then(() => {})
* .catch((error) => {})
*/
-export const getResendUserMessage = (state: SendBirdState, publishingModules: PublishingModuleType[] = []) => (
+export const getResendUserMessage = (state: SendbirdState, publishingModules: PublishingModuleType[] = []) => (
(channel: GroupChannel | OpenChannel, failedMessage: UserMessage): Promise => (
new Promise((resolve, reject) => {
const pubSub = getPubSub(state);
@@ -650,7 +650,7 @@ export const getResendUserMessage = (state: SendBirdState, publishingModules: Pu
* .then(() => {})
* .catch((error) => {})
*/
-export const getResendFileMessage = (state: SendBirdState, publishingModules: PublishingModuleType[] = []) => (
+export const getResendFileMessage = (state: SendbirdState, publishingModules: PublishingModuleType[] = []) => (
(channel: GroupChannel | OpenChannel, failedMessage: FileMessage, blob: Blob): Promise => (
new Promise((resolve, reject) => {
const pubSub = getPubSub(state);
diff --git a/src/lib/types.ts b/src/lib/types.ts
deleted file mode 100644
index ae4b57d05..000000000
--- a/src/lib/types.ts
+++ /dev/null
@@ -1,316 +0,0 @@
-import React from 'react';
-import type SendbirdChat from '@sendbird/chat';
-import type { User, SendbirdChatParams, SendbirdError } from '@sendbird/chat';
-
-import type {
- GroupChannel,
- GroupChannelCreateParams,
- GroupChannelModule,
-} from '@sendbird/chat/groupChannel';
-import type {
- OpenChannel,
- OpenChannelCreateParams,
- OpenChannelModule,
-} from '@sendbird/chat/openChannel';
-import type {
- FileMessage,
- FileMessageCreateParams,
- UserMessage,
- UserMessageCreateParams,
- UserMessageUpdateParams,
-} from '@sendbird/chat/message';
-import { SBUConfig } from '@sendbird/uikit-tools';
-import { Module, ModuleNamespaces } from '@sendbird/chat/lib/__definition';
-
-import type {
- HTMLTextDirection,
- RenderUserProfileProps,
- ReplyType,
- UserListQuery,
-} from '../types';
-import type { ImageCompressionOptions } from './Sendbird';
-import { UikitMessageHandler } from './selectors';
-import { Logger } from './SendbirdState';
-import { MarkAsReadSchedulerType } from './hooks/useMarkAsReadScheduler';
-import { MarkAsDeliveredSchedulerType } from './hooks/useMarkAsDeliveredScheduler';
-import { PartialDeep } from '../utils/typeHelpers/partialDeep';
-import { CoreMessageType } from '../utils';
-import { UserActionTypes } from './dux/user/actionTypes';
-import { SdkActionTypes } from './dux/sdk/actionTypes';
-import { ReconnectType } from './hooks/useConnect/types';
-import { SBUGlobalPubSub } from './pubSub/topics';
-import { EmojiManager } from './emojiManager';
-import { MessageTemplatesInfo, ProcessedMessageTemplate, WaitingTemplateKeyData } from './dux/appInfo/initialState';
-import { AppInfoActionTypes } from './dux/appInfo/actionTypes';
-
-// note to SDK team:
-// using enum inside .d.ts won’t work for jest, but const enum will work.
-export const Role = {
- OPERATOR: 'operator',
- NONE: 'none',
-} as const;
-
-export interface SBUEventHandlers {
- reaction?: {
- onPressUserProfile?(member: User): void;
- },
- connection?: {
- onConnected?(user: User): void;
- onFailed?(error: SendbirdError): void;
- },
- modal?: {
- onMounted?(params: { id: string; close(): void; }): void | (() => void);
- };
- message?: {
- onSendMessageFailed?: (message: CoreMessageType, error: unknown) => void;
- onUpdateMessageFailed?: (message: CoreMessageType, error: unknown) => void;
- onFileUploadFailed?: (error: unknown) => void;
- }
-}
-
-export interface SendBirdStateConfig {
- renderUserProfile?: (props: RenderUserProfileProps) => React.ReactElement;
- onStartDirectMessage?: (props: GroupChannel) => void;
- allowProfileEdit: boolean;
- isOnline: boolean;
- userId: string;
- appId: string;
- accessToken?: string;
- theme: string;
- htmlTextDirection: HTMLTextDirection;
- forceLeftToRightMessageLayout: boolean;
- pubSub: SBUGlobalPubSub;
- logger: Logger;
- setCurrentTheme: (theme: 'light' | 'dark') => void;
- userListQuery?: () => UserListQuery;
- uikitUploadSizeLimit: number;
- uikitMultipleFilesMessageLimit: number;
- voiceRecord: {
- maxRecordingTime: number;
- minRecordingTime: number;
- };
- userMention: {
- maxMentionCount: number,
- maxSuggestionCount: number,
- };
- imageCompression: ImageCompressionOptions;
- markAsReadScheduler: MarkAsReadSchedulerType;
- markAsDeliveredScheduler: MarkAsDeliveredSchedulerType;
- disableMarkAsDelivered: boolean;
- isMultipleFilesMessageEnabled: boolean;
- // Remote configs set from dashboard by UIKit feature configuration
- common: {
- enableUsingDefaultUserProfile: SBUConfig['common']['enableUsingDefaultUserProfile'];
- },
- groupChannel: {
- enableOgtag: SBUConfig['groupChannel']['channel']['enableOgtag'];
- enableTypingIndicator: SBUConfig['groupChannel']['channel']['enableTypingIndicator'];
- enableReactions: SBUConfig['groupChannel']['channel']['enableReactions'];
- enableMention: SBUConfig['groupChannel']['channel']['enableMention'];
- replyType: SBUConfig['groupChannel']['channel']['replyType'];
- threadReplySelectType: SBUConfig['groupChannel']['channel']['threadReplySelectType'];
- enableVoiceMessage: SBUConfig['groupChannel']['channel']['enableVoiceMessage'];
- typingIndicatorTypes: SBUConfig['groupChannel']['channel']['typingIndicatorTypes'];
- enableDocument: SBUConfig['groupChannel']['channel']['input']['enableDocument'];
- enableFeedback: SBUConfig['groupChannel']['channel']['enableFeedback'];
- enableSuggestedReplies: SBUConfig['groupChannel']['channel']['enableSuggestedReplies'];
- showSuggestedRepliesFor: SBUConfig['groupChannel']['channel']['showSuggestedRepliesFor'];
- suggestedRepliesDirection: SBUConfig['groupChannel']['channel']['suggestedRepliesDirection'];
- enableMarkdownForUserMessage: SBUConfig['groupChannel']['channel']['enableMarkdownForUserMessage'];
- enableFormTypeMessage: SBUConfig['groupChannel']['channel']['enableFormTypeMessage'];
- /**
- * @deprecated Currently, this feature is turned off by default. If you wish to use this feature, contact us: {@link https://dashboard.sendbird.com/settings/contact_us?category=feedback_and_feature_requests&product=UIKit}
- */
- enableReactionsSupergroup: never;
- },
- groupChannelList: {
- enableTypingIndicator: SBUConfig['groupChannel']['channelList']['enableTypingIndicator'];
- enableMessageReceiptStatus: SBUConfig['groupChannel']['channelList']['enableMessageReceiptStatus'];
- },
- groupChannelSettings: {
- enableMessageSearch: SBUConfig['groupChannel']['setting']['enableMessageSearch'];
- },
- openChannel: {
- enableOgtag: SBUConfig['openChannel']['channel']['enableOgtag'];
- enableDocument: SBUConfig['openChannel']['channel']['input']['enableDocument'];
- },
- /**
- * @deprecated Please use `onStartDirectMessage` instead. It's renamed.
- */
- onUserProfileMessage?: (props: GroupChannel) => void;
- /**
- * @deprecated Please use `!config.common.enableUsingDefaultUserProfile` instead.
- * Note that you should use the negation of `config.common.enableUsingDefaultUserProfile`
- * to replace `disableUserProfile`.
- */
- disableUserProfile: boolean;
- /** @deprecated Please use `config.groupChannel.enableReactions` instead * */
- isReactionEnabled: boolean;
- /** @deprecated Please use `config.groupChannel.enableMention` instead * */
- isMentionEnabled: boolean;
- /** @deprecated Please use `config.groupChannel.enableVoiceMessage` instead * */
- isVoiceMessageEnabled?: boolean;
- /** @deprecated Please use `config.groupChannel.replyType` instead * */
- replyType: ReplyType;
- /** @deprecated Please use `config.groupChannelSettings.enableMessageSearch` instead * */
- showSearchIcon?: boolean;
- /** @deprecated Please use `config.groupChannelList.enableTypingIndicator` instead * */
- isTypingIndicatorEnabledOnChannelList?: boolean;
- /** @deprecated Please use `config.groupChannelList.enableMessageReceiptStatus` instead * */
- isMessageReceiptStatusEnabledOnChannelList?: boolean;
- /** @deprecated Please use setCurrentTheme instead * */
- setCurrenttheme: (theme: 'light' | 'dark') => void;
-}
-
-export type SendbirdChatType = SendbirdChat & ModuleNamespaces<[GroupChannelModule, OpenChannelModule]>;
-export interface SdkStore {
- error: boolean;
- initialized: boolean;
- loading: boolean;
- sdk: SendbirdChatType;
-}
-
-export interface UserStore {
- initialized: boolean;
- loading: boolean;
- user: User;
-}
-
-export interface AppInfoStore {
- messageTemplatesInfo?: MessageTemplatesInfo;
- waitingTemplateKeysMap: Record;
-}
-
-export interface SendBirdStateStore {
- sdkStore: SdkStore;
- userStore: UserStore;
- appInfoStore: AppInfoStore;
-}
-
-export type SendBirdState = {
- config: SendBirdStateConfig;
- stores: SendBirdStateStore;
- dispatchers: {
- sdkDispatcher: React.Dispatch,
- userDispatcher: React.Dispatch,
- appInfoDispatcher: React.Dispatch,
- reconnect: ReconnectType,
- },
- // Customer provided callbacks
- eventHandlers?: SBUEventHandlers;
- emojiManager: EmojiManager;
- utils: SendbirdProviderUtils;
-};
-
-type GetSdk = SendbirdChat | undefined;
-type GetConnect = (
- userId: string,
- accessToken?: string
-) => Promise;
-type GetDisconnect = () => Promise;
-type GetUpdateUserInfo = (
- nickName: string,
- profileUrl?: string
-) => Promise;
-type GetCreateGroupChannel = (channelParams: GroupChannelCreateParams) => Promise;
-type GetCreateOpenChannel = (channelParams: OpenChannelCreateParams) => Promise;
-type GetGetGroupChannel = (
- channelUrl: string,
- isSelected?: boolean,
-) => Promise;
-type GetGetOpenChannel = (
- channelUrl: string,
-) => Promise;
-type GetLeaveGroupChannel = (channel: GroupChannel) => Promise;
-type GetEnterOpenChannel = (channel: OpenChannel) => Promise;
-type GetExitOpenChannel = (channel: OpenChannel) => Promise;
-type GetFreezeChannel = (channel: GroupChannel | OpenChannel) => Promise;
-type GetUnFreezeChannel = (channel: GroupChannel | OpenChannel) => Promise;
-type GetSendUserMessage = (
- channel: GroupChannel | OpenChannel,
- userMessageParams: UserMessageCreateParams,
-) => UikitMessageHandler;
-type GetSendFileMessage = (
- channel: GroupChannel | OpenChannel,
- fileMessageParams: FileMessageCreateParams
-) => UikitMessageHandler;
-type GetUpdateUserMessage = (
- channel: GroupChannel | OpenChannel,
- messageId: string | number,
- params: UserMessageUpdateParams
-) => Promise;
-// type getUpdateFileMessage = (
-// channel: GroupChannel | OpenChannel,
-// messageId: string | number,
-// params: FileMessageUpdateParams,
-// ) => Promise;
-type GetDeleteMessage = (
- channel: GroupChannel | OpenChannel,
- message: CoreMessageType
-) => Promise;
-type GetResendUserMessage = (
- channel: GroupChannel | OpenChannel,
- failedMessage: UserMessage
-) => Promise;
-type GetResendFileMessage = (
- channel: GroupChannel | OpenChannel,
- failedMessage: FileMessage
-) => Promise;
-
-export interface sendbirdSelectorsInterface {
- getSdk: (store: SendBirdState) => GetSdk;
- getConnect: (store: SendBirdState) => GetConnect
- getDisconnect: (store: SendBirdState) => GetDisconnect;
- getUpdateUserInfo: (store: SendBirdState) => GetUpdateUserInfo;
- getCreateGroupChannel: (store: SendBirdState) => GetCreateGroupChannel;
- getCreateOpenChannel: (store: SendBirdState) => GetCreateOpenChannel;
- getGetGroupChannel: (store: SendBirdState) => GetGetGroupChannel;
- getGetOpenChannel: (store: SendBirdState) => GetGetOpenChannel;
- getLeaveGroupChannel: (store: SendBirdState) => GetLeaveGroupChannel;
- getEnterOpenChannel: (store: SendBirdState) => GetEnterOpenChannel;
- getExitOpenChannel: (store: SendBirdState) => GetExitOpenChannel;
- getFreezeChannel: (store: SendBirdState) => GetFreezeChannel;
- getUnFreezeChannel: (store: SendBirdState) => GetUnFreezeChannel;
- getSendUserMessage: (store: SendBirdState) => GetSendUserMessage;
- getSendFileMessage: (store: SendBirdState) => GetSendFileMessage;
- getUpdateUserMessage: (store: SendBirdState) => GetUpdateUserMessage;
- // getUpdateFileMessage: (store: SendBirdState) => GetUpdateFileMessage;
- getDeleteMessage: (store: SendBirdState) => GetDeleteMessage;
- getResendUserMessage: (store: SendBirdState) => GetResendUserMessage;
- getResendFileMessage: (store: SendBirdState) => GetResendFileMessage;
-}
-
-export interface CommonUIKitConfigProps {
- /** @deprecated Please use `uikitOptions.common.enableUsingDefaultUserProfile` instead * */
- disableUserProfile?: boolean;
- /** @deprecated Please use `uikitOptions.groupChannel.replyType` instead * */
- replyType?: 'NONE' | 'QUOTE_REPLY' | 'THREAD';
- /** @deprecated Please use `uikitOptions.groupChannel.enableReactions` instead * */
- isReactionEnabled?: boolean;
- /** @deprecated Please use `uikitOptions.groupChannel.enableMention` instead * */
- isMentionEnabled?: boolean;
- /** @deprecated Please use `uikitOptions.groupChannel.enableVoiceMessage` instead * */
- isVoiceMessageEnabled?: boolean;
- /** @deprecated Please use `uikitOptions.groupChannelList.enableTypingIndicator` instead * */
- isTypingIndicatorEnabledOnChannelList?: boolean;
- /** @deprecated Please use `uikitOptions.groupChannelList.enableMessageReceiptStatus` instead * */
- isMessageReceiptStatusEnabledOnChannelList?: boolean;
- /** @deprecated Please use `uikitOptions.groupChannelSettings.enableMessageSearch` instead * */
- showSearchIcon?: boolean;
-}
-
-export type UIKitOptions = PartialDeep<{
- common: SBUConfig['common'];
- groupChannel: SBUConfig['groupChannel']['channel'];
- groupChannelList: SBUConfig['groupChannel']['channelList'];
- groupChannelSettings: SBUConfig['groupChannel']['setting'];
- openChannel: SBUConfig['openChannel']['channel'];
-}>;
-
-export type SendbirdChatInitParams = Omit, 'appId'>;
-export type CustomExtensionParams = Record;
-
-export type SendbirdProviderUtils = {
- updateMessageTemplatesInfo: (templateKeys: string[], messageId: number, createdAt: number) => Promise;
- getCachedTemplate: (key: string) => ProcessedMessageTemplate | null;
-};
diff --git a/src/lib/utils/__tests__/uikitConfigMapper.spec.ts b/src/lib/utils/__tests__/uikitConfigMapper.spec.ts
index 5171b6632..e9160db99 100644
--- a/src/lib/utils/__tests__/uikitConfigMapper.spec.ts
+++ b/src/lib/utils/__tests__/uikitConfigMapper.spec.ts
@@ -1,6 +1,6 @@
+import type { CommonUIKitConfigProps, UIKitOptions } from '../../Sendbird/types';
import { getCaseResolvedReplyType } from '../resolvedReplyType';
import { uikitConfigMapper } from '../uikitConfigMapper';
-import { CommonUIKitConfigProps, UIKitOptions } from '../../types';
const mockLegacyConfig = {
// common related
diff --git a/src/lib/utils/uikitConfigMapper.ts b/src/lib/utils/uikitConfigMapper.ts
index 574dfc017..9ecdbb471 100644
--- a/src/lib/utils/uikitConfigMapper.ts
+++ b/src/lib/utils/uikitConfigMapper.ts
@@ -1,4 +1,4 @@
-import { UIKitOptions, CommonUIKitConfigProps } from '../types';
+import type { UIKitOptions, CommonUIKitConfigProps } from '../Sendbird/types';
import { getCaseResolvedReplyType } from './resolvedReplyType';
export function uikitConfigMapper({
diff --git a/src/modules/App/AppLayout.tsx b/src/modules/App/AppLayout.tsx
index 62aa7e252..c0d160011 100644
--- a/src/modules/App/AppLayout.tsx
+++ b/src/modules/App/AppLayout.tsx
@@ -6,9 +6,9 @@ import { useMediaQueryContext } from '../../lib/MediaQueryContext';
import { DesktopLayout } from './DesktopLayout';
import { MobileLayout } from './MobileLayout';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { SendableMessageType } from '../../utils';
import { getCaseResolvedReplyType } from '../../lib/utils/resolvedReplyType';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
export const AppLayout = (props: AppLayoutProps) => {
const {
@@ -21,8 +21,8 @@ export const AppLayout = (props: AppLayoutProps) => {
enableLegacyChannelModules,
} = props;
- const globalStore = useSendbirdStateContext();
- const globalConfigs = globalStore.config;
+ const { state } = useSendbird();
+ const globalConfigs = state.config;
const [showThread, setShowThread] = useState(false);
const [threadTargetMessage, setThreadTargetMessage] = useState(null);
diff --git a/src/modules/App/MobileLayout.tsx b/src/modules/App/MobileLayout.tsx
index fae2ee3bc..c1766fe8c 100644
--- a/src/modules/App/MobileLayout.tsx
+++ b/src/modules/App/MobileLayout.tsx
@@ -13,11 +13,11 @@ import ChannelList from '../ChannelList';
import ChannelSettings from '../ChannelSettings';
import MessageSearch from '../MessageSearch';
import Thread from '../Thread';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import uuidv4 from '../../utils/uuid';
import { ALL, useVoicePlayerContext } from '../../hooks/VoicePlayer';
import { SendableMessageType } from '../../utils';
import { APP_LAYOUT_ROOT } from './const';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
enum PANELS {
CHANNEL_LIST = 'CHANNEL_LIST',
@@ -48,7 +48,7 @@ export const MobileLayout: React.FC = (props: MobileLayoutPro
} = props;
const [panel, setPanel] = useState(PANELS.CHANNEL_LIST);
- const store = useSendbirdStateContext();
+ const { state: store } = useSendbird();
const sdk = store?.stores?.sdkStore?.sdk;
const userId = store?.config?.userId;
diff --git a/src/modules/App/types.ts b/src/modules/App/types.ts
index 2fe213a97..7d7db6baf 100644
--- a/src/modules/App/types.ts
+++ b/src/modules/App/types.ts
@@ -8,7 +8,7 @@ import {
SendBirdProviderConfig,
HTMLTextDirection,
} from '../../types';
-import { CustomExtensionParams, SBUEventHandlers, SendbirdChatInitParams } from '../../lib/types';
+import { CustomExtensionParams, SBUEventHandlers, SendbirdChatInitParams } from '../../lib/Sendbird/types';
import { SendableMessageType } from '../../utils';
export interface AppLayoutProps {
diff --git a/src/modules/Channel/components/Message/index.tsx b/src/modules/Channel/components/Message/index.tsx
index a55423a4f..67b9ef301 100644
--- a/src/modules/Channel/components/Message/index.tsx
+++ b/src/modules/Channel/components/Message/index.tsx
@@ -1,15 +1,15 @@
import React from 'react';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useChannelContext } from '../../context/ChannelProvider';
import { getSuggestedReplies } from '../../../../utils';
import { isDisabledBecauseFrozen, isDisabledBecauseMuted } from '../../context/utils';
import MessageView, { MessageProps } from '../../../GroupChannel/components/Message/MessageView';
import FileViewer from '../FileViewer';
import RemoveMessageModal from '../RemoveMessageModal';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
const Message = (props: MessageProps) => {
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const {
initialized,
currentGroupChannel,
diff --git a/src/modules/Channel/components/MessageList/index.tsx b/src/modules/Channel/components/MessageList/index.tsx
index dadde6762..d9e7d9379 100644
--- a/src/modules/Channel/components/MessageList/index.tsx
+++ b/src/modules/Channel/components/MessageList/index.tsx
@@ -13,7 +13,6 @@ import { isAboutSame } from '../../context/utils';
import UnreadCount from '../UnreadCount';
import FrozenNotification from '../FrozenNotification';
import { SCROLL_BUFFER } from '../../../../utils/consts';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { MessageProvider } from '../../../Message/context/MessageProvider';
import { useHandleOnScrollCallback } from '../../../../hooks/useHandleOnScrollCallback';
import { useSetScrollToBottom } from './hooks/useSetScrollToBottom';
@@ -26,6 +25,7 @@ import { GroupChannelMessageListProps } from '../../../GroupChannel/components/M
import { GroupChannelUIBasicProps } from '../../../GroupChannel/components/GroupChannelUI/GroupChannelUIView';
import { deleteNullish } from '../../../../utils/utils';
import { getHTMLTextDirection } from '../../../../utils';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
const SCROLL_BOTTOM_PADDING = 50;
@@ -72,7 +72,7 @@ export const MessageList = (props: MessageListProps) => {
typingMembers,
} = useChannelContext();
- const store = useSendbirdStateContext();
+ const { state: store } = useSendbird();
const allMessagesFiltered = typeof filterMessageList === 'function' ? allMessages.filter(filterMessageList) : allMessages;
const markAsReadScheduler = store.config.markAsReadScheduler;
diff --git a/src/modules/Channel/context/ChannelProvider.tsx b/src/modules/Channel/context/ChannelProvider.tsx
index 8027d44ce..3c0aae610 100644
--- a/src/modules/Channel/context/ChannelProvider.tsx
+++ b/src/modules/Channel/context/ChannelProvider.tsx
@@ -21,7 +21,6 @@ import type { EmojiContainer, SendbirdError, User } from '@sendbird/chat';
import { ReplyType, Nullable } from '../../../types';
import { UserProfileProvider, UserProfileProviderProps } from '../../../lib/UserProfileContext';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { CoreMessageType, SendableMessageType } from '../../../utils';
import { ThreadReplySelectType } from './const';
@@ -51,6 +50,7 @@ import { useSendMultipleFilesMessage } from './hooks/useSendMultipleFilesMessage
import { useHandleChannelPubsubEvents } from './hooks/useHandleChannelPubsubEvents';
import { PublishingModuleType } from '../../internalInterfaces';
import { ChannelActionTypes } from './dux/actionTypes';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export { ThreadReplySelectType } from './const'; // export for external usage
@@ -199,8 +199,7 @@ const ChannelProvider = (props: ChannelContextProps) => {
scrollBehavior = 'auto',
reconnectOnIdle = true,
} = props;
-
- const globalStore = useSendbirdStateContext();
+ const { state: globalStore } = useSendbird();
const { config } = globalStore;
const replyType = props.replyType ?? getCaseResolvedReplyType(config.groupChannel.replyType).upperCase;
const {
diff --git a/src/modules/Channel/context/hooks/__test__/useSendMultipleFilesMessage.spec.ts b/src/modules/Channel/context/hooks/__test__/useSendMultipleFilesMessage.spec.ts
index eeece9115..2d97fd523 100644
--- a/src/modules/Channel/context/hooks/__test__/useSendMultipleFilesMessage.spec.ts
+++ b/src/modules/Channel/context/hooks/__test__/useSendMultipleFilesMessage.spec.ts
@@ -8,7 +8,7 @@ import {
UseSendMFMStaticParams,
useSendMultipleFilesMessage,
} from '../useSendMultipleFilesMessage';
-import { Logger } from '../../../../../lib/SendbirdState';
+import type { Logger } from '../../../../../lib/Sendbird/types';
import {
MockMessageRequestHandlerType,
getMockMessageRequestHandler,
diff --git a/src/modules/Channel/context/hooks/useGetChannel.ts b/src/modules/Channel/context/hooks/useGetChannel.ts
index 872c689c8..ed08b5c62 100644
--- a/src/modules/Channel/context/hooks/useGetChannel.ts
+++ b/src/modules/Channel/context/hooks/useGetChannel.ts
@@ -2,7 +2,7 @@ import React, { useEffect } from 'react';
import * as messageActionTypes from '../dux/actionTypes';
import { ChannelActionTypes } from '../dux/actionTypes';
-import { SdkStore } from '../../../../lib/types';
+import type { SdkStore } from '../../../../lib/Sendbird/types';
import { LoggerInterface } from '../../../../lib/Logger';
import { MarkAsReadSchedulerType } from '../../../../lib/hooks/useMarkAsReadScheduler';
diff --git a/src/modules/Channel/context/hooks/useHandleChannelEvents.ts b/src/modules/Channel/context/hooks/useHandleChannelEvents.ts
index ba1e7f34e..964166823 100644
--- a/src/modules/Channel/context/hooks/useHandleChannelEvents.ts
+++ b/src/modules/Channel/context/hooks/useHandleChannelEvents.ts
@@ -6,11 +6,11 @@ import { scrollIntoLast } from '../utils';
import uuidv4 from '../../../../utils/uuid';
import compareIds from '../../../../utils/compareIds';
import * as messageActions from '../dux/actionTypes';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { SendableMessageType } from '../../../../utils';
import { ChannelActionTypes } from '../dux/actionTypes';
import { LoggerInterface } from '../../../../lib/Logger';
-import { SdkStore } from '../../../../lib/types';
+import type { SdkStore } from '../../../../lib/Sendbird/types';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
/**
* Handles ChannelEvents and send values to dispatcher using messagesDispatcher
@@ -47,7 +47,7 @@ function useHandleChannelEvents({
setQuoteMessage,
messagesDispatcher,
}: StaticParams): void {
- const store = useSendbirdStateContext();
+ const { state: store } = useSendbird();
const {
markAsReadScheduler,
markAsDeliveredScheduler,
diff --git a/src/modules/Channel/context/hooks/useHandleReconnect.ts b/src/modules/Channel/context/hooks/useHandleReconnect.ts
index 6672afd07..efa20d4f7 100644
--- a/src/modules/Channel/context/hooks/useHandleReconnect.ts
+++ b/src/modules/Channel/context/hooks/useHandleReconnect.ts
@@ -5,12 +5,11 @@ import { MessageListParams, ReplyType } from '@sendbird/chat/message';
import * as utils from '../utils';
import { PREV_RESULT_SIZE, NEXT_RESULT_SIZE } from '../const';
import * as messageActionTypes from '../dux/actionTypes';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import { MarkAsReadSchedulerType } from '../../../../lib/hooks/useMarkAsReadScheduler';
import useReconnectOnIdle from './useReconnectOnIdle';
import { ChannelActionTypes } from '../dux/actionTypes';
import { CoreMessageType } from '../../../../utils';
-import { SdkStore } from '../../../../lib/types';
import { SCROLL_BOTTOM_DELAY_FOR_FETCH } from '../../../../utils/consts';
interface DynamicParams {
diff --git a/src/modules/Channel/context/hooks/useHandleReconnectForChannelList.ts b/src/modules/Channel/context/hooks/useHandleReconnectForChannelList.ts
index 5bc91eab3..2852257aa 100644
--- a/src/modules/Channel/context/hooks/useHandleReconnectForChannelList.ts
+++ b/src/modules/Channel/context/hooks/useHandleReconnectForChannelList.ts
@@ -4,9 +4,8 @@ import {
GroupChannel,
GroupChannelListQuery,
} from '@sendbird/chat/groupChannel';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import useReconnectOnIdle from './useReconnectOnIdle';
-import { SdkStore } from '../../../../lib/types';
import { ChannelListActionTypes } from '../../../ChannelList/dux/actionTypes';
import { GroupChannelListQueryParamsInternal } from '../../../ChannelList/context/ChannelListProvider';
import { MarkAsDeliveredSchedulerType } from '../../../../lib/hooks/useMarkAsDeliveredScheduler';
diff --git a/src/modules/Channel/context/hooks/useHandleUploadFiles.tsx b/src/modules/Channel/context/hooks/useHandleUploadFiles.tsx
index 6292365f9..31877b5c0 100644
--- a/src/modules/Channel/context/hooks/useHandleUploadFiles.tsx
+++ b/src/modules/Channel/context/hooks/useHandleUploadFiles.tsx
@@ -1,8 +1,7 @@
import React, { useCallback } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
+import { Logger } from '../../../../lib/Sendbird/types';
import { SendMFMFunctionType } from './useSendMultipleFilesMessage';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { SendableMessageType, isImage } from '../../../../utils';
// TODO: get SendFileMessageFunctionType from Channel
import { SendFileMessageFunctionType } from '../../../Thread/context/hooks/useSendFileMessage';
@@ -13,6 +12,7 @@ import { ModalFooter } from '../../../../ui/Modal';
import { FileMessage, MultipleFilesMessage } from '@sendbird/chat/message';
import { compressImages } from '../../../../utils/compressImages';
import { ONE_MiB } from '../../../../utils/consts';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
/**
* The handleUploadFiles is a function sending a FileMessage and MultipleFilesMessage
@@ -36,7 +36,7 @@ export const useHandleUploadFiles = ({
logger,
}: useHandleUploadFilesStaticProps) => {
const { stringSet } = useLocalization();
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { imageCompression } = config;
const uikitUploadSizeLimit = config?.uikitUploadSizeLimit;
const uikitMultipleFilesMessageLimit = config?.uikitMultipleFilesMessageLimit;
diff --git a/src/modules/Channel/context/hooks/useScrollCallback.ts b/src/modules/Channel/context/hooks/useScrollCallback.ts
index ab676d7c2..38a5e45b2 100644
--- a/src/modules/Channel/context/hooks/useScrollCallback.ts
+++ b/src/modules/Channel/context/hooks/useScrollCallback.ts
@@ -9,7 +9,7 @@ import { MessageListParams as MessageListParamsInternal } from '../ChannelProvid
import { LoggerInterface } from '../../../../lib/Logger';
import { ChannelActionTypes } from '../dux/actionTypes';
import { CoreMessageType } from '../../../../utils';
-import { SdkStore } from '../../../../lib/types';
+import type { SdkStore } from '../../../../lib/Sendbird/types';
type UseScrollCallbackOptions = {
currentGroupChannel: GroupChannel | null;
diff --git a/src/modules/Channel/context/hooks/useScrollDownCallback.ts b/src/modules/Channel/context/hooks/useScrollDownCallback.ts
index c61d459ef..63d0896ad 100644
--- a/src/modules/Channel/context/hooks/useScrollDownCallback.ts
+++ b/src/modules/Channel/context/hooks/useScrollDownCallback.ts
@@ -1,11 +1,11 @@
import React, { useCallback } from 'react';
+import type { SdkStore } from '../../../../lib/Sendbird/types';
import * as messageActionTypes from '../dux/actionTypes';
import { ChannelActionTypes } from '../dux/actionTypes';
import { NEXT_RESULT_SIZE } from '../const';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { LoggerInterface } from '../../../../lib/Logger';
-import { SdkStore } from '../../../../lib/types';
import { ReplyType as ReplyTypeInternal } from '../../../../types';
import { MessageListParams as MessageListParamsInternal } from '../ChannelProvider';
import { BaseMessage, MessageListParams, ReplyType } from '@sendbird/chat/message';
diff --git a/src/modules/Channel/context/hooks/useSendFileMessageCallback.ts b/src/modules/Channel/context/hooks/useSendFileMessageCallback.ts
index 37cabca5f..fc13966c3 100644
--- a/src/modules/Channel/context/hooks/useSendFileMessageCallback.ts
+++ b/src/modules/Channel/context/hooks/useSendFileMessageCallback.ts
@@ -2,6 +2,7 @@ import React, { useCallback } from 'react';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { FileMessage, FileMessageCreateParams } from '@sendbird/chat/message';
+import type { SendbirdState } from '../../../../lib/Sendbird/types';
import * as messageActionTypes from '../dux/actionTypes';
import { ChannelActionTypes } from '../dux/actionTypes';
import * as utils from '../utils';
@@ -9,13 +10,12 @@ import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics';
import { PublishingModuleType } from '../../../internalInterfaces';
import { LoggerInterface } from '../../../../lib/Logger';
import { SendableMessageType } from '../../../../utils';
-import { SendBirdState } from '../../../../lib/types';
import { SCROLL_BOTTOM_DELAY_FOR_SEND } from '../../../../utils/consts';
type UseSendFileMessageCallbackOptions = {
currentGroupChannel: null | GroupChannel;
onBeforeSendFileMessage?: (file: File, quoteMessage?: SendableMessageType) => FileMessageCreateParams;
- imageCompression?: SendBirdState['config']['imageCompression'];
+ imageCompression?: SendbirdState['config']['imageCompression'];
};
type UseSendFileMessageCallbackParams = {
logger: LoggerInterface;
diff --git a/src/modules/Channel/context/hooks/useSendMultipleFilesMessage.ts b/src/modules/Channel/context/hooks/useSendMultipleFilesMessage.ts
index f196b6fdd..bff9d72de 100644
--- a/src/modules/Channel/context/hooks/useSendMultipleFilesMessage.ts
+++ b/src/modules/Channel/context/hooks/useSendMultipleFilesMessage.ts
@@ -3,7 +3,7 @@ import type { GroupChannel } from '@sendbird/chat/groupChannel';
import type { MultipleFilesMessageCreateParams, UploadableFileInfo } from '@sendbird/chat/message';
import { MultipleFilesMessage } from '@sendbird/chat/message';
-import type { Logger } from '../../../../lib/SendbirdState';
+import type { Logger } from '../../../../lib/Sendbird/types';
import type { Nullable } from '../../../../types';
import PUBSUB_TOPICS from '../../../../lib/pubSub/topics';
import { scrollIntoLast as scrollIntoLastForChannel } from '../utils';
diff --git a/src/modules/Channel/context/hooks/useSendVoiceMessageCallback.ts b/src/modules/Channel/context/hooks/useSendVoiceMessageCallback.ts
index 1855f5c2b..a3ee4243d 100644
--- a/src/modules/Channel/context/hooks/useSendVoiceMessageCallback.ts
+++ b/src/modules/Channel/context/hooks/useSendVoiceMessageCallback.ts
@@ -3,7 +3,7 @@ import type { FileMessage, FileMessageCreateParams } from '@sendbird/chat/messag
import type { GroupChannel } from '@sendbird/chat/groupChannel';
import { MessageMetaArray } from '@sendbird/chat/message';
-import type { Logger } from '../../../../lib/SendbirdState';
+import type { Logger } from '../../../../lib/Sendbird/types';
import * as messageActionTypes from '../dux/actionTypes';
import * as utils from '../utils';
import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics';
diff --git a/src/modules/ChannelList/components/ChannelListUI/index.tsx b/src/modules/ChannelList/components/ChannelListUI/index.tsx
index 10a1a6b57..1802c6ede 100644
--- a/src/modules/ChannelList/components/ChannelListUI/index.tsx
+++ b/src/modules/ChannelList/components/ChannelListUI/index.tsx
@@ -5,11 +5,11 @@ import ChannelPreviewAction from '../ChannelPreviewAction';
import { useChannelListContext } from '../../context/ChannelListProvider';
import * as channelListActions from '../../dux/actionTypes';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { GroupChannelListUIView } from '../../../GroupChannelList/components/GroupChannelListUI/GroupChannelListUIView';
import AddChannel from '../AddChannel';
import { GroupChannelListItemBasicProps } from '../../../GroupChannelList/components/GroupChannelListItem/GroupChannelListItemView';
import { noop } from '../../../../utils/utils';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface ChannelPreviewProps extends Omit {
onLeaveChannel(channel?: GroupChannel, onLeaveChannelCb?: (channel: GroupChannel, error?: unknown) => void): Promise;
@@ -38,7 +38,8 @@ const ChannelListUI: React.FC = (props: ChannelListUIProps)
onProfileEditSuccess,
} = useChannelListContext();
- const { stores, config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { stores, config } = state;
const { logger, isOnline = false } = config;
const sdk = stores.sdkStore.sdk;
diff --git a/src/modules/ChannelList/components/ChannelPreview/index.tsx b/src/modules/ChannelList/components/ChannelPreview/index.tsx
index af4b6d9b5..9920dbaad 100644
--- a/src/modules/ChannelList/components/ChannelPreview/index.tsx
+++ b/src/modules/ChannelList/components/ChannelPreview/index.tsx
@@ -1,11 +1,11 @@
import React from 'react';
import { SendableMessageType } from '../../../../utils';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
import { useChannelListContext } from '../../context/ChannelListProvider';
import { getChannelTitle } from './utils';
import { GroupChannelListItemBasicProps, GroupChannelListItemView } from '../../../GroupChannelList/components/GroupChannelListItem/GroupChannelListItemView';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface ChannelPreviewInterface extends GroupChannelListItemBasicProps {
/** @deprecated Please use `isSelected` instead */
@@ -22,7 +22,8 @@ const ChannelPreview = ({
onClick,
tabIndex,
}: ChannelPreviewInterface) => {
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const { stringSet } = useLocalization();
const { isTypingIndicatorEnabled = false, isMessageReceiptStatusEnabled = false } = useChannelListContext();
diff --git a/src/modules/ChannelList/context/ChannelListProvider.tsx b/src/modules/ChannelList/context/ChannelListProvider.tsx
index 4964ed9b4..f7fe2b0fd 100644
--- a/src/modules/ChannelList/context/ChannelListProvider.tsx
+++ b/src/modules/ChannelList/context/ChannelListProvider.tsx
@@ -25,13 +25,13 @@ import * as channelListActions from '../dux/actionTypes';
import { ChannelListActionTypes } from '../dux/actionTypes';
import { UserProfileProvider, UserProfileProviderProps } from '../../../lib/UserProfileContext';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import channelListReducers from '../dux/reducers';
import channelListInitialState from '../dux/initialState';
import { CHANNEL_TYPE } from '../../CreateChannel/types';
import useActiveChannelUrl from './hooks/useActiveChannelUrl';
import { useFetchChannelList } from './hooks/useFetchChannelList';
import useHandleReconnectForChannelList from '../../Channel/context/hooks/useHandleReconnectForChannelList';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export interface ApplicationUserListQueryInternal {
limit?: number;
@@ -136,8 +136,8 @@ const ChannelListProvider: React.FC = (props: ChannelL
const disableAutoSelect = props?.disableAutoSelect || !!activeChannelUrl;
const onChannelSelect = props?.onChannelSelect || noop;
// fetch store from
- const globalStore = useSendbirdStateContext();
- const { config, stores } = globalStore;
+ const { state } = useSendbird();
+ const { config, stores } = state;
const { sdkStore } = stores;
const { pubSub, logger } = config;
const {
diff --git a/src/modules/ChannelList/context/hooks/useActiveChannelUrl.ts b/src/modules/ChannelList/context/hooks/useActiveChannelUrl.ts
index e33d24956..cab6046a4 100644
--- a/src/modules/ChannelList/context/hooks/useActiveChannelUrl.ts
+++ b/src/modules/ChannelList/context/hooks/useActiveChannelUrl.ts
@@ -1,8 +1,7 @@
import { useEffect } from 'react';
import * as messageActionTypes from '../../dux/actionTypes';
import { GroupChannel } from '@sendbird/chat/groupChannel';
-import { Logger } from '../../../../lib/SendbirdState';
-import { SdkStore } from '../../../../lib/types';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
export type DynamicProps = {
activeChannelUrl?: string;
diff --git a/src/modules/ChannelList/context/hooks/useFetchChannelList.ts b/src/modules/ChannelList/context/hooks/useFetchChannelList.ts
index f891dafe5..eeb047ba7 100644
--- a/src/modules/ChannelList/context/hooks/useFetchChannelList.ts
+++ b/src/modules/ChannelList/context/hooks/useFetchChannelList.ts
@@ -1,8 +1,8 @@
import React, { useCallback } from 'react';
import { GroupChannel, GroupChannelListQuery } from '@sendbird/chat/groupChannel';
+import type { Logger } from '../../../../lib/Sendbird/types';
import { Nullable } from '../../../../types';
-import { Logger } from '../../../../lib/SendbirdState';
import { MarkAsDeliveredSchedulerType } from '../../../../lib/hooks/useMarkAsDeliveredScheduler';
import * as channelListActions from '../../dux/actionTypes';
import { ChannelListActionTypes } from '../../dux/actionTypes';
diff --git a/src/modules/ChannelList/utils.ts b/src/modules/ChannelList/utils.ts
index 3a2d54245..97b8f71f8 100644
--- a/src/modules/ChannelList/utils.ts
+++ b/src/modules/ChannelList/utils.ts
@@ -7,7 +7,7 @@ import {
} from '@sendbird/chat/groupChannel';
import * as channelActions from './dux/actionTypes';
import topics, { SBUGlobalPubSub } from '../../lib/pubSub/topics';
-import { SdkStore } from '../../lib/types';
+import { SdkStore } from '../../lib/Sendbird/types';
import React from 'react';
import { ChannelListInitialStateType } from './dux/initialState';
import { ChannelListActionTypes } from './dux/actionTypes';
diff --git a/src/modules/ChannelSettings/__test__/ChannelSettingsProvider.spec.tsx b/src/modules/ChannelSettings/__test__/ChannelSettingsProvider.spec.tsx
index 0438dd5dd..cad11298c 100644
--- a/src/modules/ChannelSettings/__test__/ChannelSettingsProvider.spec.tsx
+++ b/src/modules/ChannelSettings/__test__/ChannelSettingsProvider.spec.tsx
@@ -1,10 +1,10 @@
import React from 'react';
import { renderHook, act } from '@testing-library/react-hooks';
import { ChannelSettingsProvider, useChannelSettingsContext } from '../context/ChannelSettingsProvider';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
-import { SendbirdSdkContext } from '../../../lib/SendbirdSdkContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
+import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext';
-jest.mock('../../../hooks/useSendbirdStateContext');
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird');
jest.mock('../context/hooks/useSetChannel');
const mockLogger = {
@@ -33,17 +33,19 @@ describe('ChannelSettingsProvider', () => {
let wrapper;
beforeEach(() => {
- useSendbirdStateContext.mockReturnValue({
- stores: { sdkStore: { sdk: {}, initialized: true } },
- config: { logger: mockLogger },
+ useSendbird.mockReturnValue({
+ state: {
+ stores: { sdkStore: { sdk: {}, initialized: true } },
+ config: { logger: mockLogger },
+ },
});
wrapper = ({ children }) => (
-
+
{children}
-
+
);
jest.clearAllMocks();
@@ -56,9 +58,11 @@ describe('ChannelSettingsProvider', () => {
});
it('logs a warning if SDK is not initialized', () => {
- useSendbirdStateContext.mockReturnValue({
- stores: { sdkStore: { sdk: null, initialized: false } },
- config: { logger: mockLogger },
+ useSendbird.mockReturnValue({
+ state: {
+ stores: { sdkStore: { sdk: null, initialized: false } },
+ config: { logger: mockLogger },
+ },
});
renderHook(() => useChannelSettingsContext(), { wrapper });
diff --git a/src/modules/ChannelSettings/__test__/ChannelSettingsUI.integration.test.tsx b/src/modules/ChannelSettings/__test__/ChannelSettingsUI.integration.test.tsx
index d31914917..f0c8ab800 100644
--- a/src/modules/ChannelSettings/__test__/ChannelSettingsUI.integration.test.tsx
+++ b/src/modules/ChannelSettings/__test__/ChannelSettingsUI.integration.test.tsx
@@ -1,14 +1,20 @@
import React from 'react';
import '@testing-library/jest-dom/extend-expect';
-import { render, screen } from '@testing-library/react';
+import { render, renderHook, screen } from '@testing-library/react';
import ChannelSettingsUI from '../components/ChannelSettingsUI';
import { LocalizationContext } from '../../../lib/LocalizationContext';
import * as useChannelSettingsModule from '../context/useChannelSettings';
-import { SendbirdSdkContext } from '../../../lib/SendbirdSdkContext';
+import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
jest.mock('../context/useChannelSettings');
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(),
+}));
+
const mockStringSet = {
CHANNEL_SETTING__HEADER__TITLE: 'Channel information',
CHANNEL_SETTING__OPERATORS__TITLE: 'Operators',
@@ -46,16 +52,24 @@ describe('ChannelSettings Integration Tests', () => {
});
return render(
-
+
- ,
+ ,
);
};
beforeEach(() => {
jest.clearAllMocks();
+ const stateContextValue = {
+ state: {
+ config: {},
+ stores: {},
+ },
+ };
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
});
it('renders all necessary texts correctly', () => {
diff --git a/src/modules/ChannelSettings/components/ChannelProfile/index.tsx b/src/modules/ChannelSettings/components/ChannelProfile/index.tsx
index e5439d2ba..ccd6a6c57 100644
--- a/src/modules/ChannelSettings/components/ChannelProfile/index.tsx
+++ b/src/modules/ChannelSettings/components/ChannelProfile/index.tsx
@@ -2,7 +2,6 @@ import './channel-profile.scss';
import React, { useState, useContext, useMemo } from 'react';
import useChannelSettings from '../../context/useChannelSettings';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
import ChannelAvatar from '../../../../ui/ChannelAvatar';
@@ -12,9 +11,10 @@ import Label, {
LabelColors,
} from '../../../../ui/Label';
import EditDetailsModal from '../EditDetailsModal';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
const ChannelProfile: React.FC = () => {
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const { state: { channel } } = useChannelSettings();
const { stringSet } = useContext(LocalizationContext);
const [showModal, setShowModal] = useState(false);
diff --git a/src/modules/ChannelSettings/components/ChannelSettingsUI/ChannelSettingsHeader.tsx b/src/modules/ChannelSettings/components/ChannelSettingsUI/ChannelSettingsHeader.tsx
index 7f0c3e2e9..c82698a0b 100644
--- a/src/modules/ChannelSettings/components/ChannelSettingsUI/ChannelSettingsHeader.tsx
+++ b/src/modules/ChannelSettings/components/ChannelSettingsUI/ChannelSettingsHeader.tsx
@@ -1,10 +1,10 @@
import React, { MouseEvent } from 'react';
import { useLocalization } from '../../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { IconTypes } from '../../../../ui/Icon';
import Header, { type HeaderCustomProps } from '../../../../ui/Header';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface ChannelSettingsHeaderProps extends HeaderCustomProps {
onCloseClick?: (e: MouseEvent) => void;
@@ -17,7 +17,8 @@ export const ChannelSettingsHeader = ({
renderRight,
}: ChannelSettingsHeaderProps) => {
const { stringSet } = useLocalization();
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const { logger } = config;
return (
diff --git a/src/modules/ChannelSettings/components/ChannelSettingsUI/index.tsx b/src/modules/ChannelSettings/components/ChannelSettingsUI/index.tsx
index 4eb515350..67c492518 100644
--- a/src/modules/ChannelSettings/components/ChannelSettingsUI/index.tsx
+++ b/src/modules/ChannelSettings/components/ChannelSettingsUI/index.tsx
@@ -2,7 +2,6 @@ import './channel-settings-ui.scss';
import React, { ReactNode, useState } from 'react';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import useChannelSettings from '../../context/useChannelSettings';
import { useLocalization } from '../../../../lib/LocalizationContext';
import useMenuItems from './hooks/useMenuItems';
@@ -19,6 +18,7 @@ import ChannelProfile from '../ChannelProfile';
import LeaveChannelModal from '../LeaveChannel';
import MenuItem from './MenuItem';
import MenuListByRole from './MenuListByRole';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface ModerationPanelProps {
menuItems: ReturnType;
@@ -46,9 +46,8 @@ const ChannelSettingsUI = (props: ChannelSettingsUIProps) => {
renderPlaceholderError,
renderPlaceholderLoading,
} = deleteNullish(props);
- const {
- config: { isOnline },
- } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { isOnline } = state.config;
const {
state: {
channel,
diff --git a/src/modules/ChannelSettings/components/EditDetailsModal/index.tsx b/src/modules/ChannelSettings/components/EditDetailsModal/index.tsx
index 62f957903..00c162a62 100644
--- a/src/modules/ChannelSettings/components/EditDetailsModal/index.tsx
+++ b/src/modules/ChannelSettings/components/EditDetailsModal/index.tsx
@@ -1,7 +1,6 @@
import React, { useState, useRef, useContext } from 'react';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import useChannelSettings from '../../context/useChannelSettings';
import Modal from '../../../../ui/Modal';
@@ -13,6 +12,7 @@ import TextButton from '../../../../ui/TextButton';
import ChannelAvatar from '../../../../ui/ChannelAvatar/index';
import uuidv4 from '../../../../utils/uuid';
import { FileCompat } from '@sendbird/chat';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export type EditDetailsProps = {
onSubmit: () => void;
@@ -35,7 +35,7 @@ const EditDetails: React.FC = (props: EditDetailsProps) => {
} = useChannelSettings();
const title = channel?.name;
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const userId = state?.config?.userId;
const theme = state?.config?.theme;
const logger = state?.config?.logger;
diff --git a/src/modules/ChannelSettings/components/LeaveChannel/index.tsx b/src/modules/ChannelSettings/components/LeaveChannel/index.tsx
index 9302dbb67..51f6d4e29 100644
--- a/src/modules/ChannelSettings/components/LeaveChannel/index.tsx
+++ b/src/modules/ChannelSettings/components/LeaveChannel/index.tsx
@@ -3,7 +3,6 @@ import './leave-channel.scss';
import React from 'react';
import type { GroupChannel } from '@sendbird/chat/groupChannel';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { noop } from '../../../../utils/utils';
import Modal from '../../../../ui/Modal';
@@ -15,6 +14,7 @@ import Label, {
LabelColors,
} from '../../../../ui/Label';
import useChannelSettings from '../../context/useChannelSettings';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export type LeaveChannelProps = {
onSubmit: () => void;
@@ -29,7 +29,7 @@ const LeaveChannel: React.FC = (props: LeaveChannelProps) =>
const { state: { channel, onLeaveChannel } } = useChannelSettings();
const { stringSet } = useLocalization();
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const logger = state?.config?.logger;
const isOnline = state?.config?.isOnline;
const { isMobile } = useMediaQueryContext();
diff --git a/src/modules/ChannelSettings/components/ModerationPanel/InviteUsersModal.tsx b/src/modules/ChannelSettings/components/ModerationPanel/InviteUsersModal.tsx
index 1a274ade7..8e0e9beeb 100644
--- a/src/modules/ChannelSettings/components/ModerationPanel/InviteUsersModal.tsx
+++ b/src/modules/ChannelSettings/components/ModerationPanel/InviteUsersModal.tsx
@@ -4,11 +4,11 @@ import { User } from '@sendbird/chat';
import Modal from '../../../../ui/Modal';
import { ButtonTypes } from '../../../../ui/Button';
import UserListItem, { type UserListItemProps } from '../../../../ui/UserListItem';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
import { useOnScrollPositionChangeDetector } from '../../../../hooks/useOnScrollReachedEndDetector';
import { UserListQuery } from '../../../../types';
import useChannelSettings from '../../context/useChannelSettings';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
type UserId = string;
export interface InviteUsersModalProps {
@@ -26,7 +26,7 @@ export function InviteUsersModal({
const [userListQuery, setUserListQuery] = useState(null);
const [selectedUsers, setSelectedUsers] = useState>({});
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const sdk = state?.stores?.sdkStore?.sdk;
const globalUserListQuery = state?.config?.userListQuery;
diff --git a/src/modules/ChannelSettings/context/ChannelSettingsProvider.tsx b/src/modules/ChannelSettings/context/ChannelSettingsProvider.tsx
index c7b7922eb..c964c5ba8 100644
--- a/src/modules/ChannelSettings/context/ChannelSettingsProvider.tsx
+++ b/src/modules/ChannelSettings/context/ChannelSettingsProvider.tsx
@@ -3,7 +3,6 @@ import React, { createContext, useCallback, useEffect, useRef, useState } from '
import type { ChannelSettingsContextProps, ChannelSettingsState } from './types';
import useSetChannel from './hooks/useSetChannel';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { useStore } from '../../../hooks/useStore';
import { useChannelHandler } from './hooks/useChannelHandler';
@@ -11,6 +10,7 @@ import uuidv4 from '../../../utils/uuid';
import { classnames } from '../../../utils/utils';
import { createStore } from '../../../utils/storeManager';
import { UserProfileProvider } from '../../../lib/UserProfileContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export const ChannelSettingsContext = createContext> | null>(null);
@@ -49,7 +49,8 @@ const ChannelSettingsManager = ({
queries,
renderUserListItem,
}: ChannelSettingsContextProps) => {
- const { config, stores } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config, stores } = state;
const { updateState } = useChannelSettingsStore();
const { logger } = config;
const { sdk, initialized } = stores?.sdkStore ?? {};
diff --git a/src/modules/ChannelSettings/context/hooks/useChannelHandler.ts b/src/modules/ChannelSettings/context/hooks/useChannelHandler.ts
index 9866a3f86..1cbdfb564 100644
--- a/src/modules/ChannelSettings/context/hooks/useChannelHandler.ts
+++ b/src/modules/ChannelSettings/context/hooks/useChannelHandler.ts
@@ -3,8 +3,7 @@ import { GroupChannelHandler } from '@sendbird/chat/groupChannel';
import uuidv4 from '../../../../utils/uuid';
import compareIds from '../../../../utils/compareIds';
-import type { SdkStore } from '../../../../lib/types';
-import type { Logger } from '../../../../lib/SendbirdState';
+import type { SdkStore, Logger } from '../../../../lib/Sendbird/types';
interface UseChannelHandlerProps {
sdk: SdkStore['sdk'];
diff --git a/src/modules/ChannelSettings/context/hooks/useSetChannel.ts b/src/modules/ChannelSettings/context/hooks/useSetChannel.ts
index 53c98df13..fbd9905ea 100644
--- a/src/modules/ChannelSettings/context/hooks/useSetChannel.ts
+++ b/src/modules/ChannelSettings/context/hooks/useSetChannel.ts
@@ -1,6 +1,5 @@
import { useEffect } from 'react';
-import type { Logger } from '../../../../lib/SendbirdState';
-import { SdkStore } from '../../../../lib/types';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import useChannelSettings from '../useChannelSettings';
interface Props {
diff --git a/src/modules/CreateChannel/components/CreateChannelUI/__tests__/CreateChannelUI.integration.test.tsx b/src/modules/CreateChannel/components/CreateChannelUI/__tests__/CreateChannelUI.integration.test.tsx
index 37e0dc87a..e4ddfbf7d 100644
--- a/src/modules/CreateChannel/components/CreateChannelUI/__tests__/CreateChannelUI.integration.test.tsx
+++ b/src/modules/CreateChannel/components/CreateChannelUI/__tests__/CreateChannelUI.integration.test.tsx
@@ -6,35 +6,37 @@ import '@testing-library/jest-dom/extend-expect';
import { LocalizationContext } from '../../../../../lib/LocalizationContext';
import CreateChannelUI from '../index';
-jest.mock('../../../../../hooks/useSendbirdStateContext', () => ({
+jest.mock('../../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
__esModule: true,
default: jest.fn(() => ({
- stores: {
- userStore: {
- user: {
- userId: ' test-user-id',
+ state: {
+ stores: {
+ userStore: {
+ user: {
+ userId: ' test-user-id',
+ },
},
- },
- sdkStore: {
- sdk: {
- currentUser: {
- userId: 'test-user-id',
+ sdkStore: {
+ sdk: {
+ currentUser: {
+ userId: 'test-user-id',
+ },
+ createApplicationUserListQuery: () => ({
+ next: () => Promise.resolve([{ userId: 'test-user-id' }]),
+ isLoading: false,
+ }),
},
- createApplicationUserListQuery: () => ({
- next: () => Promise.resolve([{ userId: 'test-user-id' }]),
- isLoading: false,
- }),
+ initialized: true,
},
- initialized: true,
},
- },
- config: {
- logger: console,
- userId: 'test-user-id',
- groupChannel: {
- enableMention: true,
+ config: {
+ logger: console,
+ userId: 'test-user-id',
+ groupChannel: {
+ enableMention: true,
+ },
+ isOnline: true,
},
- isOnline: true,
},
})),
}));
diff --git a/src/modules/CreateChannel/components/InviteUsers/__tests__/index.spec.tsx b/src/modules/CreateChannel/components/InviteUsers/__tests__/index.spec.tsx
index c16ff47bf..9b4a8fb5d 100644
--- a/src/modules/CreateChannel/components/InviteUsers/__tests__/index.spec.tsx
+++ b/src/modules/CreateChannel/components/InviteUsers/__tests__/index.spec.tsx
@@ -7,21 +7,23 @@ import { CHANNEL_TYPE } from '../../../types';
import * as useCreateChannelModule from '../../../context/useCreateChannel';
import { LocalizationContext } from '../../../../../lib/LocalizationContext';
-jest.mock('../../../../../hooks/useSendbirdStateContext', () => ({
- __esModule: true,
- default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- currentUser: {
- userId: 'test-user-id',
- },
+const mockState = {
+ stores: {
+ sdkStore: {
+ sdk: {
+ currentUser: {
+ userId: 'test-user-id',
},
- initialized: true,
},
+ initialized: true,
},
- config: { logger: console },
- })),
+ },
+ config: { logger: console },
+};
+jest.mock('../../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(() => ({ state: mockState })),
+ useSendbird: jest.fn(() => ({ state: mockState })),
}));
jest.mock('../../../context/useCreateChannel');
diff --git a/src/modules/CreateChannel/components/InviteUsers/index.tsx b/src/modules/CreateChannel/components/InviteUsers/index.tsx
index 04965d726..32c7ede75 100644
--- a/src/modules/CreateChannel/components/InviteUsers/index.tsx
+++ b/src/modules/CreateChannel/components/InviteUsers/index.tsx
@@ -4,7 +4,7 @@ import type { GroupChannelCreateParams } from '@sendbird/chat/groupChannel';
import './invite-users.scss';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
import { useMediaQueryContext } from '../../../../lib/MediaQueryContext';
import Modal from '../../../../ui/Modal';
import Label, { LabelColors, LabelTypography } from '../../../../ui/Label';
@@ -41,9 +41,7 @@ const InviteUsers: React.FC = ({
},
} = useCreateChannel();
- const globalStore = useSendbirdStateContext();
- const userId = globalStore?.config?.userId;
- const sdk = globalStore?.stores?.sdkStore?.sdk;
+ const { state: { config: { userId }, stores: { sdkStore: { sdk } } } } = useSendbird();
const idsToFilter = [userId];
const [users, setUsers] = useState([]);
const [selectedUsers, setSelectedUsers] = useState>({});
diff --git a/src/modules/CreateChannel/components/InviteUsers/utils.ts b/src/modules/CreateChannel/components/InviteUsers/utils.ts
index fc7d19a8b..23cbf7c1b 100644
--- a/src/modules/CreateChannel/components/InviteUsers/utils.ts
+++ b/src/modules/CreateChannel/components/InviteUsers/utils.ts
@@ -1,7 +1,7 @@
import type { ApplicationUserListQuery } from '@sendbird/chat';
import type { GroupChannelCreateParams } from '@sendbird/chat/groupChannel';
import { CHANNEL_TYPE } from '../../types';
-import { SdkStore } from '../../../../lib/types';
+import type { SdkStore } from '../../../../lib/Sendbird/types';
export const filterUser = (idsToFilter: string[]) => (currentId: string): boolean => idsToFilter?.includes(currentId);
diff --git a/src/modules/CreateChannel/components/SelectChannelType.tsx b/src/modules/CreateChannel/components/SelectChannelType.tsx
index 9414aa979..305d43a87 100644
--- a/src/modules/CreateChannel/components/SelectChannelType.tsx
+++ b/src/modules/CreateChannel/components/SelectChannelType.tsx
@@ -1,7 +1,6 @@
import React, { useContext } from 'react';
import * as sendbirdSelectors from '../../../lib/selectors';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { LocalizationContext } from '../../../lib/LocalizationContext';
import Label, { LabelColors, LabelTypography } from '../../../ui/Label';
@@ -15,6 +14,7 @@ import {
} from '../utils';
import { CHANNEL_TYPE } from '../types';
import useCreateChannel from '../context/useCreateChannel';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export interface SelectChannelTypeProps {
onCancel?(): void;
@@ -22,9 +22,8 @@ export interface SelectChannelTypeProps {
const SelectChannelType: React.FC = (props: SelectChannelTypeProps) => {
const { onCancel } = props;
- const store = useSendbirdStateContext();
-
- const sdk = sendbirdSelectors.getSdk(store);
+ const { state } = useSendbird();
+ const sdk = sendbirdSelectors.getSdk(state);
const {
actions: {
diff --git a/src/modules/CreateChannel/context/CreateChannelProvider.tsx b/src/modules/CreateChannel/context/CreateChannelProvider.tsx
index f9d229e19..a7fbfced1 100644
--- a/src/modules/CreateChannel/context/CreateChannelProvider.tsx
+++ b/src/modules/CreateChannel/context/CreateChannelProvider.tsx
@@ -5,12 +5,12 @@ import type {
GroupChannelCreateParams,
} from '@sendbird/chat/groupChannel';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { CHANNEL_TYPE } from '../types';
-import { SendbirdChatType } from '../../../lib/types';
+import { SendbirdChatType } from '../../../lib/Sendbird/types';
import { createStore } from '../../../utils/storeManager';
import { useStore } from '../../../hooks/useStore';
import useCreateChannel from './useCreateChannel';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
const CreateChannelContext = React.createContext> | null>(null);
@@ -111,8 +111,8 @@ const CreateChannelManager: React.FC = (props: Creat
} = props;
const { updateState } = useCreateChannelStore();
- const store = useSendbirdStateContext();
- const _userListQuery = userListQuery ?? store?.config?.userListQuery;
+ const { state: { config } } = useSendbird();
+ const _userListQuery = userListQuery ?? config?.userListQuery;
useEffect(() => {
updateState({
diff --git a/src/modules/CreateChannel/context/__tests__/CreateChannelProvider.spec.tsx b/src/modules/CreateChannel/context/__tests__/CreateChannelProvider.spec.tsx
index 0be826a28..2c722b6c7 100644
--- a/src/modules/CreateChannel/context/__tests__/CreateChannelProvider.spec.tsx
+++ b/src/modules/CreateChannel/context/__tests__/CreateChannelProvider.spec.tsx
@@ -5,20 +5,22 @@ import { CHANNEL_TYPE } from '../../types';
import useCreateChannel from '../useCreateChannel';
import { renderHook } from '@testing-library/react-hooks';
-jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
__esModule: true,
default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- currentUser: {
- userId: 'test-user-id',
+ state: {
+ stores: {
+ sdkStore: {
+ sdk: {
+ currentUser: {
+ userId: 'test-user-id',
+ },
},
+ initialized: true,
},
- initialized: true,
},
+ config: { logger: console },
},
- config: { logger: console },
})),
}));
diff --git a/src/modules/CreateChannel/context/__tests__/useCreateChannel.spec.tsx b/src/modules/CreateChannel/context/__tests__/useCreateChannel.spec.tsx
index 4a479958b..bdc83b5e5 100644
--- a/src/modules/CreateChannel/context/__tests__/useCreateChannel.spec.tsx
+++ b/src/modules/CreateChannel/context/__tests__/useCreateChannel.spec.tsx
@@ -5,20 +5,22 @@ import { CreateChannelProvider } from '../CreateChannelProvider';
import { renderHook } from '@testing-library/react';
import useCreateChannel from '../useCreateChannel';
-jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
__esModule: true,
default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- currentUser: {
- userId: 'test-user-id',
+ state: {
+ stores: {
+ sdkStore: {
+ sdk: {
+ currentUser: {
+ userId: 'test-user-id',
+ },
},
+ initialized: true,
},
- initialized: true,
},
+ config: { logger: console },
},
- config: { logger: console },
})),
}));
diff --git a/src/modules/CreateChannel/utils.ts b/src/modules/CreateChannel/utils.ts
index d9e44a948..3bc4d0092 100644
--- a/src/modules/CreateChannel/utils.ts
+++ b/src/modules/CreateChannel/utils.ts
@@ -1,4 +1,4 @@
-import { SdkStore } from '../../lib/types';
+import type { SdkStore } from '../../lib/Sendbird/types';
export const isBroadcastChannelEnabled = (sdk: SdkStore['sdk']): boolean => {
const ALLOW_BROADCAST_CHANNEL = 'allow_broadcast_channel';
diff --git a/src/modules/CreateOpenChannel/context/CreateOpenChannelProvider.tsx b/src/modules/CreateOpenChannel/context/CreateOpenChannelProvider.tsx
index 65cb47694..8431ed6d0 100644
--- a/src/modules/CreateOpenChannel/context/CreateOpenChannelProvider.tsx
+++ b/src/modules/CreateOpenChannel/context/CreateOpenChannelProvider.tsx
@@ -1,8 +1,7 @@
import React, { useCallback } from 'react';
import { OpenChannel, OpenChannelCreateParams } from '@sendbird/chat/openChannel';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
-import { Logger } from '../../../lib/SendbirdState';
-import { SdkStore } from '../../../lib/types';
+import { SdkStore, Logger } from '../../../lib/Sendbird/types';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export interface CreateNewOpenChannelCallbackProps {
name: string;
@@ -30,7 +29,8 @@ export const CreateOpenChannelProvider: React.FC
onCreateChannel,
onBeforeCreateChannel,
}: CreateOpenChannelProviderProps): React.ReactElement => {
- const { stores, config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { stores, config } = state;
const { logger } = config;
const sdk = stores?.sdkStore?.sdk || null;
const sdkInitialized = stores?.sdkStore?.initialized || false;
diff --git a/src/modules/EditUserProfile/components/EditUserProfileUI/EditUserProfileUIView.tsx b/src/modules/EditUserProfile/components/EditUserProfileUI/EditUserProfileUIView.tsx
index 74a53f952..bc38c9fda 100644
--- a/src/modules/EditUserProfile/components/EditUserProfileUI/EditUserProfileUIView.tsx
+++ b/src/modules/EditUserProfile/components/EditUserProfileUI/EditUserProfileUIView.tsx
@@ -6,7 +6,7 @@ import Avatar from '../../../../ui/Avatar';
import TextButton from '../../../../ui/TextButton';
import Label, { LabelColors, LabelTypography } from '../../../../ui/Label';
import Icon, { IconTypes } from '../../../../ui/Icon';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface EditUserProfileUIViewProps {
formRef: MutableRefObject;
@@ -20,7 +20,8 @@ export const EditUserProfileUIView = ({
onThemeChange,
setProfileImage,
}: EditUserProfileUIViewProps) => {
- const { stores, config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { stores, config } = state;
const { theme, setCurrentTheme } = config;
const user = stores.userStore?.user;
const { stringSet } = useLocalization();
diff --git a/src/modules/EditUserProfile/components/EditUserProfileUI/index.tsx b/src/modules/EditUserProfile/components/EditUserProfileUI/index.tsx
index 9fffc65ee..37db1baf9 100644
--- a/src/modules/EditUserProfile/components/EditUserProfileUI/index.tsx
+++ b/src/modules/EditUserProfile/components/EditUserProfileUI/index.tsx
@@ -8,22 +8,22 @@ import React, {
import { User } from '@sendbird/chat';
import './edit-user-profile.scss';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useEditUserProfileContext } from '../../context/EditUserProfileProvider';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
-import { SendBirdState } from '../../../../lib/types';
-import { USER_ACTIONS } from '../../../../lib/dux/user/actionTypes';
import Modal from '../../../../ui/Modal';
import { ButtonTypes } from '../../../../ui/Button';
import { EditUserProfileUIView } from './EditUserProfileUIView';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
+import { SendbirdState } from '../../../../lib/Sendbird/types';
interface HandleUpdateUserInfoParams {
- globalContext: SendBirdState;
+ globalContext: SendbirdState;
formRef: MutableRefObject;
inputRef: MutableRefObject;
profileImage: File | null;
onEditProfile?: (user: User) => void;
+ updateUserInfo: (user: User) => void;
}
const handleUpdateUserInfo = ({
globalContext,
@@ -31,11 +31,11 @@ const handleUpdateUserInfo = ({
inputRef,
profileImage,
onEditProfile,
+ updateUserInfo,
}: HandleUpdateUserInfoParams) => {
- const { stores, dispatchers } = globalContext;
+ const { stores } = globalContext;
const sdk = stores.sdkStore.sdk;
const user = stores.userStore.user;
- const { userDispatcher } = dispatchers;
if (user?.nickname !== '' && !inputRef.current.value) {
formRef.current.reportValidity?.(); // might not work in explorer
@@ -45,7 +45,7 @@ const handleUpdateUserInfo = ({
nickname: inputRef?.current?.value,
profileImage: profileImage ?? undefined,
}).then((updatedUser) => {
- userDispatcher({ type: USER_ACTIONS.UPDATE_USER_INFO, payload: updatedUser });
+ updateUserInfo(updatedUser);
onEditProfile?.(updatedUser);
});
};
@@ -56,17 +56,18 @@ export interface UseEditUserProfileUIStateParams {
export const useEditUserProfileUISates = ({
onEditProfile,
}: UseEditUserProfileUIStateParams) => {
- const globalContext = useSendbirdStateContext();
+ const { state, actions } = useSendbird();
const inputRef = useRef(null);
const formRef = useRef(null);
const [profileImage, setProfileImage] = useState(null);
const updateUserInfo = () => {
handleUpdateUserInfo({
- globalContext,
+ globalContext: state,
formRef,
inputRef,
profileImage,
onEditProfile,
+ updateUserInfo: actions.updateUserInfo,
});
};
diff --git a/src/modules/GroupChannel/__test__/GroupChannelUIView.integration.test.tsx b/src/modules/GroupChannel/__test__/GroupChannelUIView.integration.test.tsx
index b8d751185..d951d7a81 100644
--- a/src/modules/GroupChannel/__test__/GroupChannelUIView.integration.test.tsx
+++ b/src/modules/GroupChannel/__test__/GroupChannelUIView.integration.test.tsx
@@ -2,11 +2,11 @@ import React from 'react';
import { render, screen } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import { GroupChannelUIView } from '../components/GroupChannelUI/GroupChannelUIView';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
-jest.mock('../../../hooks/useSendbirdStateContext');
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird');
-const mockUseSendbirdStateContext = useSendbirdStateContext as jest.Mock;
+const mockUseSendbird = useSendbird as jest.Mock;
describe('GroupChannelUIView Integration Tests', () => {
const defaultProps = {
@@ -18,16 +18,18 @@ describe('GroupChannelUIView Integration Tests', () => {
};
beforeEach(() => {
- mockUseSendbirdStateContext.mockImplementation(() => ({
- stores: {
- sdkStore: { error: null },
- },
- config: {
- logger: { info: jest.fn() },
- isOnline: true,
- groupChannel: {
- enableTypingIndicator: true,
- typingIndicatorTypes: new Set(['text']),
+ mockUseSendbird.mockImplementation(() => ({
+ state: {
+ stores: {
+ sdkStore: { error: null },
+ },
+ config: {
+ logger: { info: jest.fn() },
+ isOnline: true,
+ groupChannel: {
+ enableTypingIndicator: true,
+ typingIndicatorTypes: new Set(['text']),
+ },
},
},
}));
@@ -58,13 +60,15 @@ describe('GroupChannelUIView Integration Tests', () => {
});
it('renders SDK error placeholder when SDK has error', () => {
- mockUseSendbirdStateContext.mockImplementation(() => ({
- stores: {
- sdkStore: { error: new Error('SDK Error') },
- },
- config: {
- logger: { info: jest.fn() },
- isOnline: true,
+ mockUseSendbird.mockImplementation(() => ({
+ state: {
+ stores: {
+ sdkStore: { error: new Error('SDK Error') },
+ },
+ config: {
+ logger: { info: jest.fn() },
+ isOnline: true,
+ },
},
}));
diff --git a/src/modules/GroupChannel/components/FileViewer/FileViewerView.tsx b/src/modules/GroupChannel/components/FileViewer/FileViewerView.tsx
index dccfa3f7b..62e52effc 100644
--- a/src/modules/GroupChannel/components/FileViewer/FileViewerView.tsx
+++ b/src/modules/GroupChannel/components/FileViewer/FileViewerView.tsx
@@ -10,8 +10,8 @@ import Icon, { IconColors, IconTypes } from '../../../../ui/Icon';
import Label, { LabelColors, LabelTypography, LabelStringSet } from '../../../../ui/Label';
import { isImage, isSupportedFileView, isVideo } from '../../../../utils';
import { MODAL_ROOT } from '../../../../hooks/useModal';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import Modal from '../../../../ui/Modal';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
type DeleteMessageTypeLegacy = (message: CoreMessageType) => Promise;
export interface FileViewerViewProps extends FileViewerProps {
@@ -28,7 +28,8 @@ export const FileViewerView = ({
const { sender, type, url, name = '', threadInfo } = message;
const { profileUrl, nickname, userId } = sender;
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
return createPortal(
void;
@@ -15,8 +15,7 @@ export const FileViewer = (props: FileViewerProps) => {
state: { onBeforeDownloadFileMessage },
actions: { deleteMessage },
} = useGroupChannel();
- const { config } = useSendbirdStateContext();
- const { logger } = config;
+ const { state: { config: { logger } } } = useSendbird();
return (
{
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const { userId, theme } = config;
const { isMobile } = useMediaQueryContext();
diff --git a/src/modules/GroupChannel/components/GroupChannelUI/GroupChannelUIView.tsx b/src/modules/GroupChannel/components/GroupChannelUI/GroupChannelUIView.tsx
index cae0ad075..1f490865f 100644
--- a/src/modules/GroupChannel/components/GroupChannelUI/GroupChannelUIView.tsx
+++ b/src/modules/GroupChannel/components/GroupChannelUI/GroupChannelUIView.tsx
@@ -1,8 +1,6 @@
import './index.scss';
import React from 'react';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
-
import TypingIndicator from '../TypingIndicator';
import { TypingIndicatorType } from '../../../../types';
import ConnectionStatus from '../../../../ui/ConnectionStatus';
@@ -14,6 +12,7 @@ import type { GroupChannelMessageListProps } from '../MessageList';
import type { MessageContentProps } from '../../../../ui/MessageContent';
import { SuggestedRepliesProps } from '../SuggestedReplies';
import { deleteNullish } from '../../../../utils/utils';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface GroupChannelUIBasicProps {
// Components
@@ -103,8 +102,8 @@ export const GroupChannelUIView = (props: GroupChannelUIViewProps) => {
renderPlaceholderLoader,
renderPlaceholderInvalid,
} = deleteNullish(props);
-
- const { stores, config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { stores, config } = state;
const sdkError = stores?.sdkStore?.error;
const { logger, isOnline } = config;
diff --git a/src/modules/GroupChannel/components/Message/MessageView.tsx b/src/modules/GroupChannel/components/Message/MessageView.tsx
index 397312f56..138030582 100644
--- a/src/modules/GroupChannel/components/Message/MessageView.tsx
+++ b/src/modules/GroupChannel/components/Message/MessageView.tsx
@@ -6,7 +6,6 @@ import type { FileMessage, UserMessage, UserMessageCreateParams, UserMessageUpda
import format from 'date-fns/format';
import { useLocalization } from '../../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { MAX_USER_MENTION_COUNT, MAX_USER_SUGGESTION_COUNT, ThreadReplySelectType } from '../../context/const';
import { isDisabledBecauseFrozen, isDisabledBecauseMuted } from '../../context/utils';
import { useDirtyGetMentions } from '../../../Message/hooks/useDirtyGetMentions';
@@ -22,6 +21,7 @@ import SuggestedReplies, { SuggestedRepliesProps } from '../SuggestedReplies';
import SuggestedMentionListView from '../SuggestedMentionList/SuggestedMentionListView';
import type { OnBeforeDownloadFileMessageType } from '../../context/types';
import { classnames, deleteNullish } from '../../../../utils/utils';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface MessageProps {
message: EveryMessage;
@@ -152,7 +152,7 @@ const MessageView = (props: MessageViewProps) => {
} = deleteNullish(props);
const { dateLocale, stringSet } = useLocalization();
- const globalStore = useSendbirdStateContext();
+ const { state } = useSendbird();
const {
userId,
@@ -160,7 +160,7 @@ const MessageView = (props: MessageViewProps) => {
userMention,
logger,
groupChannel,
- } = globalStore.config;
+ } = state.config;
const maxUserMentionCount = userMention?.maxMentionCount || MAX_USER_MENTION_COUNT;
const maxUserSuggestionCount = userMention?.maxSuggestionCount || MAX_USER_SUGGESTION_COUNT;
diff --git a/src/modules/GroupChannel/components/Message/index.tsx b/src/modules/GroupChannel/components/Message/index.tsx
index c4425b3d9..f86a91f9a 100644
--- a/src/modules/GroupChannel/components/Message/index.tsx
+++ b/src/modules/GroupChannel/components/Message/index.tsx
@@ -1,7 +1,6 @@
import React from 'react';
import { useIIFE } from '@sendbird/uikit-tools';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { getSuggestedReplies, isSendableMessage } from '../../../../utils';
import { isDisabledBecauseFrozen, isDisabledBecauseMuted } from '../../context/utils';
import MessageView, { MessageProps } from './MessageView';
@@ -9,9 +8,11 @@ import FileViewer from '../FileViewer';
import RemoveMessageModal from '../RemoveMessageModal';
import { ThreadReplySelectType } from '../../context/const';
import { useGroupChannel } from '../../context/hooks/useGroupChannel';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export const Message = (props: MessageProps): React.ReactElement => {
- const { config, emojiManager } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config, emojiManager } = state;
const {
state: {
loading,
diff --git a/src/modules/GroupChannel/components/MessageInputWrapper/MessageInputWrapperView.tsx b/src/modules/GroupChannel/components/MessageInputWrapper/MessageInputWrapperView.tsx
index 60aa92508..9e9b38520 100644
--- a/src/modules/GroupChannel/components/MessageInputWrapper/MessageInputWrapperView.tsx
+++ b/src/modules/GroupChannel/components/MessageInputWrapper/MessageInputWrapperView.tsx
@@ -18,7 +18,6 @@ import {
isDisabledBecauseSuggestedReplies,
isDisabledBecauseMessageForm,
} from '../../context/utils';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
import SuggestedMentionList from '../SuggestedMentionList';
import { useDirtyGetMentions } from '../../../Message/hooks/useDirtyGetMentions';
@@ -29,6 +28,7 @@ import MessageInput from '../../../../ui/MessageInput';
import { useMediaQueryContext } from '../../../../lib/MediaQueryContext';
import { MessageInputKeys } from '../../../../ui/MessageInput/const';
import { useHandleUploadFiles } from './useHandleUploadFiles';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface MessageInputWrapperViewProps {
// Basic
@@ -80,7 +80,8 @@ export const MessageInputWrapperView = React.forwardRef((
} = props;
const { stringSet } = useLocalization();
const { isMobile } = useMediaQueryContext();
- const { stores, config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { stores, config } = state;
const { isOnline, userMention, logger, groupChannel } = config;
const sdk = stores.sdkStore.sdk;
const { maxMentionCount, maxSuggestionCount } = userMention;
diff --git a/src/modules/GroupChannel/components/MessageInputWrapper/VoiceMessageInputWrapper.tsx b/src/modules/GroupChannel/components/MessageInputWrapper/VoiceMessageInputWrapper.tsx
index 5b7a57a39..696c61a58 100644
--- a/src/modules/GroupChannel/components/MessageInputWrapper/VoiceMessageInputWrapper.tsx
+++ b/src/modules/GroupChannel/components/MessageInputWrapper/VoiceMessageInputWrapper.tsx
@@ -11,9 +11,9 @@ import { VoiceMessageInput } from '../../../../ui/VoiceMessageInput';
import { VoiceMessageInputStatus } from '../../../../ui/VoiceMessageInput/types';
import Modal from '../../../../ui/Modal';
import Button, { ButtonSizes, ButtonTypes } from '../../../../ui/Button';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { VOICE_PLAYER_STATUS } from '../../../../hooks/VoicePlayer/dux/initialState';
import uuidv4 from '../../../../utils/uuid';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export type VoiceMessageInputWrapperProps = {
channel?: GroupChannel;
@@ -33,7 +33,8 @@ export const VoiceMessageInputWrapper = ({
const [isDisabled, setDisabled] = useState(false);
const [showModal, setShowModal] = useState(false);
const { stringSet } = useLocalization();
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const {
start,
stop,
diff --git a/src/modules/GroupChannel/components/MessageInputWrapper/useHandleUploadFiles.tsx b/src/modules/GroupChannel/components/MessageInputWrapper/useHandleUploadFiles.tsx
index 11252becf..48bc0c73a 100644
--- a/src/modules/GroupChannel/components/MessageInputWrapper/useHandleUploadFiles.tsx
+++ b/src/modules/GroupChannel/components/MessageInputWrapper/useHandleUploadFiles.tsx
@@ -1,7 +1,6 @@
import React, { useCallback } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
+import type { Logger } from '../../../../lib/Sendbird/types';
import { isImage, SendableMessageType } from '../../../../utils';
import { useGlobalModalContext } from '../../../../hooks/useModal';
import { ButtonTypes } from '../../../../ui/Button';
@@ -10,6 +9,7 @@ import { ModalFooter } from '../../../../ui/Modal';
import { FileMessage, MultipleFilesMessage, MultipleFilesMessageCreateParams } from '@sendbird/chat/message';
import { compressImages } from '../../../../utils/compressImages';
import { FileMessageCreateParams } from '@sendbird/chat/lib/__definition';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
/**
* The handleUploadFiles is a function sending a FileMessage and MultipleFilesMessage
@@ -29,7 +29,8 @@ export const useHandleUploadFiles = (
{ logger }: useHandleUploadFilesStaticProps,
) => {
const { stringSet } = useLocalization();
- const { config } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config } = state;
const { imageCompression } = config;
const uikitUploadSizeLimit = config?.uikitUploadSizeLimit;
const uikitMultipleFilesMessageLimit = config?.uikitMultipleFilesMessageLimit;
diff --git a/src/modules/GroupChannel/components/MessageList/index.tsx b/src/modules/GroupChannel/components/MessageList/index.tsx
index 75289ff55..a40098e0d 100644
--- a/src/modules/GroupChannel/components/MessageList/index.tsx
+++ b/src/modules/GroupChannel/components/MessageList/index.tsx
@@ -12,7 +12,6 @@ import Message from '../Message';
import UnreadCount from '../UnreadCount';
import FrozenNotification from '../FrozenNotification';
import { SCROLL_BUFFER } from '../../../../utils/consts';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import TypingIndicatorBubble from '../../../../ui/TypingIndicatorBubble';
import { GroupChannelUIBasicProps } from '../GroupChannelUI/GroupChannelUIView';
import { deleteNullish } from '../../../../utils/utils';
@@ -21,6 +20,7 @@ import { MessageProvider } from '../../../Message/context/MessageProvider';
import { getComponentKeyFromMessage } from '../../context/utils';
import { InfiniteList } from './InfiniteList';
import { useGroupChannel } from '../../context/hooks/useGroupChannel';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface GroupChannelMessageListProps {
className?: string;
@@ -91,7 +91,7 @@ export const MessageList = (props: GroupChannelMessageListProps) => {
},
} = useGroupChannel();
- const store = useSendbirdStateContext();
+ const { state } = useSendbird();
const [unreadSinceDate, setUnreadSinceDate] = useState();
@@ -167,8 +167,8 @@ export const MessageList = (props: GroupChannelMessageListProps) => {
{
currentMessage: message as CoreMessageType,
currentChannel: currentChannel!,
});
- const isOutgoingMessage = isSendableMessage(message) && message.sender.userId === store.config.userId;
+ const isOutgoingMessage = isSendableMessage(message) && message.sender.userId === state.config.userId;
return (
{renderMessage({
@@ -213,8 +213,8 @@ export const MessageList = (props: GroupChannelMessageListProps) => {
}}
typingIndicator={
!hasNext()
- && store?.config?.groupChannel?.enableTypingIndicator
- && store?.config?.groupChannel?.typingIndicatorTypes?.has(TypingIndicatorType.Bubble) && (
+ && state?.config?.groupChannel?.enableTypingIndicator
+ && state?.config?.groupChannel?.typingIndicatorTypes?.has(TypingIndicatorType.Bubble) && (
)
}
@@ -228,7 +228,7 @@ export const MessageList = (props: GroupChannelMessageListProps) => {
};
const TypingIndicatorBubbleWrapper = (props: { handleScroll: () => void; channelUrl: string }) => {
- const { stores } = useSendbirdStateContext();
+ const { state: { stores } } = useSendbird();
const [typingMembers, setTypingMembers] = useState([]);
useGroupChannelHandler(stores.sdkStore.sdk, {
diff --git a/src/modules/GroupChannel/components/SuggestedMentionList/SuggestedMentionListView.tsx b/src/modules/GroupChannel/components/SuggestedMentionList/SuggestedMentionListView.tsx
index 252835da9..54cea87d9 100644
--- a/src/modules/GroupChannel/components/SuggestedMentionList/SuggestedMentionListView.tsx
+++ b/src/modules/GroupChannel/components/SuggestedMentionList/SuggestedMentionListView.tsx
@@ -6,13 +6,13 @@ import type { GroupChannel, Member } from '@sendbird/chat/groupChannel';
import Label, { LabelColors, LabelTypography } from '../../../../ui/Label';
import Icon, { IconColors, IconTypes } from '../../../../ui/Icon';
import SuggestedUserMentionItem from './SuggestedUserMentionItem';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
import { MAX_USER_MENTION_COUNT, MAX_USER_SUGGESTION_COUNT, USER_MENTION_TEMP_CHAR } from '../../context/const';
import { MessageInputKeys } from '../../../../ui/MessageInput/const';
import uuidv4 from '../../../../utils/uuid';
import { fetchMembersFromChannel, fetchMembersFromQuery } from './utils';
import { classnames } from '../../../../utils/utils';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface SuggestedMentionListViewProps {
className?: string;
@@ -46,7 +46,8 @@ export const SuggestedMentionListView = (props: SuggestedMentionListViewProps) =
maxMentionCount = MAX_USER_MENTION_COUNT,
maxSuggestionCount = MAX_USER_SUGGESTION_COUNT,
} = props;
- const { config, stores } = useSendbirdStateContext();
+ const { state } = useSendbird();
+ const { config, stores } = state;
const { logger } = config;
const currentUserId = stores?.sdkStore?.sdk?.currentUser?.userId || '';
const scrollRef = useRef(null);
diff --git a/src/modules/GroupChannel/components/TypingIndicator.tsx b/src/modules/GroupChannel/components/TypingIndicator.tsx
index a9ff08ceb..0200e4023 100644
--- a/src/modules/GroupChannel/components/TypingIndicator.tsx
+++ b/src/modules/GroupChannel/components/TypingIndicator.tsx
@@ -4,8 +4,8 @@ import { GroupChannelHandler } from '@sendbird/chat/groupChannel';
import Label, { LabelTypography, LabelColors } from '../../../ui/Label';
import { LocalizationContext } from '../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { uuidv4 } from '../../../utils/uuid';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export interface TypingIndicatorTextProps {
members: Member[];
@@ -37,9 +37,9 @@ export interface TypingIndicatorProps {
}
export const TypingIndicator = ({ channelUrl }: TypingIndicatorProps) => {
- const globalStore = useSendbirdStateContext();
- const sb = globalStore?.stores?.sdkStore?.sdk;
- const logger = globalStore?.config?.logger;
+ const { state } = useSendbird();
+ const sb = state?.stores?.sdkStore?.sdk;
+ const logger = state?.config?.logger;
const [handlerId, setHandlerId] = useState(uuidv4());
const [typingMembers, setTypingMembers] = useState([]);
diff --git a/src/modules/GroupChannel/context/GroupChannelProvider.tsx b/src/modules/GroupChannel/context/GroupChannelProvider.tsx
index a8a33281f..4e2aca793 100644
--- a/src/modules/GroupChannel/context/GroupChannelProvider.tsx
+++ b/src/modules/GroupChannel/context/GroupChannelProvider.tsx
@@ -12,7 +12,6 @@ import {
} from '@sendbird/uikit-tools';
import { UserProfileProvider } from '../../../lib/UserProfileContext';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { useMessageListScroll } from './hooks/useMessageListScroll';
import { getIsReactionEnabled } from '../../../utils/getIsReactionEnabled';
import {
@@ -30,6 +29,7 @@ import type {
MessageListQueryParamsType,
GroupChannelState,
} from './types';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
const initialState = {
currentChannel: null,
@@ -101,9 +101,9 @@ const GroupChannelManager :React.FC {
subscriptions.forEach(subscription => subscription.remove());
};
- }, [messageDataSource.initialized, state.currentChannel?.url]);
+ }, [messageDataSource.initialized, state.currentChannel?.url, pubSub?.subscribe]);
// Starting point handling
useEffect(() => {
diff --git a/src/modules/GroupChannel/context/__test__/GroupChannelProvider.spec.tsx b/src/modules/GroupChannel/context/__test__/GroupChannelProvider.spec.tsx
index c5adeb06f..2ed036a33 100644
--- a/src/modules/GroupChannel/context/__test__/GroupChannelProvider.spec.tsx
+++ b/src/modules/GroupChannel/context/__test__/GroupChannelProvider.spec.tsx
@@ -18,37 +18,39 @@ const mockMessageCollection = {
loadPrevious: jest.fn(),
loadNext: jest.fn(),
};
-jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
__esModule: true,
default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- groupChannel: {
- getChannel: mockGetChannel,
- addGroupChannelHandler: jest.fn(),
- removeGroupChannelHandler: jest.fn(),
+ state: {
+ stores: {
+ sdkStore: {
+ sdk: {
+ groupChannel: {
+ getChannel: mockGetChannel,
+ addGroupChannelHandler: jest.fn(),
+ removeGroupChannelHandler: jest.fn(),
+ },
+ createMessageCollection: jest.fn().mockReturnValue(mockMessageCollection),
},
- createMessageCollection: jest.fn().mockReturnValue(mockMessageCollection),
+ initialized: true,
},
- initialized: true,
- },
- },
- config: {
- logger: mockLogger,
- markAsReadScheduler: {
- push: jest.fn(),
- },
- groupChannel: {
- replyType: 'NONE',
- threadReplySelectType: 'PARENT',
- },
- groupChannelSettings: {
- enableMessageSearch: true,
},
- isOnline: true,
- pubSub: {
- subscribe: () => ({ remove: jest.fn() }),
+ config: {
+ logger: mockLogger,
+ markAsReadScheduler: {
+ push: jest.fn(),
+ },
+ groupChannel: {
+ replyType: 'NONE',
+ threadReplySelectType: 'PARENT',
+ },
+ groupChannelSettings: {
+ enableMessageSearch: true,
+ },
+ isOnline: true,
+ pubSub: {
+ subscribe: () => ({ remove: jest.fn() }),
+ },
},
},
})),
@@ -90,19 +92,21 @@ describe('GroupChannelProvider', () => {
const mockError = new Error('Channel fetch failed');
jest.spyOn(console, 'error').mockImplementation(() => {});
- jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
+ jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
default: () => ({
- stores: {
- sdkStore: {
- sdk: {
- groupChannel: {
- getChannel: jest.fn().mockRejectedValue(mockError),
+ state: {
+ stores: {
+ sdkStore: {
+ sdk: {
+ groupChannel: {
+ getChannel: jest.fn().mockRejectedValue(mockError),
+ },
},
+ initialized: true,
},
- initialized: true,
},
+ config: { logger: console },
},
- config: { logger: console },
}),
}));
diff --git a/src/modules/GroupChannel/context/__test__/useGroupChannel.spec.tsx b/src/modules/GroupChannel/context/__test__/useGroupChannel.spec.tsx
index 31ba50334..99158ce7c 100644
--- a/src/modules/GroupChannel/context/__test__/useGroupChannel.spec.tsx
+++ b/src/modules/GroupChannel/context/__test__/useGroupChannel.spec.tsx
@@ -20,37 +20,39 @@ const mockMessageCollection = {
loadPrevious: jest.fn(),
loadNext: jest.fn(),
};
-jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
__esModule: true,
default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- groupChannel: {
- getChannel: mockGetChannel,
- addGroupChannelHandler: jest.fn(),
- removeGroupChannelHandler: jest.fn(),
+ state: {
+ stores: {
+ sdkStore: {
+ sdk: {
+ groupChannel: {
+ getChannel: mockGetChannel,
+ addGroupChannelHandler: jest.fn(),
+ removeGroupChannelHandler: jest.fn(),
+ },
+ createMessageCollection: jest.fn().mockReturnValue(mockMessageCollection),
},
- createMessageCollection: jest.fn().mockReturnValue(mockMessageCollection),
+ initialized: true,
},
- initialized: true,
},
- },
- config: {
- logger: mockLogger,
- markAsReadScheduler: {
- push: jest.fn(),
- },
- groupChannel: {
- replyType: 'NONE',
- threadReplySelectType: 'PARENT',
- },
- groupChannelSettings: {
- enableMessageSearch: true,
- },
- isOnline: true,
- pubSub: {
- subscribe: () => ({ remove: jest.fn() }),
+ config: {
+ logger: mockLogger,
+ markAsReadScheduler: {
+ push: jest.fn(),
+ },
+ groupChannel: {
+ replyType: 'NONE',
+ threadReplySelectType: 'PARENT',
+ },
+ groupChannelSettings: {
+ enableMessageSearch: true,
+ },
+ isOnline: true,
+ pubSub: {
+ subscribe: () => ({ remove: jest.fn() }),
+ },
},
},
})),
diff --git a/src/modules/GroupChannel/context/hooks/useGroupChannel.ts b/src/modules/GroupChannel/context/hooks/useGroupChannel.ts
index 153f5a0a9..59653fcec 100644
--- a/src/modules/GroupChannel/context/hooks/useGroupChannel.ts
+++ b/src/modules/GroupChannel/context/hooks/useGroupChannel.ts
@@ -15,7 +15,7 @@ import type {
import { SendableMessageType } from '../../../../utils';
import { getMessageTopOffset } from '../utils';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
import { GroupChannelContext } from '../GroupChannelProvider';
import type { GroupChannelState, MessageActions } from '../types';
import { useMessageActions } from './useMessageActions';
@@ -53,7 +53,7 @@ export const useGroupChannel = () => {
const store = useContext(GroupChannelContext);
if (!store) throw new Error('useGroupChannel must be used within a GroupChannelProvider');
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { markAsReadScheduler } = config;
const state: GroupChannelState = useSyncExternalStore(store.subscribe, store.getState);
diff --git a/src/modules/GroupChannelList/components/AddGroupChannel/AddGroupChannelView.tsx b/src/modules/GroupChannelList/components/AddGroupChannel/AddGroupChannelView.tsx
index 0bd6839a1..539c1f729 100644
--- a/src/modules/GroupChannelList/components/AddGroupChannel/AddGroupChannelView.tsx
+++ b/src/modules/GroupChannelList/components/AddGroupChannel/AddGroupChannelView.tsx
@@ -4,8 +4,8 @@ import IconButton from '../../../../ui/IconButton';
import Icon, { IconColors, IconTypes } from '../../../../ui/Icon';
import CreateChannel from '../../../CreateChannel';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { CreateChannelProviderProps } from '../../../CreateChannel/context/CreateChannelProvider';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
type Props = {
createChannelVisible: boolean;
@@ -22,7 +22,7 @@ export const AddGroupChannelView = ({
onCreateChannelClick,
onChannelCreated,
}: Props) => {
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
return (
<>
diff --git a/src/modules/GroupChannelList/components/GroupChannelListHeader/index.tsx b/src/modules/GroupChannelList/components/GroupChannelListHeader/index.tsx
index a67cb9a17..bd2f627af 100644
--- a/src/modules/GroupChannelList/components/GroupChannelListHeader/index.tsx
+++ b/src/modules/GroupChannelList/components/GroupChannelListHeader/index.tsx
@@ -1,12 +1,12 @@
import React from 'react';
import './index.scss';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
import Avatar from '../../../../ui/Avatar';
import Label, { LabelColors, LabelTypography } from '../../../../ui/Label';
import Header, { HeaderCustomProps } from '../../../../ui/Header';
import { classnames } from '../../../../utils/utils';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface GroupChannelListHeaderProps extends HeaderCustomProps {
/** @deprecated Use the props `renderMiddle` instead */
@@ -26,8 +26,7 @@ export const GroupChannelListHeader = ({
renderMiddle,
renderRight,
}: GroupChannelListHeaderProps) => {
- const { stores } = useSendbirdStateContext();
- const { user } = stores.userStore;
+ const { state: { stores: { userStore: { user } } } } = useSendbird();
const { stringSet } = useLocalization();
const renderProfile = renderMiddle ?? renderTitle;
diff --git a/src/modules/GroupChannelList/components/GroupChannelListItem/GroupChannelListItemView.tsx b/src/modules/GroupChannelList/components/GroupChannelListItem/GroupChannelListItemView.tsx
index 36133cb7b..704a5fbae 100644
--- a/src/modules/GroupChannelList/components/GroupChannelListItem/GroupChannelListItemView.tsx
+++ b/src/modules/GroupChannelList/components/GroupChannelListItem/GroupChannelListItemView.tsx
@@ -5,7 +5,6 @@ import React, { useState } from 'react';
import type { GroupChannel } from '@sendbird/chat/groupChannel';
import type { FileMessage } from '@sendbird/chat/message';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import useLongPress from '../../../../hooks/useLongPress';
import { useLocalization } from '../../../../lib/LocalizationContext';
import { useMediaQueryContext } from '../../../../lib/MediaQueryContext';
@@ -25,6 +24,7 @@ import MessageStatus from '../../../../ui/MessageStatus';
import Modal from '../../../../ui/Modal';
import TextButton from '../../../../ui/TextButton';
import { getChannelPreviewMessage } from '../../../Message/utils/tokens/tokenize';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface GroupChannelListItemBasicProps {
tabIndex: number;
@@ -52,7 +52,7 @@ export const GroupChannelListItemView = ({
onLeaveChannel = () => Promise.resolve(),
renderChannelAction,
}: GroupChannelListItemViewProps) => {
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { theme, userId } = config;
const { dateLocale, stringSet } = useLocalization();
const { isMobile } = useMediaQueryContext();
diff --git a/src/modules/GroupChannelList/components/GroupChannelListItem/index.tsx b/src/modules/GroupChannelList/components/GroupChannelListItem/index.tsx
index 3f3074b27..f31289163 100644
--- a/src/modules/GroupChannelList/components/GroupChannelListItem/index.tsx
+++ b/src/modules/GroupChannelList/components/GroupChannelListItem/index.tsx
@@ -3,10 +3,10 @@ import React from 'react';
import type { SendableMessageType } from '../../../../utils';
import * as utils from './utils';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
import { GroupChannelListItemBasicProps, GroupChannelListItemView } from './GroupChannelListItemView';
import { useGroupChannelList } from '../../context/useGroupChannelList';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface GroupChannelListItemProps extends GroupChannelListItemBasicProps {}
@@ -19,7 +19,7 @@ export const GroupChannelListItem = ({
onClick,
tabIndex,
}: GroupChannelListItemProps) => {
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { stringSet } = useLocalization();
const {
state: {
diff --git a/src/modules/GroupChannelList/components/GroupChannelListUI/GroupChannelListUIView.tsx b/src/modules/GroupChannelList/components/GroupChannelListUI/GroupChannelListUIView.tsx
index 4777ae7ce..837a54dd3 100644
--- a/src/modules/GroupChannelList/components/GroupChannelListUI/GroupChannelListUIView.tsx
+++ b/src/modules/GroupChannelList/components/GroupChannelListUI/GroupChannelListUIView.tsx
@@ -5,11 +5,11 @@ import type { GroupChannel } from '@sendbird/chat/groupChannel';
import GroupChannelListHeader from '../GroupChannelListHeader';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import EditUserProfile from '../../../EditUserProfile';
import PlaceHolder, { PlaceHolderTypes } from '../../../../ui/PlaceHolder';
import { useOnScrollPositionChangeDetector } from '../../../../hooks/useOnScrollReachedEndDetector';
import { User } from '@sendbird/chat';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface Props {
renderHeader?: (props: void) => React.ReactElement;
@@ -47,7 +47,7 @@ export const GroupChannelListUIView = ({
renderAddChannel,
}: Props) => {
const [showProfileEdit, setShowProfileEdit] = useState(false);
- const { stores } = useSendbirdStateContext();
+ const { state: { stores } } = useSendbird();
const renderer = {
addChannel: renderAddChannel,
diff --git a/src/modules/GroupChannelList/components/GroupChannelListUI/__tests__/GroupChannelListUI.integration.test.tsx b/src/modules/GroupChannelList/components/GroupChannelListUI/__tests__/GroupChannelListUI.integration.test.tsx
index 783750898..23434b339 100644
--- a/src/modules/GroupChannelList/components/GroupChannelListUI/__tests__/GroupChannelListUI.integration.test.tsx
+++ b/src/modules/GroupChannelList/components/GroupChannelListUI/__tests__/GroupChannelListUI.integration.test.tsx
@@ -5,33 +5,35 @@ import React from 'react';
import { useGroupChannelList as useGroupChannelListModule } from '../../../context/useGroupChannelList';
import { LocalizationContext } from '../../../../../lib/LocalizationContext';
-jest.mock('../../../../../hooks/useSendbirdStateContext', () => ({
- __esModule: true,
- default: jest.fn(() => ({
- stores: {
- userStore: {
- user: {
- userId: ' test-user-id',
- },
+const mockState = {
+ stores: {
+ userStore: {
+ user: {
+ userId: ' test-user-id',
},
- sdkStore: {
- sdk: {
- currentUser: {
- userId: 'test-user-id',
- },
+ },
+ sdkStore: {
+ sdk: {
+ currentUser: {
+ userId: 'test-user-id',
},
- initialized: true,
},
+ initialized: true,
},
- config: {
- logger: console,
- userId: 'test-user-id',
- groupChannel: {
- enableMention: true,
- },
- isOnline: true,
+ },
+ config: {
+ logger: console,
+ userId: 'test-user-id',
+ groupChannel: {
+ enableMention: true,
},
- })),
+ isOnline: true,
+ },
+};
+jest.mock('../../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(() => ({ state: mockState })),
+ useSendbird: jest.fn(() => ({ state: mockState })),
}));
jest.mock('../../../context/useGroupChannelList');
diff --git a/src/modules/GroupChannelList/components/GroupChannelListUI/index.tsx b/src/modules/GroupChannelList/components/GroupChannelListUI/index.tsx
index a38756335..10cbbb71f 100644
--- a/src/modules/GroupChannelList/components/GroupChannelListUI/index.tsx
+++ b/src/modules/GroupChannelList/components/GroupChannelListUI/index.tsx
@@ -4,12 +4,12 @@ import React from 'react';
import type { GroupChannel } from '@sendbird/chat/groupChannel';
import { GroupChannelListUIView } from './GroupChannelListUIView';
import GroupChannelPreviewAction from '../GroupChannelPreviewAction';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { GroupChannelListItem } from '../GroupChannelListItem';
import AddGroupChannel from '../AddGroupChannel';
import { GroupChannelListItemBasicProps } from '../GroupChannelListItem/GroupChannelListItemView';
import { noop } from '../../../../utils/utils';
import { useGroupChannelList } from '../../context/useGroupChannelList';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface GroupChannelItemProps extends GroupChannelListItemBasicProps {}
@@ -38,8 +38,7 @@ export const GroupChannelListUI = (props: GroupChannelListUIProps) => {
},
} = useGroupChannelList();
- const { stores, config } = useSendbirdStateContext();
- const { logger, isOnline } = config;
+ const { state: { stores, config: { logger, isOnline } } } = useSendbird();
const sdk = stores.sdkStore.sdk;
const renderListItem = (renderProps: { item: GroupChannel; index: number }) => {
diff --git a/src/modules/GroupChannelList/components/LeaveGroupChannel/index.tsx b/src/modules/GroupChannelList/components/LeaveGroupChannel/index.tsx
index cfe537393..4fb36474a 100644
--- a/src/modules/GroupChannelList/components/LeaveGroupChannel/index.tsx
+++ b/src/modules/GroupChannelList/components/LeaveGroupChannel/index.tsx
@@ -1,8 +1,8 @@
import React from 'react';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import Modal from '../../../../ui/Modal';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export type LeaveGroupChannelProps = {
channel?: GroupChannel;
@@ -15,8 +15,7 @@ export const LeaveGroupChannel = ({
onSubmit,
onCancel,
}: LeaveGroupChannelProps) => {
- const { config } = useSendbirdStateContext();
- const { logger, isOnline } = config;
+ const { state: { config: { logger, isOnline } } } = useSendbird();
const { stringSet } = useLocalization();
if (channel) {
return (
diff --git a/src/modules/GroupChannelList/context/GroupChannelListProvider.tsx b/src/modules/GroupChannelList/context/GroupChannelListProvider.tsx
index 7079d9c57..ed6d691b3 100644
--- a/src/modules/GroupChannelList/context/GroupChannelListProvider.tsx
+++ b/src/modules/GroupChannelList/context/GroupChannelListProvider.tsx
@@ -6,16 +6,16 @@ import { GroupChannelCollectionParams, GroupChannelFilter } from '@sendbird/chat
import { useGroupChannelList, useGroupChannelHandler } from '@sendbird/uikit-tools';
import type { CHANNEL_TYPE } from '../../CreateChannel/types';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { UserProfileProvider } from '../../../lib/UserProfileContext';
import type { UserProfileProviderProps } from '../../../lib/UserProfileContext';
import { useMarkAsDeliveredScheduler } from '../../../lib/hooks/useMarkAsDeliveredScheduler';
import useOnlineStatus from '../../../lib/hooks/useOnlineStatus';
-import type { SdkStore } from '../../../lib/types';
+import type { SdkStore } from '../../../lib/Sendbird/types';
import { PartialRequired } from '../../../utils/typeHelpers/partialRequired';
import { createStore } from '../../../utils/storeManager';
import { useStore } from '../../../hooks/useStore';
import { noop } from '../../../utils/utils';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
type OnCreateChannelClickParams = { users: Array; onClose: () => void; channelType: CHANNEL_TYPE };
type ChannelListDataSource = ReturnType;
@@ -104,8 +104,8 @@ export const GroupChannelListManager: React.FC =
onBeforeCreateChannel,
onUserProfileUpdated,
}: GroupChannelListProviderProps) => {
-
- const { config, stores } = useSendbirdStateContext();
+ const { state: sendbirdState } = useSendbird();
+ const { config, stores } = sendbirdState;
const { state, updateState } = useGroupChannelListStore();
const { sdkStore } = stores;
diff --git a/src/modules/GroupChannelList/context/__tests__/GroupChannelListProvider.spec.tsx b/src/modules/GroupChannelList/context/__tests__/GroupChannelListProvider.spec.tsx
index 003204623..5f4b9d643 100644
--- a/src/modules/GroupChannelList/context/__tests__/GroupChannelListProvider.spec.tsx
+++ b/src/modules/GroupChannelList/context/__tests__/GroupChannelListProvider.spec.tsx
@@ -5,21 +5,23 @@ import {
} from '../GroupChannelListProvider';
import { act, renderHook, waitFor } from '@testing-library/react';
-jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
- __esModule: true,
- default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- currentUser: {
- userId: 'test-user-id',
- },
+const mockState = {
+ stores: {
+ sdkStore: {
+ sdk: {
+ currentUser: {
+ userId: 'test-user-id',
},
- initialized: true,
},
+ initialized: true,
},
- config: { logger: console },
- })),
+ },
+ config: { logger: console },
+};
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(() => ({ state: mockState })),
+ useSendbird: jest.fn(() => ({ state: mockState })),
}));
jest.mock('@sendbird/uikit-tools', () => ({
diff --git a/src/modules/GroupChannelList/context/__tests__/useGroupChannelList.spec.tsx b/src/modules/GroupChannelList/context/__tests__/useGroupChannelList.spec.tsx
index 45e3af19d..fa9416435 100644
--- a/src/modules/GroupChannelList/context/__tests__/useGroupChannelList.spec.tsx
+++ b/src/modules/GroupChannelList/context/__tests__/useGroupChannelList.spec.tsx
@@ -3,21 +3,23 @@ import { renderHook } from '@testing-library/react';
import React from 'react';
import { useGroupChannelList } from '../useGroupChannelList';
-jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
- __esModule: true,
- default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- currentUser: {
- userId: 'test-user-id',
- },
+const mockState = {
+ stores: {
+ sdkStore: {
+ sdk: {
+ currentUser: {
+ userId: 'test-user-id',
},
- initialized: true,
},
+ initialized: true,
},
- config: { logger: console },
- })),
+ },
+ config: { logger: console },
+};
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(() => ({ state: mockState })),
+ useSendbird: jest.fn(() => ({ state: mockState })),
}));
jest.mock('@sendbird/uikit-tools', () => ({
diff --git a/src/modules/Message/hooks/useDirtyGetMentions.ts b/src/modules/Message/hooks/useDirtyGetMentions.ts
index 8229004bb..d584438f6 100644
--- a/src/modules/Message/hooks/useDirtyGetMentions.ts
+++ b/src/modules/Message/hooks/useDirtyGetMentions.ts
@@ -1,6 +1,6 @@
import { useEffect, useLayoutEffect, useState } from 'react';
-import { Logger } from '../../../lib/SendbirdState';
+import { Logger } from '../../../lib/Sendbird/types';
import { getMentionNodes } from '../utils/getMentionNodes';
interface DynamicParams {
diff --git a/src/modules/MessageSearch/context/MessageSearchProvider.tsx b/src/modules/MessageSearch/context/MessageSearchProvider.tsx
index 8a45a19d6..8c0a9645a 100644
--- a/src/modules/MessageSearch/context/MessageSearchProvider.tsx
+++ b/src/modules/MessageSearch/context/MessageSearchProvider.tsx
@@ -5,8 +5,6 @@ import { ClientSentMessages } from '../../../types';
import { SendbirdError } from '@sendbird/chat';
import type { MessageSearchQueryParams } from '@sendbird/chat/lib/__definition';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
-
import useSetChannel from './hooks/useSetChannel';
import useGetSearchMessages from './hooks/useGetSearchedMessages';
import useScrollCallback from './hooks/useScrollCallback';
@@ -15,6 +13,7 @@ import { CoreMessageType } from '../../../utils';
import { createStore } from '../../../utils/storeManager';
import { useStore } from '../../../hooks/useStore';
import useMessageSearch from './hooks/useMessageSearch';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export interface MessageSearchProviderProps {
channelUrl: string;
@@ -68,7 +67,7 @@ const MessageSearchManager: React.FC = ({
onResultClick,
}) => {
const { state, updateState } = useMessageSearchStore();
- const { config, stores } = useSendbirdStateContext();
+ const { state: { config, stores } } = useSendbird();
const sdk = stores?.sdkStore?.sdk;
const sdkInit = stores?.sdkStore?.initialized;
const { logger } = config;
diff --git a/src/modules/MessageSearch/context/__test__/MessageSearchProvider.spec.tsx b/src/modules/MessageSearch/context/__test__/MessageSearchProvider.spec.tsx
index ecd1df693..60d9c8590 100644
--- a/src/modules/MessageSearch/context/__test__/MessageSearchProvider.spec.tsx
+++ b/src/modules/MessageSearch/context/__test__/MessageSearchProvider.spec.tsx
@@ -6,20 +6,22 @@ import { MessageSearchQuery } from '@sendbird/chat/message';
import { MessageSearchProvider } from '../MessageSearchProvider';
import useMessageSearch from '../hooks/useMessageSearch';
-jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
__esModule: true,
default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- createMessageSearchQuery: jest.fn(() => ({
- next: jest.fn().mockResolvedValue([{ messageId: 1 }]),
- })),
+ state: {
+ stores: {
+ sdkStore: {
+ sdk: {
+ createMessageSearchQuery: jest.fn(() => ({
+ next: jest.fn().mockResolvedValue([{ messageId: 1 }]),
+ })),
+ },
+ initialized: true,
},
- initialized: true,
},
+ config: { logger: console },
},
- config: { logger: console },
})),
}));
diff --git a/src/modules/MessageSearch/context/__test__/useMessageSearch.spec.tsx b/src/modules/MessageSearch/context/__test__/useMessageSearch.spec.tsx
index a2fd2abc2..dfcc16a5e 100644
--- a/src/modules/MessageSearch/context/__test__/useMessageSearch.spec.tsx
+++ b/src/modules/MessageSearch/context/__test__/useMessageSearch.spec.tsx
@@ -5,21 +5,23 @@ import useMessageSearch from '../../context/hooks/useMessageSearch';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { MessageSearchQuery } from '@sendbird/chat/message';
-jest.mock('../../../../hooks/useSendbirdStateContext', () => ({
- __esModule: true,
- default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- createMessageSearchQuery: jest.fn(() => ({
- next: jest.fn().mockResolvedValue([{ messageId: 1 }]),
- })),
- },
- initialized: true,
+const mockState = {
+ stores: {
+ sdkStore: {
+ sdk: {
+ createMessageSearchQuery: jest.fn(() => ({
+ next: jest.fn().mockResolvedValue([{ messageId: 1 }]),
+ })),
},
+ initialized: true,
},
- config: { logger: console },
- })),
+ },
+ config: { logger: console },
+};
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(() => ({ state: mockState })),
+ useSendbird: jest.fn(() => ({ state: mockState })),
}));
describe('useMessageSearch', () => {
diff --git a/src/modules/MessageSearch/context/hooks/useGetSearchedMessages.ts b/src/modules/MessageSearch/context/hooks/useGetSearchedMessages.ts
index f79a94282..b2f2b1cc0 100644
--- a/src/modules/MessageSearch/context/hooks/useGetSearchedMessages.ts
+++ b/src/modules/MessageSearch/context/hooks/useGetSearchedMessages.ts
@@ -2,9 +2,8 @@ import { useEffect, useCallback } from 'react';
import type { GroupChannel } from '@sendbird/chat/groupChannel';
import type { MessageSearchQueryParams } from '@sendbird/chat/lib/__definition';
import type { SendbirdError } from '@sendbird/chat';
-import type { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import { CoreMessageType } from '../../../../utils';
-import { SdkStore } from '../../../../lib/types';
import useMessageSearch from '../hooks/useMessageSearch';
import { ClientSentMessages } from '../../../../types';
diff --git a/src/modules/MessageSearch/context/hooks/useSetChannel.ts b/src/modules/MessageSearch/context/hooks/useSetChannel.ts
index eef0ead99..d3fe8fcca 100644
--- a/src/modules/MessageSearch/context/hooks/useSetChannel.ts
+++ b/src/modules/MessageSearch/context/hooks/useSetChannel.ts
@@ -1,6 +1,5 @@
import { useEffect } from 'react';
-import type { Logger } from '../../../../lib/SendbirdState';
-import { SdkStore } from '../../../../lib/types';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import useMessageSearch from '../hooks/useMessageSearch';
interface MainProps {
diff --git a/src/modules/OpenChannel/components/OpenChannelMessage/index.tsx b/src/modules/OpenChannel/components/OpenChannelMessage/index.tsx
index 578e57119..a13ad1ead 100644
--- a/src/modules/OpenChannel/components/OpenChannelMessage/index.tsx
+++ b/src/modules/OpenChannel/components/OpenChannelMessage/index.tsx
@@ -18,10 +18,10 @@ import FileViewer from '../../../../ui/FileViewer';
import RemoveMessageModal from './RemoveMessageModal';
import { MessageTypes, SendingMessageStatus, getMessageType } from './utils';
import { useOpenChannelContext } from '../../context/OpenChannelProvider';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import type { RenderMessageProps } from '../../../../types';
import { useLocalization } from '../../../../lib/LocalizationContext';
import { CoreMessageType, SendableMessageType } from '../../../../utils';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export type OpenChannelMessageProps = {
renderMessage?: (props: RenderMessageProps) => React.ReactElement;
@@ -46,9 +46,9 @@ export default function OpenChannelMessage(
const { dateLocale, stringSet } = useLocalization();
const editDisabled = currentOpenChannel?.isFrozen;
- const globalState = useSendbirdStateContext();
- const currentUserId = globalState?.config?.userId;
- const isOgMessageEnabledInOpenChannel = globalState.config.openChannel.enableOgtag;
+ const { state } = useSendbird();
+ const currentUserId = state?.config?.userId;
+ const isOgMessageEnabledInOpenChannel = state.config.openChannel.enableOgtag;
let sender: User | undefined;
if (message?.messageType !== 'admin') {
diff --git a/src/modules/OpenChannel/components/OpenChannelMessageList/index.tsx b/src/modules/OpenChannel/components/OpenChannelMessageList/index.tsx
index ef60cc5da..c9b877656 100644
--- a/src/modules/OpenChannel/components/OpenChannelMessageList/index.tsx
+++ b/src/modules/OpenChannel/components/OpenChannelMessageList/index.tsx
@@ -11,9 +11,9 @@ import { useOpenChannelContext } from '../../context/OpenChannelProvider';
import OpenChannelMessage from '../OpenChannelMessage';
import { RenderMessageProps } from '../../../../types';
import { MessageProvider } from '../../../Message/context/MessageProvider';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useHandleOnScrollCallback } from '../../../../hooks/useHandleOnScrollCallback';
import { compareMessagesForGrouping } from '../../../../utils/messages';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export type OpenChannelMessageListProps = {
renderMessage?: (props: RenderMessageProps) => React.ReactElement;
@@ -30,8 +30,8 @@ function OpenChannelMessageList(props: OpenChannelMessageListProps, ref: React.F
hasMore,
onScroll,
} = useOpenChannelContext();
- const store = useSendbirdStateContext();
- const userId = store.config.userId;
+ const { state } = useSendbird();
+ const userId = state.config.userId;
const localRef = useRef(null);
const scrollRef = ref || localRef;
const [showScrollDownButton, setShowScrollDownButton] = useState(false);
diff --git a/src/modules/OpenChannel/context/OpenChannelProvider.tsx b/src/modules/OpenChannel/context/OpenChannelProvider.tsx
index 7bdcddb28..0db823394 100644
--- a/src/modules/OpenChannel/context/OpenChannelProvider.tsx
+++ b/src/modules/OpenChannel/context/OpenChannelProvider.tsx
@@ -29,7 +29,7 @@ import useUpdateMessageCallback from './hooks/useUpdateMessageCallback';
import useDeleteMessageCallback from './hooks/useDeleteMessageCallback';
import useResendMessageCallback from './hooks/useResendMessageCallback';
import useTrimMessageList from './hooks/useTrimMessageList';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
type OpenChannelQueries = {
// https://sendbird.github.io/core-sdk-javascript/module-model_params_messageListParams-MessageListParams.html
@@ -101,12 +101,12 @@ const OpenChannelProvider: React.FC = (props: OpenChan
// We didn't decide to support fetching participant list
const fetchingParticipants = false;
- const globalStore = useSendbirdStateContext();
+ const { state } = useSendbird();
- const sdk = globalStore?.stores?.sdkStore?.sdk;
- const sdkInit = globalStore?.stores?.sdkStore?.initialized;
- const user = globalStore?.stores?.userStore?.user;
- const config = globalStore?.config;
+ const sdk = state.stores.sdkStore.sdk;
+ const sdkInit = state.stores.sdkStore.initialized;
+ const user = state.stores.userStore.user;
+ const config = state.config;
const {
userId,
diff --git a/src/modules/OpenChannel/context/hooks/useDeleteMessageCallback.ts b/src/modules/OpenChannel/context/hooks/useDeleteMessageCallback.ts
index a46247168..bb7fd4401 100644
--- a/src/modules/OpenChannel/context/hooks/useDeleteMessageCallback.ts
+++ b/src/modules/OpenChannel/context/hooks/useDeleteMessageCallback.ts
@@ -1,9 +1,9 @@
import type { UserMessage } from '@sendbird/chat/message';
import type { OpenChannel } from '@sendbird/chat/openChannel';
+import type { Logger } from '../../../../lib/Sendbird/types';
import { useCallback } from 'react';
import * as messageActionTypes from '../dux/actionTypes';
import { SendableMessageType } from '../../../../utils';
-import { Logger } from '../../../../lib/SendbirdState';
interface DynamicParams {
currentOpenChannel: OpenChannel | null;
diff --git a/src/modules/OpenChannel/context/hooks/useFileUploadCallback.tsx b/src/modules/OpenChannel/context/hooks/useFileUploadCallback.tsx
index e29024ac2..93a8de7ed 100644
--- a/src/modules/OpenChannel/context/hooks/useFileUploadCallback.tsx
+++ b/src/modules/OpenChannel/context/hooks/useFileUploadCallback.tsx
@@ -2,18 +2,16 @@ import React, { useCallback } from 'react';
import type { OpenChannel } from '@sendbird/chat/openChannel';
import type { FileMessageCreateParams } from '@sendbird/chat/message';
-import type { Logger } from '../../../../lib/SendbirdState';
-import type { ImageCompressionOptions } from '../../../../lib/Sendbird';
+import type { Logger, SdkStore, ImageCompressionOptions } from '../../../../lib/Sendbird/types';
import * as messageActionTypes from '../dux/actionTypes';
import * as utils from '../utils';
-import { SdkStore } from '../../../../lib/types';
import { compressImages } from '../../../../utils/compressImages';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useGlobalModalContext } from '../../../../hooks/useModal';
import { useLocalization } from '../../../../lib/LocalizationContext';
import { ONE_MiB } from '../../../../utils/consts';
import { ModalFooter } from '../../../../ui/Modal';
import { ButtonTypes } from '../../../../ui/Button';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface DynamicParams {
currentOpenChannel: OpenChannel | null;
@@ -39,8 +37,7 @@ function useFileUploadCallback({
): CallbackReturn {
const { stringSet } = useLocalization();
const { openModal } = useGlobalModalContext();
- const { config } = useSendbirdStateContext();
- const { uikitUploadSizeLimit } = config;
+ const { state: { config: { uikitUploadSizeLimit } } } = useSendbird();
return useCallback(async (files) => {
if (sdk) {
diff --git a/src/modules/OpenChannel/context/hooks/useHandleChannelEvents.ts b/src/modules/OpenChannel/context/hooks/useHandleChannelEvents.ts
index 0391aa181..b5e67dc2b 100644
--- a/src/modules/OpenChannel/context/hooks/useHandleChannelEvents.ts
+++ b/src/modules/OpenChannel/context/hooks/useHandleChannelEvents.ts
@@ -4,8 +4,7 @@ import { OpenChannel, OpenChannelHandler } from '@sendbird/chat/openChannel';
import * as messageActionTypes from '../dux/actionTypes';
import uuidv4 from '../../../../utils/uuid';
import { scrollIntoLast } from '../utils';
-import { Logger } from '../../../../lib/SendbirdState';
-import { SdkStore } from '../../../../lib/types';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
type MessagesDispatcherType = {
type: string, payload: any,
diff --git a/src/modules/OpenChannel/context/hooks/useInitialMessagesFetch.ts b/src/modules/OpenChannel/context/hooks/useInitialMessagesFetch.ts
index fcaf124af..2c285ef7c 100644
--- a/src/modules/OpenChannel/context/hooks/useInitialMessagesFetch.ts
+++ b/src/modules/OpenChannel/context/hooks/useInitialMessagesFetch.ts
@@ -2,7 +2,7 @@ import { MessageListParams } from '@sendbird/chat/message';
import type { OpenChannel } from '@sendbird/chat/openChannel';
import React, { useEffect } from 'react';
-import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState';
+import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/Sendbird/types';
import * as messageActionTypes from '../dux/actionTypes';
import { scrollIntoLast } from '../utils';
diff --git a/src/modules/OpenChannel/context/hooks/useResendMessageCallback.ts b/src/modules/OpenChannel/context/hooks/useResendMessageCallback.ts
index 47615d182..357208e45 100644
--- a/src/modules/OpenChannel/context/hooks/useResendMessageCallback.ts
+++ b/src/modules/OpenChannel/context/hooks/useResendMessageCallback.ts
@@ -1,8 +1,8 @@
import type { OpenChannel } from '@sendbird/chat/openChannel';
+import type { Logger } from '../../../../lib/Sendbird/types';
import { useCallback } from 'react';
import * as messageActionTypes from '../dux/actionTypes';
import { SendableMessageType } from '../../../../utils';
-import { Logger } from '../../../../lib/SendbirdState';
interface DynamicParams {
currentOpenChannel: OpenChannel | null;
diff --git a/src/modules/OpenChannel/context/hooks/useScrollCallback.ts b/src/modules/OpenChannel/context/hooks/useScrollCallback.ts
index 9bd5a95ef..c4e89743a 100644
--- a/src/modules/OpenChannel/context/hooks/useScrollCallback.ts
+++ b/src/modules/OpenChannel/context/hooks/useScrollCallback.ts
@@ -2,9 +2,8 @@ import { useCallback } from 'react';
import type { MessageListParams } from '@sendbird/chat/message';
import type { OpenChannel } from '@sendbird/chat/openChannel';
-import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState';
+import type { CustomUseReducerDispatcher, Logger, SdkStore } from '../../../../lib/Sendbird/types';
import * as messageActionTypes from '../dux/actionTypes';
-import { SdkStore } from '../../../../lib/types';
interface DynamicParams {
currentOpenChannel: OpenChannel | null;
diff --git a/src/modules/OpenChannel/context/hooks/useSendMessageCallback.ts b/src/modules/OpenChannel/context/hooks/useSendMessageCallback.ts
index fa7286aca..55ea407dc 100644
--- a/src/modules/OpenChannel/context/hooks/useSendMessageCallback.ts
+++ b/src/modules/OpenChannel/context/hooks/useSendMessageCallback.ts
@@ -2,10 +2,9 @@ import type { UserMessageCreateParams } from '@sendbird/chat/message';
import type { OpenChannel } from '@sendbird/chat/openChannel';
import React, { useCallback } from 'react';
-import type { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import * as messageActionTypes from '../dux/actionTypes';
import * as utils from '../utils';
-import { SdkStore } from '../../../../lib/types';
import { SendableMessage } from '@sendbird/chat/lib/__definition';
interface DynamicParams {
diff --git a/src/modules/OpenChannel/context/hooks/useSetChannel.ts b/src/modules/OpenChannel/context/hooks/useSetChannel.ts
index baef53e62..deb50f332 100644
--- a/src/modules/OpenChannel/context/hooks/useSetChannel.ts
+++ b/src/modules/OpenChannel/context/hooks/useSetChannel.ts
@@ -1,9 +1,8 @@
import type { OpenChannel } from '@sendbird/chat/openChannel';
import { useEffect } from 'react';
-import type { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import * as messageActionTypes from '../dux/actionTypes';
import * as utils from '../utils';
-import { SdkStore } from '../../../../lib/types';
interface DynamicParams {
channelUrl: string;
diff --git a/src/modules/OpenChannel/context/hooks/useUpdateMessageCallback.ts b/src/modules/OpenChannel/context/hooks/useUpdateMessageCallback.ts
index f40980e4f..4c8362231 100644
--- a/src/modules/OpenChannel/context/hooks/useUpdateMessageCallback.ts
+++ b/src/modules/OpenChannel/context/hooks/useUpdateMessageCallback.ts
@@ -1,6 +1,6 @@
import type { UserMessageUpdateParams } from '@sendbird/chat/message';
-import type { Logger } from '../../../../lib/SendbirdState';
+import type { Logger } from '../../../../lib/Sendbird/types';
import type { OpenChannel } from '@sendbird/chat/openChannel';
import { useCallback } from 'react';
import * as messageActionTypes from '../dux/actionTypes';
diff --git a/src/modules/OpenChannel/context/utils.ts b/src/modules/OpenChannel/context/utils.ts
index f27548b6f..79c1bdee8 100644
--- a/src/modules/OpenChannel/context/utils.ts
+++ b/src/modules/OpenChannel/context/utils.ts
@@ -3,7 +3,7 @@ import type { User } from '@sendbird/chat';
import type { OpenChannel, ParticipantListQuery } from '@sendbird/chat/openChannel';
import format from 'date-fns/format';
-import { Logger } from '../../../lib/SendbirdState';
+import { Logger } from '../../../lib/Sendbird/types';
import { SendableMessageType } from '../../../utils';
import { useLocalization } from '../../../lib/LocalizationContext';
diff --git a/src/modules/OpenChannelApp/components/CommunityChannelList.tsx b/src/modules/OpenChannelApp/components/CommunityChannelList.tsx
index dcd5e30d8..cb7e1b46a 100644
--- a/src/modules/OpenChannelApp/components/CommunityChannelList.tsx
+++ b/src/modules/OpenChannelApp/components/CommunityChannelList.tsx
@@ -12,7 +12,7 @@ import type {
OpenChannelListQuery,
SendbirdOpenChat,
} from '@sendbird/chat/openChannel';
-import withSendBird from '../../../lib/SendbirdSdkContext';
+import { withSendBird } from '../../../lib/Sendbird/index';
import * as sendbirdSelectors from '../../../lib/selectors';
import './community-channel-list.scss';
diff --git a/src/modules/OpenChannelApp/components/StreamingChannelList.tsx b/src/modules/OpenChannelApp/components/StreamingChannelList.tsx
index e16dc78c3..ec3589048 100644
--- a/src/modules/OpenChannelApp/components/StreamingChannelList.tsx
+++ b/src/modules/OpenChannelApp/components/StreamingChannelList.tsx
@@ -1,6 +1,6 @@
import React, { ReactElement, useEffect, useState } from 'react';
-import withSendBird from '../../../lib/SendbirdSdkContext';
+import { withSendBird } from '../../../lib/Sendbird/index';
import * as sendbirdSelectors from '../../../lib/selectors';
import './streaming-channel-list.scss';
diff --git a/src/modules/OpenChannelList/context/OpenChannelListInterfaces.ts b/src/modules/OpenChannelList/context/OpenChannelListInterfaces.ts
index 72f5fdda2..de2f9f172 100644
--- a/src/modules/OpenChannelList/context/OpenChannelListInterfaces.ts
+++ b/src/modules/OpenChannelList/context/OpenChannelListInterfaces.ts
@@ -1,6 +1,6 @@
import { OpenChannel } from '@sendbird/chat/openChannel';
import { Dispatch } from 'react';
-import { Logger } from '../../../lib/SendbirdState';
+import { Logger } from '../../../lib/Sendbird/types';
import OpenChannelListActionTypes from './dux/actionTypes';
import { FetchNextCallbackType } from './hooks/useFetchNextCallback';
diff --git a/src/modules/OpenChannelList/context/OpenChannelListProvider.tsx b/src/modules/OpenChannelList/context/OpenChannelListProvider.tsx
index 89b1bc126..f8c0e2fbc 100644
--- a/src/modules/OpenChannelList/context/OpenChannelListProvider.tsx
+++ b/src/modules/OpenChannelList/context/OpenChannelListProvider.tsx
@@ -1,7 +1,6 @@
import React, { useContext, useReducer, useEffect } from 'react';
import pubSubTopics from '../../../lib/pubSub/topics';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import openChannelListReducer from './dux/reducer';
import openChannelListInitialState, { OpenChannelListInitialInterface } from './dux/initialState';
@@ -14,6 +13,7 @@ import useFetchNextCallback from './hooks/useFetchNextCallback';
import useSetupOpenChannelList from './hooks/useSetupOpenChannelList';
import useRefreshOpenChannelList from './hooks/useRefreshOpenChannelList';
import OpenChannelListActionTypes from './dux/actionTypes';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
const OpenChannelListContext = React.createContext(null);
@@ -30,7 +30,7 @@ export const OpenChannelListProvider: React.FC = (
onChannelSelected,
}: OpenChannelListProviderProps): React.ReactElement => {
// props
- const { stores, config } = useSendbirdStateContext();
+ const { state: { stores, config } } = useSendbird();
const { logger, pubSub } = config;
const sdk = stores?.sdkStore?.sdk || null;
const sdkInitialized = stores?.sdkStore?.initialized || false;
diff --git a/src/modules/OpenChannelList/context/hooks/createChannelListQuery.ts b/src/modules/OpenChannelList/context/hooks/createChannelListQuery.ts
index 15e50af5b..a6f2eb0e5 100644
--- a/src/modules/OpenChannelList/context/hooks/createChannelListQuery.ts
+++ b/src/modules/OpenChannelList/context/hooks/createChannelListQuery.ts
@@ -1,8 +1,7 @@
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import { OpenChannelListQuery, OpenChannelListQueryParams } from '@sendbird/chat/openChannel';
-import { Logger } from '../../../../lib/SendbirdState';
import OpenChannelListActionTypes from '../dux/actionTypes';
import { OpenChannelListDispatcherType, UserFilledOpenChannelListQuery } from '../OpenChannelListInterfaces';
-import { SdkStore } from '../../../../lib/types';
interface createChannelListQueryProps {
sdk: SdkStore['sdk'];
diff --git a/src/modules/OpenChannelList/context/hooks/useFetchNextCallback.ts b/src/modules/OpenChannelList/context/hooks/useFetchNextCallback.ts
index be807ef80..cdd89f229 100644
--- a/src/modules/OpenChannelList/context/hooks/useFetchNextCallback.ts
+++ b/src/modules/OpenChannelList/context/hooks/useFetchNextCallback.ts
@@ -3,7 +3,7 @@ import { useCallback } from 'react';
import { SendbirdError } from '@sendbird/chat';
import { OpenChannel, OpenChannelListQuery } from '@sendbird/chat/openChannel';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger } from '../../../../lib/Sendbird/types';
import OpenChannelListActionTypes from '../dux/actionTypes';
import { OpenChannelListDispatcherType } from '../OpenChannelListInterfaces';
diff --git a/src/modules/OpenChannelList/context/hooks/useRefreshOpenChannelList.ts b/src/modules/OpenChannelList/context/hooks/useRefreshOpenChannelList.ts
index 882bbcdc4..279193cac 100644
--- a/src/modules/OpenChannelList/context/hooks/useRefreshOpenChannelList.ts
+++ b/src/modules/OpenChannelList/context/hooks/useRefreshOpenChannelList.ts
@@ -1,10 +1,9 @@
import { useCallback } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import createChannelListQuery from './createChannelListQuery';
import { OpenChannelListDispatcherType, UserFilledOpenChannelListQuery } from '../OpenChannelListInterfaces';
import OpenChannelListActionTypes from '../dux/actionTypes';
-import { SdkStore } from '../../../../lib/types';
interface DynamicParams {
sdk: SdkStore['sdk'];
diff --git a/src/modules/OpenChannelList/context/hooks/useSetupOpenChannelList.ts b/src/modules/OpenChannelList/context/hooks/useSetupOpenChannelList.ts
index 6439ebb28..59cd35d84 100644
--- a/src/modules/OpenChannelList/context/hooks/useSetupOpenChannelList.ts
+++ b/src/modules/OpenChannelList/context/hooks/useSetupOpenChannelList.ts
@@ -1,10 +1,9 @@
import { useEffect } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import OpenChannelListActionTypes from '../dux/actionTypes';
import { OpenChannelListDispatcherType, UserFilledOpenChannelListQuery } from '../OpenChannelListInterfaces';
import createChannelListQuery from './createChannelListQuery';
-import { SdkStore } from '../../../../lib/types';
interface DynamicParams {
sdk: SdkStore['sdk'];
diff --git a/src/modules/OpenChannelSettings/components/EditDetailsModal.tsx b/src/modules/OpenChannelSettings/components/EditDetailsModal.tsx
index 514e2a8bc..2f5dca6ac 100644
--- a/src/modules/OpenChannelSettings/components/EditDetailsModal.tsx
+++ b/src/modules/OpenChannelSettings/components/EditDetailsModal.tsx
@@ -16,7 +16,7 @@ import Label, { LabelColors, LabelTypography } from '../../../ui/Label';
import TextButton from '../../../ui/TextButton';
import OpenChannelAvatar from '../../../ui/ChannelAvatar/OpenChannelAvatar';
import { useOpenChannelSettingsContext } from '../context/OpenChannelSettingsProvider';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
interface Props {
onCancel(): void;
@@ -26,8 +26,8 @@ const EditDetails = (props: Props): ReactElement => {
const {
onCancel,
} = props;
- const globalState = useSendbirdStateContext();
- const { logger, theme, pubSub } = globalState.config;
+ const { state } = useSendbird();
+ const { logger, theme, pubSub } = state.config;
const {
channel,
onBeforeUpdateChannel,
diff --git a/src/modules/OpenChannelSettings/components/OpenChannelProfile/index.tsx b/src/modules/OpenChannelSettings/components/OpenChannelProfile/index.tsx
index a32b7c35c..5b3c53a18 100644
--- a/src/modules/OpenChannelSettings/components/OpenChannelProfile/index.tsx
+++ b/src/modules/OpenChannelSettings/components/OpenChannelProfile/index.tsx
@@ -11,13 +11,13 @@ import Label, { LabelColors, LabelTypography } from '../../../../ui/Label';
import TextButton from '../../../../ui/TextButton';
import OpenChannelAvatar from '../../../../ui/ChannelAvatar/OpenChannelAvatar';
import EditDetailsModal from '../EditDetailsModal';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export default function ChannelProfile(): ReactElement {
- const globalState = useSendbirdStateContext();
- const disabled = !(globalState?.config?.isOnline);
- const theme = globalState?.config?.theme;
+ const { state } = useSendbird();
+ const disabled = !(state?.config?.isOnline);
+ const theme = state?.config?.theme;
const {
channel,
} = useOpenChannelSettingsContext();
diff --git a/src/modules/OpenChannelSettings/components/OpenChannelSettingsUI/index.tsx b/src/modules/OpenChannelSettings/components/OpenChannelSettingsUI/index.tsx
index ed55d2482..1d1806b76 100644
--- a/src/modules/OpenChannelSettings/components/OpenChannelSettingsUI/index.tsx
+++ b/src/modules/OpenChannelSettings/components/OpenChannelSettingsUI/index.tsx
@@ -1,7 +1,6 @@
import './open-channel-ui.scss';
import React, { useContext } from 'react';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
@@ -11,6 +10,7 @@ import ParticipantUI from '../ParticipantUI';
import Label, { LabelTypography, LabelColors } from '../../../../ui/Label';
import Icon, { IconTypes } from '../../../../ui/Icon';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface OpenChannelUIProps {
renderOperatorUI?: () => React.ReactElement;
@@ -26,9 +26,9 @@ const OpenChannelUI: React.FC = ({
onCloseClick,
isChannelInitialized,
} = useOpenChannelSettingsContext();
- const globalStore = useSendbirdStateContext();
- const logger = globalStore?.config?.logger;
- const user = globalStore?.stores?.userStore?.user;
+ const { state } = useSendbird();
+ const logger = state?.config?.logger;
+ const user = state?.stores?.userStore?.user;
const { stringSet } = useContext(LocalizationContext);
if (isChannelInitialized && !channel) {
diff --git a/src/modules/OpenChannelSettings/components/OperatorUI/BannedUserList.tsx b/src/modules/OpenChannelSettings/components/OperatorUI/BannedUserList.tsx
index 0a710df2a..3db541f98 100644
--- a/src/modules/OpenChannelSettings/components/OperatorUI/BannedUserList.tsx
+++ b/src/modules/OpenChannelSettings/components/OperatorUI/BannedUserList.tsx
@@ -16,8 +16,8 @@ import BannedUsersModal from './BannedUsersModal';
import { UserListItem } from '../ParticipantUI/ParticipantItem';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { RestrictedUser } from '@sendbird/chat';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export const BannedUserList = (): ReactElement => {
const [bannedUsers, setBannedUsers] = useState([]);
@@ -25,7 +25,7 @@ export const BannedUserList = (): ReactElement => {
const [showModal, setShowModal] = useState(false);
const { channel } = useOpenChannelSettingsContext();
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const { stringSet } = useContext(LocalizationContext);
const currentUserId = state?.config?.userId;
diff --git a/src/modules/OpenChannelSettings/components/OperatorUI/BannedUsersModal.tsx b/src/modules/OpenChannelSettings/components/OperatorUI/BannedUsersModal.tsx
index f4d27e41c..e94e8e64e 100644
--- a/src/modules/OpenChannelSettings/components/OperatorUI/BannedUsersModal.tsx
+++ b/src/modules/OpenChannelSettings/components/OperatorUI/BannedUsersModal.tsx
@@ -4,6 +4,7 @@ import React, {
useEffect,
useState,
} from 'react';
+import { BannedUserListQuery, RestrictedUser } from '@sendbird/chat';
import Modal from '../../../../ui/Modal';
import UserListItem from '../../../../ui/UserListItem';
@@ -14,8 +15,7 @@ import ContextMenu, { MenuItem, MenuItems } from '../../../../ui/ContextMenu';
import { noop } from '../../../../utils/utils';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
-import { BannedUserListQuery, RestrictedUser } from '@sendbird/chat';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface Props {
onCancel(): void;
@@ -27,7 +27,7 @@ export default function BannedUsersModal({
const [bannedUsers, setBannedUsers] = useState([]);
const [userListQuery, setUserListQuery] = useState(null);
const { channel } = useOpenChannelSettingsContext();
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const { stringSet } = useContext(LocalizationContext);
const currentUserId = state?.config?.userId;
diff --git a/src/modules/OpenChannelSettings/components/OperatorUI/DeleteOpenChannel.tsx b/src/modules/OpenChannelSettings/components/OperatorUI/DeleteOpenChannel.tsx
index db5468213..720f8ac6b 100644
--- a/src/modules/OpenChannelSettings/components/OperatorUI/DeleteOpenChannel.tsx
+++ b/src/modules/OpenChannelSettings/components/OperatorUI/DeleteOpenChannel.tsx
@@ -8,15 +8,13 @@ import Modal from '../../../../ui/Modal';
import Label, { LabelTypography, LabelColors } from '../../../../ui/Label';
import Icon, { IconTypes, IconColors } from '../../../../ui/Icon';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export default function DeleteChannel(): ReactElement {
const [showDeleteChannelModal, setShowDeleteChannelModal] = useState(false);
const { stringSet } = useContext(LocalizationContext);
- const globalState = useSendbirdStateContext();
- const isOnline = globalState?.config?.isOnline;
- const logger = globalState?.config?.logger;
+ const { state: { config: { isOnline, logger } } } = useSendbird();
const { channel, onDeleteChannel } = useOpenChannelSettingsContext();
diff --git a/src/modules/OpenChannelSettings/components/OperatorUI/MutedParticipantList.tsx b/src/modules/OpenChannelSettings/components/OperatorUI/MutedParticipantList.tsx
index 4e13d5133..d90ba105b 100644
--- a/src/modules/OpenChannelSettings/components/OperatorUI/MutedParticipantList.tsx
+++ b/src/modules/OpenChannelSettings/components/OperatorUI/MutedParticipantList.tsx
@@ -5,6 +5,7 @@ import React, {
useCallback,
useContext,
} from 'react';
+import { RestrictedUser } from '@sendbird/chat';
import Button, { ButtonTypes, ButtonSizes } from '../../../../ui/Button';
import IconButton from '../../../../ui/IconButton';
@@ -13,10 +14,9 @@ import ContextMenu, { MenuItem, MenuItems } from '../../../../ui/ContextMenu';
import Label, { LabelTypography, LabelColors } from '../../../../ui/Label';
import { UserListItem } from '../ParticipantUI/ParticipantItem';
import MutedParticipantsModal from './MutedParticipantsModal';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
-import { RestrictedUser } from '@sendbird/chat';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export const MutedParticipantList = (): ReactElement => {
const [mutedUsers, setMutedUsers] = useState([]);
@@ -24,7 +24,7 @@ export const MutedParticipantList = (): ReactElement => {
const [showModal, setShowModal] = useState(false);
const { channel } = useOpenChannelSettingsContext();
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const currentUserId = state?.config?.userId;
const { stringSet } = useContext(LocalizationContext);
diff --git a/src/modules/OpenChannelSettings/components/OperatorUI/MutedParticipantsModal.tsx b/src/modules/OpenChannelSettings/components/OperatorUI/MutedParticipantsModal.tsx
index 03206a0d2..28d49ae8b 100644
--- a/src/modules/OpenChannelSettings/components/OperatorUI/MutedParticipantsModal.tsx
+++ b/src/modules/OpenChannelSettings/components/OperatorUI/MutedParticipantsModal.tsx
@@ -12,9 +12,9 @@ import Icon, { IconTypes, IconColors } from '../../../../ui/Icon';
import ContextMenu, { MenuItem, MenuItems } from '../../../../ui/ContextMenu';
import { noop } from '../../../../utils/utils';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
import { MutedUserListQuery, User } from '@sendbird/chat';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface Props {
onCancel(): void;
@@ -27,7 +27,7 @@ export default function MutedParticipantsModal({
const [userListQuery, setUserListQuery] = useState(null);
const { channel } = useOpenChannelSettingsContext();
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const currentUserId = state?.config?.userId;
const { stringSet } = useContext(LocalizationContext);
diff --git a/src/modules/OpenChannelSettings/components/OperatorUI/OperatorList.tsx b/src/modules/OpenChannelSettings/components/OperatorUI/OperatorList.tsx
index f6d9c8212..e262b3b10 100644
--- a/src/modules/OpenChannelSettings/components/OperatorUI/OperatorList.tsx
+++ b/src/modules/OpenChannelSettings/components/OperatorUI/OperatorList.tsx
@@ -1,7 +1,6 @@
import React, { ReactElement, useContext, useState } from 'react';
import { UserListItem } from '../ParticipantUI/ParticipantItem';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import Button, { ButtonTypes, ButtonSizes } from '../../../../ui/Button';
import ContextMenu, { MenuItem, MenuItems, MuteMenuItem } from '../../../../ui/ContextMenu';
@@ -12,11 +11,12 @@ import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettings
import OperatorListModal from './OperatorsModal';
import AddOperatorsModal from './AddOperatorsModal';
import { Participant } from '@sendbird/chat';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
const OperatorList = (): ReactElement => {
const [showAdd, setShowAdd] = useState(false);
const [showMore, setShowMore] = useState(false);
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const currentUserId = state?.config?.userId;
const { stringSet } = useContext(LocalizationContext);
const { channel } = useOpenChannelSettingsContext();
diff --git a/src/modules/OpenChannelSettings/components/OperatorUI/OperatorsModal.tsx b/src/modules/OpenChannelSettings/components/OperatorUI/OperatorsModal.tsx
index d82d2237c..42901f3c4 100644
--- a/src/modules/OpenChannelSettings/components/OperatorUI/OperatorsModal.tsx
+++ b/src/modules/OpenChannelSettings/components/OperatorUI/OperatorsModal.tsx
@@ -11,10 +11,10 @@ import IconButton from '../../../../ui/IconButton';
import Icon, { IconTypes, IconColors } from '../../../../ui/Icon';
import ContextMenu, { MenuItem, MenuItems } from '../../../../ui/ContextMenu';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
import { OperatorListQuery, User } from '@sendbird/chat';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface Props { onCancel?(): void }
@@ -23,7 +23,7 @@ export default function OperatorListModal({ onCancel }: Props): ReactElement {
const [operatorQuery, setOperatorQuery] = useState(null);
const { channel } = useOpenChannelSettingsContext();
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const currentUserId = state?.config?.userId;
const { stringSet } = useContext(LocalizationContext);
diff --git a/src/modules/OpenChannelSettings/components/ParticipantUI/ParticipantItem.tsx b/src/modules/OpenChannelSettings/components/ParticipantUI/ParticipantItem.tsx
index 261d89c13..15f629d3f 100644
--- a/src/modules/OpenChannelSettings/components/ParticipantUI/ParticipantItem.tsx
+++ b/src/modules/OpenChannelSettings/components/ParticipantUI/ParticipantItem.tsx
@@ -18,8 +18,8 @@ import ParticipantsModal from './ParticipantsModal';
import UserProfile from '../../../../ui/UserProfile';
import ContextMenu, { MenuItems } from '../../../../ui/ContextMenu';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import MutedAvatarOverlay from '../../../../ui/Avatar/MutedAvatarOverlay';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
const SHOWN_MEMBER_MAX = 10;
@@ -153,8 +153,8 @@ export interface ParticipantsAccordionProps {
export default function ParticipantsAccordion(props: ParticipantsAccordionProps): ReactElement {
const maxMembers = props?.maxMembers || SHOWN_MEMBER_MAX;
const { channel } = useOpenChannelSettingsContext();
- const globalState = useSendbirdStateContext();
- const currentUserId = globalState?.config?.userId;
+ const { state } = useSendbird();
+ const currentUserId = state?.config?.userId;
const [participants, setParticipants] = useState([]);
const [showMoreModal, setShowMoreModal] = useState(false);
const { stringSet } = useContext(LocalizationContext);
diff --git a/src/modules/OpenChannelSettings/components/ParticipantUI/ParticipantsModal.tsx b/src/modules/OpenChannelSettings/components/ParticipantUI/ParticipantsModal.tsx
index 4d77222a2..b757d7530 100644
--- a/src/modules/OpenChannelSettings/components/ParticipantUI/ParticipantsModal.tsx
+++ b/src/modules/OpenChannelSettings/components/ParticipantUI/ParticipantsModal.tsx
@@ -15,7 +15,7 @@ import Icon, { IconTypes, IconColors } from '../../../../ui/Icon';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
import { noop } from '../../../../utils/utils';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface Props {
onCancel(): void;
@@ -24,7 +24,7 @@ interface Props {
export default function ParticipantsModal({
onCancel,
}: Props): ReactElement {
- const state = useSendbirdStateContext();
+ const { state } = useSendbird();
const { channel } = useOpenChannelSettingsContext();
const { stringSet } = useContext(LocalizationContext);
const [participants, setParticipants] = useState | null>([]);
diff --git a/src/modules/OpenChannelSettings/components/ParticipantUI/index.tsx b/src/modules/OpenChannelSettings/components/ParticipantUI/index.tsx
index 010dc959b..933533692 100644
--- a/src/modules/OpenChannelSettings/components/ParticipantUI/index.tsx
+++ b/src/modules/OpenChannelSettings/components/ParticipantUI/index.tsx
@@ -18,7 +18,7 @@ import { UserListItem } from './ParticipantItem';
import ParticipantsModal from './ParticipantsModal';
import { LocalizationContext } from '../../../../lib/LocalizationContext';
import { useOpenChannelSettingsContext } from '../../context/OpenChannelSettingsProvider';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
interface ParticipantListProps {
isOperatorView?: boolean;
@@ -27,8 +27,8 @@ interface ParticipantListProps {
export default function ParticipantList({
isOperatorView = false,
}: ParticipantListProps): ReactElement {
- const globalState = useSendbirdStateContext();
- const currentUserId = globalState?.config?.userId;
+ const { state } = useSendbird();
+ const currentUserId = state?.config?.userId;
const { channel } = useOpenChannelSettingsContext();
const { stringSet } = useContext(LocalizationContext);
const [participants, setParticipants] = useState | null>(null);
diff --git a/src/modules/OpenChannelSettings/context/OpenChannelSettingsProvider.tsx b/src/modules/OpenChannelSettings/context/OpenChannelSettingsProvider.tsx
index 253c62f0c..0e9a7d1ce 100644
--- a/src/modules/OpenChannelSettings/context/OpenChannelSettingsProvider.tsx
+++ b/src/modules/OpenChannelSettings/context/OpenChannelSettingsProvider.tsx
@@ -4,10 +4,10 @@ import React, {
} from 'react';
import { OpenChannel, OpenChannelHandler, OpenChannelUpdateParams } from '@sendbird/chat/openChannel';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { UserProfileProvider } from '../../../lib/UserProfileContext';
import { RenderUserProfileProps } from '../../../types';
import uuidv4 from '../../../utils/uuid';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export interface OpenChannelSettingsContextProps {
channelUrl: string;
@@ -44,11 +44,11 @@ const OpenChannelSettingsProvider: React.FC = (
} = props;
// fetch store from
- const globalStore = useSendbirdStateContext();
- const sdk = globalStore?.stores?.sdkStore?.sdk;
- const isSDKInitialized = globalStore?.stores?.sdkStore?.initialized;
+ const { state: { stores, config } } = useSendbird();
+ const sdk = stores?.sdkStore?.sdk;
+ const isSDKInitialized = stores?.sdkStore?.initialized;
- const logger = globalStore?.config?.logger;
+ const logger = config?.logger;
const currentUserId = sdk?.currentUser?.userId;
const [currentChannel, setChannel] = useState(null);
@@ -155,7 +155,7 @@ const OpenChannelSettingsProvider: React.FC = (
{children}
diff --git a/src/modules/Thread/components/ParentMessageInfo/ParentMessageInfoItem.tsx b/src/modules/Thread/components/ParentMessageInfo/ParentMessageInfoItem.tsx
index c990decae..407abd3f9 100644
--- a/src/modules/Thread/components/ParentMessageInfo/ParentMessageInfoItem.tsx
+++ b/src/modules/Thread/components/ParentMessageInfo/ParentMessageInfoItem.tsx
@@ -26,7 +26,6 @@ import Label, { LabelTypography, LabelColors } from '../../../../ui/Label';
import ImageRenderer from '../../../../ui/ImageRenderer';
import Icon, { IconTypes, IconColors } from '../../../../ui/Icon';
import TextButton from '../../../../ui/TextButton';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import EmojiReactions from '../../../../ui/EmojiReactions';
import VoiceMessageItemBody from '../../../../ui/VoiceMessageItemBody';
import TextFragment from '../../../Message/components/TextFragment';
@@ -39,6 +38,7 @@ import { Colors } from '../../../../utils/color';
import type { OnBeforeDownloadFileMessageType } from '../../../GroupChannel/context/types';
import { openURL } from '../../../../utils/utils';
import useThread from '../../context/useThread';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface ParentMessageInfoItemProps {
className?: string;
@@ -53,7 +53,7 @@ export default function ParentMessageInfoItem({
showFileViewer,
onBeforeDownloadFileMessage = null,
}: ParentMessageInfoItemProps): ReactElement {
- const { stores, config, eventHandlers } = useSendbirdStateContext();
+ const { state: { stores, config, eventHandlers } } = useSendbird();
const { logger } = config;
const onPressUserProfileHandler = eventHandlers?.reaction?.onPressUserProfile;
const currentUserId = stores?.userStore?.user?.userId;
diff --git a/src/modules/Thread/components/ParentMessageInfo/index.tsx b/src/modules/Thread/components/ParentMessageInfo/index.tsx
index f3238927c..b300e6b2d 100644
--- a/src/modules/Thread/components/ParentMessageInfo/index.tsx
+++ b/src/modules/Thread/components/ParentMessageInfo/index.tsx
@@ -9,7 +9,6 @@ import ParentMessageInfoItem from './ParentMessageInfoItem';
import { getSenderName, SendableMessageType } from '../../../../utils';
import { getIsReactionEnabled } from '../../../../utils/getIsReactionEnabled';
import { useLocalization } from '../../../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useUserProfileContext } from '../../../../lib/UserProfileContext';
import SuggestedMentionList from '../SuggestedMentionList';
@@ -21,7 +20,7 @@ import ContextMenu, { EMOJI_MENU_ROOT_ID, getObservingId, MENU_OBSERVING_CLASS_N
import ConnectedUserProfile from '../../../../ui/UserProfile';
import MessageInput from '../../../../ui/MessageInput';
import { MessageInputKeys } from '../../../../ui/MessageInput/const';
-import { Role } from '../../../../lib/types';
+import { Role } from '../../../../lib/Sendbird/types';
import { useMediaQueryContext } from '../../../../lib/MediaQueryContext';
import useLongPress from '../../../../hooks/useLongPress';
import MobileMenu from '../../../../ui/MobileMenu';
@@ -32,6 +31,7 @@ import { classnames } from '../../../../utils/utils';
import { MessageMenu, MessageMenuProps } from '../../../../ui/MessageMenu';
import useElementObserver from '../../../../hooks/useElementObserver';
import useThread from '../../context/useThread';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface ParentMessageInfoProps {
className?: string;
@@ -44,7 +44,7 @@ export default function ParentMessageInfo({
renderEmojiMenu = (props) => ,
renderMessageMenu = (props) => ,
}: ParentMessageInfoProps): React.ReactElement {
- const { stores, config } = useSendbirdStateContext();
+ const { state: { stores, config } } = useSendbird();
const { isOnline, userMention, logger, groupChannel } = config;
const userId = stores.userStore.user?.userId ?? '';
const { dateLocale, stringSet } = useLocalization();
diff --git a/src/modules/Thread/components/ThreadList/ThreadListItem.tsx b/src/modules/Thread/components/ThreadList/ThreadListItem.tsx
index 873e04cce..7c5bbb7f9 100644
--- a/src/modules/Thread/components/ThreadList/ThreadListItem.tsx
+++ b/src/modules/Thread/components/ThreadList/ThreadListItem.tsx
@@ -7,13 +7,12 @@ import DateSeparator from '../../../../ui/DateSeparator';
import Label, { LabelTypography, LabelColors } from '../../../../ui/Label';
import RemoveMessage from '../RemoveMessageModal';
import FileViewer from '../../../../ui/FileViewer';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import SuggestedMentionList from '../SuggestedMentionList';
import MessageInput from '../../../../ui/MessageInput';
import { ThreadListStateTypes } from '../../types';
import { MessageInputKeys } from '../../../../ui/MessageInput/const';
import ThreadListItemContent from './ThreadListItemContent';
-import { Role } from '../../../../lib/types';
+import { Role } from '../../../../lib/Sendbird/types';
import { useDirtyGetMentions } from '../../../Message/hooks/useDirtyGetMentions';
import { getIsReactionEnabled } from '../../../../utils/getIsReactionEnabled';
import { SendableMessageType } from '../../../../utils';
@@ -22,6 +21,7 @@ import { getCaseResolvedReplyType } from '../../../../lib/utils/resolvedReplyTyp
import { classnames } from '../../../../utils/utils';
import { MessageComponentRenderers } from '../../../../ui/MessageContent';
import useThread from '../../context/useThread';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface ThreadListItemProps extends MessageComponentRenderers {
className?: string;
@@ -43,7 +43,7 @@ export default function ThreadListItem(props: ThreadListItemProps): React.ReactE
renderCustomSeparator,
handleScroll,
} = props;
- const { stores, config } = useSendbirdStateContext();
+ const { state: { stores, config } } = useSendbird();
const { isOnline, userMention, logger, groupChannel } = config;
const userId = stores?.userStore?.user?.userId;
const { dateLocale, stringSet } = useLocalization();
diff --git a/src/modules/Thread/components/ThreadList/ThreadListItemContent.tsx b/src/modules/Thread/components/ThreadList/ThreadListItemContent.tsx
index 7e05bb74c..89e6ce61e 100644
--- a/src/modules/Thread/components/ThreadList/ThreadListItemContent.tsx
+++ b/src/modules/Thread/components/ThreadList/ThreadListItemContent.tsx
@@ -23,7 +23,6 @@ import { useLocalization } from '../../../../lib/LocalizationContext';
import { useMediaQueryContext } from '../../../../lib/MediaQueryContext';
import useLongPress from '../../../../hooks/useLongPress';
import MobileMenu from '../../../../ui/MobileMenu';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { ThreadMessageKind } from '../../../../ui/MultipleFilesMessageItemBody';
import { useThreadMessageKindKeySelector } from '../../../Channel/context/hooks/useThreadMessageKindKeySelector';
import { useFileInfoListWithUploaded } from '../../../Channel/context/hooks/useFileInfoListWithUploaded';
@@ -36,6 +35,7 @@ import MessageBody, { CustomSubcomponentsProps, MessageBodyProps } from '../../.
import { MessageHeaderProps, MessageHeader } from '../../../../ui/MessageContent/MessageHeader';
import { MobileBottomSheetProps } from '../../../../ui/MobileMenu/types';
import useThread from '../../context/useThread';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface ThreadListItemContentProps extends MessageComponentRenderers {
className?: string;
@@ -99,7 +99,7 @@ export default function ThreadListItemContent(props: ThreadListItemContentProps)
const { isMobile } = useMediaQueryContext();
const { dateLocale, stringSet } = useLocalization();
- const { config, eventHandlers } = useSendbirdStateContext?.() || {};
+ const { state: { config, eventHandlers } } = useSendbird();
const { logger } = config;
const onPressUserProfileHandler = eventHandlers?.reaction?.onPressUserProfile;
const isMenuMounted = useElementObserver(
diff --git a/src/modules/Thread/components/ThreadList/index.tsx b/src/modules/Thread/components/ThreadList/index.tsx
index 40c0bce1d..a5d387c6a 100644
--- a/src/modules/Thread/components/ThreadList/index.tsx
+++ b/src/modules/Thread/components/ThreadList/index.tsx
@@ -6,11 +6,11 @@ import './index.scss';
import type { SendableMessageType } from '../../../../utils';
import ThreadListItem, { ThreadListItemProps } from './ThreadListItem';
import { compareMessagesForGrouping } from '../../../../utils/messages';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { isSameDay } from 'date-fns';
import { MessageProvider } from '../../../Message/context/MessageProvider';
import { getCaseResolvedReplyType } from '../../../../lib/utils/resolvedReplyType';
import useThread from '../../context/useThread';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface ThreadListProps {
className?: string;
@@ -27,7 +27,7 @@ export default function ThreadList({
scrollRef,
scrollBottom,
}: ThreadListProps): React.ReactElement {
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { userId } = config;
const {
state: {
diff --git a/src/modules/Thread/components/ThreadMessageInput/index.tsx b/src/modules/Thread/components/ThreadMessageInput/index.tsx
index e586350b2..f1734e244 100644
--- a/src/modules/Thread/components/ThreadMessageInput/index.tsx
+++ b/src/modules/Thread/components/ThreadMessageInput/index.tsx
@@ -3,7 +3,6 @@ import { MutedState } from '@sendbird/chat/groupChannel';
import './index.scss';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useMediaQueryContext } from '../../../../lib/MediaQueryContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
@@ -11,7 +10,7 @@ import MessageInput from '../../../../ui/MessageInput';
import { MessageInputKeys } from '../../../../ui/MessageInput/const';
import { SuggestedMentionList } from '../SuggestedMentionList';
import { VoiceMessageInputWrapper } from '../../../GroupChannel/components/MessageInputWrapper';
-import { Role } from '../../../../lib/types';
+import { Role } from '../../../../lib/Sendbird/types';
import { useDirtyGetMentions } from '../../../Message/hooks/useDirtyGetMentions';
import { useHandleUploadFiles } from '../../../Channel/context/hooks/useHandleUploadFiles';
@@ -19,6 +18,7 @@ import { isDisabledBecauseFrozen, isDisabledBecauseMuted } from '../../../Channe
import { User } from '@sendbird/chat';
import { classnames } from '../../../../utils/utils';
import useThread from '../../context/useThread';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface ThreadMessageInputProps {
className?: string;
@@ -41,7 +41,7 @@ const ThreadMessageInput = (
acceptableMimeTypes,
} = props;
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { isMobile } = useMediaQueryContext();
const { stringSet } = useLocalization();
const { isOnline, userMention, logger, groupChannel } = config;
diff --git a/src/modules/Thread/components/ThreadUI/index.tsx b/src/modules/Thread/components/ThreadUI/index.tsx
index 05f1cbf34..9e5d6ceff 100644
--- a/src/modules/Thread/components/ThreadUI/index.tsx
+++ b/src/modules/Thread/components/ThreadUI/index.tsx
@@ -2,7 +2,6 @@ import React, { ReactNode, useRef, useState } from 'react';
import './index.scss';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../../lib/LocalizationContext';
import { getChannelTitle } from '../../../GroupChannel/components/GroupChannelHeader/utils';
import { ParentMessageStateTypes, ThreadListStateTypes } from '../../types';
@@ -19,6 +18,7 @@ import { MessageProvider } from '../../../Message/context/MessageProvider';
import { SendableMessageType, getHTMLTextDirection } from '../../../../utils';
import { classnames } from '../../../../utils/utils';
import useThread from '../../context/useThread';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
export interface ThreadUIProps {
renderHeader?: () => React.ReactElement;
@@ -50,10 +50,7 @@ const ThreadUI: React.FC = ({
renderVoiceMessageIcon,
renderSendMessageIcon,
}: ThreadUIProps): React.ReactElement => {
- const {
- stores,
- config,
- } = useSendbirdStateContext();
+ const { state: { stores, config } } = useSendbird();
const currentUserId = stores?.sdkStore?.sdk?.currentUser?.userId;
const {
stringSet,
diff --git a/src/modules/Thread/context/ThreadProvider.tsx b/src/modules/Thread/context/ThreadProvider.tsx
index bb4da9a93..16f543fd0 100644
--- a/src/modules/Thread/context/ThreadProvider.tsx
+++ b/src/modules/Thread/context/ThreadProvider.tsx
@@ -9,7 +9,6 @@ import type {
import { getNicknamesMapFromMembers, getParentMessageFrom } from './utils';
import { UserProfileProvider, UserProfileProviderProps } from '../../../lib/UserProfileContext';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import type { OnBeforeDownloadFileMessageType } from '../../GroupChannel/context/types';
import useGetChannel from './hooks/useGetChannel';
@@ -23,6 +22,7 @@ import { ChannelStateTypes, ParentMessageStateTypes, ThreadListStateTypes } from
import { useStore } from '../../../hooks/useStore';
import useSetCurrentUserId from './hooks/useSetCurrentUserId';
import useThread from './useThread';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
export interface ThreadProviderProps extends
Pick {
@@ -138,8 +138,7 @@ export const ThreadManager: React.FC ({
- __esModule: true,
- default: jest.fn(() => ({
- stores: {
- sdkStore: {
- sdk: {
- groupChannel: {
- getChannel: mockGetChannel,
- },
+const mockState = {
+ stores: {
+ sdkStore: {
+ sdk: {
+ groupChannel: {
+ getChannel: mockGetChannel,
},
- initialized: true,
},
- userStore: { user: { userId: 'test-user-id' } },
+ initialized: true,
},
- config: {
- logger: console,
- pubSub: {
- publish: jest.fn(),
- },
- groupChannel: {
- enableMention: true,
- enableReactions: true,
- },
+ userStore: { user: { userId: 'test-user-id' } },
+ },
+ config: {
+ logger: console,
+ pubSub: {
+ publish: jest.fn(),
+ },
+ groupChannel: {
+ enableMention: true,
+ enableReactions: true,
},
- })),
+ },
+};
+jest.mock('../../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(() => ({ state: mockState })),
}));
describe('ThreadProvider', () => {
@@ -50,6 +52,12 @@ describe('ThreadProvider', () => {
messageId: 1,
} as SendableMessageType;
+ beforeEach(() => {
+ const stateContextValue = { state: mockState };
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
+ });
+
it('provides the correct initial state', async () => {
const wrapper = ({ children }) => (
{children}
diff --git a/src/modules/Thread/context/hooks/useDeleteMessageCallback.ts b/src/modules/Thread/context/hooks/useDeleteMessageCallback.ts
index 021ca7d27..fb81a7def 100644
--- a/src/modules/Thread/context/hooks/useDeleteMessageCallback.ts
+++ b/src/modules/Thread/context/hooks/useDeleteMessageCallback.ts
@@ -1,6 +1,7 @@
-import { GroupChannel } from '@sendbird/chat/groupChannel';
import { useCallback } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
+import { GroupChannel } from '@sendbird/chat/groupChannel';
+
+import type { Logger } from '../../../../lib/Sendbird/types';
import { SendableMessageType } from '../../../../utils';
interface DynamicProps {
diff --git a/src/modules/Thread/context/hooks/useGetAllEmoji.ts b/src/modules/Thread/context/hooks/useGetAllEmoji.ts
index e0a44a846..d941aa09e 100644
--- a/src/modules/Thread/context/hooks/useGetAllEmoji.ts
+++ b/src/modules/Thread/context/hooks/useGetAllEmoji.ts
@@ -1,7 +1,6 @@
import { useEffect } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
-import { SdkStore } from '../../../../lib/types';
import useThread from '../useThread';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
interface DanamicPrpos {
sdk: SdkStore['sdk'];
diff --git a/src/modules/Thread/context/hooks/useGetChannel.ts b/src/modules/Thread/context/hooks/useGetChannel.ts
index 7319ba6a8..608e12d23 100644
--- a/src/modules/Thread/context/hooks/useGetChannel.ts
+++ b/src/modules/Thread/context/hooks/useGetChannel.ts
@@ -1,8 +1,7 @@
import { useEffect } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import { SendableMessageType } from '../../../../utils';
-import { SdkStore } from '../../../../lib/types';
import useThread from '../useThread';
interface DynamicProps {
diff --git a/src/modules/Thread/context/hooks/useGetParentMessage.ts b/src/modules/Thread/context/hooks/useGetParentMessage.ts
index adfcd491d..23424cf17 100644
--- a/src/modules/Thread/context/hooks/useGetParentMessage.ts
+++ b/src/modules/Thread/context/hooks/useGetParentMessage.ts
@@ -1,9 +1,8 @@
import { useEffect } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import { BaseMessage, MessageRetrievalParams } from '@sendbird/chat/message';
import { ChannelType } from '@sendbird/chat';
-import { SdkStore } from '../../../../lib/types';
import useThread from '../useThread';
interface DynamicProps {
diff --git a/src/modules/Thread/context/hooks/useHandleChannelEvents.ts b/src/modules/Thread/context/hooks/useHandleChannelEvents.ts
index 2cd11c4cb..a26bde2d8 100644
--- a/src/modules/Thread/context/hooks/useHandleChannelEvents.ts
+++ b/src/modules/Thread/context/hooks/useHandleChannelEvents.ts
@@ -1,8 +1,7 @@
import { GroupChannel, GroupChannelHandler } from '@sendbird/chat/groupChannel';
import { useEffect } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
import uuidv4 from '../../../../utils/uuid';
-import { SdkStore } from '../../../../lib/types';
+import type { Logger, SdkStore } from '../../../../lib/Sendbird/types';
import compareIds from '../../../../utils/compareIds';
import useThread from '../useThread';
import { SendableMessageType } from '../../../../utils';
diff --git a/src/modules/Thread/context/hooks/useHandleThreadPubsubEvents.ts b/src/modules/Thread/context/hooks/useHandleThreadPubsubEvents.ts
index 022bac16b..780acaaa2 100644
--- a/src/modules/Thread/context/hooks/useHandleThreadPubsubEvents.ts
+++ b/src/modules/Thread/context/hooks/useHandleThreadPubsubEvents.ts
@@ -1,6 +1,7 @@
import { useEffect } from 'react';
import { GroupChannel } from '@sendbird/chat/groupChannel';
-import { Logger } from '../../../../lib/SendbirdState';
+
+import type { Logger } from '../../../../lib/Sendbird/types';
import topics, { PUBSUB_TOPICS, SBUGlobalPubSub } from '../../../../lib/pubSub/topics';
import { scrollIntoLast } from '../utils';
import { SendableMessageType } from '../../../../utils';
diff --git a/src/modules/Thread/context/hooks/useResendMessageCallback.ts b/src/modules/Thread/context/hooks/useResendMessageCallback.ts
index 2e9d5e20c..428add20e 100644
--- a/src/modules/Thread/context/hooks/useResendMessageCallback.ts
+++ b/src/modules/Thread/context/hooks/useResendMessageCallback.ts
@@ -1,3 +1,4 @@
+import { useCallback } from 'react';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import {
FileMessage,
@@ -7,8 +8,8 @@ import {
UploadableFileInfo,
UserMessage,
} from '@sendbird/chat/message';
-import { useCallback } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
+
+import type { Logger } from '../../../../lib/Sendbird/types';
import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics';
import { SendableMessageType } from '../../../../utils';
import { PublishingModuleType } from '../../../internalInterfaces';
diff --git a/src/modules/Thread/context/hooks/useSendFileMessage.ts b/src/modules/Thread/context/hooks/useSendFileMessage.ts
index cf7babd54..ef1b4bc14 100644
--- a/src/modules/Thread/context/hooks/useSendFileMessage.ts
+++ b/src/modules/Thread/context/hooks/useSendFileMessage.ts
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { FileMessage, FileMessageCreateParams, SendingStatus } from '@sendbird/chat/message';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger } from '../../../../lib/Sendbird/types';
import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics';
import { scrollIntoLast } from '../utils';
import { SendableMessageType } from '../../../../utils';
diff --git a/src/modules/Thread/context/hooks/useSendUserMessageCallback.ts b/src/modules/Thread/context/hooks/useSendUserMessageCallback.ts
index 5ef9ff216..b7681d516 100644
--- a/src/modules/Thread/context/hooks/useSendUserMessageCallback.ts
+++ b/src/modules/Thread/context/hooks/useSendUserMessageCallback.ts
@@ -3,7 +3,7 @@ import { GroupChannel } from '@sendbird/chat/groupChannel';
import { UserMessage, UserMessageCreateParams } from '@sendbird/chat/message';
import { User } from '@sendbird/chat';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger } from '../../../../lib/Sendbird/types';
import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics';
import { SendableMessageType } from '../../../../utils';
import { PublishingModuleType } from '../../../internalInterfaces';
diff --git a/src/modules/Thread/context/hooks/useSendVoiceMessageCallback.ts b/src/modules/Thread/context/hooks/useSendVoiceMessageCallback.ts
index c4632826f..fbe62974e 100644
--- a/src/modules/Thread/context/hooks/useSendVoiceMessageCallback.ts
+++ b/src/modules/Thread/context/hooks/useSendVoiceMessageCallback.ts
@@ -1,7 +1,8 @@
import { useCallback } from 'react';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { FileMessage, FileMessageCreateParams, MessageMetaArray, SendingStatus } from '@sendbird/chat/message';
-import { Logger } from '../../../../lib/SendbirdState';
+
+import type { Logger } from '../../../../lib/Sendbird/types';
import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics';
import { scrollIntoLast } from '../utils';
import {
diff --git a/src/modules/Thread/context/hooks/useThreadFetchers.ts b/src/modules/Thread/context/hooks/useThreadFetchers.ts
index fa9e4d642..a3ea176e2 100644
--- a/src/modules/Thread/context/hooks/useThreadFetchers.ts
+++ b/src/modules/Thread/context/hooks/useThreadFetchers.ts
@@ -3,8 +3,8 @@ import { BaseMessage, ThreadedMessageListParams } from '@sendbird/chat/message';
import { CoreMessageType, SendableMessageType } from '../../../../utils';
import { LoggerInterface } from '../../../../lib/Logger';
import { useCallback } from 'react';
-import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext';
import { ThreadListStateTypes } from '../../types';
+import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird';
type Params = {
anchorMessage?: SendableMessageType;
@@ -52,7 +52,7 @@ export const useThreadFetchers = ({
getNextMessagesSuccess,
getNextMessagesFailure,
}: Params) => {
- const { stores } = useSendbirdStateContext();
+ const { state: { stores } } = useSendbird();
const timestamp = anchorMessage?.createdAt || 0;
const initialize = useCallback(
diff --git a/src/modules/Thread/context/hooks/useToggleReactionsCallback.ts b/src/modules/Thread/context/hooks/useToggleReactionsCallback.ts
index 237b510b2..557767b39 100644
--- a/src/modules/Thread/context/hooks/useToggleReactionsCallback.ts
+++ b/src/modules/Thread/context/hooks/useToggleReactionsCallback.ts
@@ -1,8 +1,9 @@
-import { GroupChannel } from '@sendbird/chat/groupChannel';
import { useCallback } from 'react';
-import { Logger } from '../../../../lib/SendbirdState';
+import { GroupChannel } from '@sendbird/chat/groupChannel';
import { BaseMessage } from '@sendbird/chat/message';
+import type { Logger } from '../../../../lib/Sendbird/types';
+
interface DynamicProps {
currentChannel: GroupChannel | null;
}
diff --git a/src/modules/Thread/context/hooks/useUpdateMessageCallback.ts b/src/modules/Thread/context/hooks/useUpdateMessageCallback.ts
index fb5a981e4..3a23b6658 100644
--- a/src/modules/Thread/context/hooks/useUpdateMessageCallback.ts
+++ b/src/modules/Thread/context/hooks/useUpdateMessageCallback.ts
@@ -3,7 +3,7 @@ import { User } from '@sendbird/chat';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { UserMessage, UserMessageUpdateParams } from '@sendbird/chat/message';
-import { Logger } from '../../../../lib/SendbirdState';
+import type { Logger } from '../../../../lib/Sendbird/types';
import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics';
import { PublishingModuleType } from '../../../internalInterfaces';
diff --git a/src/modules/Thread/context/useThread.ts b/src/modules/Thread/context/useThread.ts
index 58e3f352c..7d68ebcaf 100644
--- a/src/modules/Thread/context/useThread.ts
+++ b/src/modules/Thread/context/useThread.ts
@@ -14,7 +14,7 @@ import {
} from '@sendbird/chat/message';
import { NEXT_THREADS_FETCH_SIZE, PREV_THREADS_FETCH_SIZE } from '../consts';
import useToggleReactionCallback from './hooks/useToggleReactionsCallback';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
import useSendUserMessageCallback from './hooks/useSendUserMessageCallback';
import { PublishingModuleType } from '../../../lib/pubSub/topics';
@@ -37,7 +37,7 @@ const useThread = () => {
if (!store) throw new Error('useCreateChannel must be used within a CreateChannelProvider');
// SendbirdStateContext config
- const { stores, config } = useSendbirdStateContext();
+ const { state: { stores, config } } = useSendbird();
const { logger, pubSub } = config;
const isMentionEnabled = config.groupChannel.enableMention;
const isReactionEnabled = config.groupChannel.enableReactions;
diff --git a/src/ui/BottomSheet/__tests__/BottomSheet.spec.js b/src/ui/BottomSheet/__tests__/BottomSheet.spec.js
index 8aa6296d0..bd8be5d76 100644
--- a/src/ui/BottomSheet/__tests__/BottomSheet.spec.js
+++ b/src/ui/BottomSheet/__tests__/BottomSheet.spec.js
@@ -1,15 +1,35 @@
import React from 'react';
-import { render } from '@testing-library/react';
+import { render, renderHook } from '@testing-library/react';
import BottomSheet from "../index";
-import { SendbirdSdkContext } from '../../../lib/SendbirdSdkContext';
+import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
+
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(),
+ useSendbird: jest.fn(),
+}));
+
describe('ui/BottomSheet', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ const stateContextValue = {
+ state: {
+ config: {},
+ stores: {},
+ },
+ };
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
+ });
+
it('should do a snapshot test of the default Button DOM', function () {
render(
-
+
-
+
);
expect(document.body.lastChild).toMatchSnapshot();
});
diff --git a/src/ui/BottomSheet/index.tsx b/src/ui/BottomSheet/index.tsx
index 6467353ae..b9f5ad35e 100644
--- a/src/ui/BottomSheet/index.tsx
+++ b/src/ui/BottomSheet/index.tsx
@@ -3,7 +3,7 @@ import React, { useRef } from 'react';
import { createPortal } from 'react-dom';
import { MODAL_ROOT } from '../../hooks/useModal';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
interface BottomSheetProps {
className?: string;
@@ -17,7 +17,7 @@ const BottomSheet: React.FunctionComponent = (props: BottomShe
children,
onBackdropClick,
} = props;
- const logger = useSendbirdStateContext()?.config?.logger;
+ const { state: { config: { logger } } } = useSendbird();
// https://github.com/testing-library/react-testing-library/issues/62#issuecomment-438653348
const portalRoot = useRef();
diff --git a/src/ui/EmojiReactions/ReactionItem.tsx b/src/ui/EmojiReactions/ReactionItem.tsx
index ebf52be26..caa539bf5 100644
--- a/src/ui/EmojiReactions/ReactionItem.tsx
+++ b/src/ui/EmojiReactions/ReactionItem.tsx
@@ -16,11 +16,11 @@ import { getEmojiTooltipString, isReactedBy, SendableMessageType } from '../../u
import { useMediaQueryContext } from '../../lib/MediaQueryContext';
import useLongPress from '../../hooks/useLongPress';
import { LocalizationContext } from '../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { useMessageContext } from '../../modules/Message/context/MessageProvider';
import { ModalFooter } from '../Modal';
import { ButtonTypes } from '../Button';
import { useGlobalModalContext } from '../../hooks/useModal';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
type Props = {
reaction: Reaction;
@@ -44,12 +44,11 @@ export default function ReactionItem({
isFiltered,
}: Props) {
const { openModal } = useGlobalModalContext();
- const store = useSendbirdStateContext();
+ const { state: { config: { userId } } } = useSendbird();
const { isMobile } = useMediaQueryContext();
const messageStore = useMessageContext();
const { stringSet } = useContext(LocalizationContext);
- const userId = store.config.userId;
const reactedByMe = isReactedBy(userId, reaction);
const showHoverTooltip = (reaction.userIds.length > 0)
&& (channel?.isGroupChannel() && !channel.isSuper);
diff --git a/src/ui/EmojiReactions/index.tsx b/src/ui/EmojiReactions/index.tsx
index 50f0a46a2..8c7926299 100644
--- a/src/ui/EmojiReactions/index.tsx
+++ b/src/ui/EmojiReactions/index.tsx
@@ -22,8 +22,8 @@ import ReactionItem from './ReactionItem';
import { useMediaQueryContext } from '../../lib/MediaQueryContext';
import { AddReactionBadgeItem } from './AddReactionBadgeItem';
import { MobileEmojisBottomSheet } from '../MobileMenu/MobileEmojisBottomSheet';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { getIsReactionEnabled } from '../../utils/getIsReactionEnabled';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
export interface EmojiReactionsProps {
className?: string | Array;
@@ -54,7 +54,7 @@ const EmojiReactions = ({
}: EmojiReactionsProps): ReactElement => {
let showTheReactedMembers = false;
try {
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
showTheReactedMembers = channel ? getIsReactionEnabled({
channel,
config,
diff --git a/src/ui/FileMessageItemBody/index.tsx b/src/ui/FileMessageItemBody/index.tsx
index 47e784cda..c5f476024 100644
--- a/src/ui/FileMessageItemBody/index.tsx
+++ b/src/ui/FileMessageItemBody/index.tsx
@@ -8,10 +8,10 @@ import TextButton from '../TextButton';
import { getClassName, getUIKitFileType, truncateString } from '../../utils';
import { Colors } from '../../utils/color';
import { useMediaQueryContext } from '../../lib/MediaQueryContext';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import type { OnBeforeDownloadFileMessageType } from '../../modules/GroupChannel/context/types';
import { LoggerInterface } from '../../lib/Logger';
import { openURL } from '../../utils/utils';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
interface Props {
className?: string | Array;
@@ -34,7 +34,8 @@ export default function FileMessageItemBody({
}: Props): ReactElement {
let logger: LoggerInterface | null = null;
try {
- logger = useSendbirdStateContext()?.config?.logger;
+ const { state: { config: { logger: globalLogger } } } = useSendbird();
+ logger = globalLogger;
} catch (err) {
// TODO: Handle error
}
diff --git a/src/ui/FileViewer/__tests__/FileViewer.spec.js b/src/ui/FileViewer/__tests__/FileViewer.spec.js
index 56694befa..0a714f9d6 100644
--- a/src/ui/FileViewer/__tests__/FileViewer.spec.js
+++ b/src/ui/FileViewer/__tests__/FileViewer.spec.js
@@ -1,10 +1,17 @@
import React from 'react';
-import { render, screen } from '@testing-library/react';
+import { render, screen, renderHook } from '@testing-library/react';
import { FileViewerComponent as FileViewer } from "../index";
import { msg0, msg1 } from '../data.mock';
-import { SendbirdSdkContext } from '../../../lib/SendbirdSdkContext';
import { MODAL_ROOT } from '../../../hooks/useModal';
+import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
+
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(),
+ useSendbird: jest.fn(),
+}));
describe('ui/FileViewer', () => {
let modalRoot;
@@ -21,6 +28,18 @@ describe('ui/FileViewer', () => {
document.body.removeChild(modalRoot);
});
+ beforeEach(() => {
+ jest.clearAllMocks();
+ const stateContextValue = {
+ state: {
+ config: {},
+ stores: {},
+ },
+ };
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
+ });
+
it('should display image', function () {
const {
sender,
@@ -30,7 +49,7 @@ describe('ui/FileViewer', () => {
} = msg0;
const { profileUrl, nickname = '' } = sender;
render(
-
+
{
onClose={() => { }}
onDelete={() => { }}
/>
-
+
);
expect(
screen.getByAltText(msg0.name).className
@@ -62,7 +81,7 @@ describe('ui/FileViewer', () => {
} = msg1;
const { profileUrl, nickname = '' } = sender;
const { container } = render(
-
+
{
onClose={() => { }}
onDelete={() => { }}
/>
-
+
);
// Use document to search for the element inside the modal root
@@ -98,7 +117,7 @@ describe('ui/FileViewer', () => {
name = '',
} = unsupportedMsg;
const { container } = render(
-
+
{
onClose={() => { }}
onDelete={() => { }}
/>
-
+
);
// Use document to search for the element inside the modal root
@@ -137,7 +156,7 @@ describe('ui/FileViewer', () => {
} = msg0;
const { profileUrl, nickname = '' } = sender;
const { asFragment } = render(
-
+
{
onDelete={() => { }}
message={msg0}
/>
-
+
);
expect(asFragment()).toMatchSnapshot();
});
diff --git a/src/ui/LegacyEditUserProfile/index.tsx b/src/ui/LegacyEditUserProfile/index.tsx
index 097d6cc10..930902424 100644
--- a/src/ui/LegacyEditUserProfile/index.tsx
+++ b/src/ui/LegacyEditUserProfile/index.tsx
@@ -8,7 +8,7 @@ import React, {
import type { User } from '@sendbird/chat';
import Modal from '../Modal';
-import withSendbirdContext from '../../lib/SendbirdSdkContext';
+import { withSendBird } from '../../lib/Sendbird/index';
import { LocalizationContext } from '../../lib/LocalizationContext';
import Input, { InputLabel } from '../Input';
@@ -179,6 +179,6 @@ interface ConnectedEditUserProfileProps {
const ConnectedEditUserProfile: (
props: ConnectedEditUserProfileProps
-) => React.ReactElement = withSendbirdContext(EditUserProfile, mapStoreToProps);
+) => React.ReactElement = withSendBird(EditUserProfile, mapStoreToProps);
export default ConnectedEditUserProfile;
diff --git a/src/ui/MentionLabel/index.tsx b/src/ui/MentionLabel/index.tsx
index 6b8c13745..4e948c0a2 100644
--- a/src/ui/MentionLabel/index.tsx
+++ b/src/ui/MentionLabel/index.tsx
@@ -11,8 +11,8 @@ import type { User } from '@sendbird/chat';
import ContextMenu, { MenuItems } from '../ContextMenu';
import Label, { LabelTypography, LabelColors } from '../Label';
import UserProfile from '../UserProfile';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { classnames } from '../../utils/utils';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
interface MentionLabelProps {
mentionTemplate: string;
@@ -31,9 +31,9 @@ export default function MentionLabel(props: MentionLabelProps): JSX.Element {
const mentionRef = useRef();
- const sendbirdState = useSendbirdStateContext();
- const userId = sendbirdState?.config?.userId;
- const sdk = sendbirdState?.stores?.sdkStore?.sdk;
+ const { state } = useSendbird();
+ const userId = state?.config?.userId;
+ const sdk = state?.stores?.sdkStore?.sdk;
const amIBeingMentioned = userId === mentionedUserId;
const [user, setUser] = useState();
const fetchUser = useCallback(
diff --git a/src/ui/MessageContent/MessageBody/index.tsx b/src/ui/MessageContent/MessageBody/index.tsx
index bbc679144..b8f2617ce 100644
--- a/src/ui/MessageContent/MessageBody/index.tsx
+++ b/src/ui/MessageContent/MessageBody/index.tsx
@@ -16,7 +16,7 @@ import ThumbnailMessageItemBody from '../../ThumbnailMessageItemBody';
import UnknownMessageItemBody from '../../UnknownMessageItemBody';
import { useThreadMessageKindKeySelector } from '../../../modules/Channel/context/hooks/useThreadMessageKindKeySelector';
import { useFileInfoListWithUploaded } from '../../../modules/Channel/context/hooks/useFileInfoListWithUploaded';
-import { SendBirdStateConfig } from '../../../lib/types';
+import type { SendbirdStateConfig } from '../../../lib/Sendbird/types';
import { Nullable, SendbirdTheme } from '../../../types';
import { GroupChannel } from '@sendbird/chat/groupChannel';
import { match } from 'ts-pattern';
@@ -42,7 +42,7 @@ export interface MessageBodyProps {
mouseHover: boolean;
isMobile: boolean;
- config: SendBirdStateConfig;
+ config: SendbirdStateConfig;
isReactionEnabledInChannel: boolean;
isByMe: boolean;
}
diff --git a/src/ui/MessageContent/MessageContentForTemplateMessage.tsx b/src/ui/MessageContent/MessageContentForTemplateMessage.tsx
index d6dbb654e..cfc53441e 100644
--- a/src/ui/MessageContent/MessageContentForTemplateMessage.tsx
+++ b/src/ui/MessageContent/MessageContentForTemplateMessage.tsx
@@ -4,10 +4,10 @@ import { classnames } from '../../utils/utils';
import format from 'date-fns/format';
import { MessageTemplateData, TemplateType } from '../TemplateMessageItemBody/types';
import { MessageComponentRenderers, MessageContentProps } from './index';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { uiContainerType } from '../../utils';
import { useLocalization } from '../../lib/LocalizationContext';
import { MESSAGE_TEMPLATE_KEY } from '../../utils/consts';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
type MessageContentForTemplateMessageProps = MessageContentProps & MessageComponentRenderers & {
isByMe: boolean;
@@ -42,7 +42,7 @@ export function MessageContentForTemplateMessage(props: MessageContentForTemplat
useReplying,
} = props;
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { dateLocale } = useLocalization();
const uiContainerTypeClassName = uiContainerType[templateType] ?? '';
diff --git a/src/ui/MessageContent/__tests__/MessageContent.spec.js b/src/ui/MessageContent/__tests__/MessageContent.spec.js
index 8cd3cbf1e..2330b2902 100644
--- a/src/ui/MessageContent/__tests__/MessageContent.spec.js
+++ b/src/ui/MessageContent/__tests__/MessageContent.spec.js
@@ -1,24 +1,33 @@
-import React, { useContext } from 'react';
+import React from 'react';
import { render, renderHook } from '@testing-library/react';
import MessageContent from "../index";
import { useMessageContext } from '../../../modules/Message/context/MessageProvider';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../../lib/LocalizationContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
jest.mock('date-fns/format', () => () => ('mock-date'));
-// to mock useSendbirdStateContext
-jest.mock('react', () => ({
- ...jest.requireActual('react'),
- useContext: jest.fn(),
-}));
-jest.mock('../../../lib/LocalizationContext', () => ({
- ...jest.requireActual('../../../lib/LocalizationContext'),
- useLocalization: jest.fn(),
+// to mock useSendbird
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(),
+ useSendbird: jest.fn(),
}));
+jest.mock('../../../lib/LocalizationContext', () => {
+ const React = require('react');
+ return {
+ __esModule: true,
+ LocalizationContext: React.createContext({
+ stringSet: {
+ DATE_FORMAT__MESSAGE_CREATED_AT: 'p',
+ },
+ }),
+ useLocalization: jest.fn(),
+ };
+});
jest.mock('../../../modules/Message/context/MessageProvider', () => ({
- ...jest.requireActual('../../../modules/Message/context/MessageProvider'),
+ __esModule: true,
useMessageContext: jest.fn(),
}));
@@ -63,10 +72,13 @@ describe('ui/MessageContent', () => {
/** Mocking necessary hooks */
beforeEach(() => {
const stateContextValue = {
- config: {
- groupChannel: {
- enableOgtag: true,
- }
+ state: {
+ config: {
+ groupChannel: {
+ enableOgtag: true,
+ }
+ },
+ eventHandlers: {},
}
};
const localeContextValue = {
@@ -77,13 +89,15 @@ describe('ui/MessageContent', () => {
};
const messageContextValue = {
message: {},
- }
+ };
+
+ // Mocking the hooks
- useContext.mockReturnValue(stateContextValue);
+ useSendbird.mockReturnValue(stateContextValue);
useLocalization.mockReturnValue(localeContextValue);
- useMessageContext.mockReturnValue(messageContextValue)
+ useMessageContext.mockReturnValue(messageContextValue);
- renderHook(() => useSendbirdStateContext());
+ renderHook(() => useSendbird());
renderHook(() => useLocalization());
renderHook(() => useMessageContext());
})
@@ -290,11 +304,13 @@ describe('ui/MessageContent', () => {
it('should render OGMessageItemBody if config.groupChannel.enableOgtag == true', function () {
const message = createMockMessage();
const contextValue = {
- config: {
- groupChannel: { enableOgtag: true },
+ state: {
+ config: {
+ groupChannel: { enableOgtag: true },
+ }
}
};
- useContext.mockReturnValue(contextValue);
+ useSendbird.mockReturnValue(contextValue);
const { container } = render(
{
it('should not render OGMessageItemBody if config.groupChannel.enableOgtag == false', function () {
const message = createMockMessage();
const contextValue = {
- config: {
- groupChannel: { enableOgtag: false },
+ state: {
+ config: {
+ groupChannel: { enableOgtag: false },
+ }
}
};
- useContext.mockReturnValue(contextValue);
+ useSendbird.mockReturnValue(contextValue);
const { container } = render(
();
diff --git a/src/ui/MessageInput/__tests__/MessageInput.spec.js b/src/ui/MessageInput/__tests__/MessageInput.spec.js
index c86e46c41..3f99de316 100644
--- a/src/ui/MessageInput/__tests__/MessageInput.spec.js
+++ b/src/ui/MessageInput/__tests__/MessageInput.spec.js
@@ -1,17 +1,18 @@
-import React, { useContext } from 'react';
+import React from 'react';
import { render, renderHook, screen,fireEvent } from '@testing-library/react';
import userEvent from '@testing-library/user-event';
-import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext';
-import { useLocalization } from '../../../lib/LocalizationContext';
import MessageInput from "../index";
+import { useLocalization } from '../../../lib/LocalizationContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
const noop = () => {};
// to mock useSendbirdStateContext
-jest.mock('react', () => ({
- ...jest.requireActual('react'),
- useContext: jest.fn(),
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(),
+ useSendbird: jest.fn(),
}));
jest.mock('../../../lib/LocalizationContext', () => ({
...jest.requireActual('../../../lib/LocalizationContext'),
@@ -22,9 +23,11 @@ describe('ui/MessageInput', () => {
/** Mocking necessary hooks */
beforeEach(() => {
const stateContextValue = {
- config: {
- groupChannel: {
- enableDocument: true,
+ state: {
+ config: {
+ groupChannel: {
+ enableDocument: true,
+ }
}
}
};
@@ -32,25 +35,27 @@ describe('ui/MessageInput', () => {
stringSet: {},
};
- useContext.mockReturnValue(stateContextValue);
+ useSendbird.mockReturnValue(stateContextValue);
useLocalization.mockReturnValue(localeContextValue);
- renderHook(() => useSendbirdStateContext());
+ renderHook(() => useSendbird());
renderHook(() => useLocalization());
})
describe('Dashboard enableDocument config', () => {
it('should not render file upload icon if groupChannel.enableDocument: false', () => {
const stateContextValue = {
- config: {
- groupChannel: {
- enableDocument: false,
+ state: {
+ config: {
+ groupChannel: {
+ enableDocument: false,
+ }
}
}
};
- useContext.mockReturnValue(stateContextValue);
- renderHook(() => useSendbirdStateContext());
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
const { container } = render();
expect(
@@ -60,15 +65,17 @@ describe('ui/MessageInput', () => {
it('should not render file upload icon if openChannel.enableDocument: false', () => {
const stateContextValue = {
- config: {
- openChannel: {
- enableDocument: false,
+ state: {
+ config: {
+ openChannel: {
+ enableDocument: false,
+ }
}
}
};
- useContext.mockReturnValue(stateContextValue);
- renderHook(() => useSendbirdStateContext());
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
const { container } = render();
expect(
@@ -78,15 +85,17 @@ describe('ui/MessageInput', () => {
it('should not render file upload icon if openChannel.enableDocument: true', () => {
const stateContextValue = {
- config: {
- openChannel: {
- enableDocument: true,
+ state: {
+ config: {
+ openChannel: {
+ enableDocument: true,
+ }
}
}
};
- useContext.mockReturnValue(stateContextValue);
- renderHook(() => useSendbirdStateContext());
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
const { container } = render();
expect(
@@ -242,27 +251,29 @@ describe('ui/MessageInput', () => {
describe('MessageInput error handling', () => {
beforeEach(() => {
const stateContextValue = {
- config: {
- groupChannel: {
- enableDocument: true,
+ state: {
+ config: {
+ groupChannel: {
+ enableDocument: true,
+ },
},
- },
- eventHandlers: {
- message: {
- onSendMessageFailed: jest.fn(),
- onUpdateMessageFailed: jest.fn(),
- onFileUploadFailed: jest.fn(),
+ eventHandlers: {
+ message: {
+ onSendMessageFailed: jest.fn(),
+ onUpdateMessageFailed: jest.fn(),
+ onFileUploadFailed: jest.fn(),
+ },
},
- },
+ }
};
const localeContextValue = {
stringSet: {},
};
- useContext.mockReturnValue(stateContextValue);
+ useSendbird.mockReturnValue(stateContextValue);
useLocalization.mockReturnValue(localeContextValue);
- renderHook(() => useSendbirdStateContext());
+ renderHook(() => useSendbird());
renderHook(() => useLocalization());
});
@@ -271,7 +282,7 @@ describe('MessageInput error handling', () => {
const onSendMessage = jest.fn(() => {
throw new Error(mockErrorMessage);
});
- const { eventHandlers } = useSendbirdStateContext();
+ const { state: { eventHandlers } } = useSendbird();
const textRef = { current: { innerText: null } };
const mockText = 'Test Value';
@@ -291,7 +302,7 @@ describe('MessageInput error handling', () => {
const onSendMessage = jest.fn(() => {
throw new Error(mockErrorMessage);
});
- const { eventHandlers } = useSendbirdStateContext();
+ const { state: { eventHandlers } } = useSendbird();
const textRef = { current: { innerText: null } };
const mockText = 'Test Value';
@@ -312,7 +323,7 @@ describe('MessageInput error handling', () => {
const onUpdateMessage = jest.fn(() => {
throw new Error(mockErrorMessage);
});
- const { eventHandlers } = useSendbirdStateContext();
+ const { state: { eventHandlers } } = useSendbird();
const messageId = 123;
const textRef = { current: { innerText: null } };
const mockText = 'Updated Text';
@@ -342,7 +353,7 @@ describe('MessageInput error handling', () => {
const onFileUpload = jest.fn(() => {
throw new Error(mockErrorMessage);
});
- const { eventHandlers } = useSendbirdStateContext();
+ const { state: { eventHandlers } } = useSendbird();
const file = new File(['dummy content'], 'example.txt', { type: 'text/plain' });
render();
diff --git a/src/ui/MessageInput/index.tsx b/src/ui/MessageInput/index.tsx
index fc05d5de2..3d9441f02 100644
--- a/src/ui/MessageInput/index.tsx
+++ b/src/ui/MessageInput/index.tsx
@@ -10,7 +10,6 @@ import renderMentionLabelToString from '../MentionUserLabel/renderToString';
import Icon, { IconColors, IconTypes } from '../Icon';
import Label, { LabelColors, LabelTypography } from '../Label';
import { useLocalization } from '../../lib/LocalizationContext';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { extractTextAndMentions, isChannelTypeSupportsMultipleFilesMessage, nodeListToArray, sanitizeString } from './utils';
import { arrayEqual, getMimeTypesUIKitAccepts } from '../../utils';
@@ -26,6 +25,7 @@ import { GroupChannel } from '@sendbird/chat/groupChannel';
import { User } from '@sendbird/chat';
import { OpenChannel } from '@sendbird/chat/openChannel';
import { UserMessage } from '@sendbird/chat/message';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
const TEXT_FIELD_ID = 'sendbird-message-input-text-field';
const noop = () => {
@@ -126,7 +126,7 @@ const MessageInput = React.forwardRef((prop
const textFieldId = messageFieldId || TEXT_FIELD_ID;
const { stringSet } = useLocalization();
- const { config, eventHandlers } = useSendbirdStateContext();
+ const { state: { config, eventHandlers } } = useSendbird();
const isFileUploadEnabled = checkIfFileUploadEnabled({
channel,
diff --git a/src/ui/MessageInput/messageInputUtils.ts b/src/ui/MessageInput/messageInputUtils.ts
index 5b2a129d7..02febf0d3 100644
--- a/src/ui/MessageInput/messageInputUtils.ts
+++ b/src/ui/MessageInput/messageInputUtils.ts
@@ -7,7 +7,7 @@ import type { GroupChannel } from '@sendbird/chat/groupChannel';
import type { OpenChannel } from '@sendbird/chat/openChannel';
import { match } from 'ts-pattern';
-import type { SendBirdStateConfig } from '../../lib/types';
+import type { SendbirdStateConfig } from '../../lib/Sendbird/types';
/**
* FIXME:
@@ -26,12 +26,12 @@ enum ChannelType {
* If customer is using MessageInput outside our modules(ie: custom UI),
* we expect Channel to be undefined and customer gets control to show/hide file-upload.
* @param {*} channel GroupChannel | OpenChannel
- * @param {*} config SendBirdStateConfig
+ * @param {*} config SendbirdStateConfig
* @returns boolean
*/
export const checkIfFileUploadEnabled = ({ channel, config }: {
channel?: GroupChannel | OpenChannel,
- config?: SendBirdStateConfig,
+ config?: SendbirdStateConfig,
}) => {
const isEnabled = match(channel?.channelType)
.with(ChannelType.GROUP, () => config?.groupChannel?.enableDocument)
diff --git a/src/ui/MessageItemMenu/index.tsx b/src/ui/MessageItemMenu/index.tsx
index fdf0eb16b..f481e3b52 100644
--- a/src/ui/MessageItemMenu/index.tsx
+++ b/src/ui/MessageItemMenu/index.tsx
@@ -17,7 +17,7 @@ import {
SendableMessageType,
} from '../../utils/index';
import { LocalizationContext } from '../../lib/LocalizationContext';
-import { Role } from '../../lib/types';
+import { Role } from '../../lib/Sendbird/types';
import { ReplyType } from '../../types';
import { deleteNullish } from '../../utils/utils';
diff --git a/src/ui/MessageMenu/MessageMenu.tsx b/src/ui/MessageMenu/MessageMenu.tsx
index ede8070bc..ead309151 100644
--- a/src/ui/MessageMenu/MessageMenu.tsx
+++ b/src/ui/MessageMenu/MessageMenu.tsx
@@ -4,7 +4,6 @@ import { OpenChannel } from '@sendbird/chat/openChannel';
import { SendableMessageType } from '../../utils';
import { classnames, noop } from '../../utils/utils';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { MenuItems, getObservingId } from '../ContextMenu';
import {
type PrebuildMenuItemPropsType,
@@ -31,6 +30,7 @@ import {
} from '../../utils/menuConditions';
import { MessageMenuProvider } from './MessageMenuProvider';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
export type RenderMenuItemsParams = {
items: {
@@ -79,8 +79,7 @@ export const MessageMenu = ({
onReplyInThread,
onMoveToParentMessage,
}: MessageMenuProps) => {
- const { config } = useSendbirdStateContext();
- const { isOnline } = config;
+ const { state: { config: { isOnline } } } = useSendbird();
const triggerRef = useRef(null);
const containerRef = useRef(null);
diff --git a/src/ui/MobileMenu/MobileBottomSheet.tsx b/src/ui/MobileMenu/MobileBottomSheet.tsx
index 90f9f1755..c78959d2a 100644
--- a/src/ui/MobileMenu/MobileBottomSheet.tsx
+++ b/src/ui/MobileMenu/MobileBottomSheet.tsx
@@ -19,7 +19,6 @@ import BottomSheet from '../BottomSheet';
import ImageRenderer from '../ImageRenderer';
import ReactionButton from '../ReactionButton';
import Icon, { IconTypes, IconColors } from '../Icon';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { classnames } from '../../utils/utils';
import { MessageMenuProvider, MobileMessageMenuContextProps } from '../MessageMenu/MessageMenuProvider';
import {
@@ -31,6 +30,7 @@ import {
DeleteMenuItem,
DownloadMenuItem,
} from '../MessageMenu/menuItems/BottomSheetMenuItems';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
const EMOJI_SIZE = 38;
@@ -56,8 +56,7 @@ const MobileBottomSheet: React.FunctionComponent = (prop
renderMenuItems,
} = props;
const isByMe = message?.sender?.userId === userId;
- const { config } = useSendbirdStateContext();
- const { isOnline } = config;
+ const { state: { config: { isOnline } } } = useSendbird();
const showMenuItemCopy: boolean = isUserMessage(message as UserMessage);
const showMenuItemEdit: boolean = (isUserMessage(message as UserMessage) && isSentMessage(message) && isByMe);
const showMenuItemResend: boolean = (isOnline && isFailedMessage(message) && message?.isResendable && isByMe);
diff --git a/src/ui/MobileMenu/MobileContextMenu.tsx b/src/ui/MobileMenu/MobileContextMenu.tsx
index 16e3bb757..97a116664 100644
--- a/src/ui/MobileMenu/MobileContextMenu.tsx
+++ b/src/ui/MobileMenu/MobileContextMenu.tsx
@@ -24,9 +24,9 @@ import {
DeleteMenuItem,
DownloadMenuItem,
} from '../MessageMenu/menuItems/MobileMenuItems';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { MenuItems } from '../ContextMenu';
import { noop } from '../../utils/utils';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
const MobileContextMenu: React.FunctionComponent = (props: BaseMenuProps): React.ReactElement => {
const {
@@ -48,8 +48,7 @@ const MobileContextMenu: React.FunctionComponent = (props: BaseMe
hideMenu: hideMobileMenu,
} = props;
const isByMe = message?.sender?.userId === userId;
- const { config } = useSendbirdStateContext();
- const { isOnline } = config;
+ const { state: { config: { isOnline } } } = useSendbird();
// Menu Items condition
const showMenuItemCopy = isUserMessage(message as UserMessage);
diff --git a/src/ui/Modal/index.tsx b/src/ui/Modal/index.tsx
index 03aeb8ba6..27a581671 100644
--- a/src/ui/Modal/index.tsx
+++ b/src/ui/Modal/index.tsx
@@ -13,7 +13,7 @@ import Button, { ButtonTypes } from '../Button';
import Icon, { IconTypes, IconColors } from '../Icon';
import Label, { LabelTypography, LabelColors } from '../Label';
import uuidv4 from '../../utils/uuid';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
export interface ModalHeaderProps {
titleText: string;
@@ -113,7 +113,7 @@ export function Modal(props: ModalProps): ReactElement {
customFooter,
} = props;
const handleClose = onClose ?? onCancel ?? noop;
- const { eventHandlers } = useSendbirdStateContext();
+ const { state: { eventHandlers } } = useSendbird();
const [id] = useState(() => `sbu-modal-${uuidv4()}`);
diff --git a/src/ui/MultipleFilesMessageItemBody/index.tsx b/src/ui/MultipleFilesMessageItemBody/index.tsx
index 2ce03436e..cfb5aa008 100644
--- a/src/ui/MultipleFilesMessageItemBody/index.tsx
+++ b/src/ui/MultipleFilesMessageItemBody/index.tsx
@@ -2,7 +2,6 @@ import React, { ReactElement, useState } from 'react';
import { MultipleFilesMessage, SendingStatus } from '@sendbird/chat/message';
import type { OnBeforeDownloadFileMessageType } from '../../modules/GroupChannel/context/types';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import Icon, { IconColors, IconTypes } from '../Icon';
import ImageRenderer, { getBorderRadiusForMultipleImageRenderer } from '../ImageRenderer';
import ImageGrid from '../ImageGrid';
@@ -11,6 +10,7 @@ import './index.scss';
import { MULTIPLE_FILES_IMAGE_BORDER_RADIUS, MULTIPLE_FILES_IMAGE_SIDE_LENGTH, MULTIPLE_FILES_IMAGE_THUMBNAIL_SIDE_LENGTH } from './const';
import { isGif } from '../../utils';
import { UploadedFileInfoWithUpload } from '../../types';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
export const ThreadMessageKind = {
PARENT: 'parent',
@@ -39,7 +39,7 @@ export default function MultipleFilesMessageItemBody({
statefulFileInfoList = [],
onBeforeDownloadFileMessage = null,
}: Props): ReactElement {
- const logger = useSendbirdStateContext?.()?.config?.logger;
+ const { state: { config: { logger } } } = useSendbird();
const [currentFileViewerIndex, setCurrentFileViewerIndex] = useState(-1);
function onClose() {
diff --git a/src/ui/OpenChannelMobileMenu/index.tsx b/src/ui/OpenChannelMobileMenu/index.tsx
index 23c70d617..67d382d0b 100644
--- a/src/ui/OpenChannelMobileMenu/index.tsx
+++ b/src/ui/OpenChannelMobileMenu/index.tsx
@@ -10,9 +10,9 @@ import {
isFineEdit,
isFineDownload,
} from '../../utils/openChannelUtils';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { useLocalization } from '../../lib/LocalizationContext';
import { SendableMessageType } from '../../utils';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
type Props = {
message: SendableMessageType;
@@ -39,7 +39,7 @@ const OpenChannelMobileMenu: React.FC = (props: Props) => {
const userMessage = message as UserMessage;
const status = message?.sendingStatus;
const { stringSet } = useLocalization();
- const userId = useSendbirdStateContext()?.config?.userId;
+ const { state: { config: { userId } } } = useSendbird();
const fileMessage = message as FileMessage;
return (
{
diff --git a/src/ui/Toggle/utils.ts b/src/ui/Toggle/utils.ts
index b4832fc91..827bdd26c 100644
--- a/src/ui/Toggle/utils.ts
+++ b/src/ui/Toggle/utils.ts
@@ -1,10 +1,9 @@
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
export function filterNumber(input: string | number): Array {
if (typeof input !== 'string' && typeof input !== 'number') {
try {
- const { config } = useSendbirdStateContext();
- const { logger } = config;
+ const { state: { config: { logger } } } = useSendbird();
logger.warning('@sendbird/uikit-react/ui/Toggle: TypeError - expected string or number.', input);
} catch (_) { /* noop */ }
return [];
diff --git a/src/ui/UserListItem/__tests__/UserListItem.spec.js b/src/ui/UserListItem/__tests__/UserListItem.spec.js
index df926da27..59eb4538e 100644
--- a/src/ui/UserListItem/__tests__/UserListItem.spec.js
+++ b/src/ui/UserListItem/__tests__/UserListItem.spec.js
@@ -1,8 +1,15 @@
import React from 'react';
-import { render } from '@testing-library/react';
+import { render, renderHook } from '@testing-library/react';
import UserListItem from "../index";
-import { SendbirdSdkContext } from '../../../lib/SendbirdSdkContext';
+import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext';
+import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird';
+
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(),
+ useSendbird: jest.fn(),
+}));
const getUserList = () => [
{
@@ -23,6 +30,18 @@ const getUserList = () => [
];
describe('ui/UserListItem', () => {
+ beforeEach(() => {
+ jest.clearAllMocks();
+ const stateContextValue = {
+ state: {
+ config: {},
+ stores: {},
+ },
+ };
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
+ });
+
it.skip('should render text prop', function () {
const [user1] = getUserList();
render();
@@ -35,14 +54,14 @@ describe('ui/UserListItem', () => {
it('should do a snapshot test of the UserListItem DOM', function () {
const [user1] = getUserList();
const { asFragment } = render(
-
+
{ }}
/>
-
+
);
expect(asFragment()).toMatchSnapshot();
});
diff --git a/src/ui/UserListItem/index.tsx b/src/ui/UserListItem/index.tsx
index 7eb2157f6..f08294ea8 100644
--- a/src/ui/UserListItem/index.tsx
+++ b/src/ui/UserListItem/index.tsx
@@ -3,7 +3,6 @@ import type { User } from '@sendbird/chat';
import type { GroupChannel, Member } from '@sendbird/chat/groupChannel';
import './index.scss';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
import { useUserProfileContext } from '../../lib/UserProfileContext';
import { useLocalization } from '../../lib/LocalizationContext';
@@ -16,6 +15,7 @@ import Label, { LabelTypography, LabelColors } from '../Label';
import { UserListItemMenuProps } from '../UserListItemMenu/UserListItemMenu';
import { classnames } from '../../utils/utils';
import pxToNumber from '../../utils/pxToNumber';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
export interface UserListItemProps {
user: User | Member;
@@ -63,7 +63,7 @@ export function UserListItem({
const avatarRef = useRef(null);
const { disableUserProfile, renderUserProfile } = useUserProfileContext();
const { stringSet } = useLocalization();
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const currentUser = config.userId;
const itemClassName = size === 'small' ? 'sendbird-user-list-item--small' : 'sendbird-user-list-item';
diff --git a/src/ui/UserListItemMenu/UserListItemMenu.tsx b/src/ui/UserListItemMenu/UserListItemMenu.tsx
index 90312543a..97762efdc 100644
--- a/src/ui/UserListItemMenu/UserListItemMenu.tsx
+++ b/src/ui/UserListItemMenu/UserListItemMenu.tsx
@@ -6,7 +6,7 @@ import { OperatorToggleMenuItem, MuteToggleMenuItem, BanToggleMenuItem } from '.
import { classnames } from '../../utils/utils';
import { MenuItems } from '../ContextMenu';
import { DefaultMenuItems, TriggerIcon } from './DefaultElements';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
export type RenderUserListItemMenuItemsParams = {
items: {
@@ -32,7 +32,7 @@ export const UserListItemMenu = (props: UserListItemMenuProps) => {
const containerRef = useRef(null);
const triggerRef = useRef(null);
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { userId: currentUserId } = config;
const toggleMenu = () => {
diff --git a/src/ui/UserListItemMenu/context.tsx b/src/ui/UserListItemMenu/context.tsx
index bac2fa698..3aac6239d 100644
--- a/src/ui/UserListItemMenu/context.tsx
+++ b/src/ui/UserListItemMenu/context.tsx
@@ -4,7 +4,7 @@ import type { GroupChannel } from '@sendbird/chat/groupChannel';
import { OpenChannel } from '@sendbird/chat/openChannel';
import { useToggleBan, useToggleMute, useToggleOperator } from './hooks';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
interface UserListItemMenuContextInterface extends
UserListItemMenuContextValues,
@@ -38,7 +38,7 @@ export interface UserListItemMenuProviderProps extends UserListItemMenuContextVa
isBanned?: boolean;
}
export const UserListItemMenuProvider = ({ children, ...values }: UserListItemMenuProviderProps) => {
- const { config } = useSendbirdStateContext();
+ const { state: { config } } = useSendbird();
const { userId: currentUserId } = config;
const { channel, user } = values;
const isCurrentUser = user.userId === currentUserId;
diff --git a/src/ui/UserProfile/index.tsx b/src/ui/UserProfile/index.tsx
index 627d33e28..50106d15e 100644
--- a/src/ui/UserProfile/index.tsx
+++ b/src/ui/UserProfile/index.tsx
@@ -9,7 +9,7 @@ import { getCreateGroupChannel } from '../../lib/selectors';
import Avatar from '../Avatar/index';
import Label, { LabelColors, LabelTypography } from '../Label';
import Button, { ButtonTypes } from '../Button';
-import useSendbirdStateContext from '../../hooks/useSendbirdStateContext';
+import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird';
interface Logger {
info?(message: string, channel: GroupChannel): void;
@@ -30,11 +30,11 @@ function UserProfile({
disableMessaging = false,
onSuccess,
}: Props): ReactElement {
- const store = useSendbirdStateContext();
- const createChannel = getCreateGroupChannel(store);
- const logger = store?.config?.logger;
+ const { state } = useSendbird();
+ const createChannel = getCreateGroupChannel(state);
+ const logger = state?.config?.logger;
const { stringSet } = useContext(LocalizationContext);
- const currentUserId_ = currentUserId || store?.config?.userId;
+ const currentUserId_ = currentUserId || state?.config?.userId;
const { onStartDirectMessage } = useUserProfileContext();
return (
diff --git a/src/ui/Word/__tests__/Word.spec.js b/src/ui/Word/__tests__/Word.spec.js
index b11270f43..a1a29b13c 100644
--- a/src/ui/Word/__tests__/Word.spec.js
+++ b/src/ui/Word/__tests__/Word.spec.js
@@ -1,20 +1,44 @@
import React from "react";
-import { render } from "@testing-library/react";
+import { render, renderHook } from "@testing-library/react";
import Word from "../index";
-import { SendbirdSdkContext } from "../../../lib/SendbirdSdkContext";
+import useSendbird from "../../../lib/Sendbird/context/hooks/useSendbird";
+import { SendbirdContext } from "../../../lib/Sendbird/context/SendbirdContext";
+
+jest.mock('../../../lib/Sendbird/context/hooks/useSendbird', () => ({
+ __esModule: true,
+ default: jest.fn(),
+ useSendbird: jest.fn(),
+}));
describe("ui/Word", () => {
+ beforeEach(() => {
+ const stateContextValue = {
+ state: {
+ config: {
+ userId: 'hoon',
+ },
+ stores: {
+ sdkStore: {
+ sdk: {}
+ }
+ }
+ }
+ }
+ useSendbird.mockReturnValue(stateContextValue);
+ renderHook(() => useSendbird());
+ })
+
it("should do a snapshot test of the Word DOM", function () {
const { asFragment } = render(
-
+
-
+
);
expect(asFragment()).toMatchSnapshot();
});
diff --git a/src/ui/Word/__tests__/__snapshots__/Word.spec.js.snap b/src/ui/Word/__tests__/__snapshots__/Word.spec.js.snap
index 0a7afdc97..8e5e05147 100644
--- a/src/ui/Word/__tests__/__snapshots__/Word.spec.js.snap
+++ b/src/ui/Word/__tests__/__snapshots__/Word.spec.js.snap
@@ -11,7 +11,7 @@ exports[`ui/Word should do a snapshot test of the Word DOM 1`] = `
class="sendbird-context-menu"
>
({
@@ -16,7 +16,7 @@ const normalConfigs = (props?: any, groupChannelProps?: any) => ({
...groupChannelProps,
},
...props,
-} as SendBirdStateConfig);
+} as SendbirdStateConfig);
describe('Global-utils/getIsReactionEnabled', () => {
it('should prioritize the moduleLevel than global config', () => {
diff --git a/src/utils/__tests__/isReplyTypeMessageEnabled.spec.ts b/src/utils/__tests__/isReplyTypeMessageEnabled.spec.ts
index fe6badaf0..0fa355834 100644
--- a/src/utils/__tests__/isReplyTypeMessageEnabled.spec.ts
+++ b/src/utils/__tests__/isReplyTypeMessageEnabled.spec.ts
@@ -1,4 +1,4 @@
-import { Role } from '../../lib/types';
+import { Role } from '../../lib/Sendbird/types';
import { isFailedMessage, isPendingMessage } from '..';
import { isReplyTypeMessageEnabled } from '../menuConditions';
diff --git a/src/utils/compressImages.ts b/src/utils/compressImages.ts
index 06ea9efb1..c4a755e04 100644
--- a/src/utils/compressImages.ts
+++ b/src/utils/compressImages.ts
@@ -1,6 +1,5 @@
-import type { ImageCompressionOptions, ImageCompressionOutputFormatType } from '../lib/Sendbird';
+import type { ImageCompressionOptions, ImageCompressionOutputFormatType, Logger } from '../lib/Sendbird/types';
import pxToNumber from './pxToNumber';
-import { Logger } from '../lib/SendbirdState';
interface CompressImageParams {
imageFile: File;
diff --git a/src/utils/getIsReactionEnabled.ts b/src/utils/getIsReactionEnabled.ts
index 4272ecbb7..7ba534cf3 100644
--- a/src/utils/getIsReactionEnabled.ts
+++ b/src/utils/getIsReactionEnabled.ts
@@ -4,11 +4,11 @@
*/
import type { GroupChannel } from '@sendbird/chat/groupChannel';
-import type { SendBirdStateConfig } from '../lib/types';
+import type { SendbirdStateConfig } from '../lib/Sendbird/types';
export interface IsReactionEnabledProps {
channel: GroupChannel | null;
- config: SendBirdStateConfig;
+ config: SendbirdStateConfig;
moduleLevel?: boolean;
}