UNPKG

stream-chat-react-native-core

Version:

The official React Native and Expo components for Stream Chat, a service for building chat applications

949 lines 42.4 kB
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.MessageFlashList = void 0; var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties")); var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray")); var _react = _interopRequireWildcard(require("react")); var _reactNative = require("react-native"); var _reactNativeReanimated = _interopRequireDefault(require("react-native-reanimated")); var _useMessageList2 = require("./hooks/useMessageList"); var _useScrollToBottomAccessibilityAction = require("./hooks/useScrollToBottomAccessibilityAction"); var _useShouldScrollToRecentOnNewOwnMessage = require("./hooks/useShouldScrollToRecentOnNewOwnMessage"); var _useTypingUsers = require("./hooks/useTypingUsers"); var _InlineLoadingMoreIndicator = require("./InlineLoadingMoreIndicator"); var _InlineLoadingMoreRecentIndicator = require("./InlineLoadingMoreRecentIndicator"); var _InlineLoadingMoreRecentThreadIndicator = require("./InlineLoadingMoreRecentThreadIndicator"); var _AttachmentPickerContext = require("../../contexts/attachmentPickerContext/AttachmentPickerContext"); var _ChannelContext = require("../../contexts/channelContext/ChannelContext"); var _ChatContext = require("../../contexts/chatContext/ChatContext"); var _ComponentsContext = require("../../contexts/componentsContext/ComponentsContext"); var _MessageInputContext = require("../../contexts/messageInputContext/MessageInputContext"); var _MessageListItemContext = require("../../contexts/messageListItemContext/MessageListItemContext"); var _MessagesContext = require("../../contexts/messagesContext/MessagesContext"); var _OwnCapabilitiesContext = require("../../contexts/ownCapabilitiesContext/OwnCapabilitiesContext"); var _PaginatedMessageListContext = require("../../contexts/paginatedMessageListContext/PaginatedMessageListContext"); var _ThemeContext = require("../../contexts/themeContext/ThemeContext"); var _ThreadContext = require("../../contexts/threadContext/ThreadContext"); var _hooks = require("../../hooks"); var _native = require("../../native"); var _stateStore = require("../../state-store"); var _theme = require("../../theme"); var _types = require("../../types/types"); var _transitions = require("../../utils/animations/transitions"); var _MessageWrapper = require("../Message/MessageItemView/MessageWrapper"); var _notificationFilters = require("../Notifications/notificationFilters"); var _PortalWhileClosingView = require("../UIComponents/PortalWhileClosingView"); var _jsxRuntime = require("react/jsx-runtime"); var _excluded = ["contentContainerStyle", "style"]; var _jsxFileName = "/home/runner/work/stream-chat-react-native/stream-chat-react-native/package/src/components/MessageList/MessageFlashList.tsx"; function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (var _t in e) "default" !== _t && {}.hasOwnProperty.call(e, _t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, _t)) && (i.get || i.set) ? o(f, _t, i) : f[_t] = e[_t]); return f; })(e, t); } var FlashList; var useFlashListContext = () => undefined; try { var flashListModule = require('@shopify/flash-list'); FlashList = flashListModule.FlashList; useFlashListContext = flashListModule.useFlashListContext; } catch { FlashList = undefined; } var keyExtractor = item => { if (item.id) { return item.id; } if (item.created_at) { return typeof item.created_at === 'string' ? item.created_at : item.created_at.toISOString(); } return Date.now().toString(); }; var flatListViewabilityConfig = { viewAreaCoveragePercentThreshold: 1 }; var hasReadLastMessage = (channel, userId) => { var latestMessageIdInChannel = channel.state.latestMessages[channel.state.latestMessages.length - 1]?.id; var lastReadMessageIdServer = channel.state.read[userId]?.last_read_message_id; return latestMessageIdInChannel === lastReadMessageIdServer; }; var getPreviousLastMessage = (messages, newMessage) => { if (!newMessage) return; var previousLastMessage; for (var i = messages.length - 1; i >= 0; i--) { var msg = messages[i]; if (!msg?.id) break; if (msg.id !== newMessage.id) { previousLastMessage = msg; break; } } return previousLastMessage; }; var messageInputHeightStoreSelector = state => ({ height: state.height }); var WAIT_FOR_SCROLL_TIMEOUT = 0; var getAttachmentItemType = message => { var attachments = message.attachments ?? []; var hasGiphy = false; var hasAudio = false; var hasFile = false; var hasCard = false; for (var attachment of attachments) { var isGalleryImage = attachment.type === _types.FileTypes.Image && !attachment.og_scrape_url && !attachment.title_link && (!!attachment.image_url || !!attachment.thumb_url); var isGalleryVideo = attachment.type === _types.FileTypes.Video && !attachment.og_scrape_url && (0, _native.isVideoPlayerAvailable)(); if (isGalleryImage || isGalleryVideo) { return 'message-with-gallery'; } if (attachment.type === _types.FileTypes.Giphy) { hasGiphy = true; } else if (attachment.type === _types.FileTypes.Audio || attachment.type === _types.FileTypes.VoiceRecording) { hasAudio = true; } else if (attachment.type === _types.FileTypes.File) { hasFile = true; } else if (attachment.og_scrape_url || attachment.title_link) { hasCard = true; } } if (hasGiphy) { return 'message-with-giphy'; } if (hasAudio) { return 'message-with-audio'; } if (hasFile) { return 'message-with-file'; } if (hasCard) { return 'message-with-card'; } return 'message-with-attachments'; }; var getItemTypeInternal = message => { if (message.type === 'regular') { if ((message.attachments?.length ?? 0) > 0) { return getAttachmentItemType(message); } if (message.poll_id) { return 'message-with-poll'; } if (message.quoted_message_id) { return 'message-with-quote'; } if (message.shared_location) { return 'message-with-shared-location'; } if (message.text) { return 'message-with-text'; } return 'message-with-nothing'; } if (message.type === 'deleted') { return 'deleted-message'; } if (message.type === 'system') { return 'system-message'; } return 'generic-message'; }; var MessageFlashListWithContext = props => { var LoadingMoreRecentIndicator = props.threadList ? _InlineLoadingMoreRecentThreadIndicator.InlineLoadingMoreRecentThreadIndicator : _InlineLoadingMoreRecentIndicator.InlineLoadingMoreRecentIndicator; var allowSendBeforeAttachmentsUpload = props.allowSendBeforeAttachmentsUpload, attachmentPickerStore = props.attachmentPickerStore, additionalFlashListProps = props.additionalFlashListProps, channel = props.channel, channelUnreadStateStore = props.channelUnreadStateStore, client = props.client, closePicker = props.closePicker, disabled = props.disabled, disableTypingIndicator = props.disableTypingIndicator, FooterComponent = props.FooterComponent, _props$HeaderComponen = props.HeaderComponent, HeaderComponent = _props$HeaderComponen === void 0 ? _InlineLoadingMoreIndicator.InlineLoadingMoreIndicator : _props$HeaderComponen, hideStickyDateHeader = props.hideStickyDateHeader, _props$isLiveStreamin = props.isLiveStreaming, isLiveStreaming = _props$isLiveStreamin === void 0 ? false : _props$isLiveStreamin, loadChannelAroundMessage = props.loadChannelAroundMessage, loading = props.loading, loadMore = props.loadMore, loadMoreRecent = props.loadMoreRecent, loadMoreRecentThread = props.loadMoreRecentThread, loadMoreThread = props.loadMoreThread, markRead = props.markRead, maximumMessageLimit = props.maximumMessageLimit, messageInputFloating = props.messageInputFloating, messageInputHeightStore = props.messageInputHeightStore, myMessageTheme = props.myMessageTheme, readEvents = props.readEvents, noGroupByUser = props.noGroupByUser, onListScroll = props.onListScroll, onThreadSelect = props.onThreadSelect, reloadChannel = props.reloadChannel, setChannelUnreadState = props.setChannelUnreadState, setFlatListRef = props.setFlatListRef, setTargetedMessage = props.setTargetedMessage, hasPendingInitialTargetLoad = props.hasPendingInitialTargetLoad, targetedMessage = props.targetedMessage, thread = props.thread, threadInstance = props.threadInstance, _props$threadList = props.threadList, threadList = _props$threadList === void 0 ? false : _props$threadList; var _useComponentsContext = (0, _ComponentsContext.useComponentsContext)(), AutoCompleteSuggestionList = _useComponentsContext.AutoCompleteSuggestionList, EmptyStateIndicator = _useComponentsContext.EmptyStateIndicator, LoadingIndicator = _useComponentsContext.MessageListLoadingIndicator, NetworkDownIndicator = _useComponentsContext.NetworkDownIndicator, NotificationList = _useComponentsContext.NotificationList, ScrollToBottomButton = _useComponentsContext.ScrollToBottomButton, StickyHeader = _useComponentsContext.StickyHeader, TypingIndicator = _useComponentsContext.TypingIndicator, TypingIndicatorContainer = _useComponentsContext.TypingIndicatorContainer, UnreadMessagesNotification = _useComponentsContext.UnreadMessagesNotification; var flashListRef = (0, _react.useRef)(null); var _useStateStore = (0, _hooks.useStateStore)(messageInputHeightStore.store, messageInputHeightStoreSelector), messageInputHeight = _useStateStore.height; var _useState = (0, _react.useState)(false), _useState2 = (0, _slicedToArray2.default)(_useState, 2), hasMoved = _useState2[0], setHasMoved = _useState2[1]; var _useState3 = (0, _react.useState)(false), _useState4 = (0, _slicedToArray2.default)(_useState3, 2), scrollToBottomButtonVisible = _useState4[0], setScrollToBottomButtonVisible = _useState4[1]; var _useState5 = (0, _react.useState)(false), _useState6 = (0, _slicedToArray2.default)(_useState5, 2), isUnreadNotificationOpen = _useState6[0], setIsUnreadNotificationOpen = _useState6[1]; var _useState7 = (0, _react.useState)(), _useState8 = (0, _slicedToArray2.default)(_useState7, 2), stickyHeaderDate = _useState8[0], setStickyHeaderDate = _useState8[1]; var _useState9 = (0, _react.useState)(true), _useState0 = (0, _slicedToArray2.default)(_useState9, 2), scrollEnabled = _useState0[0], setScrollEnabled = _useState0[1]; var stickyHeaderDateRef = (0, _react.useRef)(undefined); var onStartReachedTracker = (0, _react.useRef)({}); var onEndReachedTracker = (0, _react.useRef)({}); var onStartReachedInPromise = (0, _react.useRef)(null); var onEndReachedInPromise = (0, _react.useRef)(null); var scrollToDebounceTimeoutRef = (0, _react.useRef)(undefined); var channelResyncScrollSet = (0, _react.useRef)(true); var _useTheme = (0, _ThemeContext.useTheme)(), theme = _useTheme.theme; var styles = useStyles(); var myMessageThemeString = (0, _react.useMemo)(() => JSON.stringify(myMessageTheme), [myMessageTheme]); var modifiedTheme = (0, _react.useMemo)(() => (0, _ThemeContext.mergeThemes)({ style: myMessageTheme, theme }), [myMessageThemeString, theme]); var _useMessageList = (0, _useMessageList2.useMessageList)({ isFlashList: true, isLiveStreaming, threadList }), processedMessageList = _useMessageList.processedMessageList, rawMessageList = _useMessageList.rawMessageList, viewabilityChangedCallback = _useMessageList.viewabilityChangedCallback; var renderItem = (0, _react.useCallback)(({ item: message, index }) => { var previousMessage = processedMessageList[index - 1]; var nextMessage = processedMessageList[index + 1]; return (0, _jsxRuntime.jsx)(_MessageWrapper.MessageWrapper, { message: message, previousMessage: previousMessage, nextMessage: nextMessage }); }, [processedMessageList]); var topMessageBeforeUpdate = (0, _react.useRef)(undefined); var topMessageAfterUpdate = rawMessageList[0]; var latestNonCurrentMessageBeforeUpdateRef = (0, _react.useRef)(undefined); var messageListLengthBeforeUpdate = (0, _react.useRef)(0); var messageListLengthAfterUpdate = processedMessageList.length; var shouldScrollToRecentOnNewOwnMessageRef = (0, _useShouldScrollToRecentOnNewOwnMessage.useShouldScrollToRecentOnNewOwnMessage)(rawMessageList, client.userID); var _useState1 = (0, _react.useState)(true), _useState10 = (0, _slicedToArray2.default)(_useState1, 2), autoscrollToRecent = _useState10[0], setAutoscrollToRecent = _useState10[1]; (0, _react.useEffect)(() => { if (autoscrollToRecent && flashListRef.current) { if (hasPendingInitialTargetLoad?.()) { return; } flashListRef.current.scrollToEnd({ animated: true }); } }, [autoscrollToRecent, hasPendingInitialTargetLoad]); var isOverlayOpen = (0, _stateStore.useHasActiveId)(); var maintainVisibleContentPosition = (0, _react.useMemo)(() => { return { animateAutoscrollToBottom: true, autoscrollToBottomThreshold: autoscrollToRecent && !isOverlayOpen ? 1 : undefined, startRenderingFromBottom: true }; }, [isOverlayOpen, autoscrollToRecent]); (0, _react.useEffect)(() => { if (disabled) { setScrollToBottomButtonVisible(false); } }, [disabled]); (0, _react.useEffect)(() => { if (!targetedMessage) { return; } var indexOfParentInMessageList = processedMessageList.findIndex(message => message?.id === targetedMessage); if (indexOfParentInMessageList === -1) { loadChannelAroundMessage({ messageId: targetedMessage, setTargetedMessage }); } else { scrollToDebounceTimeoutRef.current = setTimeout((0, _asyncToGenerator2.default)(function* () { clearTimeout(scrollToDebounceTimeoutRef.current); var scrollToIndex = function () { var _ref2 = (0, _asyncToGenerator2.default)(function* () { var list = flashListRef.current; if (!list) { return false; } yield list.scrollToIndex({ animated: true, index: indexOfParentInMessageList, viewPosition: 0.5 }); return true; }); return function scrollToIndex() { return _ref2.apply(this, arguments); }; }(); yield scrollToIndex(); requestAnimationFrame((0, _asyncToGenerator2.default)(function* () { yield scrollToIndex(); setTargetedMessage(undefined); })); }), WAIT_FOR_SCROLL_TIMEOUT); } }, [loadChannelAroundMessage, processedMessageList, setTargetedMessage, targetedMessage]); var goToMessage = (0, _hooks.useStableCallback)(function () { var _ref4 = (0, _asyncToGenerator2.default)(function* (messageId) { var indexOfParentInMessageList = processedMessageList.findIndex(message => message?.id === messageId); try { if (indexOfParentInMessageList === -1) { clearTimeout(scrollToDebounceTimeoutRef.current); yield loadChannelAroundMessage({ messageId, setTargetedMessage }); } else { setTargetedMessage(messageId); } } catch (e) { console.warn('Error while scrolling to message', e); } }); return function (_x) { return _ref4.apply(this, arguments); }; }()); (0, _react.useEffect)(() => { var isMessageRemovedFromMessageList = messageListLengthBeforeUpdate.current - messageListLengthAfterUpdate === 1; var scrollToBottomIfNeeded = () => { if (!client || !channel || processedMessageList.length === 0) { return; } if (isMessageRemovedFromMessageList || topMessageBeforeUpdate.current?.created_at && topMessageAfterUpdate?.created_at && topMessageBeforeUpdate.current.created_at < topMessageAfterUpdate.created_at) { channelResyncScrollSet.current = false; setScrollToBottomButtonVisible(false); resetPaginationTrackersRef.current(); setTimeout(() => { channelResyncScrollSet.current = true; if (channel.countUnread() > 0) { markRead(); } }, WAIT_FOR_SCROLL_TIMEOUT); } }; if (isMessageRemovedFromMessageList && !maximumMessageLimit) { scrollToBottomIfNeeded(); } messageListLengthBeforeUpdate.current = messageListLengthAfterUpdate; topMessageBeforeUpdate.current = topMessageAfterUpdate; }, [messageListLengthAfterUpdate, topMessageAfterUpdate?.id, maximumMessageLimit]); (0, _react.useEffect)(() => { if (!processedMessageList.length) { return; } var notLatestSet = channel.state.messages !== channel.state.latestMessages; if (notLatestSet) { latestNonCurrentMessageBeforeUpdateRef.current = channel.state.latestMessages[channel.state.latestMessages.length - 1]; setAutoscrollToRecent(false); setScrollToBottomButtonVisible(true); return; } else { setAutoscrollToRecent(true); } var latestNonCurrentMessageBeforeUpdate = latestNonCurrentMessageBeforeUpdateRef.current; latestNonCurrentMessageBeforeUpdateRef.current = undefined; var latestCurrentMessageAfterUpdate = processedMessageList[processedMessageList.length - 1]; if (!latestCurrentMessageAfterUpdate) { return; } var didMergeMessageSetsWithNoUpdates = latestNonCurrentMessageBeforeUpdate?.id === latestCurrentMessageAfterUpdate.id; if (!didMergeMessageSetsWithNoUpdates) { var shouldScrollToRecentOnNewOwnMessage = shouldScrollToRecentOnNewOwnMessageRef.current(); if (shouldScrollToRecentOnNewOwnMessage) { flashListRef.current?.scrollToEnd({ animated: true }); } } }, [channel, processedMessageList, shouldScrollToRecentOnNewOwnMessageRef, threadList]); (0, _react.useEffect)(() => { var shouldMarkRead = () => { var channelUnreadState = channelUnreadStateStore.channelUnreadState; return !channelUnreadState?.first_unread_message_id && !scrollToBottomButtonVisible && client.user?.id && !hasReadLastMessage(channel, client.user?.id); }; var handleEvent = function () { var _ref5 = (0, _asyncToGenerator2.default)(function* (event) { var mainChannelUpdated = !event.message?.parent_id || event.message?.show_in_channel; var isMyOwnMessage = event.message?.user?.id === client.user?.id; var channelUnreadState = channelUnreadStateStore.channelUnreadState; if ((scrollToBottomButtonVisible || channelUnreadState?.first_unread_message_id) && !isMyOwnMessage) { var previousUnreadCount = channelUnreadState?.unread_messages ?? 0; var previousLastMessage = getPreviousLastMessage(channel.state.messages, event.message); setChannelUnreadState({ ...channelUnreadState, last_read: channelUnreadState?.last_read ?? (previousUnreadCount === 0 && previousLastMessage?.created_at ? new Date(previousLastMessage.created_at) : new Date(0)), unread_messages: previousUnreadCount + 1 }); } else if (mainChannelUpdated && shouldMarkRead()) { yield markRead(); } }); return function handleEvent(_x2) { return _ref5.apply(this, arguments); }; }(); var listener = channel.on('message.new', handleEvent); return () => { listener?.unsubscribe(); }; }, [channel, channelUnreadStateStore, client.user?.id, markRead, scrollToBottomButtonVisible, setChannelUnreadState, threadList]); var updateStickyHeaderDateIfNeeded = (0, _hooks.useStableCallback)(viewableItems => { if (!viewableItems.length) { return; } var lastItem = viewableItems[0]; if (!lastItem) return; if (!channel.state.messagePagination.hasPrev && processedMessageList[0].id === lastItem.item.id) { setStickyHeaderDate(undefined); return; } var isMessageTypeDeleted = lastItem.item.type === 'deleted'; if (lastItem?.item?.created_at && !isMessageTypeDeleted && typeof lastItem.item.created_at !== 'string' && lastItem.item.created_at.toDateString() !== stickyHeaderDateRef.current?.toDateString()) { stickyHeaderDateRef.current = lastItem.item.created_at; setStickyHeaderDate(lastItem.item.created_at); } }); var updateStickyUnreadIndicator = (0, _hooks.useStableCallback)(viewableItems => { var channelUnreadState = channelUnreadStateStore.channelUnreadState; var lastReadMessageId = channelUnreadState?.last_read_message_id; var lastReadMessageVisible = viewableItems.some(item => item.item.id === lastReadMessageId); var unreadNotificationSupported = readEvents || client.options.isLocalUnreadCountEnabled; if (!viewableItems.length || !unreadNotificationSupported || lastReadMessageVisible || attachmentPickerStore.state.getLatestValue().selectedPicker === 'images') { setIsUnreadNotificationOpen(false); return; } var lastItem = viewableItems[0]; if (!lastItem) return; var lastItemMessage = lastItem.item; var lastItemCreatedAt = lastItemMessage.created_at; var unreadIndicatorDate = channelUnreadState?.last_read?.getTime(); var lastItemDate = lastItemCreatedAt.getTime(); if (!channel.state.messagePagination.hasPrev && processedMessageList[0].id === lastItemMessage.id) { setIsUnreadNotificationOpen(false); return; } if (viewableItems.length === 1 && channel.countUnread() === 0 && lastItemMessage.user.id === client.userID) { setIsUnreadNotificationOpen(false); return; } if (unreadIndicatorDate && lastItemDate > unreadIndicatorDate) { setIsUnreadNotificationOpen(true); } else { setIsUnreadNotificationOpen(false); } }); var unstableOnViewableItemsChanged = ({ viewableItems }) => { if (!viewableItems) { return; } viewabilityChangedCallback({ inverted: false, viewableItems }); if (!hideStickyDateHeader) { updateStickyHeaderDateIfNeeded(viewableItems); } updateStickyUnreadIndicator(viewableItems); }; var onViewableItemsChanged = (0, _react.useRef)(unstableOnViewableItemsChanged); onViewableItemsChanged.current = unstableOnViewableItemsChanged; var stableOnViewableItemsChanged = (0, _react.useCallback)(({ viewableItems }) => { onViewableItemsChanged.current({ viewableItems }); }, []); var setNativeScrollability = (0, _hooks.useStableCallback)(value => { setScrollEnabled(value); }); var messageListItemContextValue = (0, _react.useMemo)(() => ({ goToMessage, modifiedTheme, noGroupByUser, onThreadSelect, setNativeScrollability }), [goToMessage, modifiedTheme, noGroupByUser, onThreadSelect, setNativeScrollability]); var maybeCallOnStartReached = (0, _hooks.useStableCallback)((0, _asyncToGenerator2.default)(function* () { if (processedMessageList?.length && onStartReachedTracker.current[processedMessageList.length]) { return; } if (processedMessageList?.length) { onStartReachedTracker.current[processedMessageList.length] = true; } var callback = () => { onStartReachedInPromise.current = null; return Promise.resolve(); }; var onError = () => { setTimeout(() => { onStartReachedTracker.current = {}; }, 2000); }; if (onEndReachedInPromise.current) { yield onEndReachedInPromise.current; } onStartReachedInPromise.current = (threadList && !!threadInstance && loadMoreRecentThread ? loadMoreRecentThread({}) : loadMoreRecent()).then(callback).catch(onError); })); var maybeCallOnEndReached = (0, _hooks.useStableCallback)((0, _asyncToGenerator2.default)(function* () { if (processedMessageList?.length && onEndReachedTracker.current[processedMessageList.length]) { return; } if (processedMessageList?.length) { onEndReachedTracker.current[processedMessageList.length] = true; } var callback = () => { onEndReachedInPromise.current = null; return Promise.resolve(); }; var onError = () => { setTimeout(() => { onEndReachedTracker.current = {}; }, 2000); }; if (onStartReachedInPromise.current) { yield onStartReachedInPromise.current; } onEndReachedInPromise.current = (threadList ? loadMoreThread() : loadMore()).then(callback).catch(onError); })); var onUserScrollEvent = (0, _hooks.useStableCallback)(event => { var nativeEvent = event.nativeEvent; var offset = nativeEvent.contentOffset.y; var visibleLength = nativeEvent.layoutMeasurement.height; var contentLength = nativeEvent.contentSize.height; if (!channel || !channelResyncScrollSet.current) { return; } var isScrollAtEnd = offset < 100; var isScrollAtStart = contentLength - visibleLength - offset < 100; if (isScrollAtEnd) { maybeCallOnEndReached(); } if (isScrollAtStart) { maybeCallOnStartReached(); } }); var resetPaginationTrackersRef = (0, _react.useRef)(() => { onStartReachedTracker.current = {}; onEndReachedTracker.current = {}; }); var currentScrollOffsetRef = (0, _react.useRef)(0); var handleScroll = (0, _hooks.useStableCallback)(event => { var messageListHasMessages = processedMessageList.length > 0; var nativeEvent = event.nativeEvent; var offset = nativeEvent.contentOffset.y; currentScrollOffsetRef.current = offset; var visibleLength = nativeEvent.layoutMeasurement.height; var contentLength = nativeEvent.contentSize.height; var isScrollAtStart = contentLength - visibleLength - offset < messageInputHeight; var notLatestSet = channel.state.messages !== channel.state.latestMessages; var showScrollToBottomButton = messageListHasMessages && (!threadList && notLatestSet || !isScrollAtStart); setScrollToBottomButtonVisible(showScrollToBottomButton); if (onListScroll) { onListScroll(event); } }); var goToNewMessages = (0, _hooks.useStableCallback)((0, _asyncToGenerator2.default)(function* () { var isNotLatestSet = channel.state.messages !== channel.state.latestMessages; if (isNotLatestSet) { resetPaginationTrackersRef.current(); yield reloadChannel(); } else if (flashListRef.current) { flashListRef.current.scrollToEnd({ animated: true }); } setScrollToBottomButtonVisible(false); yield markRead({ updateChannelUnreadState: false }); })); var scrollToBottomUnreadCount = scrollToBottomButtonVisible && !threadList ? channel?.countUnread() : undefined; var _useScrollToBottomAcc = (0, _useScrollToBottomAccessibilityAction.useScrollToBottomAccessibilityAction)({ accessibilityActions: additionalFlashListProps?.accessibilityActions, onAccessibilityAction: additionalFlashListProps?.onAccessibilityAction, onScrollToBottom: goToNewMessages, unreadCount: scrollToBottomUnreadCount, visible: scrollToBottomButtonVisible }), messageListAccessibilityActions = _useScrollToBottomAcc.accessibilityActions, messageListOnAccessibilityAction = _useScrollToBottomAcc.onAccessibilityAction; var dismissImagePicker = (0, _hooks.useStableCallback)(() => { if (attachmentPickerStore.state.getLatestValue().selectedPicker) { attachmentPickerStore.setSelectedPicker(undefined); closePicker(); } }); var onScrollBeginDrag = (0, _hooks.useStableCallback)(event => { !hasMoved && attachmentPickerStore.state.getLatestValue().selectedPicker && setHasMoved(true); onUserScrollEvent(event); }); var onScrollEndDrag = (0, _hooks.useStableCallback)(event => { hasMoved && attachmentPickerStore.state.getLatestValue().selectedPicker && setHasMoved(false); onUserScrollEvent(event); }); var refCallback = (0, _hooks.useStableCallback)(ref => { flashListRef.current = ref; if (setFlatListRef) { setFlatListRef(ref); } }); var onUnreadNotificationClose = (0, _hooks.useStableCallback)((0, _asyncToGenerator2.default)(function* () { yield markRead(); setIsUnreadNotificationOpen(false); })); var additionalFlashListPropsExcludingStyle; if (additionalFlashListProps) { var contentContainerStyle = additionalFlashListProps.contentContainerStyle, style = additionalFlashListProps.style, rest = (0, _objectWithoutProperties2.default)(additionalFlashListProps, _excluded); additionalFlashListPropsExcludingStyle = rest; } var flatListStyle = (0, _react.useMemo)(() => [styles.listContainer, additionalFlashListProps?.style], [additionalFlashListProps?.style, styles.listContainer]); var flatListContentContainerStyle = (0, _react.useMemo)(() => [styles.contentContainer, { paddingBottom: messageInputFloating ? messageInputHeight : 0 }, additionalFlashListProps?.contentContainerStyle], [additionalFlashListProps?.contentContainerStyle, styles.contentContainer, messageInputFloating, messageInputHeight]); var currentListHeightRef = (0, _react.useRef)(undefined); var onLayout = (0, _hooks.useStableCallback)(e => { var height = e.nativeEvent.layout.height; if (!currentListHeightRef.current) { currentListHeightRef.current = height; return; } var closeCorrectionDeltaY = height - currentListHeightRef.current; (0, _stateStore.bumpOverlayLayoutRevision)(closeCorrectionDeltaY); var changedBy = currentListHeightRef.current - height; flashListRef.current?.getNativeScrollRef()?.setNativeProps({ contentOffset: { x: 0, y: flashListRef.current?.getAbsoluteLastScrollOffset() + changedBy } }); currentListHeightRef.current = height; }); var ListFooterComponent = (0, _react.useCallback)(() => { if (FooterComponent) { return (0, _jsxRuntime.jsx)(FooterComponent, {}); } return (0, _jsxRuntime.jsxs)(FlashListFooterTypingAdapter, { enabled: !disableTypingIndicator && !!TypingIndicator, children: [(0, _jsxRuntime.jsx)(LoadingMoreRecentIndicator, {}), !disableTypingIndicator && TypingIndicator && (0, _jsxRuntime.jsx)(TypingIndicatorContainer, { children: (0, _jsxRuntime.jsx)(TypingIndicator, {}) })] }); }, [FooterComponent, LoadingMoreRecentIndicator, TypingIndicator, TypingIndicatorContainer, disableTypingIndicator]); if (loading) { return (0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.container, children: (0, _jsxRuntime.jsx)(LoadingIndicator, { listType: "message" }) }); } if (!FlashList) { throw new Error('The package @shopify/flash-list is not installed. Installing this package will enable the use of the FlashList component.'); } return (0, _jsxRuntime.jsxs)(_reactNative.View, { onLayout: onLayout, style: styles.container, testID: "message-flat-list-wrapper", children: [processedMessageList.length === 0 && !thread ? (0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.flex, testID: "empty-state", children: EmptyStateIndicator ? (0, _jsxRuntime.jsx)(EmptyStateIndicator, { listType: "message" }) : null }) : (0, _jsxRuntime.jsx)(_MessageListItemContext.MessageListItemProvider, { value: messageListItemContextValue, children: (0, _jsxRuntime.jsx)(FlashList, { contentContainerStyle: flatListContentContainerStyle, data: processedMessageList, drawDistance: 800, getItemType: getItemTypeInternal, keyboardShouldPersistTaps: "handled", keyExtractor: keyExtractor, ListFooterComponent: ListFooterComponent, ListHeaderComponent: HeaderComponent, maintainVisibleContentPosition: maintainVisibleContentPosition, onMomentumScrollEnd: onUserScrollEvent, onScroll: handleScroll, onScrollBeginDrag: onScrollBeginDrag, onScrollEndDrag: onScrollEndDrag, onTouchEnd: dismissImagePicker, onViewableItemsChanged: stableOnViewableItemsChanged, ref: refCallback, renderItem: renderItem, scrollEnabled: scrollEnabled, scrollEventThrottle: isLiveStreaming ? 16 : undefined, showsVerticalScrollIndicator: false, style: flatListStyle, testID: "message-flash-list", viewabilityConfig: flatListViewabilityConfig, ...additionalFlashListPropsExcludingStyle, accessibilityActions: messageListAccessibilityActions, onAccessibilityAction: messageListOnAccessibilityAction }) }), (0, _jsxRuntime.jsx)(_reactNative.View, { accessibilityElementsHidden: true, accessible: false, importantForAccessibility: "no-hide-descendants", style: styles.stickyHeaderContainer, children: messageListLengthAfterUpdate && StickyHeader ? (0, _jsxRuntime.jsx)(StickyHeader, { date: stickyHeaderDate }) : null }), (0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, { layout: _transitions.transitions.layout200, style: [styles.scrollToBottomButtonContainer, { bottom: messageInputFloating ? messageInputHeight + _theme.primitives.spacingMd : _theme.primitives.spacingMd }], children: (0, _jsxRuntime.jsx)(ScrollToBottomButton, { onPress: goToNewMessages, showNotification: scrollToBottomButtonVisible, unreadCount: scrollToBottomUnreadCount }) }), (0, _jsxRuntime.jsx)(NetworkDownIndicator, {}), isUnreadNotificationOpen && !threadList ? (0, _jsxRuntime.jsx)(_reactNative.View, { style: styles.unreadMessagesNotificationContainer, children: (0, _jsxRuntime.jsx)(UnreadMessagesNotification, { onCloseHandler: onUnreadNotificationClose, channelUnreadStateStore: channelUnreadStateStore }) }) : null, (0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, { layout: _transitions.transitions.layout200, style: [{ bottom: messageInputFloating ? messageInputHeight + 16 : 0 }, styles.suggestionsListContainer], children: (0, _jsxRuntime.jsx)(_PortalWhileClosingView.PortalWhileClosingView, { portalHostName: "overlay-suggestion-list", portalName: "autocomplete-suggestion-list", children: (0, _jsxRuntime.jsx)(AutoCompleteSuggestionList, {}) }) }), (0, _jsxRuntime.jsx)(NotificationList, { bottomOffset: messageInputFloating ? messageInputHeight + 16 : undefined, filter: allowSendBeforeAttachmentsUpload ? _notificationFilters.excludeCanceledUploadNotifications : undefined })] }); }; var FlashListFooterTypingAdapter = ({ enabled, children }) => { var api = useFlashListContext(); var typingUsers = (0, _useTypingUsers.useTypingUsers)(); var typingUsersLengthRef = (0, _react.useRef)(typingUsers.length); (0, _react.useEffect)(() => { var listApi = api?.getRef?.(); if (!enabled || !listApi) { return; } var lastScrollOffset = listApi.getAbsoluteLastScrollOffset(); var contentSize = listApi.getChildContainerDimensions(); var windowSize = listApi.getWindowSize(); var visibleLength = windowSize.height; var contentLength = contentSize.height + listApi.getFirstItemOffset(); var isNearEnd = Math.ceil(lastScrollOffset + visibleLength) >= contentLength; if (listApi && typingUsersLengthRef.current === 0 && typingUsers.length > 0 && isNearEnd) { listApi.scrollToEnd({ animated: true }); } typingUsersLengthRef.current = typingUsers.length; }, [enabled, api, typingUsers.length]); return children; }; var MessageFlashList = props => { var _useAttachmentPickerC = (0, _AttachmentPickerContext.useAttachmentPickerContext)(), closePicker = _useAttachmentPickerC.closePicker, attachmentPickerStore = _useAttachmentPickerC.attachmentPickerStore; var _useChannelContext = (0, _ChannelContext.useChannelContext)(), channel = _useChannelContext.channel, channelUnreadStateStore = _useChannelContext.channelUnreadStateStore, disabled = _useChannelContext.disabled, enableMessageGroupingByUser = _useChannelContext.enableMessageGroupingByUser, error = _useChannelContext.error, hideStickyDateHeader = _useChannelContext.hideStickyDateHeader, highlightedMessageId = _useChannelContext.highlightedMessageId, isChannelActive = _useChannelContext.isChannelActive, loadChannelAroundMessage = _useChannelContext.loadChannelAroundMessage, loading = _useChannelContext.loading, markRead = _useChannelContext.markRead, maximumMessageLimit = _useChannelContext.maximumMessageLimit, reloadChannel = _useChannelContext.reloadChannel, scrollToFirstUnreadThreshold = _useChannelContext.scrollToFirstUnreadThreshold, setChannelUnreadState = _useChannelContext.setChannelUnreadState, setTargetedMessage = _useChannelContext.setTargetedMessage, hasPendingInitialTargetLoad = _useChannelContext.hasPendingInitialTargetLoad, targetedMessage = _useChannelContext.targetedMessage, threadList = _useChannelContext.threadList; var _useChatContext = (0, _ChatContext.useChatContext)(), client = _useChatContext.client; var _useMessagesContext = (0, _MessagesContext.useMessagesContext)(), disableTypingIndicator = _useMessagesContext.disableTypingIndicator, FlatList = _useMessagesContext.FlatList, myMessageTheme = _useMessagesContext.myMessageTheme, shouldShowUnreadUnderlay = _useMessagesContext.shouldShowUnreadUnderlay; var _usePaginatedMessageL = (0, _PaginatedMessageListContext.usePaginatedMessageListContext)(), loadMore = _usePaginatedMessageL.loadMore, loadMoreRecent = _usePaginatedMessageL.loadMoreRecent; var _useThreadContext = (0, _ThreadContext.useThreadContext)(), loadMoreRecentThread = _useThreadContext.loadMoreRecentThread, loadMoreThread = _useThreadContext.loadMoreThread, thread = _useThreadContext.thread, threadInstance = _useThreadContext.threadInstance; var _useOwnCapabilitiesCo = (0, _OwnCapabilitiesContext.useOwnCapabilitiesContext)(), readEvents = _useOwnCapabilitiesCo.readEvents; var _useMessageInputConte = (0, _MessageInputContext.useMessageInputContext)(), allowSendBeforeAttachmentsUpload = _useMessageInputConte.allowSendBeforeAttachmentsUpload, messageInputFloating = _useMessageInputConte.messageInputFloating, messageInputHeightStore = _useMessageInputConte.messageInputHeightStore; return (0, _jsxRuntime.jsx)(MessageFlashListWithContext, { allowSendBeforeAttachmentsUpload, attachmentPickerStore, channel, channelUnreadStateStore, client, closePicker, disabled, disableTypingIndicator, enableMessageGroupingByUser, error, FlatList, hideStickyDateHeader, highlightedMessageId, isListActive: isChannelActive, loadChannelAroundMessage, loading, loadMore, loadMoreRecent, loadMoreRecentThread, loadMoreThread, markRead, maximumMessageLimit, messageInputFloating, messageInputHeightStore, myMessageTheme, readEvents, reloadChannel, scrollToFirstUnreadThreshold, setChannelUnreadState, setTargetedMessage, hasPendingInitialTargetLoad, shouldShowUnreadUnderlay, targetedMessage, thread, threadInstance, threadList, ...props, noGroupByUser: !enableMessageGroupingByUser || props.noGroupByUser }); }; exports.MessageFlashList = MessageFlashList; var useStyles = () => { var _useTheme2 = (0, _ThemeContext.useTheme)(), _useTheme2$theme = _useTheme2.theme, semantics = _useTheme2$theme.semantics, _useTheme2$theme$mess = _useTheme2$theme.messageList, container = _useTheme2$theme$mess.container, contentContainer = _useTheme2$theme$mess.contentContainer, listContainer = _useTheme2$theme$mess.listContainer, stickyHeaderContainer = _useTheme2$theme$mess.stickyHeaderContainer, scrollToBottomButtonContainer = _useTheme2$theme$mess.scrollToBottomButtonContainer, unreadMessagesNotificationContainer = _useTheme2$theme$mess.unreadMessagesNotificationContainer, suggestionListContainer = _useTheme2$theme.messageComposer.suggestionsListContainer.container; var backgroundCoreApp = semantics.backgroundCoreApp; return (0, _react.useMemo)(() => _reactNative.StyleSheet.create({ suggestionsListContainer: { backgroundColor: 'transparent', position: 'absolute', width: '100%', ...suggestionListContainer }, container: { flex: 1, width: '100%', backgroundColor: backgroundCoreApp, ...container }, contentContainer: { paddingBottom: 4, ...contentContainer }, flex: { flex: 1, backgroundColor: backgroundCoreApp }, listContainer: { flex: 1, width: '100%', ...listContainer }, scrollToBottomButtonContainer: { position: 'absolute', right: 16, ...scrollToBottomButtonContainer }, stickyHeaderContainer: { left: 0, position: 'absolute', right: 0, top: _theme.primitives.spacingMd, ...stickyHeaderContainer }, unreadMessagesNotificationContainer: { position: 'absolute', top: _theme.primitives.spacingMd, left: 0, right: 0, alignItems: 'center', ...unreadMessagesNotificationContainer } }), [backgroundCoreApp, container, contentContainer, listContainer, scrollToBottomButtonContainer, stickyHeaderContainer, unreadMessagesNotificationContainer, suggestionListContainer]); }; //# sourceMappingURL=MessageFlashList.js.map