import React, { useCallback, useContext, useReducer, useRef, useState } from 'react'; import type { SendbirdBaseChannel, SendbirdBaseMessage } from '@sendbird/uikit-utils'; import { NOOP } from '@sendbird/uikit-utils'; import { ReactionBottomSheetProps, ReactionBottomSheets } from '../components/ReactionBottomSheets'; import { LocalizationContext } from '../contexts/LocalizationCtx'; import { SendbirdChatContext } from '../contexts/SendbirdChatCtx'; import { UserProfileContext } from '../contexts/UserProfileCtx'; type State = { message?: SendbirdBaseMessage; channel?: SendbirdBaseChannel; }; export type ReactionContextType = { openReactionList(param: Required): void; openReactionUserList(param: Required & { focusIndex?: number }): void; updateReactionFocusedItem(param?: State): void; focusIndex: number; } & State; type Props = React.PropsWithChildren<{ onPressUserProfile?: ReactionBottomSheetProps['onPressUserProfile']; }>; export const ReactionContext = React.createContext(null); export const ReactionProvider = ({ children, onPressUserProfile }: Props) => { const chatCtx = useContext(SendbirdChatContext); const localizationCtx = useContext(LocalizationContext); const userProfileCtx = useContext(UserProfileContext); if (!chatCtx) throw new Error('SendbirdChatContext is not provided'); if (!localizationCtx) throw new Error('LocalizationContext is not provided'); if (!userProfileCtx) throw new Error('UserProfileContext is not provided'); const [state, setState] = useReducer((prev: State, next: State) => ({ ...prev, ...next }), {}); const [reactionListVisible, setReactionListVisible] = useState(false); const [reactionUserListVisible, setReactionUserListVisible] = useState(false); const [reactionUserListFocusIndex, setReactionUserListFocusIndex] = useState(0); const closeResolver = useRef<() => void>(NOOP); const openReactionList: ReactionContextType['openReactionList'] = useCallback((params) => { setState(params); setReactionListVisible(true); }, []); const openReactionUserList: ReactionContextType['openReactionUserList'] = useCallback( ({ channel, message, focusIndex = 0 }) => { setState({ channel, message }); setReactionUserListFocusIndex(focusIndex); setReactionUserListVisible(true); }, [], ); const updateReactionFocusedItem: ReactionContextType['updateReactionFocusedItem'] = useCallback((params) => { if (params) setState(params); else setState({}); }, []); const createOnCloseWithResolver = (callback: () => void) => { return () => { return new Promise((resolve) => { closeResolver.current = resolve; callback(); }); }; }; const reactionCtx = { ...state, openReactionList, openReactionUserList, updateReactionFocusedItem, focusIndex: reactionUserListFocusIndex, }; const sheetProps: Omit = { chatCtx, reactionCtx, localizationCtx, onPressUserProfile: onPressUserProfile ?? userProfileCtx.show, onDismiss: () => { setState({}); closeResolver.current?.(); }, }; return ( {children} setReactionUserListVisible(false))} /> setReactionListVisible(false))} /> ); };