import { useNavigation } from '@react-navigation/native' import React from 'react' import { Alert } from 'react-native' import { useMutation, useQueryClient } from 'react-query' import client from '@api/client' import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu' import { toast } from '@components/toast' import { TimelineData } from '@root/components/Timelines/Timeline' import { findIndex } from 'lodash' const fireMutation = async ({ id, type, stateKey, prevState }: { id: string type: 'mute' | 'pin' | 'delete' stateKey: 'muted' | 'pinned' | 'id' prevState?: boolean }) => { let res switch (type) { case 'mute': case 'pin': 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 case 'delete': res = await client({ method: 'delete', instance: 'local', url: `statuses/${id}` }) if (res.body[stateKey] === id) { 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 setBottomSheetVisible: React.Dispatch> } const HeaderDefaultActionsStatus: React.FC = ({ queryKey, status, setBottomSheetVisible }) => { const navigation = useNavigation() const queryClient = useQueryClient() const { mutate } = useMutation(fireMutation, { onMutate: ({ id, type, stateKey, prevState }) => { queryClient.cancelQueries(queryKey) const oldData = queryClient.getQueryData(queryKey) switch (type) { case 'mute': case 'pin': queryClient.setQueryData(queryKey, old => { let tootIndex = -1 const pageIndex = findIndex(old?.pages, page => { const tempIndex = findIndex(page.toots, ['id', id]) if (tempIndex >= 0) { tootIndex = tempIndex return true } else { return false } }) if (pageIndex >= 0 && tootIndex >= 0) { old!.pages[pageIndex].toots[tootIndex][ stateKey as 'muted' | 'pinned' ] = typeof prevState === 'boolean' ? !prevState : true } return old }) break case 'delete': queryClient.setQueryData( queryKey, old => old && { ...old, pages: old?.pages.map(paging => ({ ...paging, toots: paging.toots.filter(toot => toot.id !== id) })) } ) break } return oldData }, onError: (err, _, oldData) => { toast({ type: 'error', content: '请重试' }) queryClient.setQueryData(queryKey, oldData) } }) return ( { setBottomSheetVisible(false) mutate({ type: 'delete', id: status.id, stateKey: 'id' }) }} iconFront='trash' title='删除嘟嘟' /> { Alert.alert( '确认删除嘟嘟?', '你确定要删除这条嘟文并重新编辑它吗?所有相关的转嘟和喜欢都会被清除,回复将会失去关联。', [ { text: '取消', style: 'cancel' }, { text: '删除并重新编辑', style: 'destructive', onPress: async () => { await client({ method: 'delete', instance: 'local', url: `statuses/${status.id}` }) .then(res => { queryClient.invalidateQueries(queryKey) setBottomSheetVisible(false) navigation.navigate('Screen-Shared-Compose', { type: 'edit', incomingStatus: res.body }) }) .catch(() => { toast({ type: 'error', content: '删除失败' }) }) } } ] ) }} iconFront='trash' title='删除并重新编辑' /> { setBottomSheetVisible(false) mutate({ type: 'mute', id: status.id, stateKey: 'muted', prevState: status.muted }) }} iconFront='volume-x' title={status.muted ? '取消静音对话' : '静音对话'} /> {/* Also note that reblogs cannot be pinned. */} {(status.visibility === 'public' || status.visibility === 'unlisted') && ( { setBottomSheetVisible(false) mutate({ type: 'pin', id: status.id, stateKey: 'pinned', prevState: status.pinned }) }} iconFront='anchor' title={status.pinned ? '取消置顶' : '置顶'} /> )} ) } export default HeaderDefaultActionsStatus