@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.
224 lines (223 loc) • 10.5 kB
JavaScript
import * as React from 'react';
import { View, Text, StyleSheet } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import { HMSPollQuestionType, HMSPollState, HMSPollType } from '@100mslive/react-native-hms';
import { useHMSInstance, useHMSRoomColorPalette, useHMSRoomStyleSheet } from '../hooks-util';
import { RadioInputRow } from './RadioInputRow';
import { HMSPrimaryButton } from './HMSPrimaryButton';
import { HMSBaseButton } from './HMSBaseButton';
import { addPollQuestionResponse, removePollQuestionResponse, setPollQuestionResponse } from '../redux/actions';
import { PollResponseProgressView } from './PollResponseProgressView';
import { CheckboxInputRow } from './CheckboxInputRow';
import { checkIsCorrectAnswer, checkIsCorrectOption, checkIsSelected, getLabelFromPollQuestionType } from '../utils/functions';
import { CheckIcon, CrossCircleIcon } from '../Icons';
import { QuizEndOptionsView } from './QuizEndOptionsView';
export const PollAndQuizQuestionResponseCard = ({
pollState,
totalQuestions,
pollId,
pollQuestion,
containerStyle,
onSubmit
}) => {
var _pollQuestion$options, _pollQuestion$options2, _pollQuestion$options3;
const {
primary_bright: primaryBrightColor,
on_surface_low: onSurfaceLowColor
} = useHMSRoomColorPalette();
const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({
container: {
backgroundColor: theme.palette.surface_default,
borderColor: theme.palette.surface_default
},
surfaceLowSemiBoldText: {
color: theme.palette.on_surface_low,
fontFamily: `${typography.font_family}-SemiBold`
},
surfaceHighRegularText: {
color: theme.palette.on_surface_high,
fontFamily: `${typography.font_family}-Regular`
},
wrongAnswer: {
borderColor: theme.palette.alert_error_default
},
correctAnswer: {
borderColor: theme.palette.alert_success
},
wrongAnswerText: {
color: theme.palette.alert_error_default
},
correctAnswerText: {
color: theme.palette.alert_success
},
wrongAnswerIcon: {
tintColor: theme.palette.alert_error_default
},
correctAnswerIcon: {
tintColor: theme.palette.alert_success
},
skipButton: {
borderColor: theme.palette.border_bright,
borderWidth: 1,
marginRight: 16
},
skipButtonText: {
color: theme.palette.on_surface_high,
fontFamily: `${typography.font_family}-SemiBold`
}
}));
// variable to save timestamp when the question became visible to user
const startTime = React.useRef(null);
React.useEffect(() => {
startTime.current = Date.now();
}, [pollQuestion.index]);
const hmsInstance = useHMSInstance();
const dispatch = useDispatch();
const selectedOptions = useSelector(state => {
var _state$polls$pollsRes;
return ((_state$polls$pollsRes = state.polls.pollsResponses[pollId]) === null || _state$polls$pollsRes === void 0 ? void 0 : _state$polls$pollsRes[pollQuestion.index]) ?? null;
});
const pollType = useSelector(state => {
var _state$polls$polls$po;
return ((_state$polls$polls$po = state.polls.polls[pollId]) === null || _state$polls$polls$po === void 0 ? void 0 : _state$polls$polls$po.type) ?? HMSPollType.poll;
});
const canViewPollResponse = useSelector(state => {
var _state$hmsStates$loca, _state$polls$polls$po2;
const localPeerRole = (_state$hmsStates$loca = state.hmsStates.localPeer) === null || _state$hmsStates$loca === void 0 ? void 0 : _state$hmsStates$loca.role;
const rolesThatCanViewResponses = (_state$polls$polls$po2 = state.polls.polls[pollId]) === null || _state$polls$polls$po2 === void 0 ? void 0 : _state$polls$polls$po2.rolesThatCanViewResponses;
return Array.isArray(rolesThatCanViewResponses) && rolesThatCanViewResponses.length > 0 ? localPeerRole && rolesThatCanViewResponses.findIndex(role => role.name === localPeerRole.name) !== -1 : true;
});
const handleOptionSelection = (selected, option) => {
if (pollQuestion.type === HMSPollQuestionType.singleChoice) {
dispatch(setPollQuestionResponse(pollId, pollQuestion.index, option.index));
} else {
if (selected) {
dispatch(addPollQuestionResponse(pollId, pollQuestion.index, option.index));
} else {
dispatch(removePollQuestionResponse(pollId, pollQuestion.index, option.index));
}
}
};
const handleVotePress = async e => {
if (!selectedOptions) {
return;
}
onSubmit === null || onSubmit === void 0 || onSubmit(e);
const result = await hmsInstance.interactivityCenter.add({
pollId,
pollQuestionIndex: pollQuestion.index,
responses: {
options: Array.isArray(selectedOptions) ? selectedOptions : [selectedOptions],
duration: pollType === HMSPollType.quiz && startTime.current !== null ? Date.now() - startTime.current : undefined
}
});
console.log(JSON.stringify(result, null, 4));
};
const handleSkipPress = async e => {
onSubmit === null || onSubmit === void 0 || onSubmit(e);
// TODO: Implement skip API
};
const anyOptionSelected = Array.isArray(selectedOptions) ? selectedOptions.length > 0 : selectedOptions !== null;
const isVoted = pollQuestion.myResponses.length > 0;
const InputComponent = pollQuestion.type === HMSPollQuestionType.singleChoice ? RadioInputRow : pollQuestion.type === HMSPollQuestionType.multipleChoice ? CheckboxInputRow : null;
const isCorrectAnswer = checkIsCorrectAnswer(pollQuestion.type, pollQuestion.myResponses, pollQuestion.answer);
return /*#__PURE__*/React.createElement(View, {
style: [hmsRoomStyles.container, styles.container, pollType === HMSPollType.quiz && isVoted && pollState === HMSPollState.stopped ? isCorrectAnswer ? hmsRoomStyles.correctAnswer : hmsRoomStyles.wrongAnswer : null, containerStyle]
}, /*#__PURE__*/React.createElement(View, {
style: {
flexDirection: 'row'
}
}, pollType === HMSPollType.quiz && isVoted && pollState === HMSPollState.stopped ? isCorrectAnswer ? /*#__PURE__*/React.createElement(CheckIcon, {
type: "in-circle",
style: [hmsRoomStyles.correctAnswerIcon, {
marginRight: 8,
width: 16,
height: 16
}]
}) : /*#__PURE__*/React.createElement(CrossCircleIcon, {
style: [hmsRoomStyles.wrongAnswerIcon, {
marginRight: 8,
width: 16,
height: 16
}]
}) : null, /*#__PURE__*/React.createElement(Text, {
numberOfLines: 2,
style: [styles.tinyText, hmsRoomStyles.surfaceLowSemiBoldText, styles.uppercaseContent, pollType === HMSPollType.quiz && isVoted && pollState === HMSPollState.stopped ? isCorrectAnswer ? hmsRoomStyles.correctAnswerText : hmsRoomStyles.wrongAnswerText : null]
}, "Question ", pollQuestion.index, " of ", totalQuestions, ":", ' ', getLabelFromPollQuestionType(pollQuestion.type))), /*#__PURE__*/React.createElement(Text, {
style: [hmsRoomStyles.surfaceHighRegularText, styles.regularText, styles.verticalNormalSpacer]
}, pollQuestion.text), !InputComponent ? null : /*#__PURE__*/React.createElement(React.Fragment, null, pollType === HMSPollType.poll && canViewPollResponse && (pollQuestion.myResponses.length > 0 || pollState === HMSPollState.stopped) ? /*#__PURE__*/React.createElement(React.Fragment, null, (_pollQuestion$options = pollQuestion.options) === null || _pollQuestion$options === void 0 ? void 0 : _pollQuestion$options.sort((a, b) => a.index - b.index).map((option, _, arr) => {
return /*#__PURE__*/React.createElement(PollResponseProgressView, {
key: option.index,
option: option,
totalVotes: arr.reduce((acc, curr) => acc + curr.voteCount, 0)
});
})) : pollType === HMSPollType.quiz && pollState === HMSPollState.stopped ? /*#__PURE__*/React.createElement(React.Fragment, null, (_pollQuestion$options2 = pollQuestion.options) === null || _pollQuestion$options2 === void 0 ? void 0 : _pollQuestion$options2.sort((a, b) => a.index - b.index).map(option => {
const isSelected = checkIsSelected(pollQuestion, option, null);
const isCorrect = checkIsCorrectOption(pollQuestion.type, option, pollQuestion.answer);
return /*#__PURE__*/React.createElement(QuizEndOptionsView, {
key: option.index,
option: option,
isSelected: isSelected,
isCorrect: isCorrect
});
})) : /*#__PURE__*/React.createElement(React.Fragment, null, (_pollQuestion$options3 = pollQuestion.options) === null || _pollQuestion$options3 === void 0 ? void 0 : _pollQuestion$options3.sort((a, b) => a.index - b.index).map(option => {
const isSelected = checkIsSelected(pollQuestion, option, selectedOptions);
return /*#__PURE__*/React.createElement(InputComponent, {
key: option.index,
disabled: isVoted,
selected: isSelected,
radioColor: isVoted ? isSelected ? primaryBrightColor : onSurfaceLowColor : undefined,
onChange: selected => handleOptionSelection(selected, option),
text: option.text,
containerStyle: {
marginBottom: 16
}
});
}))), isVoted && (pollType === HMSPollType.poll || pollState === HMSPollState.started) ? /*#__PURE__*/React.createElement(Text, {
style: [styles.regularText, styles.votedLabel, hmsRoomStyles.surfaceLowSemiBoldText]
}, pollType === HMSPollType.quiz ? 'Answered' : 'Voted') : pollState === HMSPollState.started ? /*#__PURE__*/React.createElement(View, {
style: {
alignSelf: 'flex-end',
flexDirection: 'row'
}
}, pollQuestion.skippable ? /*#__PURE__*/React.createElement(HMSBaseButton, {
loading: false,
onPress: handleSkipPress,
title: "Skip",
style: hmsRoomStyles.skipButton,
textStyle: hmsRoomStyles.skipButtonText,
useTouchableOpacity: true
}) : null, /*#__PURE__*/React.createElement(HMSPrimaryButton, {
loading: false,
disabled: !anyOptionSelected,
onPress: handleVotePress,
title: pollType === HMSPollType.quiz ? 'Answer' : 'Vote'
})) : null);
};
const styles = StyleSheet.create({
container: {
padding: 16,
borderRadius: 8,
borderWidth: 1
},
tinyText: {
fontSize: 10,
lineHeight: 16,
letterSpacing: 1.5
},
regularText: {
fontSize: 16,
lineHeight: 24
},
verticalNormalSpacer: {
marginVertical: 16
},
votedLabel: {
paddingVertical: 8,
alignSelf: 'flex-end'
},
uppercaseContent: {
textTransform: 'uppercase'
}
});
//# sourceMappingURL=PollAndQuizQuestionResponseCard.js.map