import { Feather } from '@expo/vector-icons' import React, { useMemo, useState } from 'react' import { Pressable, StyleSheet, Text, View } from 'react-native' import { useMutation, useQueryCache } from 'react-query' import client from 'src/api/client' import Button from 'src/components/Button' import { toast } from 'src/components/toast' import relativeTime from 'src/utils/relativeTime' import { StyleConstants } from 'src/utils/styles/constants' import { useTheme } from 'src/utils/styles/ThemeManager' import Emojis from './Emojis' const fireMutation = async ({ id, options }: { id: string options: { [key: number]: boolean } }) => { const formData = new FormData() Object.keys(options).forEach(option => { // @ts-ignore if (options[option]) { formData.append('choices[]', option) } }) console.log(formData) const res = await client({ method: 'post', instance: 'local', endpoint: `polls/${id}/votes`, body: formData }) if (res.body.id === id) { toast({ type: 'success', content: '投票成功成功' }) return Promise.resolve() } else { toast({ type: 'error', content: '隐藏域名失败,请重试', autoHide: false }) return Promise.reject() } } export interface Props { queryKey: App.QueryKey poll: Mastodon.Poll } const TimelinePoll: React.FC = ({ queryKey, poll }) => { console.log('render poll ' + Math.random()) console.log(poll) const { theme } = useTheme() const queryCache = useQueryCache() const [mutateAction] = useMutation(fireMutation, { onMutate: ({ id, options }) => { queryCache.cancelQueries(queryKey) const oldData = queryCache.getQueryData(queryKey) queryCache.setQueryData(queryKey, old => (old as {}[]).map((paging: any) => ({ toots: paging.toots.map((toot: any) => { if (toot.poll?.id === id) { const poll = toot.poll console.log('update votes') console.log( Object.keys(options) .filter(option => options[option]) .map(option => parseInt(option)) ) console.log(toot.poll) toot.poll = { ...toot.poll, voters_count: poll.voters_count ? poll.voters_count + 1 : 1, voted: true, own_votes: [ Object.keys(options) // @ts-ignore .filter(option => options[option]) .map(option => parseInt(option)) ] } console.log(toot.poll) } return toot }), pointer: paging.pointer })) ) return oldData }, onError: (err, _, oldData) => { toast({ type: 'error', content: '请重试' }) queryCache.setQueryData(queryKey, oldData) } }) const pollExpiration = useMemo(() => { // how many voted if (poll.expired) { return ( 投票已结束 ) } else { return ( 截止至{relativeTime(poll.expires_at)} ) } }, []) const [singleOptions, setSingleOptions] = useState({ ...[false, false, false, false].slice(0, poll.options.length) }) const [multipleOptions, setMultipleOptions] = useState({ ...[false, false, false, false].slice(0, poll.options.length) }) const isSelected = (index: number) => { if (poll.multiple) { return multipleOptions[index] ? 'check-square' : 'square' } else { return singleOptions[index] ? 'check-circle' : 'circle' } } return ( {poll.options.map((option, index) => poll.voted ? ( {poll.own_votes!.includes(index) && ( )} {Math.round((option.votes_count / poll.votes_count) * 100)}% ) : ( { if (poll.multiple) { setMultipleOptions({ ...multipleOptions, [index]: !multipleOptions[index] }) } else { setSingleOptions({ ...[ index === 0, index === 1, index === 2, index === 3 ].slice(0, poll.options.length) }) } }} > ) )} {!poll.expired && !poll.own_votes?.length && (