瀏覽代碼

fix(polls): Fix 'Skip' button functionality

master
Vlad Piersec 3 年之前
父節點
當前提交
70af0d6b78

+ 11
- 0
react/features/polls/actionTypes.js 查看文件

@@ -1,5 +1,16 @@
1 1
 // @flow
2 2
 
3
+/**
4
+ * The type of the action which signals that a Poll will be changed
5
+ *
6
+ * {
7
+ *     type: CHANGE_VOTE,
8
+ * }
9
+ *
10
+ */
11
+export const CHANGE_VOTE = 'CHANGE_VOTE';
12
+
13
+
3 14
 /**
4 15
  * The type of the action which signals that a new Poll was received.
5 16
  *

+ 21
- 0
react/features/polls/actions.js 查看文件

@@ -1,6 +1,7 @@
1 1
 // @flow
2 2
 
3 3
 import {
4
+    CHANGE_VOTE,
4 5
     RESET_NB_UNREAD_POLLS,
5 6
     RECEIVE_ANSWER,
6 7
     RECEIVE_POLL,
@@ -9,6 +10,26 @@ import {
9 10
 } from './actionTypes';
10 11
 import type { Answer, Poll } from './types';
11 12
 
13
+/**
14
+ * Action to signal that a poll's vote will be changed.
15
+ *
16
+ * @param {string} pollId - The id of the incoming poll.
17
+ * @param {boolean} value - The value of the 'changing' state.
18
+
19
+ * @returns {{
20
+ *     type: CHANGE_VOTE,
21
+ *     pollId: string,
22
+ *     value: boolean
23
+ * }}
24
+ */
25
+export const setVoteChanging = (pollId: string, value: boolean) => {
26
+    return {
27
+        type: CHANGE_VOTE,
28
+        pollId,
29
+        value
30
+    };
31
+};
32
+
12 33
 /**
13 34
  * Action to signal that a new poll was received.
14 35
  *

+ 7
- 1
react/features/polls/components/AbstractPollAnswer.js 查看文件

@@ -7,7 +7,7 @@ import { useDispatch, useSelector } from 'react-redux';
7 7
 
8 8
 import { sendAnalytics, createPollEvent } from '../../analytics';
9 9
 import { getLocalParticipant, getParticipantById } from '../../base/participants';
10
-import { registerVote } from '../actions';
10
+import { registerVote, setVoteChanging } from '../actions';
11 11
 import { COMMAND_ANSWER_POLL } from '../constants';
12 12
 import type { Poll } from '../types';
13 13
 
@@ -27,6 +27,7 @@ export type AbstractProps = {
27 27
     poll: Poll,
28 28
     setCheckbox: Function,
29 29
     skipAnswer: Function,
30
+    skipChangeVote: Function,
30 31
     submitAnswer: Function,
31 32
     t: Function,
32 33
 };
@@ -90,6 +91,10 @@ const AbstractPollAnswer = (Component: AbstractComponent<AbstractProps>) => (pro
90 91
 
91 92
     }, [ pollId ]);
92 93
 
94
+    const skipChangeVote = useCallback(() => {
95
+        dispatch(setVoteChanging(pollId, false));
96
+    }, [ dispatch, pollId ]);
97
+
93 98
     const { t } = useTranslation();
94 99
 
95 100
     return (<Component
@@ -97,6 +102,7 @@ const AbstractPollAnswer = (Component: AbstractComponent<AbstractProps>) => (pro
97 102
         poll = { poll }
98 103
         setCheckbox = { setCheckbox }
99 104
         skipAnswer = { skipAnswer }
105
+        skipChangeVote = { skipChangeVote }
100 106
         submitAnswer = { submitAnswer }
101 107
         t = { t } />);
102 108
 

+ 15
- 26
react/features/polls/components/AbstractPollResults.js 查看文件

@@ -6,9 +6,8 @@ import { useTranslation } from 'react-i18next';
6 6
 import { useDispatch, useSelector } from 'react-redux';
7 7
 
8 8
 import { sendAnalytics, createPollEvent } from '../../analytics';
9
-import { getLocalParticipant, getParticipantById } from '../../base/participants/functions';
10
-import { retractVote } from '../actions';
11
-import { COMMAND_ANSWER_POLL } from '../constants';
9
+import { setVoteChanging } from '../actions';
10
+import { getPoll } from '../functions';
12 11
 
13 12
 /**
14 13
  * The type of the React {@code Component} props of inheriting component.
@@ -51,7 +50,7 @@ export type AbstractProps = {
51 50
 const AbstractPollResults = (Component: AbstractComponent<AbstractProps>) => (props: InputProps) => {
52 51
     const { pollId } = props;
53 52
 
54
-    const pollDetails = useSelector(state => state['features/polls'].polls[pollId]);
53
+    const pollDetails = useSelector(getPoll(pollId));
55 54
 
56 55
     const [ showDetails, setShowDetails ] = useState(false);
57 56
     const toggleIsDetailed = useCallback(() => {
@@ -95,33 +94,23 @@ const AbstractPollResults = (Component: AbstractComponent<AbstractProps>) => (pr
95 94
     }, [ pollDetails.answers, showDetails ]);
96 95
 
97 96
     const dispatch = useDispatch();
98
-
99
-    const conference: Object = useSelector(state => state['features/base/conference'].conference);
100
-    const localId = useSelector(state => getLocalParticipant(state).id);
101
-    const localParticipant = useSelector(state => getParticipantById(state, localId));
102
-    const localName: string = localParticipant ? localParticipant.name : 'Fellow Jitster';
103 97
     const changeVote = useCallback(() => {
104
-        conference.sendMessage({
105
-            type: COMMAND_ANSWER_POLL,
106
-            pollId,
107
-            voterId: localId,
108
-            voterName: localName,
109
-            answers: new Array(pollDetails.answers.length).fill(false)
110
-        });
111
-        dispatch(retractVote(pollId));
98
+        dispatch(setVoteChanging(pollId, true));
112 99
         sendAnalytics(createPollEvent('vote.changed'));
113
-    }, [ pollId, localId, localName, pollDetails ]);
100
+    }, [ dispatch, pollId ]);
114 101
 
115 102
     const { t } = useTranslation();
116 103
 
117
-    return (<Component
118
-        answers = { answers }
119
-        changeVote = { changeVote }
120
-        haveVoted = { pollDetails.lastVote !== null }
121
-        question = { pollDetails.question }
122
-        showDetails = { showDetails }
123
-        t = { t }
124
-        toggleIsDetailed = { toggleIsDetailed } />);
104
+    return (
105
+        <Component
106
+            answers = { answers }
107
+            changeVote = { changeVote }
108
+            haveVoted = { pollDetails.lastVote !== null }
109
+            question = { pollDetails.question }
110
+            showDetails = { showDetails }
111
+            t = { t }
112
+            toggleIsDetailed = { toggleIsDetailed } />
113
+    );
125 114
 };
126 115
 
127 116
 export default AbstractPollResults;

+ 3
- 1
react/features/polls/components/native/PollAnswer.js 查看文件

@@ -18,9 +18,11 @@ const PollAnswer = (props: AbstractProps) => {
18 18
         poll,
19 19
         setCheckbox,
20 20
         skipAnswer,
21
+        skipChangeVote,
21 22
         submitAnswer,
22 23
         t
23 24
     } = props;
25
+    const { changingVote } = poll;
24 26
 
25 27
     return (
26 28
         <View>
@@ -44,7 +46,7 @@ const PollAnswer = (props: AbstractProps) => {
44 46
                 <Button
45 47
                     color = '#3D3D3D'
46 48
                     mode = { BUTTON_MODES.CONTAINED }
47
-                    onPress = { skipAnswer }
49
+                    onPress = { changingVote ? skipChangeVote : skipAnswer }
48 50
                     style = { chatStyles.pollCreateButton } >
49 51
                     {t('polls.answer.skip')}
50 52
                 </Button>

+ 1
- 1
react/features/polls/components/native/PollItem.js 查看文件

@@ -20,7 +20,7 @@ type Props = {
20 20
 }
21 21
 
22 22
 const PollItem = ({ pollId }: Props) => {
23
-    const showResults = useSelector(state => shouldShowResults(state, pollId));
23
+    const showResults = useSelector(shouldShowResults(pollId));
24 24
 
25 25
     return (
26 26
         <View

+ 3
- 1
react/features/polls/components/web/PollAnswer.js 查看文件

@@ -13,9 +13,11 @@ const PollAnswer = (props: AbstractProps) => {
13 13
         poll,
14 14
         setCheckbox,
15 15
         skipAnswer,
16
+        skipChangeVote,
16 17
         submitAnswer,
17 18
         t
18 19
     } = props;
20
+    const { changingVote } = poll;
19 21
 
20 22
     return (
21 23
         <div className = 'poll-answer'>
@@ -45,7 +47,7 @@ const PollAnswer = (props: AbstractProps) => {
45 47
                 <button
46 48
                     aria-label = { t('polls.answer.skip') }
47 49
                     className = 'poll-button poll-button-secondary poll-button-shortest'
48
-                    onClick = { skipAnswer } >
50
+                    onClick = { changingVote ? skipChangeVote : skipAnswer } >
49 51
                     <span>{t('polls.answer.skip')}</span>
50 52
                 </button>
51 53
                 <button

+ 1
- 1
react/features/polls/components/web/PollItem.js 查看文件

@@ -17,7 +17,7 @@ type Props = {
17 17
 }
18 18
 
19 19
 const PollItem = React.forwardRef<Props, HTMLElement>(({ pollId }, ref) => {
20
-    const showResults = useSelector(state => shouldShowResults(state, pollId));
20
+    const showResults = useSelector(shouldShowResults(pollId));
21 21
 
22 22
     return (
23 23
         <div ref = { ref }>

+ 18
- 4
react/features/polls/functions.js 查看文件

@@ -1,14 +1,28 @@
1 1
 // @flow
2 2
 
3 3
 /**
4
- * Should poll results be shown.
4
+ * Selector creator for determining if poll results should be displayed or not.
5 5
  *
6
- * @param {Object} state - Global state.
7 6
  * @param {string} id - Id of the poll.
8
- * @returns {boolean} Should poll results be shown.
7
+ * @returns {Function}
9 8
  */
