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.

275 lines 9.31 kB
import * as React from 'react'; import { Text, StyleSheet, View, Keyboard, TouchableOpacity, ActivityIndicator } from 'react-native'; import { useDispatch, useSelector } from 'react-redux'; import { FlashList } from '@shopify/flash-list'; import { useHMSInstance, useHMSRoomColorPalette, useHMSRoomStyleSheet } from '../hooks-util'; import { popFromNavigationStack } from '../redux/actions'; import { BottomSheet } from './BottomSheet'; import { ChevronIcon, CloseIcon } from '../Icons'; import { PollAndQuizzStateLabel } from './PollAndQuizzStateLabel'; import { LeaderboardEntry } from './LeaderboardEntry'; export const QuizLeaderboardEntriesScreen = ({ currentIdx, dismissModal, unmountScreenWithAnimation }) => { var _selectedPoll$questio, _selectedPoll$questio2; const hmsInstance = useHMSInstance(); const dispatch = useDispatch(); const selectedPoll = useSelector(state => { const pollsData = state.polls; if (pollsData.selectedPollId !== null) { return pollsData.polls[pollsData.selectedPollId] || null; } return null; }); const initialLeaderboardEntries = useSelector(state => { var _state$polls$leaderbo; return selectedPoll !== null && selectedPoll !== void 0 && selectedPoll.pollId ? (_state$polls$leaderbo = state.polls.leaderboards[selectedPoll.pollId]) === null || _state$polls$leaderbo === void 0 ? void 0 : _state$polls$leaderbo.entries : null; }); const [leaderboardEntries, setLeaderboardEntries] = React.useState(initialLeaderboardEntries ? [...initialLeaderboardEntries] : []); const startIndexRef = React.useRef(leaderboardEntries.length); const { primary_default: primaryDefaultColor } = useHMSRoomColorPalette(); const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({ regularHighText: { color: theme.palette.on_surface_high, fontFamily: `${typography.font_family}-Regular` }, regularMediumText: { color: theme.palette.on_surface_medium, fontFamily: `${typography.font_family}-Regular` }, semiBoldMediumText: { color: theme.palette.on_surface_medium, fontFamily: `${typography.font_family}-SemiBold` }, semiBoldHighText: { color: theme.palette.on_surface_high, fontFamily: `${typography.font_family}-SemiBold` }, headerText: { color: theme.palette.on_surface_high, fontFamily: `${typography.font_family}-SemiBold` }, container: { backgroundColor: theme.palette.surface_dim }, summaryContainer: { backgroundColor: theme.palette.surface_default }, entriesCard: { backgroundColor: theme.palette.surface_default }, divider: { backgroundColor: theme.palette.border_bright } })); const handleBackPress = () => { Keyboard.dismiss(); if (typeof unmountScreenWithAnimation === 'function') { unmountScreenWithAnimation(() => dispatch(popFromNavigationStack())); } else { dispatch(popFromNavigationStack()); } }; const handleClosePress = () => { Keyboard.dismiss(); dismissModal(); }; const [loading, setLoading] = React.useState(false); const loadingRef = React.useRef(false); const mounted = React.useRef(true); const canFetchMore = React.useRef(true); const fetchLeaderboard = React.useCallback(async () => { if (selectedPoll !== null && selectedPoll !== void 0 && selectedPoll.pollId && canFetchMore.current && !loadingRef.current) { setLoading(true); loadingRef.current = true; const response = await hmsInstance.interactivityCenter.fetchLeaderboard(selectedPoll.pollId, 50, startIndexRef.current + 1, // Indexing starts from 1 false); if (mounted) { setLoading(false); loadingRef.current = false; if (Array.isArray(response.entries)) { const entries = response.entries; setLeaderboardEntries(prev => { const list = [...prev, ...entries]; startIndexRef.current = list.length; return list; }); if (entries.length <= 0) { canFetchMore.current = false; } } if (response.hasNext === false) { canFetchMore.current = false; } } } }, [selectedPoll === null || selectedPoll === void 0 ? void 0 : selectedPoll.pollId]); const totalPoints = (selectedPoll === null || selectedPoll === void 0 || (_selectedPoll$questio = selectedPoll.questions) === null || _selectedPoll$questio === void 0 ? void 0 : _selectedPoll$questio.reduce((acc, curr) => { acc += curr.weight; return acc; }, 0)) ?? 0; const totalQuestions = (selectedPoll === null || selectedPoll === void 0 || (_selectedPoll$questio2 = selectedPoll.questions) === null || _selectedPoll$questio2 === void 0 ? void 0 : _selectedPoll$questio2.length) ?? 0; const _keyExtractor = React.useCallback((item, index) => { var _item$peer; return ((_item$peer = item.peer) === null || _item$peer === void 0 ? void 0 : _item$peer.peerId) ?? index.toString(); }, []); const _renderItem = React.useCallback(data => { return /*#__PURE__*/React.createElement(LeaderboardEntry, { totalPoints: totalPoints, totalQuestions: totalQuestions, entry: data.item, style: { marginBottom: 16 } }); }, [totalPoints, totalQuestions]); return /*#__PURE__*/React.createElement(View, { style: [styles.fullView, hmsRoomStyles.container] }, /*#__PURE__*/React.createElement(View, { style: styles.header }, /*#__PURE__*/React.createElement(View, { style: styles.headerControls }, currentIdx > 0 ? /*#__PURE__*/React.createElement(TouchableOpacity, { onPress: handleBackPress, hitSlop: styles.closeIconHitSlop, style: styles.backIcon }, /*#__PURE__*/React.createElement(ChevronIcon, { direction: "left" })) : null, /*#__PURE__*/React.createElement(Text, { numberOfLines: 2, style: [styles.headerText, { flexShrink: 1 }, hmsRoomStyles.headerText] }, selectedPoll === null || selectedPoll === void 0 ? void 0 : selectedPoll.title), selectedPoll !== null && selectedPoll !== void 0 && selectedPoll.state ? /*#__PURE__*/React.createElement(PollAndQuizzStateLabel, { state: selectedPoll === null || selectedPoll === void 0 ? void 0 : selectedPoll.state }) : null), /*#__PURE__*/React.createElement(TouchableOpacity, { onPress: handleClosePress, hitSlop: styles.closeIconHitSlop, style: { marginLeft: 16 } }, /*#__PURE__*/React.createElement(CloseIcon, null))), /*#__PURE__*/React.createElement(BottomSheet.Divider, { style: styles.halfDivider }), /*#__PURE__*/React.createElement(FlashList, { data: leaderboardEntries, ListHeaderComponent: () => /*#__PURE__*/React.createElement(View, { style: { paddingTop: 24, paddingBottom: 28 } }, /*#__PURE__*/React.createElement(Text, { style: [styles.normalText, hmsRoomStyles.semiBoldHighText] }, "Leaderboard"), /*#__PURE__*/React.createElement(Text, { style: [styles.smallerText, hmsRoomStyles.regularMediumText] }, "Based on time taken to cast the correct answer")), ListFooterComponent: () => loading ? /*#__PURE__*/React.createElement(ActivityIndicator, { size: "small", color: primaryDefaultColor }) : null, estimatedItemSize: 56, onEndReached: () => { fetchLeaderboard(); } // showsVerticalScrollIndicator={Platform.OS !== 'android'} , contentContainerStyle: { paddingHorizontal: 24 } // keyboardShouldPersistTaps="always" // ItemSeparatorComponent={() => <View style={{ height: 16 }} />} // TODO: There is a bug related to this: https://github.com/Shopify/flash-list/issues/638 , renderItem: _renderItem, keyExtractor: _keyExtractor })); }; const styles = StyleSheet.create({ tinyText: { fontSize: 10, lineHeight: 16, letterSpacing: 1.5 }, smallerText: { fontSize: 12, lineHeight: 16 }, smallText: { fontSize: 14, lineHeight: 20 }, normalText: { fontSize: 16, lineHeight: 24 }, marginBottom16: { marginBottom: 16 }, iconWrapper: { flexDirection: 'row', alignItems: 'center', marginLeft: 12 }, // Utilities fullView: { flex: 1 }, // Header header: { flexDirection: 'row', alignItems: 'center', justifyContent: 'space-between', marginTop: 24, marginHorizontal: 24 }, headerControls: { flexDirection: 'row', alignItems: 'center', flexShrink: 1 }, headerText: { fontSize: 20, lineHeight: 24, letterSpacing: 0.15, marginRight: 12 }, closeIconHitSlop: { bottom: 16, left: 16, right: 16, top: 16 }, backIcon: { marginRight: 8 }, // Divider halfDivider: { marginHorizontal: 24, marginVertical: 0, marginTop: 24, width: undefined }, divider: { height: 1, width: '100%' }, viewAllBtn: { flexDirection: 'row', alignItems: 'center', justifyContent: 'flex-end', paddingVertical: 12, paddingHorizontal: 16 }, leaderboardEntry: { marginBottom: 16, marginHorizontal: 16 }, entriesCard: { paddingTop: 12, borderRadius: 8 } }); //# sourceMappingURL=QuizLeaderboardEntriesScreen.js.map