1- import React , { useMemo } from 'react' ;
1+ import React , { useCallback , useMemo } from 'react' ;
22
3- import { ScrollViewProps , StyleSheet , Text , View } from 'react-native' ;
3+ import { Pressable , ScrollViewProps , StyleSheet , Text , View } from 'react-native' ;
44
55import { ScrollView } from 'react-native-gesture-handler' ;
66
77import { PollOption as PollOptionClass , PollVote } from 'stream-chat' ;
88
9- import { VoteButton } from './Button' ;
9+ import { PollVoteButtonProps } from './Button' ;
1010
11- import { PollContextProvider , PollContextValue , useTheme } from '../../../contexts' ;
11+ import {
12+ PollContextProvider ,
13+ PollContextValue ,
14+ useOwnCapabilitiesContext ,
15+ usePollContext ,
16+ useTheme ,
17+ } from '../../../contexts' ;
1218
19+ import { Check } from '../../../icons' ;
1320import { Avatar } from '../../Avatar/Avatar' ;
1421import { usePollState } from '../hooks/usePollState' ;
1522
@@ -141,6 +148,61 @@ export const PollOption = ({ option, showProgressBar = true }: PollOptionProps)
141148 ) ;
142149} ;
143150
151+ export const VoteButton = ( { onPress, option } : PollVoteButtonProps ) => {
152+ const { message, poll } = usePollContext ( ) ;
153+ const { isClosed, ownVotesByOptionId } = usePollState ( ) ;
154+ const ownCapabilities = useOwnCapabilitiesContext ( ) ;
155+
156+ const {
157+ theme : {
158+ colors : { accent_dark_blue, disabled } ,
159+ poll : {
160+ message : {
161+ option : { voteButtonActive, voteButtonContainer, voteButtonInactive } ,
162+ } ,
163+ } ,
164+ } ,
165+ } = useTheme ( ) ;
166+
167+ const toggleVote = useCallback ( async ( ) => {
168+ if ( ownVotesByOptionId [ option . id ] ) {
169+ await poll . removeVote ( ownVotesByOptionId [ option . id ] ?. id , message . id ) ;
170+ } else {
171+ await poll . castVote ( option . id , message . id ) ;
172+ }
173+ } , [ message . id , option . id , ownVotesByOptionId , poll ] ) ;
174+
175+ const onPressHandler = useCallback ( ( ) => {
176+ if ( onPress ) {
177+ onPress ( { message, poll } ) ;
178+ return ;
179+ }
180+
181+ toggleVote ( ) ;
182+ } , [ message , onPress , poll , toggleVote ] ) ;
183+
184+ return ownCapabilities . castPollVote && ! isClosed ? (
185+ < Pressable
186+ onPress = { onPressHandler }
187+ style = { ( { pressed } ) => [
188+ { opacity : pressed ? 0.5 : 1 } ,
189+ styles . voteContainer ,
190+ {
191+ backgroundColor : ownVotesByOptionId [ option . id ]
192+ ? voteButtonActive || accent_dark_blue
193+ : 'transparent' ,
194+ borderColor : ownVotesByOptionId [ option . id ]
195+ ? voteButtonActive || accent_dark_blue
196+ : voteButtonInactive || disabled ,
197+ } ,
198+ voteButtonContainer ,
199+ ] }
200+ >
201+ { ownVotesByOptionId [ option . id ] ? < Check height = { 15 } pathFill = 'white' width = { 20 } /> : null }
202+ </ Pressable >
203+ ) : null ;
204+ } ;
205+
144206const styles = StyleSheet . create ( {
145207 allOptionsListContainer : {
146208 borderRadius : 12 ,
@@ -162,6 +224,14 @@ const styles = StyleSheet.create({
162224 fontSize : 16 ,
163225 marginLeft : 4 ,
164226 } ,
227+ voteContainer : {
228+ alignItems : 'center' ,
229+ borderRadius : 18 ,
230+ borderWidth : 1 ,
231+ height : 18 ,
232+ justifyContent : 'center' ,
233+ width : 18 ,
234+ } ,
165235 votesContainer : { flexDirection : 'row' , marginLeft : 4 } ,
166236 wrapper : { marginTop : 8 , paddingVertical : 8 } ,
167237} ) ;
0 commit comments