@100mslive/react-native-room-kit 1.1.1 → 1.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (255) hide show
  1. package/README.md +1 -1
  2. package/lib/commonjs/HMSRoomSetup.js +15 -5
  3. package/lib/commonjs/HMSRoomSetup.js.map +1 -1
  4. package/lib/commonjs/Icons/Check/assets/check-in-circle.png +0 -0
  5. package/lib/commonjs/Icons/Check/assets/check-in-circle@2x.png +0 -0
  6. package/lib/commonjs/Icons/Check/assets/check-in-circle@3x.png +0 -0
  7. package/lib/commonjs/Icons/Check/index.js +2 -1
  8. package/lib/commonjs/Icons/Check/index.js.map +1 -1
  9. package/lib/commonjs/Icons/CheckBox/index.js +8 -1
  10. package/lib/commonjs/Icons/CheckBox/index.js.map +1 -1
  11. package/lib/commonjs/Icons/Clock/assets/clock-vector.png +0 -0
  12. package/lib/commonjs/Icons/Clock/assets/clock-vector@2x.png +0 -0
  13. package/lib/commonjs/Icons/Clock/assets/clock-vector@3x.png +0 -0
  14. package/lib/commonjs/Icons/Clock/assets/clock.png +0 -0
  15. package/lib/commonjs/Icons/Clock/assets/clock@2x.png +0 -0
  16. package/lib/commonjs/Icons/Clock/assets/clock@3x.png +0 -0
  17. package/lib/commonjs/Icons/Clock/index.js +7 -2
  18. package/lib/commonjs/Icons/Clock/index.js.map +1 -1
  19. package/lib/commonjs/components/CreatePoll.js +100 -53
  20. package/lib/commonjs/components/CreatePoll.js.map +1 -1
  21. package/lib/commonjs/components/GridView.js +4 -8
  22. package/lib/commonjs/components/GridView.js.map +1 -1
  23. package/lib/commonjs/components/HLSView.js +15 -1
  24. package/lib/commonjs/components/HLSView.js.map +1 -1
  25. package/lib/commonjs/components/HMSPollsQuizzesNotification.js +2 -2
  26. package/lib/commonjs/components/HMSPollsQuizzesNotification.js.map +1 -1
  27. package/lib/commonjs/components/LeaderboardEntry.js +135 -0
  28. package/lib/commonjs/components/LeaderboardEntry.js.map +1 -0
  29. package/lib/commonjs/components/PollAndQuizQuestionResponseCard.js +80 -32
  30. package/lib/commonjs/components/PollAndQuizQuestionResponseCard.js.map +1 -1
  31. package/lib/commonjs/components/PollAndQuizQuestionResponseCards.js +53 -0
  32. package/lib/commonjs/components/PollAndQuizQuestionResponseCards.js.map +1 -0
  33. package/lib/commonjs/components/PollAndQuizSheetScreen.js +69 -0
  34. package/lib/commonjs/components/PollAndQuizSheetScreen.js.map +1 -0
  35. package/lib/commonjs/components/PollAndQuizVoting.js +145 -17
  36. package/lib/commonjs/components/PollAndQuizVoting.js.map +1 -1
  37. package/lib/commonjs/components/PollQuestion.js +70 -14
  38. package/lib/commonjs/components/PollQuestion.js.map +1 -1
  39. package/lib/commonjs/components/PollQuestions.js +126 -12
  40. package/lib/commonjs/components/PollQuestions.js.map +1 -1
  41. package/lib/commonjs/components/PollsAndQuizBottomSheet.js +9 -11
  42. package/lib/commonjs/components/PollsAndQuizBottomSheet.js.map +1 -1
  43. package/lib/commonjs/components/PollsAndQuizzesCard.js +1 -1
  44. package/lib/commonjs/components/PollsAndQuizzesCard.js.map +1 -1
  45. package/lib/commonjs/components/PollsAndQuizzesModalContent.js +26 -120
  46. package/lib/commonjs/components/PollsAndQuizzesModalContent.js.map +1 -1
  47. package/lib/commonjs/components/PollsConfigAndList.js +81 -4
  48. package/lib/commonjs/components/PollsConfigAndList.js.map +1 -1
  49. package/lib/commonjs/components/PreviousPollsAndQuizzesList.js +7 -15
  50. package/lib/commonjs/components/PreviousPollsAndQuizzesList.js.map +1 -1
  51. package/lib/commonjs/components/QuizEndOptionsView.js +63 -0
  52. package/lib/commonjs/components/QuizEndOptionsView.js.map +1 -0
  53. package/lib/commonjs/components/QuizLeaderboardEntriesScreen.js +284 -0
  54. package/lib/commonjs/components/QuizLeaderboardEntriesScreen.js.map +1 -0
  55. package/lib/commonjs/components/QuizLeaderboardScreen.js +279 -0
  56. package/lib/commonjs/components/QuizLeaderboardScreen.js.map +1 -0
  57. package/lib/commonjs/components/QuizLeaderboardSummary.js +195 -0
  58. package/lib/commonjs/components/QuizLeaderboardSummary.js.map +1 -0
  59. package/lib/commonjs/components/RadioInput.js +9 -2
  60. package/lib/commonjs/components/RadioInput.js.map +1 -1
  61. package/lib/commonjs/components/RoomSettingsModalContent.js +1 -1
  62. package/lib/commonjs/components/RoomSettingsModalContent.js.map +1 -1
  63. package/lib/commonjs/components/TilesContainer.js +3 -4
  64. package/lib/commonjs/components/TilesContainer.js.map +1 -1
  65. package/lib/commonjs/components/VoterParticipationSummary.js +46 -0
  66. package/lib/commonjs/components/VoterParticipationSummary.js.map +1 -0
  67. package/lib/commonjs/hooks-util.js +1 -1
  68. package/lib/commonjs/hooks-util.js.map +1 -1
  69. package/lib/commonjs/redux/actionTypes.js +9 -1
  70. package/lib/commonjs/redux/actionTypes.js.map +1 -1
  71. package/lib/commonjs/redux/actions/index.js +38 -5
  72. package/lib/commonjs/redux/actions/index.js.map +1 -1
  73. package/lib/commonjs/redux/reducers/polls.js +95 -8
  74. package/lib/commonjs/redux/reducers/polls.js.map +1 -1
  75. package/lib/commonjs/utils/functions.js +48 -3
  76. package/lib/commonjs/utils/functions.js.map +1 -1
  77. package/lib/commonjs/utils/hooks.js +107 -2
  78. package/lib/commonjs/utils/hooks.js.map +1 -1
  79. package/lib/module/HMSRoomSetup.js +16 -6
  80. package/lib/module/HMSRoomSetup.js.map +1 -1
  81. package/lib/module/Icons/Check/assets/check-in-circle.png +0 -0
  82. package/lib/module/Icons/Check/assets/check-in-circle@2x.png +0 -0
  83. package/lib/module/Icons/Check/assets/check-in-circle@3x.png +0 -0
  84. package/lib/module/Icons/Check/index.js +2 -1
  85. package/lib/module/Icons/Check/index.js.map +1 -1
  86. package/lib/module/Icons/CheckBox/index.js +9 -2
  87. package/lib/module/Icons/CheckBox/index.js.map +1 -1
  88. package/lib/module/Icons/Clock/assets/clock-vector.png +0 -0
  89. package/lib/module/Icons/Clock/assets/clock-vector@2x.png +0 -0
  90. package/lib/module/Icons/Clock/assets/clock-vector@3x.png +0 -0
  91. package/lib/module/Icons/Clock/assets/clock.png +0 -0
  92. package/lib/module/Icons/Clock/assets/clock@2x.png +0 -0
  93. package/lib/module/Icons/Clock/assets/clock@3x.png +0 -0
  94. package/lib/module/Icons/Clock/index.js +7 -2
  95. package/lib/module/Icons/Clock/index.js.map +1 -1
  96. package/lib/module/components/CreatePoll.js +102 -56
  97. package/lib/module/components/CreatePoll.js.map +1 -1
  98. package/lib/module/components/GridView.js +5 -9
  99. package/lib/module/components/GridView.js.map +1 -1
  100. package/lib/module/components/HLSView.js +17 -3
  101. package/lib/module/components/HLSView.js.map +1 -1
  102. package/lib/module/components/HMSPollsQuizzesNotification.js +3 -3
  103. package/lib/module/components/HMSPollsQuizzesNotification.js.map +1 -1
  104. package/lib/module/components/LeaderboardEntry.js +126 -0
  105. package/lib/module/components/LeaderboardEntry.js.map +1 -0
  106. package/lib/module/components/PollAndQuizQuestionResponseCard.js +81 -33
  107. package/lib/module/components/PollAndQuizQuestionResponseCard.js.map +1 -1
  108. package/lib/module/components/PollAndQuizQuestionResponseCards.js +44 -0
  109. package/lib/module/components/PollAndQuizQuestionResponseCards.js.map +1 -0
  110. package/lib/module/components/PollAndQuizSheetScreen.js +60 -0
  111. package/lib/module/components/PollAndQuizSheetScreen.js.map +1 -0
  112. package/lib/module/components/PollAndQuizVoting.js +148 -20
  113. package/lib/module/components/PollAndQuizVoting.js.map +1 -1
  114. package/lib/module/components/PollQuestion.js +73 -17
  115. package/lib/module/components/PollQuestion.js.map +1 -1
  116. package/lib/module/components/PollQuestions.js +129 -15
  117. package/lib/module/components/PollQuestions.js.map +1 -1
  118. package/lib/module/components/PollsAndQuizBottomSheet.js +11 -13
  119. package/lib/module/components/PollsAndQuizBottomSheet.js.map +1 -1
  120. package/lib/module/components/PollsAndQuizzesCard.js +2 -2
  121. package/lib/module/components/PollsAndQuizzesCard.js.map +1 -1
  122. package/lib/module/components/PollsAndQuizzesModalContent.js +28 -122
  123. package/lib/module/components/PollsAndQuizzesModalContent.js.map +1 -1
  124. package/lib/module/components/PollsConfigAndList.js +82 -5
  125. package/lib/module/components/PollsConfigAndList.js.map +1 -1
  126. package/lib/module/components/PreviousPollsAndQuizzesList.js +7 -15
  127. package/lib/module/components/PreviousPollsAndQuizzesList.js.map +1 -1
  128. package/lib/module/components/QuizEndOptionsView.js +54 -0
  129. package/lib/module/components/QuizEndOptionsView.js.map +1 -0
  130. package/lib/module/components/QuizLeaderboardEntriesScreen.js +275 -0
  131. package/lib/module/components/QuizLeaderboardEntriesScreen.js.map +1 -0
  132. package/lib/module/components/QuizLeaderboardScreen.js +270 -0
  133. package/lib/module/components/QuizLeaderboardScreen.js.map +1 -0
  134. package/lib/module/components/QuizLeaderboardSummary.js +186 -0
  135. package/lib/module/components/QuizLeaderboardSummary.js.map +1 -0
  136. package/lib/module/components/RadioInput.js +10 -3
  137. package/lib/module/components/RadioInput.js.map +1 -1
  138. package/lib/module/components/RoomSettingsModalContent.js +1 -1
  139. package/lib/module/components/RoomSettingsModalContent.js.map +1 -1
  140. package/lib/module/components/TilesContainer.js +5 -6
  141. package/lib/module/components/TilesContainer.js.map +1 -1
  142. package/lib/module/components/VoterParticipationSummary.js +37 -0
  143. package/lib/module/components/VoterParticipationSummary.js.map +1 -0
  144. package/lib/module/hooks-util.js +2 -4
  145. package/lib/module/hooks-util.js.map +1 -1
  146. package/lib/module/redux/actionTypes.js +9 -1
  147. package/lib/module/redux/actionTypes.js.map +1 -1
  148. package/lib/module/redux/actions/index.js +29 -3
  149. package/lib/module/redux/actions/index.js.map +1 -1
  150. package/lib/module/redux/reducers/polls.js +96 -9
  151. package/lib/module/redux/reducers/polls.js.map +1 -1
  152. package/lib/module/utils/functions.js +43 -3
  153. package/lib/module/utils/functions.js.map +1 -1
  154. package/lib/module/utils/hooks.js +105 -2
  155. package/lib/module/utils/hooks.js.map +1 -1
  156. package/lib/typescript/HMSRoomSetup.d.ts.map +1 -1
  157. package/lib/typescript/Icons/Check/index.d.ts +1 -0
  158. package/lib/typescript/Icons/Check/index.d.ts.map +1 -1
  159. package/lib/typescript/Icons/CheckBox/index.d.ts +1 -0
  160. package/lib/typescript/Icons/CheckBox/index.d.ts.map +1 -1
  161. package/lib/typescript/Icons/Clock/index.d.ts +1 -0
  162. package/lib/typescript/Icons/Clock/index.d.ts.map +1 -1
  163. package/lib/typescript/components/CreatePoll.d.ts.map +1 -1
  164. package/lib/typescript/components/GridView.d.ts.map +1 -1
  165. package/lib/typescript/components/HLSView.d.ts.map +1 -1
  166. package/lib/typescript/components/LeaderboardEntry.d.ts +11 -0
  167. package/lib/typescript/components/LeaderboardEntry.d.ts.map +1 -0
  168. package/lib/typescript/components/PollAndQuizQuestionResponseCard.d.ts.map +1 -1
  169. package/lib/typescript/components/PollAndQuizQuestionResponseCards.d.ts +9 -0
  170. package/lib/typescript/components/PollAndQuizQuestionResponseCards.d.ts.map +1 -0
  171. package/lib/typescript/components/PollAndQuizSheetScreen.d.ts +8 -0
  172. package/lib/typescript/components/PollAndQuizSheetScreen.d.ts.map +1 -0
  173. package/lib/typescript/components/PollAndQuizVoting.d.ts +2 -0
  174. package/lib/typescript/components/PollAndQuizVoting.d.ts.map +1 -1
  175. package/lib/typescript/components/PollQuestion.d.ts +1 -0
  176. package/lib/typescript/components/PollQuestion.d.ts.map +1 -1
  177. package/lib/typescript/components/PollQuestions.d.ts +2 -0
  178. package/lib/typescript/components/PollQuestions.d.ts.map +1 -1
  179. package/lib/typescript/components/PollsAndQuizBottomSheet.d.ts.map +1 -1
  180. package/lib/typescript/components/PollsAndQuizzesModalContent.d.ts +0 -1
  181. package/lib/typescript/components/PollsAndQuizzesModalContent.d.ts.map +1 -1
  182. package/lib/typescript/components/PollsConfigAndList.d.ts +1 -0
  183. package/lib/typescript/components/PollsConfigAndList.d.ts.map +1 -1
  184. package/lib/typescript/components/PreviousPollsAndQuizzesList.d.ts.map +1 -1
  185. package/lib/typescript/components/QuizEndOptionsView.d.ts +10 -0
  186. package/lib/typescript/components/QuizEndOptionsView.d.ts.map +1 -0
  187. package/lib/typescript/components/QuizLeaderboardEntriesScreen.d.ts +8 -0
  188. package/lib/typescript/components/QuizLeaderboardEntriesScreen.d.ts.map +1 -0
  189. package/lib/typescript/components/QuizLeaderboardScreen.d.ts +8 -0
  190. package/lib/typescript/components/QuizLeaderboardScreen.d.ts.map +1 -0
  191. package/lib/typescript/components/QuizLeaderboardSummary.d.ts +9 -0
  192. package/lib/typescript/components/QuizLeaderboardSummary.d.ts.map +1 -0
  193. package/lib/typescript/components/RadioInput.d.ts +1 -0
  194. package/lib/typescript/components/RadioInput.d.ts.map +1 -1
  195. package/lib/typescript/components/VoterParticipationSummary.d.ts +7 -0
  196. package/lib/typescript/components/VoterParticipationSummary.d.ts.map +1 -0
  197. package/lib/typescript/hooks-util.d.ts.map +1 -1
  198. package/lib/typescript/redux/actionTypes.d.ts +45 -9
  199. package/lib/typescript/redux/actionTypes.d.ts.map +1 -1
  200. package/lib/typescript/redux/actions/index.d.ts +8 -2
  201. package/lib/typescript/redux/actions/index.d.ts.map +1 -1
  202. package/lib/typescript/redux/index.d.ts +2 -1
  203. package/lib/typescript/redux/index.d.ts.map +1 -1
  204. package/lib/typescript/redux/reducers/index.d.ts +2 -1
  205. package/lib/typescript/redux/reducers/index.d.ts.map +1 -1
  206. package/lib/typescript/redux/reducers/polls.d.ts +3 -2
  207. package/lib/typescript/redux/reducers/polls.d.ts.map +1 -1
  208. package/lib/typescript/utils/functions.d.ts +6 -2
  209. package/lib/typescript/utils/functions.d.ts.map +1 -1
  210. package/lib/typescript/utils/hooks.d.ts +6 -0
  211. package/lib/typescript/utils/hooks.d.ts.map +1 -1
  212. package/package.json +3 -3
  213. package/src/HMSRoomSetup.tsx +25 -6
  214. package/src/Icons/Check/assets/check-in-circle.png +0 -0
  215. package/src/Icons/Check/assets/check-in-circle@2x.png +0 -0
  216. package/src/Icons/Check/assets/check-in-circle@3x.png +0 -0
  217. package/src/Icons/Check/index.tsx +9 -2
  218. package/src/Icons/CheckBox/index.tsx +16 -2
  219. package/src/Icons/Clock/assets/clock-vector.png +0 -0
  220. package/src/Icons/Clock/assets/clock-vector@2x.png +0 -0
  221. package/src/Icons/Clock/assets/clock-vector@3x.png +0 -0
  222. package/src/Icons/Clock/assets/clock.png +0 -0
  223. package/src/Icons/Clock/assets/clock@2x.png +0 -0
  224. package/src/Icons/Clock/assets/clock@3x.png +0 -0
  225. package/src/Icons/Clock/index.tsx +16 -3
  226. package/src/components/CreatePoll.tsx +150 -72
  227. package/src/components/GridView.tsx +4 -14
  228. package/src/components/HLSView.tsx +27 -1
  229. package/src/components/HMSPollsQuizzesNotification.tsx +3 -3
  230. package/src/components/LeaderboardEntry.tsx +172 -0
  231. package/src/components/PollAndQuizQuestionResponseCard.tsx +151 -48
  232. package/src/components/PollAndQuizQuestionResponseCards.tsx +62 -0
  233. package/src/components/PollAndQuizSheetScreen.tsx +85 -0
  234. package/src/components/PollAndQuizVoting.tsx +206 -28
  235. package/src/components/PollQuestion.tsx +140 -25
  236. package/src/components/PollQuestions.tsx +214 -74
  237. package/src/components/PollsAndQuizBottomSheet.tsx +20 -42
  238. package/src/components/PollsAndQuizzesCard.tsx +2 -2
  239. package/src/components/PollsAndQuizzesModalContent.tsx +40 -163
  240. package/src/components/PollsConfigAndList.tsx +107 -11
  241. package/src/components/PreviousPollsAndQuizzesList.tsx +33 -40
  242. package/src/components/QuizEndOptionsView.tsx +71 -0
  243. package/src/components/QuizLeaderboardEntriesScreen.tsx +323 -0
  244. package/src/components/QuizLeaderboardScreen.tsx +342 -0
  245. package/src/components/QuizLeaderboardSummary.tsx +207 -0
  246. package/src/components/RadioInput.tsx +14 -2
  247. package/src/components/RoomSettingsModalContent.tsx +1 -1
  248. package/src/components/TilesContainer.tsx +4 -4
  249. package/src/components/VoterParticipationSummary.tsx +67 -0
  250. package/src/hooks-util.ts +1 -3
  251. package/src/redux/actionTypes.ts +56 -6
  252. package/src/redux/actions/index.ts +56 -6
  253. package/src/redux/reducers/polls.ts +139 -11
  254. package/src/utils/functions.ts +90 -6
  255. package/src/utils/hooks.ts +190 -3
