stream-chat-react-native-core
Version:
The official React Native and Expo components for Stream Chat, a service for building chat applications
961 lines • 46 kB
JavaScript
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.MessageList = 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 _debounce = _interopRequireDefault(require("lodash/debounce"));
var _useMessageList2 = require("./hooks/useMessageList");
var _useScrollToBottomAccessibilityAction = require("./hooks/useScrollToBottomAccessibilityAction");
var _useShouldScrollToRecentOnNewOwnMessage = require("./hooks/useShouldScrollToRecentOnNewOwnMessage");
var _InlineLoadingMoreIndicator = require("./InlineLoadingMoreIndicator");
var _InlineLoadingMoreRecentIndicator = require("./InlineLoadingMoreRecentIndicator");
var _InlineLoadingMoreRecentThreadIndicator = require("./InlineLoadingMoreRecentThreadIndicator");
var _buildMessageListWithNeighbours = require("./utils/buildMessageListWithNeighbours");
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 _DebugContext = require("../../contexts/debugContext/DebugContext");
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 _useStateStore2 = require("../../hooks/useStateStore");
var _stateStore = require("../../state-store");
var _theme = require("../../theme");
var _transitions = require("../../utils/animations/transitions");
var _useIncomingMessageAnnouncements = require("../Accessibility/hooks/useIncomingMessageAnnouncements");
var _MessageWrapper = require("../Message/MessageItemView/MessageWrapper");
var _notificationFilters = require("../Notifications/notificationFilters");
var _UIComponents = require("../UIComponents");
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/MessageList.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 WAIT_FOR_SCROLL_TIMEOUT = 0;
var MAX_RETRIES_AFTER_SCROLL_FAILURE = 10;
var useStyles = () => {
var _useTheme = (0, _ThemeContext.useTheme)(),
_useTheme$theme = _useTheme.theme,
semantics = _useTheme$theme.semantics,
_useTheme$theme$messa = _useTheme$theme.messageList,
container = _useTheme$theme$messa.container,
contentContainer = _useTheme$theme$messa.contentContainer,
listContainer = _useTheme$theme$messa.listContainer,
stickyHeaderContainer = _useTheme$theme$messa.stickyHeaderContainer,
scrollToBottomButtonContainer = _useTheme$theme$messa.scrollToBottomButtonContainer,
unreadMessagesNotificationContainer = _useTheme$theme$messa.unreadMessagesNotificationContainer,
suggestionListContainer = _useTheme$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]);
};
var keyExtractor = derivedItem => {
var item = derivedItem.message;
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 _channel$state$latest, _channel$state$read$u;
var latestMessageIdInChannel = (_channel$state$latest = channel.state.latestMessages.slice(-1)[0]) == null ? void 0 : _channel$state$latest.id;
var lastReadMessageIdServer = (_channel$state$read$u = channel.state.read[userId]) == null ? void 0 : _channel$state$read$u.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 != null && msg.id)) break;
if (msg.id !== newMessage.id) {
previousLastMessage = msg;
break;
}
}
return previousLastMessage;
};
var messageInputHeightStoreSelector = state => ({
height: state.height
});
var MessageListWithContext = props => {
var _client$user, _client$user5;
var LoadingMoreRecentIndicator = props.threadList ? _InlineLoadingMoreRecentThreadIndicator.InlineLoadingMoreRecentThreadIndicator : _InlineLoadingMoreRecentIndicator.InlineLoadingMoreRecentIndicator;
var allowSendBeforeAttachmentsUpload = props.allowSendBeforeAttachmentsUpload,
_props$animateLayout = props.animateLayout,
animateLayout = _props$animateLayout === void 0 ? true : _props$animateLayout,
attachmentPickerStore = props.attachmentPickerStore,
additionalFlatListProps = props.additionalFlatListProps,
channel = props.channel,
channelUnreadStateStore = props.channelUnreadStateStore,
client = props.client,
closePicker = props.closePicker,
disabled = props.disabled,
disableTypingIndicator = props.disableTypingIndicator,
FlatList = props.FlatList,
_props$FooterComponen = props.FooterComponent,
FooterComponent = _props$FooterComponen === void 0 ? _InlineLoadingMoreIndicator.InlineLoadingMoreIndicator : _props$FooterComponen,
HeaderComponent = props.HeaderComponent,
hideStickyDateHeader = props.hideStickyDateHeader,
_props$inverted = props.inverted,
inverted = _props$inverted === void 0 ? true : _props$inverted,
_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,
noGroupByUser = props.noGroupByUser,
onListScroll = props.onListScroll,
onThreadSelect = props.onThreadSelect,
readEvents = props.readEvents,
reloadChannel = props.reloadChannel,
setChannelUnreadState = props.setChannelUnreadState,
setFlatListRef = props.setFlatListRef,
setTargetedMessage = props.setTargetedMessage,
targetedMessage = props.targetedMessage,
thread = props.thread,
threadInstance = props.threadInstance,
_props$threadList = props.threadList,
threadList = _props$threadList === void 0 ? false : _props$threadList,
hasMore = props.hasMore,
threadHasMore = props.threadHasMore;
var _useComponentsContext = (0, _ComponentsContext.useComponentsContext)(),
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,
AutoCompleteSuggestionList = _useComponentsContext.AutoCompleteSuggestionList;
var _useState = (0, _react.useState)(false),
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
isUnreadNotificationOpen = _useState2[0],
setIsUnreadNotificationOpen = _useState2[1];
var _useTheme2 = (0, _ThemeContext.useTheme)(),
theme = _useTheme2.theme;
var styles = useStyles();
var _useStateStore = (0, _useStateStore2.useStateStore)(messageInputHeightStore.store, messageInputHeightStoreSelector),
messageInputHeight = _useStateStore.height;
(0, _useIncomingMessageAnnouncements.useIncomingMessageAnnouncements)({
activeThreadId: thread == null ? void 0 : thread.id,
channel,
ownUserId: (_client$user = client.user) == null ? void 0 : _client$user.id,
threadList
});
var myMessageThemeString = (0, _react.useMemo)(() => JSON.stringify(myMessageTheme), [myMessageTheme]);
var scheme = (0, _reactNative.useColorScheme)();
var modifiedTheme = (0, _react.useMemo)(() => (0, _ThemeContext.mergeThemes)({
scheme,
style: myMessageTheme,
theme
}), [myMessageThemeString, scheme, theme]);
var _useMessageList = (0, _useMessageList2.useMessageList)({
isLiveStreaming,
threadList
}),
processedMessageList = _useMessageList.processedMessageList,
rawMessageList = _useMessageList.rawMessageList,
viewabilityChangedCallback = _useMessageList.viewabilityChangedCallback;
var previousDerivedItemsRef = (0, _react.useRef)(undefined);
var processedMessageListWithNeighbors = (0, _react.useMemo)(() => {
if (!previousDerivedItemsRef.current) {
previousDerivedItemsRef.current = new Map();
}
var _buildMessageListWith = (0, _buildMessageListWithNeighbours.buildMessageListWithNeighbours)(processedMessageList, previousDerivedItemsRef.current),
items = _buildMessageListWith.items,
nextDerivedItems = _buildMessageListWith.nextDerivedItems;
previousDerivedItemsRef.current = nextDerivedItems;
return items;
}, [processedMessageList]);
var renderItem = (0, _hooks.useStableCallback)(({
item
}) => {
var message = item.message,
previousMessage = item.previousMessage,
nextMessage = item.nextMessage;
return (0, _jsxRuntime.jsx)(_MessageWrapper.MessageWrapper, {
message: message,
previousMessage: previousMessage,
nextMessage: nextMessage
});
});
var messageListLengthBeforeUpdate = (0, _react.useRef)(0);
var messageListLengthAfterUpdate = processedMessageList.length;
var topMessageBeforeUpdate = (0, _react.useRef)(undefined);
var latestNonCurrentMessageBeforeUpdateRef = (0, _react.useRef)(undefined);
var topMessageAfterUpdate = rawMessageList[0];
var shouldScrollToRecentOnNewOwnMessageRef = (0, _useShouldScrollToRecentOnNewOwnMessage.useShouldScrollToRecentOnNewOwnMessage)(rawMessageList, client.userID);
var _useState3 = (0, _react.useState)(false),
_useState4 = (0, _slicedToArray2.default)(_useState3, 2),
autoscrollToRecent = _useState4[0],
setAutoscrollToRecent = _useState4[1];
var minIndexForVisible = Math.min(1, processedMessageList.length);
var isOverlayOpen = (0, _stateStore.useHasActiveId)();
var autoscrollToTopThreshold = autoscrollToRecent && !isOverlayOpen ? isLiveStreaming ? 300 : 10 : undefined;
var maintainVisibleContentPosition = (0, _react.useMemo)(() => ({
autoscrollToTopThreshold,
minIndexForVisible
}), [autoscrollToTopThreshold, minIndexForVisible]);
var onStartReachedTracker = (0, _react.useRef)({});
var onEndReachedTracker = (0, _react.useRef)({});
var onStartReachedInPromise = (0, _react.useRef)(null);
var onEndReachedInPromise = (0, _react.useRef)(null);
var flatListRef = (0, _react.useRef)(null);
var channelResyncScrollSet = (0, _react.useRef)(true);
var scrollToDebounceTimeoutRef = (0, _react.useRef)(undefined);
var onScrollEventTimeoutRef = (0, _react.useRef)(undefined);
var messageIdLastScrolledToRef = (0, _react.useRef)(undefined);
var _useState5 = (0, _react.useState)(false),
_useState6 = (0, _slicedToArray2.default)(_useState5, 2),
hasMoved = _useState6[0],
setHasMoved = _useState6[1];
var _useState7 = (0, _react.useState)(false),
_useState8 = (0, _slicedToArray2.default)(_useState7, 2),
scrollToBottomButtonVisible = _useState8[0],
setScrollToBottomButtonVisible = _useState8[1];
var _useState9 = (0, _react.useState)(),
_useState0 = (0, _slicedToArray2.default)(_useState9, 2),
stickyHeaderDate = _useState0[0],
setStickyHeaderDate = _useState0[1];
var stickyHeaderDateRef = (0, _react.useRef)(undefined);
var channelRef = (0, _react.useRef)(channel);
channelRef.current = channel;
var updateStickyHeaderDateIfNeeded = (0, _hooks.useStableCallback)(viewableItems => {
var _viewableItems$item;
if (!viewableItems.length) {
return;
}
var lastMessage = (_viewableItems$item = viewableItems[viewableItems.length - 1].item) == null ? void 0 : _viewableItems$item.message;
if (lastMessage) {
var _stickyHeaderDateRef$;
if (!channel.state.messagePagination.hasPrev && processedMessageList[processedMessageList.length - 1].id === lastMessage.id) {
setStickyHeaderDate(undefined);
return;
}
var isMessageTypeDeleted = lastMessage.type === 'deleted';
if (lastMessage != null && lastMessage.created_at && !isMessageTypeDeleted && typeof lastMessage.created_at !== 'string' && lastMessage.created_at.toDateString() !== ((_stickyHeaderDateRef$ = stickyHeaderDateRef.current) == null ? void 0 : _stickyHeaderDateRef$.toDateString())) {
stickyHeaderDateRef.current = lastMessage.created_at;
setStickyHeaderDate(lastMessage.created_at);
}
}
});
var updateStickyUnreadIndicator = (0, _hooks.useStableCallback)(viewableItems => {
var channelUnreadState = channelUnreadStateStore.channelUnreadState;
var lastReadMessageId = channelUnreadState == null ? void 0 : channelUnreadState.last_read_message_id;
var lastReadMessageVisible = viewableItems.some(item => item.item.message.id === lastReadMessageId);
var unreadNotificationSupported = readEvents || client.options.isLocalUnreadCountEnabled;
if (!viewableItems.length || !unreadNotificationSupported || lastReadMessageVisible || attachmentPickerStore.state.getLatestValue().selectedPicker === 'images') {
setIsUnreadNotificationOpen(false);
return;
}
var lastItem = viewableItems[viewableItems.length - 1].item;
if (lastItem) {
var _channelUnreadState$l, _lastItemMessage$user;
var lastItemMessage = lastItem.message;
var lastItemCreatedAt = lastItemMessage.created_at;
var unreadIndicatorDate = channelUnreadState == null || (_channelUnreadState$l = channelUnreadState.last_read) == null ? void 0 : _channelUnreadState$l.getTime();
var lastItemDate = lastItemCreatedAt.getTime();
if (!channel.state.messagePagination.hasPrev && processedMessageList[processedMessageList.length - 1].id === lastItemMessage.id) {
setIsUnreadNotificationOpen(false);
return;
}
if (viewableItems.length === 1 && channel.countUnread() === 0 && ((_lastItemMessage$user = lastItemMessage.user) == null ? void 0 : _lastItemMessage$user.id) === client.userID) {
setIsUnreadNotificationOpen(false);
return;
}
if (unreadIndicatorDate && lastItemDate > unreadIndicatorDate) {
setIsUnreadNotificationOpen(true);
} else {
setIsUnreadNotificationOpen(false);
}
}
});
var unstableOnViewableItemsChanged = ({
viewableItems
}) => {
viewabilityChangedCallback({
inverted,
viewableItems
});
if (!viewableItems) {
return;
}
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 resetPaginationTrackersRef = (0, _react.useRef)(() => {
onStartReachedTracker.current = {};
onEndReachedTracker.current = {};
});
(0, _react.useEffect)(() => {
if (disabled) {
setScrollToBottomButtonVisible(false);
}
}, [disabled]);
(0, _react.useEffect)(() => {
var shouldMarkRead = () => {
var _client$user2, _client$user3;
var channelUnreadState = channelUnreadStateStore.channelUnreadState;
return !(channelUnreadState != null && channelUnreadState.first_unread_message_id) && !scrollToBottomButtonVisible && ((_client$user2 = client.user) == null ? void 0 : _client$user2.id) && !hasReadLastMessage(channel, (_client$user3 = client.user) == null ? void 0 : _client$user3.id);
};
var handleEvent = function () {
var _ref = (0, _asyncToGenerator2.default)(function* (event) {
var _event$message, _event$message2, _event$message3, _client$user4;
var mainChannelUpdated = !((_event$message = event.message) != null && _event$message.parent_id) || ((_event$message2 = event.message) == null ? void 0 : _event$message2.show_in_channel);
var isMyOwnMessage = ((_event$message3 = event.message) == null || (_event$message3 = _event$message3.user) == null ? void 0 : _event$message3.id) === ((_client$user4 = client.user) == null ? void 0 : _client$user4.id);
var channelUnreadState = channelUnreadStateStore.channelUnreadState;
if ((scrollToBottomButtonVisible || channelUnreadState != null && channelUnreadState.first_unread_message_id) && !isMyOwnMessage) {
var _channelUnreadState$u, _channelUnreadState$l2;
var previousUnreadCount = (_channelUnreadState$u = channelUnreadState == null ? void 0 : channelUnreadState.unread_messages) != null ? _channelUnreadState$u : 0;
var previousLastMessage = getPreviousLastMessage(channel.state.messages, event.message);
setChannelUnreadState({
...channelUnreadState,
last_read: (_channelUnreadState$l2 = channelUnreadState == null ? void 0 : channelUnreadState.last_read) != null ? _channelUnreadState$l2 : previousUnreadCount === 0 && previousLastMessage != null && previousLastMessage.created_at ? new Date(previousLastMessage.created_at) : new Date(0),
unread_messages: previousUnreadCount + 1
});
} else if (mainChannelUpdated && shouldMarkRead()) {
yield markRead();
}
});
return function handleEvent(_x) {
return _ref.apply(this, arguments);
};
}();
var listener = channel.on('message.new', handleEvent);
return () => {
listener == null || listener.unsubscribe();
};
}, [channel, channelUnreadStateStore, (_client$user5 = client.user) == null ? void 0 : _client$user5.id, markRead, scrollToBottomButtonVisible, setChannelUnreadState, threadList]);
(0, _react.useEffect)(() => {
var isMessageRemovedFromMessageList = messageListLengthAfterUpdate < messageListLengthBeforeUpdate.current;
var scrollToBottomIfNeeded = () => {
var _topMessageBeforeUpda;
if (!client || !channel || rawMessageList.length === 0) {
return;
}
if (isMessageRemovedFromMessageList || (_topMessageBeforeUpda = topMessageBeforeUpdate.current) != null && _topMessageBeforeUpda.created_at && topMessageAfterUpdate != null && topMessageAfterUpdate.created_at && topMessageBeforeUpdate.current.created_at < topMessageAfterUpdate.created_at) {
channelResyncScrollSet.current = false;
setScrollToBottomButtonVisible(false);
resetPaginationTrackersRef.current();
setTimeout(() => {
var _flatListRef$current;
(_flatListRef$current = flatListRef.current) == null || _flatListRef$current.scrollToOffset({
offset: 0
});
}, WAIT_FOR_SCROLL_TIMEOUT);
setTimeout(() => {
channelResyncScrollSet.current = true;
if (channel.countUnread() > 0) {
markRead();
}
}, 500);
}
};
if (threadList || isMessageRemovedFromMessageList) {
if (maximumMessageLimit) {
resetPaginationTrackersRef.current();
} else {
scrollToBottomIfNeeded();
}
}
messageListLengthBeforeUpdate.current = messageListLengthAfterUpdate;
topMessageBeforeUpdate.current = topMessageAfterUpdate;
}, [threadList, messageListLengthAfterUpdate, topMessageAfterUpdate == null ? void 0 : topMessageAfterUpdate.id, maximumMessageLimit]);
(0, _react.useEffect)(() => {
if (threadList) {
setAutoscrollToRecent(true);
return;
}
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;
}
var latestNonCurrentMessageBeforeUpdate = latestNonCurrentMessageBeforeUpdateRef.current;
latestNonCurrentMessageBeforeUpdateRef.current = undefined;
var latestCurrentMessageAfterUpdate = processedMessageList[0];
if (!latestCurrentMessageAfterUpdate) {
setAutoscrollToRecent(true);
return;
}
var didMergeMessageSetsWithNoUpdates = (latestNonCurrentMessageBeforeUpdate == null ? void 0 : latestNonCurrentMessageBeforeUpdate.id) === latestCurrentMessageAfterUpdate.id;
var shouldForceScrollToRecent = !didMergeMessageSetsWithNoUpdates || processedMessageList.length - messageListLengthBeforeUpdate.current > 0;
if (maximumMessageLimit && shouldForceScrollToRecent || !maximumMessageLimit) {
setAutoscrollToRecent(shouldForceScrollToRecent);
}
if (!didMergeMessageSetsWithNoUpdates) {
var shouldScrollToRecentOnNewOwnMessage = shouldScrollToRecentOnNewOwnMessageRef.current();
if (shouldScrollToRecentOnNewOwnMessage) {
setTimeout(() => {
var _flatListRef$current2;
(_flatListRef$current2 = flatListRef.current) == null || _flatListRef$current2.scrollToOffset({
animated: true,
offset: 0
});
}, WAIT_FOR_SCROLL_TIMEOUT);
}
}
}, [channel, threadList, processedMessageList, shouldScrollToRecentOnNewOwnMessageRef, maximumMessageLimit]);
var goToMessage = (0, _hooks.useStableCallback)(function () {
var _ref2 = (0, _asyncToGenerator2.default)(function* (messageId) {
var indexOfParentInMessageList = processedMessageList.findIndex(message => (message == null ? void 0 : message.id) === messageId);
try {
if (indexOfParentInMessageList === -1) {
yield loadChannelAroundMessage({
messageId
});
return;
} else {
if (!flatListRef.current) {
return;
}
clearTimeout(failScrollTimeoutId.current);
scrollToIndexFailedRetryCountRef.current = 0;
messageIdLastScrolledToRef.current = messageId;
setTargetedMessage(messageId);
flatListRef.current.scrollToIndex({
animated: true,
index: indexOfParentInMessageList,
viewPosition: 0.5
});
return;
}
} catch (e) {
console.warn('Error while scrolling to message', e);
}
});
return function (_x2) {
return _ref2.apply(this, arguments);
};
}());
(0, _react.useEffect)(() => {
if (!targetedMessage) {
return;
}
scrollToDebounceTimeoutRef.current = setTimeout((0, _asyncToGenerator2.default)(function* () {
var indexOfParentInMessageList = processedMessageList.findIndex(message => (message == null ? void 0 : message.id) === targetedMessage);
if (indexOfParentInMessageList === -1) {
yield loadChannelAroundMessage({
messageId: targetedMessage,
setTargetedMessage
});
} else {
if (!flatListRef.current) {
return;
}
clearTimeout(scrollToDebounceTimeoutRef.current);
clearTimeout(failScrollTimeoutId.current);
scrollToIndexFailedRetryCountRef.current = 0;
flatListRef.current.scrollToIndex({
animated: true,
index: indexOfParentInMessageList,
viewPosition: 0.5
});
setTargetedMessage(undefined);
}
}), WAIT_FOR_SCROLL_TIMEOUT);
}, [targetedMessage]);
var setNativeScrollability = (0, _hooks.useStableCallback)(value => {
if (flatListRef.current) {
flatListRef.current.setNativeProps({
scrollEnabled: 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 != null && processedMessageList.length && onStartReachedTracker.current[processedMessageList.length]) {
return;
}
if (processedMessageList != null && 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* () {
var shouldQuery = threadList && threadHasMore || !threadList && hasMore;
if (processedMessageList != null && processedMessageList.length && onEndReachedTracker.current[processedMessageList.length] || !shouldQuery) {
return;
}
if (processedMessageList != null && 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;
clearTimeout(onScrollEventTimeoutRef.current);
var offset = nativeEvent.contentOffset.y;
var visibleLength = nativeEvent.layoutMeasurement.height;
var contentLength = nativeEvent.contentSize.height;
if (!channel || !channelResyncScrollSet.current) {
return;
}
var isScrollAtStart = offset < 100;
var isScrollAtEnd = contentLength - visibleLength - offset < 100;
if (isScrollAtStart) {
maybeCallOnStartReached();
}
if (isScrollAtEnd) {
maybeCallOnEndReached();
}
});
var handleScroll = (0, _hooks.useStableCallback)(event => {
var messageListHasMessages = processedMessageList.length > 0;
var offset = event.nativeEvent.contentOffset.y;
var isScrollAtBottom = offset <= messageInputHeight;
var notLatestSet = channel.state.messages !== channel.state.latestMessages;
var showScrollToBottomButton = messageListHasMessages && (!threadList && notLatestSet || !isScrollAtBottom);
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 (flatListRef.current) {
flatListRef.current.scrollToOffset({
animated: true,
offset: 0
});
}
setScrollToBottomButtonVisible(false);
yield markRead({
updateChannelUnreadState: false
});
}));
var scrollToBottomUnreadCount = scrollToBottomButtonVisible && !threadList ? channel == null ? void 0 : channel.countUnread() : undefined;
var _useScrollToBottomAcc = (0, _useScrollToBottomAccessibilityAction.useScrollToBottomAccessibilityAction)({
accessibilityActions: additionalFlatListProps == null ? void 0 : additionalFlatListProps.accessibilityActions,
onAccessibilityAction: additionalFlatListProps == null ? void 0 : additionalFlatListProps.onAccessibilityAction,
onScrollToBottom: goToNewMessages,
unreadCount: scrollToBottomUnreadCount,
visible: scrollToBottomButtonVisible
}),
messageListAccessibilityActions = _useScrollToBottomAcc.accessibilityActions,
messageListOnAccessibilityAction = _useScrollToBottomAcc.onAccessibilityAction;
var scrollToIndexFailedRetryCountRef = (0, _react.useRef)(0);
var failScrollTimeoutId = (0, _react.useRef)(undefined);
var onScrollToIndexFailedRef = (0, _react.useRef)(info => {
if (!flatListRef.current) {
return;
}
failScrollTimeoutId.current = setTimeout(() => {
try {
var _flatListRef$current3;
(_flatListRef$current3 = flatListRef.current) == null || _flatListRef$current3.scrollToIndex({
animated: true,
index: info.index,
viewPosition: 0.5
});
if (messageIdLastScrolledToRef.current) {
setTargetedMessage(messageIdLastScrolledToRef.current);
}
scrollToIndexFailedRetryCountRef.current = 0;
} catch (e) {
if (!onScrollToIndexFailedRef.current || scrollToIndexFailedRetryCountRef.current > MAX_RETRIES_AFTER_SCROLL_FAILURE) {
scrollToIndexFailedRetryCountRef.current = 0;
return;
}
scrollToIndexFailedRetryCountRef.current += 1;
onScrollToIndexFailedRef.current(info);
}
}, WAIT_FOR_SCROLL_TIMEOUT);
});
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 => {
flatListRef.current = ref;
if (setFlatListRef) {
setFlatListRef(ref);
}
});
var onUnreadNotificationClose = (0, _hooks.useStableCallback)((0, _asyncToGenerator2.default)(function* () {
yield markRead();
setIsUnreadNotificationOpen(false);
}));
var debugRef = (0, _DebugContext.useDebugContext)();
var isDebugModeEnabled = __DEV__ && debugRef && debugRef.current;
if (isDebugModeEnabled) {
if (debugRef.current.setEventType) {
debugRef.current.setEventType('send');
}
if (debugRef.current.setSendEventParams) {
debugRef.current.setSendEventParams({
action: thread ? 'ThreadList' : 'Messages',
data: processedMessageList
});
}
}
var additionalFlatListPropsExcludingStyle;
if (additionalFlatListProps) {
var contentContainerStyle = additionalFlatListProps.contentContainerStyle,
style = additionalFlatListProps.style,
rest = (0, _objectWithoutProperties2.default)(additionalFlatListProps, _excluded);
additionalFlatListPropsExcludingStyle = rest;
}
var flatListStyle = (0, _react.useMemo)(() => [styles.listContainer, additionalFlatListProps == null ? void 0 : additionalFlatListProps.style], [additionalFlatListProps == null ? void 0 : additionalFlatListProps.style, styles.listContainer]);
var liveStreamingListProps = (0, _react.useMemo)(() => ({
strictMode: isLiveStreaming
}), [isLiveStreaming]);
var flatListContentContainerStyle = (0, _react.useMemo)(() => [{
paddingTop: messageInputFloating ? messageInputHeight : 0
}, styles.contentContainer, additionalFlatListProps == null ? void 0 : additionalFlatListProps.contentContainerStyle], [additionalFlatListProps == null ? void 0 : additionalFlatListProps.contentContainerStyle, styles.contentContainer, messageInputHeight, messageInputFloating]);
var ListComponent = animateLayout ? AnimatedList : FlatList;
var viewportHeightRef = (0, _react.useRef)(undefined);
var debouncedPrefillMessages = (0, _react.useMemo)(() => (0, _debounce.default)((viewportHeight, contentHeight) => {
if (viewportHeight >= contentHeight) {
maybeCallOnEndReached();
}
}, 500, {
leading: false,
trailing: true
}), [maybeCallOnEndReached]);
var onContentSizeChange = (0, _hooks.useStableCallback)((width, height) => {
var _viewportHeightRef$cu;
if (additionalFlatListProps != null && additionalFlatListProps.onContentSizeChange) {
additionalFlatListProps.onContentSizeChange(width, height);
}
debouncedPrefillMessages((_viewportHeightRef$cu = viewportHeightRef.current) != null ? _viewportHeightRef$cu : 0, height);
});
var onLayout = (0, _hooks.useStableCallback)(event => {
if (additionalFlatListProps != null && additionalFlatListProps.onLayout) {
additionalFlatListProps.onLayout(event);
}
var nextViewportHeight = event.nativeEvent.layout.height;
if (viewportHeightRef.current !== nextViewportHeight) {
var _viewportHeightRef$cu2;
var previousViewportHeight = (_viewportHeightRef$cu2 = viewportHeightRef.current) != null ? _viewportHeightRef$cu2 : nextViewportHeight;
var closeCorrectionDeltaY = nextViewportHeight - previousViewportHeight;
(0, _stateStore.bumpOverlayLayoutRevision)(closeCorrectionDeltaY);
}
viewportHeightRef.current = nextViewportHeight;
});
var ListHeaderComponent = (0, _react.useCallback)(() => {
if (HeaderComponent) {
return (0, _jsxRuntime.jsx)(HeaderComponent, {});
}
return (0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
children: [(0, _jsxRuntime.jsx)(LoadingMoreRecentIndicator, {}), !disableTypingIndicator && TypingIndicator && (0, _jsxRuntime.jsx)(TypingIndicatorContainer, {
children: (0, _jsxRuntime.jsx)(TypingIndicator, {})
})]
});
}, [HeaderComponent, LoadingMoreRecentIndicator, TypingIndicator, TypingIndicatorContainer, disableTypingIndicator]);
if (!ListComponent) {
return null;
}
if (loading) {
return (0, _jsxRuntime.jsx)(_reactNative.View, {
style: styles.container,
children: (0, _jsxRuntime.jsx)(LoadingIndicator, {
listType: "message"
})
});
}
return (0, _jsxRuntime.jsxs)(_reactNative.View, {
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)(ListComponent, {
layout: _transitions.transitions.layout200,
contentContainerStyle: flatListContentContainerStyle,
data: processedMessageListWithNeighbors,
extraData: disabled,
inverted: inverted,
keyboardShouldPersistTaps: "handled",
keyExtractor: keyExtractor,
ListFooterComponent: FooterComponent,
ListHeaderComponent: ListHeaderComponent,
maintainVisibleContentPosition: maintainVisibleContentPosition,
maxToRenderPerBatch: 30,
onContentSizeChange: onContentSizeChange,
onLayout: onLayout,
onMomentumScrollEnd: onUserScrollEvent,
onScroll: handleScroll,
onScrollBeginDrag: onScrollBeginDrag,
onScrollEndDrag: onScrollEndDrag,
onScrollToIndexFailed: onScrollToIndexFailedRef.current,
onTouchEnd: dismissImagePicker,
onViewableItemsChanged: stableOnViewableItemsChanged,
ref: refCallback,
renderItem: renderItem,
scrollEventThrottle: isLiveStreaming ? 16 : undefined,
showsVerticalScrollIndicator: false,
style: flatListStyle,
testID: "message-flat-list",
viewabilityConfig: flatListViewabilityConfig,
...liveStreamingListProps,
...additionalFlatListPropsExcludingStyle,
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
}), scrollToBottomButtonVisible ? (0, _jsxRuntime.jsx)(_reactNativeReanimated.default.View, {
layout: _transitions.transitions.layout200,
style: [{
bottom: messageInputFloating ? messageInputHeight + _theme.primitives.spacingMd + 16 : _theme.primitives.spacingMd
}, styles.scrollToBottomButtonContainer],
children: (0, _jsxRuntime.jsx)(ScrollToBottomButton, {
onPress: goToNewMessages,
showNotification: scrollToBottomButtonVisible,
unreadCount: scrollToBottomUnreadCount
})
}) : null, (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)(_UIComponents.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 MessageList = 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,
loadChannelAroundMessage = _useChannelContext.loadChannelAroundMessage,
loading = _useChannelContext.loading,
maximumMessageLimit = _useChannelContext.maximumMessageLimit,
markRead = _useChannelContext.markRead,
reloadChannel = _useChannelContext.reloadChannel,
scrollToFirstUnreadThreshold = _useChannelContext.scrollToFirstUnreadThreshold,
setChannelUnreadState = _useChannelContext.setChannelUnreadState,
setTargetedMessage = _useChannelContext.setTargetedMessage,
targetedMessage = _useChannelContext.targetedMessage,
threadList = _useChannelContext.threadList;
var _useChatContext = (0, _ChatContext.useChatContext)(),
client = _useChatContext.client;
var _useOwnCapabilitiesCo = (0, _OwnCapabilitiesContext.useOwnCapabilitiesContext)(),
readEvents = _useOwnCapabilitiesCo.readEvents;
var _useMessagesContext = (0, _MessagesContext.useMessagesContext)(),
disableTypingIndicator = _useMessagesContext.disableTypingIndicator,
FlatList = _useMessagesContext.FlatList,
myMessageTheme = _useMessagesContext.myMessageTheme,
shouldShowUnreadUnderlay = _useMessagesContext.shouldShowUnreadUnderlay;
var _useMessageInputConte = (0, _MessageInputContext.useMessageInputContext)(),
allowSendBeforeAttachmentsUpload = _useMessageInputConte.allowSendBeforeAttachmentsUpload,
messageInputFloating = _useMessageInputConte.messageInputFloating,
messageInputHeightStore = _useMessageInputConte.messageInputHeightStore;
var _usePaginatedMessageL = (0, _PaginatedMessageListContext.usePaginatedMessageListContext)(),
loadMore = _usePaginatedMessageL.loadMore,
loadMoreRecent = _usePaginatedMessageL.loadMoreRecent,
hasMore = _usePaginatedMessageL.hasMore;
var _useThreadContext = (0, _ThreadContext.useThreadContext)(),
loadMoreRecentThread = _useThreadContext.loadMoreRecentThread,
loadMoreThread = _useThreadContext.loadMoreThread,
threadHasMore = _useThreadContext.threadHasMore,
thread = _useThreadContext.thread,
threadInstance = _useThreadContext.threadInstance;
return (0, _jsxRuntime.jsx)(MessageListWithContext, {
allowSendBeforeAttachmentsUpload,
attachmentPickerStore,
channel,
channelUnreadStateStore,
client,
closePicker,
disabled,
disableTypingIndicator,
enableMessageGroupingByUser,
error,
FlatList,
hideStickyDateHeader,
highlightedMessageId,
loadChannelAroundMessage,
loading,
loadMore,
loadMoreRecent,
loadMoreRecentThread,
loadMoreThread,
markRead,
maximumMessageLimit,
messageInputFloating,
messageInputHeightStore,
myMessageTheme,
readEvents,
reloadChannel,
scrollToFirstUnreadThreshold,
setChannelUnreadState,
setTargetedMessage,
shouldShowUnreadUnderlay,
targetedMessage,
thread,
threadInstance,
threadList,
hasMore,
threadHasMore,
...props,
noGroupByUser: !enableMessageGroupingByUser || props.noGroupByUser
});
};
exports.MessageList = MessageList;
var AnimatedList = _react.default.memo(_reactNativeReanimated.default.createAnimatedComponent(_reactNative.FlatList));
//# sourceMappingURL=MessageList.js.map