@gathertown/uikit-react-native
Version:
Sendbird UIKit for React Native: A feature-rich and customizable chat UI kit with messaging, channel management, and user authentication.
214 lines (213 loc) • 8.75 kB
JavaScript
import React, { useCallback, useMemo, useState } from 'react';
import { ReplyType } from '@sendbird/chat/message';
import { useGroupChannelMessages } from '@gathertown/uikit-chat-hooks';
import { NOOP, PASS, messageComparator, useFreshCallback, useIIFE, useRefTracker } from '@gathertown/uikit-utils';
import GroupChannelMessageRenderer from '../components/GroupChannelMessageRenderer';
import NewMessagesButton from '../components/NewMessagesButton';
import ScrollToBottomButton from '../components/ScrollToBottomButton';
import StatusComposition from '../components/StatusComposition';
import createGroupChannelModule from '../domain/groupChannel/module/createGroupChannelModule';
import { useSendbirdChat } from '../hooks/useContext';
import pubsub from '../utils/pubsub';
const createGroupChannelFragment = initModule => {
const GroupChannelModule = createGroupChannelModule(initModule);
return _ref => {
let {
searchItem,
renderNewMessagesButton = props => /*#__PURE__*/React.createElement(NewMessagesButton, props),
renderScrollToBottomButton = props => /*#__PURE__*/React.createElement(ScrollToBottomButton, props),
renderMessage,
enableMessageGrouping = true,
enableTypingIndicator,
onPressHeaderLeft = NOOP,
onPressHeaderRight = NOOP,
onPressMediaMessage = NOOP,
onChannelDeleted = NOOP,
onBeforeSendUserMessage = PASS,
onBeforeSendFileMessage = PASS,
onBeforeUpdateUserMessage = PASS,
onBeforeUpdateFileMessage = PASS,
onAfterSendUserMessage = PASS,
onAfterSendFileMessage = PASS,
onAfterUpdateUserMessage = PASS,
onAfterUpdateFileMessage = PASS,
onAfterDeleteMessage = PASS,
channel,
keyboardAvoidOffset,
collectionCreator,
sortComparator = messageComparator,
flatListProps
} = _ref;
const {
sdk,
currentUser,
sbOptions
} = useSendbirdChat();
const [internalSearchItem, setInternalSearchItem] = useState(searchItem);
const navigateFromMessageSearch = useCallback(() => Boolean(searchItem), []);
const [groupChannelPubSub] = useState(() => pubsub());
const [scrolledAwayFromBottom, setScrolledAwayFromBottom] = useState(false);
const scrolledAwayFromBottomRef = useRefTracker(scrolledAwayFromBottom);
const replyType = useIIFE(() => {
if (sbOptions.uikit.groupChannel.channel.replyType === 'none') return ReplyType.NONE;else return ReplyType.ONLY_REPLY_TO_CHANNEL;
});
const {
loading,
messages,
newMessages,
resetNewMessages,
next,
prev,
hasNext,
sendFileMessage,
sendUserMessage,
updateFileMessage,
updateUserMessage,
resendMessage,
deleteMessage,
resetWithStartingPoint
} = useGroupChannelMessages(sdk, channel, currentUser === null || currentUser === void 0 ? void 0 : currentUser.userId, {
shouldCountNewMessages: () => scrolledAwayFromBottomRef.current,
onMessagesReceived(messages) {
groupChannelPubSub.publish({
type: 'MESSAGES_RECEIVED',
data: {
messages
}
});
},
onMessagesUpdated(messages) {
groupChannelPubSub.publish({
type: 'MESSAGES_UPDATED',
data: {
messages
}
});
},
collectionCreator,
sortComparator,
onChannelDeleted,
replyType,
startingPoint: internalSearchItem === null || internalSearchItem === void 0 ? void 0 : internalSearchItem.startingPoint,
enableCollectionWithoutLocalCache: true
});
const renderItem = useFreshCallback(props => {
if (renderMessage) return renderMessage(props);
return /*#__PURE__*/React.createElement(GroupChannelMessageRenderer, props);
});
const memoizedFlatListProps = useMemo(() => ({
ListEmptyComponent: /*#__PURE__*/React.createElement(GroupChannelModule.StatusEmpty, null),
contentContainerStyle: {
flexGrow: 1
},
...flatListProps
}), [flatListProps]);
const onResetMessageList = useCallback(callback => {
resetWithStartingPoint(Number.MAX_SAFE_INTEGER, callback);
}, []);
const onResetMessageListWithStartingPoint = useCallback((startingPoint, callback) => {
resetWithStartingPoint(startingPoint, callback);
}, []);
// Changing the search item will trigger the focus animation on messages.
const onUpdateSearchItem = useCallback(searchItem => {
// Clean up for animation trigger with useEffect
setInternalSearchItem(undefined);
setInternalSearchItem(searchItem);
}, []);
const onPending = message => {
groupChannelPubSub.publish({
type: 'MESSAGE_SENT_PENDING',
data: {
message
}
});
};
const onSent = message => {
groupChannelPubSub.publish({
type: 'MESSAGE_SENT_SUCCESS',
data: {
message
}
});
};
const onPressSendUserMessage = useFreshCallback(async params => {
const processedParams = await onBeforeSendUserMessage(params);
const message = await sendUserMessage(processedParams, onPending);
await onAfterSendUserMessage(message);
onSent(message);
});
const onPressSendFileMessage = useFreshCallback(async params => {
const processedParams = await onBeforeSendFileMessage(params);
const message = await sendFileMessage(processedParams, onPending);
await onAfterSendFileMessage(message);
onSent(message);
});
const onPressUpdateUserMessage = useFreshCallback(async (message, params) => {
const processedParams = await onBeforeUpdateUserMessage(params);
await updateUserMessage(message.messageId, processedParams);
await onAfterUpdateUserMessage(message);
});
const onPressUpdateFileMessage = useFreshCallback(async (message, params) => {
const processedParams = await onBeforeUpdateFileMessage(params);
await updateFileMessage(message.messageId, processedParams);
await onAfterUpdateFileMessage(message);
});
const onScrolledAwayFromBottom = useFreshCallback(value => {
if (!value) resetNewMessages();
setScrolledAwayFromBottom(value);
});
return /*#__PURE__*/React.createElement(GroupChannelModule.Provider, {
channel: channel,
groupChannelPubSub: groupChannelPubSub,
enableTypingIndicator: enableTypingIndicator ?? sbOptions.uikit.groupChannel.channel.enableTypingIndicator,
keyboardAvoidOffset: keyboardAvoidOffset
}, /*#__PURE__*/React.createElement(GroupChannelModule.Header, {
shouldHideRight: navigateFromMessageSearch,
onPressHeaderLeft: onPressHeaderLeft,
onPressHeaderRight: onPressHeaderRight
}), /*#__PURE__*/React.createElement(StatusComposition, {
loading: loading,
LoadingComponent: /*#__PURE__*/React.createElement(GroupChannelModule.StatusLoading, null)
}, /*#__PURE__*/React.createElement(GroupChannelModule.MessageList, {
channel: channel,
searchItem: internalSearchItem,
onResetMessageList: onResetMessageList,
onResetMessageListWithStartingPoint: onResetMessageListWithStartingPoint,
onUpdateSearchItem: onUpdateSearchItem,
enableMessageGrouping: enableMessageGrouping,
currentUserId: currentUser === null || currentUser === void 0 ? void 0 : currentUser.userId,
renderMessage: renderItem,
messages: messages,
newMessages: newMessages,
onTopReached: prev,
onBottomReached: next,
hasNext: hasNext,
scrolledAwayFromBottom: scrolledAwayFromBottom,
onScrolledAwayFromBottom: onScrolledAwayFromBottom,
renderNewMessagesButton: renderNewMessagesButton,
renderScrollToBottomButton: renderScrollToBottomButton,
onResendFailedMessage: resendMessage,
onDeleteMessage: async message => {
await deleteMessage(message);
await onAfterDeleteMessage(message);
},
onPressMediaMessage: onPressMediaMessage,
flatListProps: memoizedFlatListProps
}), /*#__PURE__*/React.createElement(GroupChannelModule.Input, {
SuggestedMentionList: GroupChannelModule.SuggestedMentionList,
shouldRenderInput: shouldRenderInput(channel),
onPressSendUserMessage: onPressSendUserMessage,
onPressSendFileMessage: onPressSendFileMessage,
onPressUpdateUserMessage: onPressUpdateUserMessage,
onPressUpdateFileMessage: onPressUpdateFileMessage
})));
};
};
function shouldRenderInput(channel) {
if (channel.isBroadcast) {
return channel.myRole === 'operator';
}
return true;
}
export default createGroupChannelFragment;
//# sourceMappingURL=createGroupChannelFragment.js.map