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/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/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 index b2fba9258..b992665e6 100644 --- a/src/lib/Sendbird/context/SendbirdProvider.tsx +++ b/src/lib/Sendbird/context/SendbirdProvider.tsx @@ -1,9 +1,9 @@ /* External libraries */ -import React, { useEffect, useMemo, useRef, useState } from 'react'; +import React, { ReactElement, useEffect, useMemo, useRef, useState } from 'react'; import { useUIKitConfig } from '@sendbird/uikit-tools'; /* Types */ -import type { SendbirdProviderProps, SendbirdProviderUtils, SendbirdState } from '../types'; +import type { ImageCompressionOptions, SendbirdProviderProps, SendbirdStateConfig } from '../types'; /* Providers */ import VoiceMessageProvider from '../../VoiceMessageProvider'; @@ -20,9 +20,7 @@ import PUBSUB_TOPICS, { SBUGlobalPubSubTopicPayloadUnion } from '../../pubSub/to /* Hooks */ import useTheme from '../../hooks/useTheme'; import useMessageTemplateUtils from '../../hooks/useMessageTemplateUtils'; -import useConnect from '../../hooks/useConnect'; import { useUnmount } from '../../../hooks/useUnmount'; -import { disconnectSdk } from '../../hooks/useConnect/disconnectSdk'; import useHTMLTextDirection from '../../../hooks/useHTMLTextDirection'; import useOnlineStatus from '../../hooks/useOnlineStatus'; import { useMarkAsReadScheduler } from '../../hooks/useMarkAsReadScheduler'; @@ -34,23 +32,17 @@ 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'; -// TODO: remove -import { useReducer } from 'react'; +import useSendbird from './hooks/useSendbird'; +import { SendbirdContext, useSendbirdStore } from './SendbirdContext'; import { createStore } from '../../../utils/storeManager'; import { initialState } from './initialState'; -/** - * SendbirdContext - */ -export const SendbirdContext = React.createContext> | null>(null); - /** * SendbirdContext - Manager */ const SendbirdContextManager = ({ appId, userId, - children, accessToken, customApiHost, customWebSocketHost, @@ -59,8 +51,6 @@ const SendbirdContextManager = ({ config = {}, nickname = '', colorSet, - stringSet, - dateLocale, profileUrl = '', voiceRecord, userListQuery, @@ -70,7 +60,6 @@ const SendbirdContextManager = ({ renderUserProfile, onUserProfileMessage: _onUserProfileMessage, onStartDirectMessage: _onStartDirectMessage, - breakpoint = false, isUserIdUsedForNickname = true, sdkInitParams, customExtensionParams, @@ -78,15 +67,16 @@ const SendbirdContextManager = ({ eventHandlers, htmlTextDirection = 'ltr', forceLeftToRightMessageLayout = false, -}: SendbirdProviderProps): React.ReactElement => { +}: 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 [sdkStore, sdkDispatcher] = useReducer(sdkReducers, sdkInitialState); - const [userStore, userDispatcher] = useReducer(userReducers, userInitialState); - const [appInfoStore, appInfoDispatcher] = useReducer(appInfoReducers, appInfoInitialState); + const [pubSub] = useState(customPubSub ?? pubSubFactory()); + + const { state, updateState } = useSendbirdStore(); + const { actions } = useSendbird(); + const { sdkStore, appInfoStore } = state.stores; const { configs, configsWithAppAttr, initDashboardConfigs } = useUIKitConfig(); @@ -100,23 +90,17 @@ const SendbirdContextManager = ({ sdk, logger, appInfoStore, - appInfoDispatcher, + actions, }); - const utils: SendbirdProviderUtils = { - updateMessageTemplatesInfo, - getCachedTemplate, - }; - - const reconnect = useConnect( - { + // Reconnect when necessary + useEffect(() => { + actions.connect({ appId, userId, accessToken, isUserIdUsedForNickname, isMobile, - }, - { logger, nickname, profileUrl, @@ -125,26 +109,16 @@ const SendbirdContextManager = ({ customWebSocketHost, sdkInitParams, customExtensionParams, - sdk, - sdkDispatcher, - userDispatcher, - appInfoDispatcher, initDashboardConfigs, eventHandlers, initializeMessageTemplatesInfo, - }, - ); + }); + }, [appId, userId]); + // Disconnect on unmount useUnmount(() => { - if (typeof sdk.disconnect === 'function') { - disconnectSdk({ - logger, - sdkDispatcher, - userDispatcher, - sdk, - }); - } - }, [sdk.disconnectWebSocket]); + actions.disconnect({ logger }); + }); // to create a pubsub to communicate between parent and child useEffect(() => { @@ -194,10 +168,6 @@ const SendbirdContextManager = ({ 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 @@ -214,106 +184,200 @@ const SendbirdContextManager = ({ }); }, [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} + + {children} + @@ -325,17 +389,14 @@ const SendbirdContextManager = ({ ); }; -const createSendbirdContextStore = () => createStore(initialState); export const SendbirdContextProvider = (props: SendbirdProviderProps) => { const { children } = props; - const storeRef = useRef(createSendbirdContextStore()); return ( - - - {children} - - + + + {children} + ); }; diff --git a/src/lib/Sendbird/context/hooks/useSendbird.tsx b/src/lib/Sendbird/context/hooks/useSendbird.tsx index e69de29bb..908242fe3 100644 --- a/src/lib/Sendbird/context/hooks/useSendbird.tsx +++ 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 index 37b80a396..74812b544 100644 --- a/src/lib/Sendbird/context/initialState.ts +++ b/src/lib/Sendbird/context/initialState.ts @@ -1,8 +1,9 @@ -import type { SendbirdState, SendbirdStateConfig, ReplyType, SendbirdStateStore } from '../types'; +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 @@ -88,13 +89,13 @@ const config: SendbirdStateConfig = { */ const stores: SendbirdStateStore = { sdkStore: { - sdk: undefined, + sdk: {} as SdkStore['sdk'], initialized: false, loading: false, error: undefined, }, userStore: { - user: undefined, + user: {} as User, initialized: false, loading: false, }, diff --git a/src/lib/Sendbird/index.scss b/src/lib/Sendbird/index.scss index f47fae2e5..99ebdc01f 100644 --- a/src/lib/Sendbird/index.scss +++ b/src/lib/Sendbird/index.scss @@ -1,6 +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'; +@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 index 869d7c0cc..ef8d1fe57 100644 --- a/src/lib/Sendbird/index.tsx +++ b/src/lib/Sendbird/index.tsx @@ -2,11 +2,15 @@ import React from 'react'; import './index.scss'; import './__experimental__typography.scss'; -import type { SendbirdProviderProps, UIKitOptions } from './types'; 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) => { @@ -44,11 +48,35 @@ export const SendbirdProvider = (props: SendbirdProviderProps) => { ); }; -// 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(SendbirdContext); -// if (!context) throw new Error(NO_CONTEXT_ERROR); -// return context; -// } +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 index d42da6942..5e1bf9854 100644 --- a/src/lib/Sendbird/types.ts +++ b/src/lib/Sendbird/types.ts @@ -6,17 +6,20 @@ 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, @@ -24,7 +27,7 @@ import type { UserMessageCreateParams, UserMessageUpdateParams, } from '@sendbird/chat/message'; -import { MessageTemplateInfo, Module, ModuleNamespaces } from '@sendbird/chat/lib/__definition'; +import { Module, ModuleNamespaces } from '@sendbird/chat/lib/__definition'; import { SBUConfig } from '@sendbird/uikit-tools'; import { PartialDeep } from '../../utils/typeHelpers/partialDeep'; @@ -33,16 +36,20 @@ import { LoggerInterface } from '../Logger'; import { MarkAsReadSchedulerType } from '../hooks/useMarkAsReadScheduler'; import { MarkAsDeliveredSchedulerType } from '../hooks/useMarkAsDeliveredScheduler'; import { SBUGlobalPubSub } from '../pubSub/topics'; -import { ConfigureSessionTypes } from '../hooks/useConnect/types'; import { EmojiManager } from '../emojiManager'; import { StringSet } from '../../ui/Label/stringSet'; -import { ProcessedMessageTemplate, WaitingTemplateKeyData } from '../dux/appInfo/initialState'; /* -------------------------------------------------------------------------- */ /* 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 */ @@ -61,12 +68,6 @@ export interface ImageCompressionOptions { // Logger type export type Logger = LoggerInterface; -// Sendbird state dispatcher -export type CustomUseReducerDispatcher = React.Dispatch<{ - type: string; - payload: any; -}>; - // Roles for a user in a channel export const Role = { OPERATOR: 'operator', @@ -90,6 +91,36 @@ export interface UserListQuery { 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 */ /* -------------------------------------------------------------------------- */ @@ -309,7 +340,11 @@ export interface UserStore { } export interface AppInfoStore { - messageTemplatesInfo?: MessageTemplateInfo; + 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; } 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 8c8d769e3..44ec56420 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..9b3629af8 100644 --- a/src/modules/ChannelSettings/__test__/ChannelSettingsProvider.spec.tsx +++ b/src/modules/ChannelSettings/__test__/ChannelSettingsProvider.spec.tsx @@ -1,8 +1,8 @@ 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 useSendbirdStateContext from '../../../lib/Sendbird/context/hooks/useSendbirdStateContext'; +import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext'; jest.mock('../../../hooks/useSendbirdStateContext'); jest.mock('../context/hooks/useSetChannel'); @@ -39,11 +39,11 @@ describe('ChannelSettingsProvider', () => { }); wrapper = ({ children }) => ( - + {children} - + ); jest.clearAllMocks(); diff --git a/src/modules/ChannelSettings/__test__/ChannelSettingsUI.integration.test.tsx b/src/modules/ChannelSettings/__test__/ChannelSettingsUI.integration.test.tsx index d31914917..1ef03ed90 100644 --- a/src/modules/ChannelSettings/__test__/ChannelSettingsUI.integration.test.tsx +++ b/src/modules/ChannelSettings/__test__/ChannelSettingsUI.integration.test.tsx @@ -5,7 +5,7 @@ import { render, 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'; jest.mock('../context/useChannelSettings'); @@ -46,11 +46,11 @@ describe('ChannelSettings Integration Tests', () => { }); return render( - + - , + , ); }; 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/InviteUsers/__tests__/index.spec.tsx b/src/modules/CreateChannel/components/InviteUsers/__tests__/index.spec.tsx index 7cafa9820..5db5b4918 100644 --- a/src/modules/CreateChannel/components/InviteUsers/__tests__/index.spec.tsx +++ b/src/modules/CreateChannel/components/InviteUsers/__tests__/index.spec.tsx @@ -4,8 +4,7 @@ import '@testing-library/jest-dom/extend-expect'; import '@testing-library/jest-dom/matchers'; import InviteUsers from '../index'; import { ApplicationUserListQuery } from '@sendbird/chat'; -import { SendbirdSdkContext } from '../../../../../lib/SendbirdSdkContext'; -import { SendBirdState } from '../../../../../lib/types'; +import { SendbirdContext } from '../../../../../lib/Sendbird/context/SendbirdContext'; jest.mock('../../../context/CreateChannelProvider', () => ({ useCreateChannelContext: jest.fn(() => ({ @@ -33,9 +32,9 @@ describe('InviteUsers', () => { ); render( - + - , + , ); expect(await screen.findByText('Create')).toBeEnabled(); diff --git a/src/modules/CreateChannel/components/InviteUsers/index.tsx b/src/modules/CreateChannel/components/InviteUsers/index.tsx index 2cb75a0b3..81a84c065 100644 --- a/src/modules/CreateChannel/components/InviteUsers/index.tsx +++ b/src/modules/CreateChannel/components/InviteUsers/index.tsx @@ -5,7 +5,6 @@ import type { GroupChannelCreateParams } from '@sendbird/chat/groupChannel'; import './invite-users.scss'; import { LocalizationContext } from '../../../../lib/LocalizationContext'; import { useCreateChannelContext } from '../../context/CreateChannelProvider'; -import useSendbirdStateContext from '../../../../hooks/useSendbirdStateContext'; import { useMediaQueryContext } from '../../../../lib/MediaQueryContext'; import Modal from '../../../../ui/Modal'; import Label, { LabelColors, LabelTypography } from '../../../../ui/Label'; @@ -15,6 +14,7 @@ import UserListItem from '../../../../ui/UserListItem'; import { createDefaultUserListQuery, filterUser, setChannelType } from './utils'; import { noop } from '../../../../utils/utils'; import { UserListQuery } from '../../../../types'; +import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird'; export interface InviteUsersProps { onCancel?: () => void; @@ -36,10 +36,9 @@ const InviteUsers: React.FC = ({ overrideInviteUser, type, } = useCreateChannelContext(); - - const globalStore = useSendbirdStateContext(); - const userId = globalStore?.config?.userId; - const sdk = globalStore?.stores?.sdkStore?.sdk; + const { state } = useSendbird(); + const userId = state?.config?.userId; + const sdk = state?.stores?.sdkStore?.sdk; 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 9394d7667..e04c68bc0 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 { useCreateChannelContext } from '../context/CreateChannelProvider'; @@ -16,6 +15,7 @@ import { isSuperGroupChannelEnabled, } from '../utils'; import { CHANNEL_TYPE } from '../types'; +import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird'; export interface SelectChannelTypeProps { onCancel?(): void; @@ -23,9 +23,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 createChannelProps = useCreateChannelContext(); const { diff --git a/src/modules/CreateChannel/context/CreateChannelProvider.tsx b/src/modules/CreateChannel/context/CreateChannelProvider.tsx index 94bb70028..a2b6c1d03 100644 --- a/src/modules/CreateChannel/context/CreateChannelProvider.tsx +++ b/src/modules/CreateChannel/context/CreateChannelProvider.tsx @@ -6,9 +6,9 @@ import type { } from '@sendbird/chat/groupChannel'; import { getCreateGroupChannel } from '../../../lib/selectors'; -import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext'; import { CHANNEL_TYPE } from '../types'; -import { SendbirdChatType } from '../../../lib/types'; +import { SendbirdChatType } from '../../../lib/Sendbird/types'; +import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird'; const CreateChannelContext = React.createContext(null); @@ -102,16 +102,16 @@ const CreateChannelProvider: React.FC = (props: Crea overrideInviteUser, } = props; - const store = useSendbirdStateContext(); - const _userListQuery = userListQuery ?? store?.config?.userListQuery; + const { state } = useSendbird(); + const _userListQuery = userListQuery ?? state?.config?.userListQuery; const [step, setStep] = useState(0); const [type, setType] = useState(CHANNEL_TYPE.GROUP); return ( { 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/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; @@ -12,7 +12,8 @@ export interface FileViewerProps { export const FileViewer = (props: FileViewerProps) => { const { deleteMessage, onBeforeDownloadFileMessage } = useGroupChannelContext(); - const { config } = useSendbirdStateContext(); + const { state } = useSendbird(); + const { config } = state; const { logger } = config; 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 4ad40fc16..deea83787 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/GroupChannelProvider'; 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 96f0ff675..2369d9ed1 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 { useGroupChannelContext } from '../../context/GroupChannelProvider'; @@ -9,9 +8,11 @@ import MessageView, { MessageProps } from './MessageView'; import FileViewer from '../FileViewer'; import RemoveMessageModal from '../RemoveMessageModal'; import { ThreadReplySelectType } from '../../context/const'; +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 { loading, currentChannel, 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 7e8019df6..19cff5d95 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 { useGroupChannelContext } from '../../context/GroupChannelProvider'; import { GroupChannelUIBasicProps } from '../GroupChannelUI/GroupChannelUIView'; @@ -21,6 +20,7 @@ import { getMessagePartsInfo } from './getMessagePartsInfo'; import { MessageProvider } from '../../../Message/context/MessageProvider'; import { getComponentKeyFromMessage } from '../../context/utils'; import { InfiniteList } from './InfiniteList'; +import useSendbird from '../../../../lib/Sendbird/context/hooks/useSendbird'; export interface GroupChannelMessageListProps { className?: string; @@ -86,8 +86,7 @@ export const MessageList = (props: GroupChannelMessageListProps) => { setIsScrollBottomReached, resetNewMessages, } = useGroupChannelContext(); - - const store = useSendbirdStateContext(); + const { state } = useSendbird(); const [unreadSinceDate, setUnreadSinceDate] = useState(); @@ -163,8 +162,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({ @@ -209,8 +208,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) && ( ) } @@ -224,7 +223,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 8213cf5e1..34e78303f 100644 --- a/src/modules/GroupChannel/context/GroupChannelProvider.tsx +++ b/src/modules/GroupChannel/context/GroupChannelProvider.tsx @@ -15,7 +15,6 @@ import { useAsyncEffect, useAsyncLayoutEffect, useGroupChannelMessages, useIIFE, import type { SendableMessageType } from '../../../utils'; import { UserProfileProvider, UserProfileProviderProps } from '../../../lib/UserProfileContext'; -import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext'; import { ThreadReplySelectType } from './const'; import { ReplyType } from '../../../types'; import useToggleReactionCallback from './hooks/useToggleReactionCallback'; @@ -26,6 +25,7 @@ import PUBSUB_TOPICS, { PubSubSendMessagePayload } from '../../../lib/pubSub/top import { PubSubTypes } from '../../../lib/pubSub'; import { useMessageActions } from './hooks/useMessageActions'; import { getIsReactionEnabled } from '../../../utils/getIsReactionEnabled'; +import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird'; export { ThreadReplySelectType } from './const'; // export for external usage @@ -142,10 +142,11 @@ export const GroupChannelProvider = (props: GroupChannelProviderProps) => { } = props; // Global context - const { config, stores } = useSendbirdStateContext(); + const { state } = useSendbird(); + const { config, stores } = state; const { sdkStore } = stores; - const { markAsReadScheduler, logger } = config; + const { markAsReadScheduler, logger, pubSub } = config; // State const [quoteMessage, setQuoteMessage] = useState(null); @@ -238,14 +239,16 @@ export const GroupChannelProvider = (props: GroupChannelProviderProps) => { const onSentMessageFromOtherModule = (data: PubSubSendMessagePayload) => { if (data.channel.url === currentChannel?.url) scrollPubSub.publish('scrollToBottom', {}); }; + + if (pubSub?.subscribe === undefined) return; const subscribes = [ - config.pubSub.subscribe(PUBSUB_TOPICS.SEND_USER_MESSAGE, onSentMessageFromOtherModule), - config.pubSub.subscribe(PUBSUB_TOPICS.SEND_FILE_MESSAGE, onSentMessageFromOtherModule), + pubSub.subscribe(PUBSUB_TOPICS.SEND_USER_MESSAGE, onSentMessageFromOtherModule), + pubSub.subscribe(PUBSUB_TOPICS.SEND_FILE_MESSAGE, onSentMessageFromOtherModule), ]; return () => { subscribes.forEach((subscribe) => subscribe.remove()); }; - }, [messageDataSource.initialized, currentChannel?.url]); + }, [messageDataSource.initialized, currentChannel?.url, pubSub?.subscribe]); // SideEffect: Reset MessageCollection with startingPoint prop. useEffect(() => { 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/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/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 a526f924c..4651e5d37 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'; @@ -14,6 +12,7 @@ import useSearchStringEffect from './hooks/useSearchStringEffect'; import { CoreMessageType } from '../../../utils'; import { createStore } from '../../../utils/storeManager'; import { useStore } from '../../../hooks/useStore'; +import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird'; export interface MessageSearchProviderProps { channelUrl: string; @@ -67,7 +66,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/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 97bb7fb06..b133fa13c 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 { useThreadContext } from '../../context/ThreadProvider'; import VoiceMessageItemBody from '../../../../ui/VoiceMessageItemBody'; @@ -39,6 +38,7 @@ import { useFileInfoListWithUploaded } from '../../../Channel/context/hooks/useF import { Colors } from '../../../../utils/color'; import type { OnBeforeDownloadFileMessageType } from '../../../GroupChannel/context/GroupChannelProvider'; import { openURL } from '../../../../utils/utils'; +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 3c4042785..b3c0f3296 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 { useThreadContext } from '../../context/ThreadProvider'; import { useUserProfileContext } from '../../../../lib/UserProfileContext'; import SuggestedMentionList from '../SuggestedMentionList'; @@ -22,7 +21,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 { getCaseResolvedReplyType } from '../../../../lib/utils/resolvedReplyTyp import { classnames } from '../../../../utils/utils'; import { MessageMenu, MessageMenuProps } from '../../../../ui/MessageMenu'; import useElementObserver from '../../../../hooks/useElementObserver'; +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 33ef61916..e9768ca11 100644 --- a/src/modules/Thread/components/ThreadList/ThreadListItem.tsx +++ b/src/modules/Thread/components/ThreadList/ThreadListItem.tsx @@ -8,13 +8,12 @@ import Label, { LabelTypography, LabelColors } from '../../../../ui/Label'; import RemoveMessage from '../RemoveMessageModal'; import FileViewer from '../../../../ui/FileViewer'; import { useThreadContext } from '../../context/ThreadProvider'; -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 { User } from '@sendbird/chat'; import { getCaseResolvedReplyType } from '../../../../lib/utils/resolvedReplyType'; import { classnames } from '../../../../utils/utils'; import { MessageComponentRenderers } from '../../../../ui/MessageContent'; +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 236434edb..3108d9f29 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 MessageProfile, { MessageProfileProps } from '../../../../ui/MessageConte import MessageBody, { CustomSubcomponentsProps, MessageBodyProps } from '../../../../ui/MessageContent/MessageBody'; import { MessageHeaderProps, MessageHeader } from '../../../../ui/MessageContent/MessageHeader'; import { MobileBottomSheetProps } from '../../../../ui/MobileMenu/types'; +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 9d7fab756..751fa7629 100644 --- a/src/modules/Thread/components/ThreadList/index.tsx +++ b/src/modules/Thread/components/ThreadList/index.tsx @@ -7,10 +7,10 @@ import type { SendableMessageType } from '../../../../utils'; import ThreadListItem, { ThreadListItemProps } from './ThreadListItem'; import { useThreadContext } from '../../context/ThreadProvider'; 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 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 { currentChannel, diff --git a/src/modules/Thread/components/ThreadMessageInput/index.tsx b/src/modules/Thread/components/ThreadMessageInput/index.tsx index e51827a8a..ff235e58f 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 { useThreadContext } from '../../context/ThreadProvider'; import { useLocalization } from '../../../../lib/LocalizationContext'; @@ -12,13 +11,14 @@ 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'; import { isDisabledBecauseFrozen, isDisabledBecauseMuted } from '../../../Channel/context/utils'; import { User } from '@sendbird/chat'; import { classnames } from '../../../../utils/utils'; +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 915da2908..746fb2320 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 { useThreadContext } from '../../context/ThreadProvider'; @@ -19,6 +18,7 @@ import { isAboutSame } from '../../context/utils'; import { MessageProvider } from '../../../Message/context/MessageProvider'; import { SendableMessageType, getHTMLTextDirection } from '../../../../utils'; import { classnames } from '../../../../utils/utils'; +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 a72a0d33f..6683bb580 100644 --- a/src/modules/Thread/context/ThreadProvider.tsx +++ b/src/modules/Thread/context/ThreadProvider.tsx @@ -10,8 +10,7 @@ import type { import { getNicknamesMapFromMembers, getParentMessageFrom } from './utils'; import { UserProfileProvider, UserProfileProviderProps } from '../../../lib/UserProfileContext'; -import { CustomUseReducerDispatcher } from '../../../lib/SendbirdState'; -import useSendbirdStateContext from '../../../hooks/useSendbirdStateContext'; +import { CustomUseReducerDispatcher } from '../../../lib/Sendbird/types'; import threadReducer from './dux/reducer'; import { ThreadContextActionTypes } from './dux/actionTypes'; @@ -33,6 +32,7 @@ import useSendVoiceMessageCallback from './hooks/useSendVoiceMessageCallback'; import { PublishingModuleType, useSendMultipleFilesMessage } from './hooks/useSendMultipleFilesMessage'; import { SendableMessageType } from '../../../utils'; import { useThreadFetchers } from './hooks/useThreadFetchers'; +import useSendbird from '../../../lib/Sendbird/context/hooks/useSendbird'; export interface ThreadProviderProps extends Pick { @@ -82,8 +82,7 @@ export const ThreadProvider = (props: ThreadProviderProps) => { const propsMessage = props?.message; const propsParentMessage = getParentMessageFrom(propsMessage); // Context from SendbirdProvider - const globalStore = useSendbirdStateContext(); - const { stores, config } = globalStore; + const { state: { stores, config } } = useSendbird(); // // stores const { sdkStore, userStore } = stores; const { sdk } = sdkStore; diff --git a/src/modules/Thread/context/hooks/useDeleteMessageCallback.ts b/src/modules/Thread/context/hooks/useDeleteMessageCallback.ts index 30c113931..9d3e6d96d 100644 --- a/src/modules/Thread/context/hooks/useDeleteMessageCallback.ts +++ b/src/modules/Thread/context/hooks/useDeleteMessageCallback.ts @@ -1,6 +1,6 @@ import { GroupChannel } from '@sendbird/chat/groupChannel'; import { useCallback } from 'react'; -import { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; +import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/Sendbird/types'; import { ThreadContextActionTypes } from '../dux/actionTypes'; import { SendableMessageType } from '../../../../utils'; diff --git a/src/modules/Thread/context/hooks/useGetAllEmoji.ts b/src/modules/Thread/context/hooks/useGetAllEmoji.ts index 65a01ed37..642c5a8ac 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 { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; +import type { CustomUseReducerDispatcher, Logger, SdkStore } from '../../../../lib/Sendbird/types'; import { ThreadContextActionTypes } from '../dux/actionTypes'; -import { SdkStore } from '../../../../lib/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 19b0d25f0..426816149 100644 --- a/src/modules/Thread/context/hooks/useGetChannel.ts +++ b/src/modules/Thread/context/hooks/useGetChannel.ts @@ -1,9 +1,8 @@ import { useEffect } from 'react'; -import { Logger } from '../../../../lib/SendbirdState'; +import type { Logger, SdkStore } from '../../../../lib/Sendbird/types'; import { ThreadContextActionTypes } from '../dux/actionTypes'; import { SendableMessageType } from '../../../../utils'; -import { SdkStore } from '../../../../lib/types'; interface DynamicProps { channelUrl: string; diff --git a/src/modules/Thread/context/hooks/useGetParentMessage.ts b/src/modules/Thread/context/hooks/useGetParentMessage.ts index bc1b05185..ff4d56ea0 100644 --- a/src/modules/Thread/context/hooks/useGetParentMessage.ts +++ b/src/modules/Thread/context/hooks/useGetParentMessage.ts @@ -1,10 +1,9 @@ import { useEffect } from 'react'; -import { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; +import type { CustomUseReducerDispatcher, Logger, SdkStore } from '../../../../lib/Sendbird/types'; import { BaseMessage, MessageRetrievalParams } from '@sendbird/chat/message'; import { ThreadContextActionTypes } from '../dux/actionTypes'; import { ChannelType } from '@sendbird/chat'; -import { SdkStore } from '../../../../lib/types'; interface DynamicProps { channelUrl: string; diff --git a/src/modules/Thread/context/hooks/useHandleChannelEvents.ts b/src/modules/Thread/context/hooks/useHandleChannelEvents.ts index 363a7e3e2..9e051bd97 100644 --- a/src/modules/Thread/context/hooks/useHandleChannelEvents.ts +++ b/src/modules/Thread/context/hooks/useHandleChannelEvents.ts @@ -1,9 +1,8 @@ import { GroupChannel, GroupChannelHandler } from '@sendbird/chat/groupChannel'; import { useEffect } from 'react'; -import { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; +import type { CustomUseReducerDispatcher, Logger, SdkStore } from '../../../../lib/Sendbird/types'; import uuidv4 from '../../../../utils/uuid'; import { ThreadContextActionTypes } from '../dux/actionTypes'; -import { SdkStore } from '../../../../lib/types'; import compareIds from '../../../../utils/compareIds'; import * as messageActions from '../../../Channel/context/dux/actionTypes'; diff --git a/src/modules/Thread/context/hooks/useHandleThreadPubsubEvents.ts b/src/modules/Thread/context/hooks/useHandleThreadPubsubEvents.ts index 8498c0387..8cd41d72e 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 { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; + +import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/Sendbird/types'; import topics, { PUBSUB_TOPICS, SBUGlobalPubSub } from '../../../../lib/pubSub/topics'; import { scrollIntoLast } from '../utils'; import { ThreadContextActionTypes } from '../dux/actionTypes'; diff --git a/src/modules/Thread/context/hooks/useResendMessageCallback.ts b/src/modules/Thread/context/hooks/useResendMessageCallback.ts index aab62ec10..2f9b3a26e 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 { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; + +import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/Sendbird/types'; import { ThreadContextActionTypes } from '../dux/actionTypes'; import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics'; import { SendableMessageType } from '../../../../utils'; diff --git a/src/modules/Thread/context/hooks/useSendFileMessage.ts b/src/modules/Thread/context/hooks/useSendFileMessage.ts index 1c9d07924..538051ae0 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 } from '@sendbird/chat/message'; -import { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; +import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/Sendbird/types'; import { ThreadContextActionTypes } from '../dux/actionTypes'; import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics'; import { scrollIntoLast } from '../utils'; diff --git a/src/modules/Thread/context/hooks/useSendUserMessageCallback.ts b/src/modules/Thread/context/hooks/useSendUserMessageCallback.ts index ae14fa174..62acf9c89 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 { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; +import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/Sendbird/types'; import { ThreadContextActionTypes } from '../dux/actionTypes'; import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics'; import { SendableMessageType } from '../../../../utils'; diff --git a/src/modules/Thread/context/hooks/useSendVoiceMessageCallback.ts b/src/modules/Thread/context/hooks/useSendVoiceMessageCallback.ts index 987d73e5e..44100b39f 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 } from '@sendbird/chat/message'; -import { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; + +import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/Sendbird/types'; import { ThreadContextActionTypes } from '../dux/actionTypes'; import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics'; import { scrollIntoLast } from '../utils'; diff --git a/src/modules/Thread/context/hooks/useThreadFetchers.ts b/src/modules/Thread/context/hooks/useThreadFetchers.ts index 7947d276a..14eb1fed8 100644 --- a/src/modules/Thread/context/hooks/useThreadFetchers.ts +++ b/src/modules/Thread/context/hooks/useThreadFetchers.ts @@ -1,12 +1,13 @@ -import { ThreadContextActionTypes } from '../dux/actionTypes'; -import { NEXT_THREADS_FETCH_SIZE, PREV_THREADS_FETCH_SIZE } from '../../consts'; import { BaseMessage, ThreadedMessageListParams } from '@sendbird/chat/message'; +import { NEXT_THREADS_FETCH_SIZE, PREV_THREADS_FETCH_SIZE } from '../../consts'; +import { ThreadContextActionTypes } from '../dux/actionTypes'; + +import type { CustomUseReducerDispatcher } from '../../../../lib/Sendbird/types'; import { SendableMessageType } from '../../../../utils'; -import { CustomUseReducerDispatcher } from '../../../../lib/SendbirdState'; 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; @@ -38,7 +39,7 @@ export const useThreadFetchers = ({ latestMessageTimeStamp, threadListState, }: 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 db58e4a2b..6d19abae9 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 { CustomUseReducerDispatcher, Logger } from '../../../../lib/SendbirdState'; +import type { CustomUseReducerDispatcher, Logger } from '../../../../lib/Sendbird/types'; import { ThreadContextActionTypes } from '../dux/actionTypes'; import topics, { SBUGlobalPubSub } from '../../../../lib/pubSub/topics'; diff --git a/src/ui/BottomSheet/__tests__/BottomSheet.spec.js b/src/ui/BottomSheet/__tests__/BottomSheet.spec.js index 8aa6296d0..db52412ac 100644 --- a/src/ui/BottomSheet/__tests__/BottomSheet.spec.js +++ b/src/ui/BottomSheet/__tests__/BottomSheet.spec.js @@ -2,14 +2,14 @@ import React from 'react'; import { render } from '@testing-library/react'; import BottomSheet from "../index"; -import { SendbirdSdkContext } from '../../../lib/SendbirdSdkContext'; +import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext'; describe('ui/BottomSheet', () => { 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 8290d5748..2e600505d 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/GroupChannelProvider'; 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..1f3912b24 100644 --- a/src/ui/FileViewer/__tests__/FileViewer.spec.js +++ b/src/ui/FileViewer/__tests__/FileViewer.spec.js @@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react'; import { FileViewerComponent as FileViewer } from "../index"; import { msg0, msg1 } from '../data.mock'; -import { SendbirdSdkContext } from '../../../lib/SendbirdSdkContext'; +import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext'; import { MODAL_ROOT } from '../../../hooks/useModal'; describe('ui/FileViewer', () => { @@ -30,7 +30,7 @@ describe('ui/FileViewer', () => { } = msg0; const { profileUrl, nickname = '' } = sender; render( - + { onClose={() => { }} onDelete={() => { }} /> - + ); expect( screen.getByAltText(msg0.name).className @@ -62,7 +62,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 +98,7 @@ describe('ui/FileViewer', () => { name = '', } = unsupportedMsg; const { container } = render( - + { onClose={() => { }} onDelete={() => { }} /> - + ); // Use document to search for the element inside the modal root @@ -137,7 +137,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 7b090e586..1cc13b821 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/index.tsx b/src/ui/MessageContent/index.tsx index 433ad1cbc..01136e41c 100644 --- a/src/ui/MessageContent/index.tsx +++ b/src/ui/MessageContent/index.tsx @@ -25,7 +25,6 @@ import { SendableMessageType, } from '../../utils'; import { useLocalization } from '../../lib/LocalizationContext'; -import useSendbirdStateContext from '../../hooks/useSendbirdStateContext'; import { GroupChannel } from '@sendbird/chat/groupChannel'; import { type EmojiCategory, EmojiContainer } from '@sendbird/chat'; import { Feedback, FeedbackRating } from '@sendbird/chat/message'; @@ -50,6 +49,7 @@ import useElementObserver from '../../hooks/useElementObserver'; import { EMOJI_MENU_ROOT_ID, getObservingId, MENU_OBSERVING_CLASS_NAME, MENU_ROOT_ID } from '../ContextMenu'; import { MessageContentForTemplateMessage } from './MessageContentForTemplateMessage'; import { MESSAGE_TEMPLATE_KEY } from '../../utils/consts'; +import useSendbird from '../../lib/Sendbird/context/hooks/useSendbird'; export { MessageBody } from './MessageBody'; export { MessageHeader } from './MessageHeader'; @@ -139,7 +139,7 @@ export function MessageContent(props: MessageContentProps): ReactElement { } = deleteNullish(props); const { dateLocale, stringSet } = useLocalization(); - const { config, eventHandlers } = useSendbirdStateContext(); + const { state: { config, eventHandlers } } = useSendbird(); const { logger } = config; const onPressUserProfileHandler = eventHandlers?.reaction?.onPressUserProfile; const contentRef = useRef(); 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 45482746e..27a581671 100644 --- a/src/ui/Modal/index.tsx +++ b/src/ui/Modal/index.tsx @@ -12,8 +12,8 @@ import IconButton from '../IconButton'; import Button, { ButtonTypes } from '../Button'; import Icon, { IconTypes, IconColors } from '../Icon'; import Label, { LabelTypography, LabelColors } from '../Label'; -import { useSendbirdStateContext } from '../../lib/Sendbird'; import uuidv4 from '../../utils/uuid'; +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 c94b673c4..a517394d0 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/GroupChannelProvider'; -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..f69469810 100644 --- a/src/ui/UserListItem/__tests__/UserListItem.spec.js +++ b/src/ui/UserListItem/__tests__/UserListItem.spec.js @@ -2,7 +2,7 @@ import React from 'react'; import { render } from '@testing-library/react'; import UserListItem from "../index"; -import { SendbirdSdkContext } from '../../../lib/SendbirdSdkContext'; +import { SendbirdContext } from '../../../lib/Sendbird/context/SendbirdContext'; const getUserList = () => [ { @@ -35,14 +35,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 f584f35f8..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 '../../lib/Sendbird'; 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/utils/__tests__/getIsReactionEnabled.spec.ts b/src/utils/__tests__/getIsReactionEnabled.spec.ts index f507ee7dc..2081ae55b 100644 --- a/src/utils/__tests__/getIsReactionEnabled.spec.ts +++ b/src/utils/__tests__/getIsReactionEnabled.spec.ts @@ -1,6 +1,6 @@ import type { GroupChannel } from '@sendbird/chat/groupChannel'; -import type { SendBirdStateConfig } from '../../lib/types'; +import type { SendbirdStateConfig } from '../../lib/Sendbird/types'; import { getIsReactionEnabled } from '../getIsReactionEnabled'; const normalGroupChannel = (props?: any) => ({ @@ -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; }