@@ -0,0 +1,323 @@
1
+ import * as React from 'react';
2
+ import {
3
+ Text,
4
+ StyleSheet,
5
+ View,
6
+ Keyboard,
7
+ TouchableOpacity,
8
+ ActivityIndicator,
9
+ } from 'react-native';
10
+ import { useDispatch, useSelector } from 'react-redux';
11
+ import type { HMSPollLeaderboardEntry } from '@100mslive/react-native-hms';
12
+ import { FlashList } from '@shopify/flash-list';
13
+
14
+ import {
15
+ useHMSInstance,
16
+ useHMSRoomColorPalette,
17
+ useHMSRoomStyleSheet,
18
+ } from '../hooks-util';
19
+ import type { RootState } from '../redux';
20
+ import { popFromNavigationStack } from '../redux/actions';
21
+ import { BottomSheet } from './BottomSheet';
22
+ import { ChevronIcon, CloseIcon } from '../Icons';
23
+ import { PollAndQuizzStateLabel } from './PollAndQuizzStateLabel';
24
+ import { LeaderboardEntry } from './LeaderboardEntry';
25
+
26
+ export interface QuizLeaderboardEntriesScreenProps {
27
+ currentIdx: number;
28
+ dismissModal(): void;
29
+ unmountScreenWithAnimation?(cb: Function): void;
30
+ }
31
+
32
+ export const QuizLeaderboardEntriesScreen: React.FC<
33
+ QuizLeaderboardEntriesScreenProps
34
+ > = ({ currentIdx, dismissModal, unmountScreenWithAnimation }) => {
35
+ const hmsInstance = useHMSInstance();
36
+ const dispatch = useDispatch();
37
+
38
+ const selectedPoll = useSelector((state: RootState) => {
39
+ const pollsData = state.polls;
40
+ if (pollsData.selectedPollId !== null) {
41
+ return pollsData.polls[pollsData.selectedPollId] || null;
42
+ }
43
+ return null;
44
+ });
45
+
46
+ const initialLeaderboardEntries = useSelector((state: RootState) => {
47
+ return selectedPoll?.pollId
48
+ ? state.polls.leaderboards[selectedPoll.pollId]?.entries
49
+ : null;
50
+ });
51
+
52
+ const [leaderboardEntries, setLeaderboardEntries] = React.useState<
53
+ HMSPollLeaderboardEntry[]
54
+ >(initialLeaderboardEntries ? [...initialLeaderboardEntries] : []);
55
+
56
+ const startIndexRef = React.useRef(leaderboardEntries.length);
57
+
58
+ const { primary_default: primaryDefaultColor } = useHMSRoomColorPalette();
59
+ const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({
60
+ regularHighText: {
61
+ color: theme.palette.on_surface_high,
62
+ fontFamily: `${typography.font_family}-Regular`,
63
+ },
64
+ regularMediumText: {
65
+ color: theme.palette.on_surface_medium,
66
+ fontFamily: `${typography.font_family}-Regular`,
67
+ },
68
+ semiBoldMediumText: {
69
+ color: theme.palette.on_surface_medium,
70
+ fontFamily: `${typography.font_family}-SemiBold`,
71
+ },
72
+ semiBoldHighText: {
73
+ color: theme.palette.on_surface_high,
74
+ fontFamily: `${typography.font_family}-SemiBold`,
75
+ },
76
+ headerText: {
77
+ color: theme.palette.on_surface_high,
78
+ fontFamily: `${typography.font_family}-SemiBold`,
79
+ },
80
+ container: {
81
+ backgroundColor: theme.palette.surface_dim,
82
+ },
83
+ summaryContainer: {
84
+ backgroundColor: theme.palette.surface_default,
85
+ },
86
+ entriesCard: {
87
+ backgroundColor: theme.palette.surface_default,
88
+ },
89
+ divider: {
90
+ backgroundColor: theme.palette.border_bright,
91
+ },
92
+ }));
93
+
94
+ const handleBackPress = () => {
95
+ Keyboard.dismiss();
96
+ if (typeof unmountScreenWithAnimation === 'function') {
97
+ unmountScreenWithAnimation(() => dispatch(popFromNavigationStack()));
98
+ } else {
99
+ dispatch(popFromNavigationStack());
100
+ }
101
+ };
102
+
103
+ const handleClosePress = () => {
104
+ Keyboard.dismiss();
105
+ dismissModal();
106
+ };
107
+
108
+ const [loading, setLoading] = React.useState(false);
109
+ const loadingRef = React.useRef(false);
110
+ const mounted = React.useRef(true);
111
+ const canFetchMore = React.useRef(true);
112
+
113
+ const fetchLeaderboard = React.useCallback(async () => {
114
+ if (selectedPoll?.pollId && canFetchMore.current && !loadingRef.current) {
115
+ setLoading(true);
116
+ loadingRef.current = true;
117
+ const response = await hmsInstance.interactivityCenter.fetchLeaderboard(
118
+ selectedPoll.pollId,
119
+ 50,
120
+ startIndexRef.current + 1, // Indexing starts from 1
121
+ false
122
+ );
123
+ if (mounted) {
124
+ setLoading(false);
125
+ loadingRef.current = false;
126
+ if (Array.isArray(response.entries)) {
127
+ const entries = response.entries;
128
+ setLeaderboardEntries((prev) => {
129
+ const list = [...prev, ...entries];
130
+ startIndexRef.current = list.length;
131
+ return list;
132
+ });
133
+ if (entries.length <= 0) {
134
+ canFetchMore.current = false;
135
+ }
136
+ }
137
+ if (response.hasNext === false) {
138
+ canFetchMore.current = false;
139
+ }
140
+ }
141
+ }
142
+ }, [selectedPoll?.pollId]);
143
+
144
+ const totalPoints =
145
+ selectedPoll?.questions?.reduce((acc, curr) => {
146
+ acc += curr.weight;
147
+ return acc;
148
+ }, 0) ?? 0;
149
+
150
+ const totalQuestions = selectedPoll?.questions?.length ?? 0;
151
+
152
+ const _keyExtractor = React.useCallback(
153
+ (item: HMSPollLeaderboardEntry, index: number) =>
154
+ item.peer?.peerId ?? index.toString(),
155
+ []
156
+ );
157
+
158
+ const _renderItem = React.useCallback(
159
+ (data: { item: HMSPollLeaderboardEntry }) => {
160
+ return (
161
+ <LeaderboardEntry
162
+ totalPoints={totalPoints}
163
+ totalQuestions={totalQuestions}
164
+ entry={data.item}
165
+ style={{ marginBottom: 16 }}
166
+ />
167
+ );
168
+ },
169
+ [totalPoints, totalQuestions]
170
+ );
171
+
172
+ return (
173
+ <View style={[styles.fullView, hmsRoomStyles.container]}>
174
+ {/* Header */}
175
+ <View style={styles.header}>
176
+ <View style={styles.headerControls}>
177
+ {currentIdx > 0 ? (
178
+ <TouchableOpacity
179
+ onPress={handleBackPress}
180
+ hitSlop={styles.closeIconHitSlop}
181
+ style={styles.backIcon}
182
+ >
183
+ <ChevronIcon direction="left" />
184
+ </TouchableOpacity>
185
+ ) : null}
186
+
187
+ <Text
188
+ numberOfLines={2}
189
+ style={[
190
+ styles.headerText,
191
+ { flexShrink: 1 },
192
+ hmsRoomStyles.headerText,
193
+ ]}
194
+ >
195
+ {selectedPoll?.title}
196
+ </Text>
197
+
198
+ {selectedPoll?.state ? (
199
+ <PollAndQuizzStateLabel state={selectedPoll?.state} />
200
+ ) : null}
201
+ </View>
202
+
203
+ <TouchableOpacity
204
+ onPress={handleClosePress}
205
+ hitSlop={styles.closeIconHitSlop}
206
+ style={{ marginLeft: 16 }}
207
+ >
208
+ <CloseIcon />
209
+ </TouchableOpacity>
210
+ </View>
211
+
212
+ {/* Divider */}
213
+ <BottomSheet.Divider style={styles.halfDivider} />
214
+
215
+ {/* Content */}
216
+ <FlashList
217
+ data={leaderboardEntries}
218
+ ListHeaderComponent={() => (
219
+ <View style={{ paddingTop: 24, paddingBottom: 28 }}>
220
+ <Text style={[styles.normalText, hmsRoomStyles.semiBoldHighText]}>
221
+ Leaderboard
222
+ </Text>
223
+ <Text style={[styles.smallerText, hmsRoomStyles.regularMediumText]}>
224
+ Based on time taken to cast the correct answer
225
+ </Text>
226
+ </View>
227
+ )}
228
+ ListFooterComponent={() =>
229
+ loading ? (
230
+ <ActivityIndicator size="small" color={primaryDefaultColor} />
231
+ ) : null
232
+ }
233
+ estimatedItemSize={56}
234
+ onEndReached={() => {
235
+ fetchLeaderboard();
236
+ }}
237
+ // showsVerticalScrollIndicator={Platform.OS !== 'android'}
238
+ contentContainerStyle={{ paddingHorizontal: 24 }}
239
+ // keyboardShouldPersistTaps="always"
240
+ // ItemSeparatorComponent={() => <View style={{ height: 16 }} />} // TODO: There is a bug related to this: https://github.com/Shopify/flash-list/issues/638
241
+ renderItem={_renderItem}
242
+ keyExtractor={_keyExtractor}
243
+ />
244
+ </View>
245
+ );
246
+ };
247
+
248
+ const styles = StyleSheet.create({
249
+ tinyText: {
250
+ fontSize: 10,
251
+ lineHeight: 16,
252
+ letterSpacing: 1.5,
253
+ },
254
+ smallerText: {
255
+ fontSize: 12,
256
+ lineHeight: 16,
257
+ },
258
+ smallText: {
259
+ fontSize: 14,
260
+ lineHeight: 20,
261
+ },
262
+ normalText: {
263
+ fontSize: 16,
264
+ lineHeight: 24,
265
+ },
266
+ marginBottom16: {
267
+ marginBottom: 16,
268
+ },
269
+ iconWrapper: {
270
+ flexDirection: 'row',
271
+ alignItems: 'center',
272
+ marginLeft: 12,
273
+ },
274
+ // Utilities
275
+ fullView: {
276
+ flex: 1,
277
+ },
278
+ // Header
279
+ header: {
280
+ flexDirection: 'row',
281
+ alignItems: 'center',
282
+ justifyContent: 'space-between',
283
+ marginTop: 24,
284
+ marginHorizontal: 24,
285
+ },
286
+ headerControls: {
287
+ flexDirection: 'row',
288
+ alignItems: 'center',
289
+ flexShrink: 1,
290
+ },
291
+ headerText: {
292
+ fontSize: 20,
293
+ lineHeight: 24,
294
+ letterSpacing: 0.15,
295
+ marginRight: 12,
296
+ },
297
+ closeIconHitSlop: {
298
+ bottom: 16,
299
+ left: 16,
300
+ right: 16,
301
+ top: 16,
302
+ },
303
+ backIcon: {
304
+ marginRight: 8,
305
+ },
306
+ // Divider
307
+ halfDivider: {
308
+ marginHorizontal: 24,
309
+ marginVertical: 0,
310
+ marginTop: 24,
311
+ width: undefined,
312
+ },
313
+ divider: { height: 1, width: '100%' },
314
+ viewAllBtn: {
315
+ flexDirection: 'row',
316
+ alignItems: 'center',
317
+ justifyContent: 'flex-end',
318
+ paddingVertical: 12,
319
+ paddingHorizontal: 16,
320
+ },
321
+ leaderboardEntry: { marginBottom: 16, marginHorizontal: 16 },
322
+ entriesCard: { paddingTop: 12, borderRadius: 8 },
323
+ });
@@ -0,0 +1,342 @@
1
+ import * as React from 'react';
2
+ import {
3
+ Text,
4
+ StyleSheet,
5
+ ScrollView,
6
+ View,
7
+ Keyboard,
8
+ TouchableOpacity,
9
+ } from 'react-native';
10
+ import { useDispatch, useSelector } from 'react-redux';
11
+
12
+ import { useHMSRoomStyleSheet } from '../hooks-util';
13
+ import type { RootState } from '../redux';
14
+ import {
15
+ popFromNavigationStack,
16
+ pushToNavigationStack,
17
+ } from '../redux/actions';
18
+ import { BottomSheet } from './BottomSheet';
19
+ import { ChevronIcon, CloseIcon } from '../Icons';
20
+ import { PollAndQuizzStateLabel } from './PollAndQuizzStateLabel';
21
+ import { LeaderboardEntry } from './LeaderboardEntry';
22
+ import { CreatePollStages } from '../redux/actionTypes';
23
+ import { QuizLeaderboardSummary } from './QuizLeaderboardSummary';
24
+ import {
25
+ useFetchLeaderboardResponse,
26
+ useLeaderboardSummaryData,
27
+ } from '../utils/hooks';
28
+
29
+ export interface QuizLeaderboardScreenProps {
30
+ currentIdx: number;
31
+ dismissModal(): void;
32
+ unmountScreenWithAnimation?(cb: Function): void;
33
+ }
34
+
35
+ export const QuizLeaderboardScreen: React.FC<QuizLeaderboardScreenProps> = ({
36
+ currentIdx,
37
+ dismissModal,
38
+ unmountScreenWithAnimation,
39
+ }) => {
40
+ const dispatch = useDispatch();
41
+
42
+ const selectedPoll = useSelector((state: RootState) => {
43
+ const pollsData = state.polls;
44
+ if (pollsData.selectedPollId !== null) {
45
+ return pollsData.polls[pollsData.selectedPollId] || null;
46
+ }
47
+ return null;
48
+ });
49
+ const headerTitle = useSelector((state: RootState) => {
50
+ const pollsData = state.polls;
51
+ if (pollsData.selectedPollId !== null) {
52
+ return pollsData.polls[pollsData.selectedPollId]?.title || null;
53
+ }
54
+ return null;
55
+ });
56
+
57
+ const hmsRoomStyles = useHMSRoomStyleSheet((theme, typography) => ({
58
+ regularHighText: {
59
+ color: theme.palette.on_surface_high,
60
+ fontFamily: `${typography.font_family}-Regular`,
61
+ },
62
+ regularMediumText: {
63
+ color: theme.palette.on_surface_medium,
64
+ fontFamily: `${typography.font_family}-Regular`,
65
+ },
66
+ semiBoldMediumText: {
67
+ color: theme.palette.on_surface_medium,
68
+ fontFamily: `${typography.font_family}-SemiBold`,
69
+ },
70
+ semiBoldHighText: {
71
+ color: theme.palette.on_surface_high,
72
+ fontFamily: `${typography.font_family}-SemiBold`,
73
+ },
74
+ headerText: {
75
+ color: theme.palette.on_surface_high,
76
+ fontFamily: `${typography.font_family}-SemiBold`,
77
+ },
78
+ container: {
79
+ backgroundColor: theme.palette.surface_dim,
80
+ },
81
+ summaryContainer: {
82
+ backgroundColor: theme.palette.surface_default,
83
+ },
84
+ entriesCard: {
85
+ backgroundColor: theme.palette.surface_default,
86
+ },
87
+ divider: {
88
+ backgroundColor: theme.palette.border_bright,
89
+ },
90
+ }));
91
+
92
+ const handleBackPress = () => {
93
+ Keyboard.dismiss();
94
+ if (typeof unmountScreenWithAnimation === 'function') {
95
+ unmountScreenWithAnimation(() => dispatch(popFromNavigationStack()));
96
+ } else {
97
+ dispatch(popFromNavigationStack());
98
+ }
99
+ };
100
+
101
+ const handleClosePress = () => {
102
+ Keyboard.dismiss();
103
+ dismissModal();
104
+ };
105
+
106
+ const viewAllLeaderboardEntries = () => {
107
+ dispatch(pushToNavigationStack(CreatePollStages.QUIZ_LEADERBOARD_ENTRIES));
108
+ };
109
+
110
+ const leaderboardData = useFetchLeaderboardResponse(selectedPoll?.pollId);
111
+
112
+ const leaderboardEntries = leaderboardData?.entries;
113
+
114
+ const summaryData = useLeaderboardSummaryData(selectedPoll?.pollId);
115
+
116
+ const totalPoints =
117
+ selectedPoll?.questions?.reduce((acc, curr) => {
118
+ acc += curr.weight;
119
+ return acc;
120
+ }, 0) ?? 0;
121
+
122
+ return (
123
+ <View style={[styles.fullView, hmsRoomStyles.container]}>
124
+ {/* Header */}
125
+ <View style={styles.header}>
126
+ <View style={styles.headerControls}>
127
+ {currentIdx > 0 ? (
128
+ <TouchableOpacity
129
+ onPress={handleBackPress}
130
+ hitSlop={styles.closeIconHitSlop}
131
+ style={styles.backIcon}
132
+ >
133
+ <ChevronIcon direction="left" />
134
+ </TouchableOpacity>
135
+ ) : null}
136
+
137
+ <Text
138
+ numberOfLines={2}
139
+ style={[
140
+ styles.headerText,
141
+ { flexShrink: 1 },
142
+ hmsRoomStyles.headerText,
143
+ ]}
144
+ >
145
+ {headerTitle}
146
+ </Text>
147
+
148
+ {selectedPoll?.state ? (
149
+ <PollAndQuizzStateLabel state={selectedPoll?.state} />
150
+ ) : null}
151
+ </View>
152
+
153
+ <TouchableOpacity
154
+ onPress={handleClosePress}
155
+ hitSlop={styles.closeIconHitSlop}
156
+ style={{ marginLeft: 16 }}
157
+ >
158
+ <CloseIcon />
159
+ </TouchableOpacity>
160
+ </View>
161
+
162
+ {/* Divider */}
163
+ <BottomSheet.Divider style={styles.halfDivider} />
164
+
165
+ {/* Content */}
166
+ <ScrollView
167
+ style={styles.contentContainer}
168
+ contentContainerStyle={styles.scrollViewContentContainer}
169
+ >
170
+ {summaryData ? <QuizLeaderboardSummary data={summaryData} /> : null}
171
+
172
+ {selectedPoll &&
173
+ Array.isArray(selectedPoll.questions) &&
174
+ Array.isArray(leaderboardEntries) &&
175
+ leaderboardEntries.length > 0 ? (
176
+ <React.Fragment>
177
+ <Text style={[styles.normalText, hmsRoomStyles.semiBoldHighText]}>
178
+ Leaderboard
179
+ </Text>
180
+ <Text
181
+ style={[
182
+ styles.smallerText,
183
+ hmsRoomStyles.regularMediumText,
184
+ styles.marginBottom16,
185
+ ]}
186
+ >
187
+ Based on time taken to cast the correct answer
188
+ </Text>
189
+
190
+ <View style={[styles.entriesCard, hmsRoomStyles.entriesCard]}>
191
+ {leaderboardEntries.map((entry, index) => {
192
+ return (
193
+ <LeaderboardEntry
194
+ key={index}
195
+ entry={entry}
196
+ totalPoints={totalPoints}
197
+ totalQuestions={selectedPoll.questions?.length ?? 0}
198
+ style={styles.leaderboardEntry}
199
+ />
200
+ );
201
+ })}
202
+
203
+ {leaderboardData?.hasNext && leaderboardEntries.length <= 5 ? (
204
+ <React.Fragment>
205
+ <View style={[styles.divider, hmsRoomStyles.divider]} />
206
+
207
+ <TouchableOpacity
208
+ onPress={viewAllLeaderboardEntries}
209
+ style={styles.viewAllBtn}
210
+ >
211
+ <Text
212
+ style={[
213
+ styles.smallText,
214
+ hmsRoomStyles.regularHighText,
215
+ { marginRight: 4 },
216
+ ]}
217
+ >
218
+ View All
219
+ </Text>
220
+
221
+ <ChevronIcon direction="right" />
222
+ </TouchableOpacity>
223
+ </React.Fragment>
224
+ ) : null}
225
+ </View>
226
+ </React.Fragment>
227
+ ) : null}
228
+ </ScrollView>
229
+ </View>
230
+ );
231
+ };
232
+
233
+ const styles = StyleSheet.create({
234
+ tinyText: {
235
+ fontSize: 10,
236
+ lineHeight: 16,
237
+ letterSpacing: 1.5,
238
+ },
239
+ smallerText: {
240
+ fontSize: 12,
241
+ lineHeight: 16,
242
+ },
243
+ smallText: {
244
+ fontSize: 14,
245
+ lineHeight: 20,
246
+ },
247
+ normalText: {
248
+ fontSize: 16,
249
+ lineHeight: 24,
250
+ },
251
+ marginBottom8: {
252
+ marginBottom: 8,
253
+ },
254
+ marginBottom16: {
255
+ marginBottom: 16,
256
+ },
257
+ contentContainer: {
258
+ paddingHorizontal: 24,
259
+ },
260
+ scrollViewContentContainer: {
261
+ flexGrow: 1,
262
+ paddingVertical: 24,
263
+ },
264
+ summaryWrapper: {
265
+ flexBasis: '50%',
266
+ flexGrow: 1,
267
+ flexShrink: 1,
268
+ padding: 16,
269
+ borderRadius: 12,
270
+ },
271
+ position: {
272
+ width: 24,
273
+ height: 24,
274
+ borderRadius: 12,
275
+ textAlign: 'center',
276
+ textAlignVertical: 'center',
277
+ marginRight: 12,
278
+ },
279
+ firstPosition: {
280
+ backgroundColor: '#D69516', // '#FFD700'
281
+ },
282
+ secondPosition: {
283
+ backgroundColor: '#3E3E3E', // '#C0C0C0'
284
+ },
285
+ thirdPosition: {
286
+ backgroundColor: '#583B0F', // '#CD7F32'
287
+ },
288
+ iconWrapper: {
289
+ flexDirection: 'row',
290
+ alignItems: 'center',
291
+ marginLeft: 12,
292
+ },
293
+ // Utilities
294
+ fullView: {
295
+ flex: 1,
296
+ },
297
+ // Header
298
+ header: {
299
+ flexDirection: 'row',
300
+ alignItems: 'center',
301
+ justifyContent: 'space-between',
302
+ marginTop: 24,
303
+ marginHorizontal: 24,
304
+ },
305
+ headerControls: {
306
+ flexDirection: 'row',
307
+ alignItems: 'center',
308
+ flexShrink: 1,
309
+ },
310
+ headerText: {
311
+ fontSize: 20,
312
+ lineHeight: 24,
313
+ letterSpacing: 0.15,
314
+ marginRight: 12,
315
+ },
316
+ closeIconHitSlop: {
317
+ bottom: 16,
318
+ left: 16,
319
+ right: 16,
320
+ top: 16,
321
+ },
322
+ backIcon: {
323
+ marginRight: 8,
324
+ },
325
+ // Divider
326
+ halfDivider: {
327
+ marginHorizontal: 24,
328
+ marginVertical: 0,
329
+ marginTop: 24,
330
+ width: undefined,
331
+ },
332
+ divider: { height: 1, width: '100%' },
333
+ viewAllBtn: {
334
+ flexDirection: 'row',
335
+ alignItems: 'center',
336
+ justifyContent: 'flex-end',
337
+ paddingVertical: 12,
338
+ paddingHorizontal: 16,
339
+ },
340
+ leaderboardEntry: { marginBottom: 16, marginHorizontal: 16 },
341
+ entriesCard: { paddingTop: 12, borderRadius: 8 },
342
+ });