UNPKG

@100mslive/react-native-room-kit

Version:

100ms Room Kit provides simple & easy to use UI components to build Live Streaming & Video Conferencing experiences in your apps.

288 lines 10.7 kB
import * as React from 'react'; import { View, StyleSheet, Text, TouchableOpacity, ScrollView, Platform } from 'react-native'; import { useSelector } from 'react-redux'; import { FlashList } from '@shopify/flash-list'; import { GestureDetector, Gesture } from 'react-native-gesture-handler'; import { useAllowPinningMessage, useHMSMessagePinningActions, useHMSRoomStyleSheet } from '../../hooks-util'; import { PinIcon } from '../../Icons'; import { hexToRgbA } from '../../utils/theme'; const FLATLIST_VIEWABILITY_CONFIG = { waitForInteraction: true, itemVisiblePercentThreshold: 90 }; const LINE_HEIGHT = 20; var NumOfLines = /*#__PURE__*/function (NumOfLines) { NumOfLines[NumOfLines["EXPANDED"] = 6] = "EXPANDED"; NumOfLines[NumOfLines["COLLAPSED"] = 3] = "COLLAPSED"; return NumOfLines; }(NumOfLines || {}); const Heights = { EXAPANDED: NumOfLines.EXPANDED * LINE_HEIGHT + 2, COLLAPSED: NumOfLines.COLLAPSED * LINE_HEIGHT + 2 }; export const _PinnedMessages = ({ insetMode = false }) => { const listRef = React.useRef(null); const [numOfLinesInText, setNumOfLinesInText] = React.useState({}); const numOfLinesInTextRef = React.useRef(numOfLinesInText); const [listHeight, setListHeight] = React.useState(Heights.COLLAPSED); const listHeightRef = React.useRef(Heights.COLLAPSED); const [selectedPinnedMessageIndex, setSelectedMessageIndex] = React.useState(0); const selectedPinnedMessageIndexRef = React.useRef(0); const allowPinningMessage = useAllowPinningMessage(); const { unpinMessage } = useHMSMessagePinningActions(); const pinnedMessages = useSelector(state => state.messages.pinnedMessages); const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ insetContainer: { backgroundColor: theme.palette.background_dim && hexToRgbA(theme.palette.background_dim, 0.64) }, pinContainer: { backgroundColor: theme.palette.surface_default }, activeMessageContainer: { backgroundColor: theme.palette.on_surface_high }, inactiveMessageContainer: { backgroundColor: theme.palette.on_surface_low }, closeIcon: { tintColor: theme.palette.on_surface_medium }, highlightedText: { fontFamily: `${typography.font_family}-SemiBold`, color: theme.palette.on_surface_high }, text: { fontFamily: `${typography.font_family}-Regular`, color: theme.palette.on_surface_high }, ellipsis: { backgroundColor: theme.palette.background_dim && hexToRgbA(theme.palette.background_dim, 0.64) } })); const handleTapOnPinnedMessage = React.useCallback(() => { setListHeight(prevListHeight => { let updated = prevListHeight > Heights.COLLAPSED ? Heights.COLLAPSED : Heights.EXAPANDED; listHeightRef.current = updated; return updated; }); }, []); const handleUnpinMessagePress = React.useCallback(() => { const visiblePinnedMessage = pinnedMessages[selectedPinnedMessageIndexRef.current]; if (visiblePinnedMessage) { if (listHeight > Heights.COLLAPSED) { setListHeight(Heights.COLLAPSED); listHeightRef.current = Heights.COLLAPSED; } unpinMessage(visiblePinnedMessage); } }, [listHeight, pinnedMessages]); const _handleViewableItemsChanged = React.useCallback(info => { const firstViewable = info.viewableItems[0]; if (firstViewable !== null && firstViewable !== void 0 && firstViewable.isViewable && typeof firstViewable.index === 'number') { let viewableIndexChanged = false; setSelectedMessageIndex(currIndex => { if (currIndex !== firstViewable.index) { viewableIndexChanged = true; } if (firstViewable.index !== null) { return firstViewable.index; } return currIndex; }); selectedPinnedMessageIndexRef.current = firstViewable.index; const visiblePinnedMessage = pinnedMessages[selectedPinnedMessageIndexRef.current]; if (viewableIndexChanged && listHeightRef.current > Heights.COLLAPSED && visiblePinnedMessage) { const visibleMessageExpandable = numOfLinesInTextRef.current[visiblePinnedMessage.id]; if (!visibleMessageExpandable) { setListHeight(Heights.COLLAPSED); listHeightRef.current = Heights.COLLAPSED; } } } }, [pinnedMessages]); const _renderItem = React.useCallback(data => { const numOfLines = numOfLinesInText[data.item.id]; const [sender, text] = data.item.text.split(':'); return /*#__PURE__*/React.createElement(TouchableOpacity, { activeOpacity: 0.8, disabled: typeof numOfLines !== 'number', onPress: typeof numOfLines === 'number' ? handleTapOnPinnedMessage : undefined, style: { height: listHeight, justifyContent: 'center', overflow: Platform.OS === 'ios' && typeof numOfLines !== 'number' ? 'scroll' : 'hidden' } }, listHeight >= Heights.EXAPANDED && typeof numOfLines === 'number' && numOfLines > NumOfLines.EXPANDED ? /*#__PURE__*/React.createElement(ScrollView, { nestedScrollEnabled: true, contentContainerStyle: { paddingBottom: 12 } }, /*#__PURE__*/React.createElement(TouchableOpacity, { activeOpacity: 0.8, onPress: handleTapOnPinnedMessage }, /*#__PURE__*/React.createElement(Text, { onTextLayout: ({ nativeEvent }) => { if (nativeEvent.lines.length > NumOfLines.COLLAPSED) { setNumOfLinesInText(prev => { const currentValue = prev[data.item.id]; let updated; if (typeof currentValue === 'number' && currentValue === nativeEvent.lines.length) { updated = prev; } else { updated = { ...prev, [data.item.id]: nativeEvent.lines.length }; } numOfLinesInTextRef.current = updated; return updated; }); } }, style: [styles.text, hmsRoomStyles.text], numberOfLines: listHeight === Heights.COLLAPSED && typeof numOfLines === 'number' ? 3 : undefined }, text ? /*#__PURE__*/React.createElement(Text, { style: hmsRoomStyles.highlightedText }, sender, ":", ' ') : null, text ?? sender))) : /*#__PURE__*/React.createElement(Text, { onTextLayout: ({ nativeEvent }) => { if (nativeEvent.lines.length > NumOfLines.COLLAPSED) { setNumOfLinesInText(prev => { const currentValue = prev[data.item.id]; let updated; if (typeof currentValue === 'number' && currentValue === nativeEvent.lines.length) { updated = prev; } else { updated = { ...prev, [data.item.id]: nativeEvent.lines.length }; } numOfLinesInTextRef.current = updated; return updated; }); } }, style: [styles.text, hmsRoomStyles.text], numberOfLines: listHeight === Heights.COLLAPSED && typeof numOfLines === 'number' ? 3 : undefined }, text ? /*#__PURE__*/React.createElement(Text, { style: hmsRoomStyles.highlightedText }, sender, ": ") : null, text ?? sender)); }, [listHeight, numOfLinesInText, handleTapOnPinnedMessage]); const _keyExtractor = React.useCallback(item => item.id, []); const _onContentSizeChange = React.useCallback((_w, _h) => { var _listRef$current; (_listRef$current = listRef.current) === null || _listRef$current === void 0 || _listRef$current.scrollToOffset({ offset: listHeight * selectedPinnedMessageIndexRef.current, animated: false }); }, [listHeight]); const tapGesture = React.useMemo(() => Gesture.Tap(), []); const extraData = React.useMemo(() => [listHeight, numOfLinesInText, pinnedMessages], [listHeight, numOfLinesInText, pinnedMessages]); if (pinnedMessages.length <= 0) { return null; } return /*#__PURE__*/React.createElement(GestureDetector, { gesture: tapGesture }, /*#__PURE__*/React.createElement(View, { style: [insetMode ? styles.insetContainer : styles.container, insetMode ? hmsRoomStyles.insetContainer : null] }, /*#__PURE__*/React.createElement(View, { style: [styles.pinContainer, insetMode ? { paddingRight: 0 } : hmsRoomStyles.pinContainer, { height: listHeight + 16 }] }, pinnedMessages.length > 1 ? /*#__PURE__*/React.createElement(View, { style: { marginRight: 8, flexDirection: 'column' } }, pinnedMessages.map((message, idx) => { const isFirst = idx === 0; const isSelected = selectedPinnedMessageIndex === idx; return /*#__PURE__*/React.createElement(React.Fragment, { key: message.id }, isFirst ? null : /*#__PURE__*/React.createElement(View, { style: [{ height: 3, width: 2 }] }), /*#__PURE__*/React.createElement(View, { style: [{ width: 2, flexGrow: 1, borderRadius: 16 }, isSelected ? hmsRoomStyles.activeMessageContainer : hmsRoomStyles.inactiveMessageContainer] })); })) : null, /*#__PURE__*/React.createElement(FlashList, { ref: listRef, data: pinnedMessages, extraData: extraData, showsVerticalScrollIndicator: false, pagingEnabled: true, nestedScrollEnabled: true, keyboardShouldPersistTaps: "always", renderItem: _renderItem, keyExtractor: _keyExtractor, onContentSizeChange: _onContentSizeChange, estimatedItemSize: 40, onViewableItemsChanged: _handleViewableItemsChanged, viewabilityConfig: FLATLIST_VIEWABILITY_CONFIG })), allowPinningMessage ? /*#__PURE__*/React.createElement(TouchableOpacity, { style: { marginLeft: 8 }, onPress: handleUnpinMessagePress }, /*#__PURE__*/React.createElement(PinIcon, { type: "unpin", style: [styles.icon, hmsRoomStyles.closeIcon] })) : null)); }; export const PinnedMessages = /*#__PURE__*/React.memo(_PinnedMessages); const styles = StyleSheet.create({ container: { flexDirection: 'row', alignItems: 'center', marginTop: 8 }, insetContainer: { flexDirection: 'row', alignItems: 'center', marginTop: 8, marginHorizontal: 8, marginBottom: 4, borderRadius: 8, paddingRight: 8 }, pinContainer: { flexDirection: 'row', flexGrow: 1, flexShrink: 1, borderRadius: 8, paddingVertical: 8, paddingRight: 8, paddingLeft: 8 }, textWrapper: { maxHeight: 50, marginHorizontal: 8 }, icon: { width: 20, height: 20 // marginTop: 8, }, text: { fontSize: 14, lineHeight: 20, letterSpacing: 0.25 } }); //# sourceMappingURL=PinnedMessages.js.map