import React, { useCallback, useMemo } from 'react' import { ActionSheetIOS, Pressable, StyleSheet, Text, View } from 'react-native' import { useMutation, useQueryClient } from 'react-query' import { Feather } from '@expo/vector-icons' import client from '@api/client' import { useTheme } from '@utils/styles/ThemeManager' import { toast } from '@components/toast' import { StyleConstants } from '@utils/styles/constants' import { useNavigation } from '@react-navigation/native' import { findIndex } from 'lodash' import { TimelineData } from '../../Timeline' const fireMutation = async ({ id, type, stateKey, prevState }: { id: string type: 'favourite' | 'reblog' | 'bookmark' stateKey: 'favourited' | 'reblogged' | 'bookmarked' prevState?: boolean }) => { let res switch (type) { case 'favourite': case 'reblog': case 'bookmark': res = await client({ method: 'post', instance: 'local', url: `statuses/${id}/${prevState ? 'un' : ''}${type}` }) // bug in response from Mastodon if (!res.body[stateKey] === prevState) { toast({ type: 'success', content: '功能成功' }) return Promise.resolve(res.body) } else { toast({ type: 'error', content: '功能错误' }) return Promise.reject() } break } } export interface Props { queryKey: QueryKey.Timeline status: Mastodon.Status reblog: boolean } const TimelineActions: React.FC = ({ queryKey, status, reblog }) => { const navigation = useNavigation() const { theme } = useTheme() const iconColor = theme.secondary const iconColorAction = (state: boolean) => state ? theme.primary : theme.secondary const queryClient = useQueryClient() const { mutate } = useMutation(fireMutation, { onMutate: ({ id, type, stateKey, prevState }) => { queryClient.cancelQueries(queryKey) const oldData = queryClient.getQueryData(queryKey) switch (type) { case 'favourite': case 'reblog': case 'bookmark': queryClient.setQueryData(queryKey, old => { let tootIndex = -1 const pageIndex = findIndex(old?.pages, page => { const tempIndex = findIndex(page.toots, [ queryKey[0] === 'Notifications' ? 'status.id' : reblog ? 'reblog.id' : 'id', id ]) if (tempIndex >= 0) { tootIndex = tempIndex return true } else { return false } }) if (pageIndex >= 0 && tootIndex >= 0) { if ( (type === 'favourite' && queryKey[0] === 'Favourites') || (type === 'bookmark' && queryKey[0] === 'Bookmarks') ) { old!.pages[pageIndex].toots.splice(tootIndex, 1) } else { if (queryKey[0] === 'Notifications') { old!.pages[pageIndex].toots[tootIndex].status[stateKey] = typeof prevState === 'boolean' ? !prevState : true } else { if (reblog) { old!.pages[pageIndex].toots[tootIndex].reblog![stateKey] = typeof prevState === 'boolean' ? !prevState : true } else { old!.pages[pageIndex].toots[tootIndex][stateKey] = typeof prevState === 'boolean' ? !prevState : true } } } } return old }) break } return oldData }, onError: (err, _, oldData) => { toast({ type: 'error', content: '请重试' }) queryClient.setQueryData(queryKey, oldData) } }) const onPressReply = useCallback( () => navigation.navigate('Screen-Shared-Compose', { type: 'reply', incomingStatus: status, visibilityLock: status.visibility === 'direct' }), [] ) const onPressReblog = useCallback( () => mutate({ id: status.id, type: 'reblog', stateKey: 'reblogged', prevState: status.reblogged }), [status.reblogged] ) const onPressFavourite = useCallback( () => mutate({ id: status.id, type: 'favourite', stateKey: 'favourited', prevState: status.favourited }), [status.favourited] ) const onPressBookmark = useCallback( () => mutate({ id: status.id, type: 'bookmark', stateKey: 'bookmarked', prevState: status.bookmarked }), [status.bookmarked] ) const onPressShare = useCallback( () => ActionSheetIOS.showShareActionSheetWithOptions( { url: status.uri, excludedActivityTypes: [ 'com.apple.UIKit.activity.Mail', 'com.apple.UIKit.activity.Print', 'com.apple.UIKit.activity.SaveToCameraRoll', 'com.apple.UIKit.activity.OpenInIBooks' ] }, () => {}, () => {} ), [] ) const childrenReply = useMemo( () => ( <> {status.replies_count > 0 && ( {status.replies_count} )} ), [status.replies_count] ) const childrenReblog = useMemo( () => ( ), [status.reblogged] ) const childrenFavourite = useMemo( () => ( ), [status.favourited] ) const childrenBookmark = useMemo( () => ( ), [status.bookmarked] ) const childrenShare = useMemo( () => ( ), [] ) return ( <> ) } const styles = StyleSheet.create({ actions: { width: '100%', flex: 1, flexDirection: 'row', marginTop: StyleConstants.Spacing.M }, action: { width: '20%', flexDirection: 'row', justifyContent: 'center' } }) export default TimelineActions