10
-export const shouldShowResults = (state: Object, id: string) => Boolean(state['features/polls']?.polls[id].showResults);
9
+export function shouldShowResults(id: string) {
10
+    return function(state: Object) {
11
+        return Boolean(state['features/polls']?.polls[id].showResults);
12
+    };
13
+}
11 14
 
15
+/**
16
+ * Selector creator for polls.
17
+ *
18
+ * @param {string} pollId - Id of the poll to get.
19
+ * @returns {Function}
20
+ */
21
+export function getPoll(pollId: string) {
22
+    return function(state: Object) {
23
+        return state['features/polls'].polls[pollId];
24
+    };
25
+}
12 26
 
13 27
 /**
14 28
  * Selector for calculating the number of unread poll messages.

+ 18
- 0
react/features/polls/reducer.js 查看文件

@@ -3,6 +3,7 @@
3 3
 import { ReducerRegistry } from '../base/redux';
4 4
 
5 5
 import {
6
+    CHANGE_VOTE,
6 7
     RECEIVE_POLL,
7 8
     RECEIVE_ANSWER,
8 9
     REGISTER_VOTE,
@@ -21,6 +22,22 @@ const INITIAL_STATE = {
21 22
 ReducerRegistry.register('features/polls', (state = INITIAL_STATE, action) => {
22 23
     switch (action.type) {
23 24
 
25
+    case CHANGE_VOTE: {
26
+        const { pollId, value } = action;
27
+
28
+        return {
29
+            ...state,
30
+            polls: {
31
+                ...state.polls,
32
+                [pollId]: {
33
+                    ...state.polls[pollId],
34
+                    changingVote: value,
35
+                    showResults: !value
36
+                }
37
+            }
38
+        };
39
+    }
40
+
24 41
     // Reducer triggered when a poll is received
25 42
     case RECEIVE_POLL: {
26 43
         const newState = {
@@ -93,6 +110,7 @@ ReducerRegistry.register('features/polls', (state = INITIAL_STATE, action) => {
93 110
                 ...state.polls,
94 111
                 [pollId]: {
95 112
                     ...state.polls[pollId],
113
+                    changingVote: false,
96 114
                     lastVote: answers,
97 115
                     showResults: true
98 116
                 }

+ 2
- 0
react/features/polls/subscriber.js 查看文件

@@ -44,6 +44,7 @@ const parsePollData = (pollData): Poll | null => {
44 44
     }
45 45
 
46 46
     return {
47
+        changingVote: false,
47 48
         senderId,
48 49
         senderName,
49 50
         question,
@@ -63,6 +64,7 @@ StateListenerRegistry.register(
63 64
                     const { question, answers, pollId, senderId, senderName } = data;
64 65
 
65 66
                     const poll = {
67
+                        changingVote: false,
66 68
                         senderId,
67 69
                         senderName,
68 70
                         showResults: false,

+ 5
- 0
react/features/polls/types.js 查看文件

@@ -25,6 +25,11 @@ export type Answer = {
25 25
 
26 26
 export type Poll = {
27 27
 
28
+    /**
29
+     * Whether the poll vote is being edited/changed.
30
+     */
31
+    changingVote: boolean,
32
+
28 33
     /**
29 34
      * ID of the sender of this poll
30 35
      */

Loading…
取消
儲存