import { useNavigation } from '@react-navigation/native' import React from 'react' import { Alert } from 'react-native' import { useMutation, useQueryCache } from 'react-query' import client from '@api/client' import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu' import { toast } from '@components/toast' import getCurrentTab from '@utils/getCurrentTab' 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: App.QueryKey status: Mastodon.Status setBottomSheetVisible: React.Dispatch> } const HeaderDefaultActionsStatus: React.FC = ({ queryKey, status, setBottomSheetVisible }) => { const navigation = useNavigation() const queryCache = useQueryCache() const [mutateAction] = useMutation(fireMutation, { onMutate: ({ id, type, stateKey, prevState }) => { queryCache.cancelQueries(queryKey) const oldData = queryCache.getQueryData(queryKey) switch (type) { case 'mute': case 'pin': queryCache.setQueryData(queryKey, old => (old as {}[]).map((paging: any) => ({ toots: paging.toots.map((toot: any) => { if (toot.id === id) { toot[stateKey] = typeof prevState === 'boolean' ? !prevState : true } return toot }), pointer: paging.pointer })) ) break case 'delete': queryCache.setQueryData(queryKey, old => (old as {}[]).map((paging: any) => ({ toots: paging.toots.filter((toot: any) => toot.id !== id), pointer: paging.pointer })) ) break } return oldData }, onError: (err, _, oldData) => { toast({ type: 'error', content: '请重试' }) queryCache.setQueryData(queryKey, oldData) } }) return ( { setBottomSheetVisible(false) mutateAction({ 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 => { queryCache.invalidateQueries(queryKey) setBottomSheetVisible(false) navigation.navigate(getCurrentTab(navigation), { screen: 'Screen-Shared-Compose', params: { type: 'edit', incomingStatus: res.body } }) }) .catch(() => { toast({ type: 'error', content: '删除失败' }) }) } } ] ) }} iconFront='trash' title='删除并重新编辑' /> { setBottomSheetVisible(false) mutateAction({ 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) mutateAction({ type: 'pin', id: status.id, stateKey: 'pinned', prevState: status.pinned }) }} iconFront='anchor' title={status.pinned ? '取消置顶' : '置顶'} /> )} ) } export default HeaderDefaultActionsStatus