From 4cbba779c5eda8636d3f13765630320fb2d4cc75 Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Fri, 6 Nov 2020 18:40:14 +0100 Subject: [PATCH] Account actions doen except reports --- src/components/Status/Header.tsx | 276 ++++++++++++++++++++++++++-- src/components/StatusInTimeline.tsx | 3 + 2 files changed, 268 insertions(+), 11 deletions(-) diff --git a/src/components/Status/Header.tsx b/src/components/Status/Header.tsx index dad96076..90931e7b 100644 --- a/src/components/Status/Header.tsx +++ b/src/components/Status/Header.tsx @@ -1,11 +1,124 @@ import React, { useEffect, useState } from 'react' -import { StyleSheet, Text, View } from 'react-native' +import { Modal, Pressable, StyleSheet, Text, View } from 'react-native' import { useNavigation } from '@react-navigation/native' +import { Feather } from '@expo/vector-icons' +import Toast from 'react-native-toast-message' +import { useMutation, useQueryCache } from 'react-query' import Emojis from './Emojis' import relativeTime from 'src/utils/relativeTime' +import client from 'src/api/client' +import { useSelector } from 'react-redux' + +const fireMutation = async ({ + id, + type, + stateKey +}: { + id: string + type: 'mute' | 'block' | 'domain_blocks' | 'reports' + stateKey?: 'muting' | 'blocking' +}) => { + let res + switch (type) { + case 'mute': + case 'block': + res = await client({ + method: 'post', + instance: 'local', + endpoint: `accounts/${id}/${type}` + }) + + if (res.body[stateKey] === true) { + Toast.show({ + type: 'success', + position: 'bottom', + text1: '功能成功', + visibilityTime: 2000, + autoHide: true, + bottomOffset: 65 + }) + return Promise.resolve() + } else { + Toast.show({ + type: 'error', + position: 'bottom', + text1: '请重试', + autoHide: false, + bottomOffset: 65 + }) + return Promise.reject() + } + break + case 'domain_blocks': + res = await client({ + method: 'post', + instance: 'local', + endpoint: `domain_blocks`, + query: { + domain: id || '' + } + }) + + if (!res.body.error) { + Toast.show({ + type: 'success', + position: 'bottom', + text1: '隐藏域名成功', + visibilityTime: 2000, + autoHide: true, + bottomOffset: 65 + }) + return Promise.resolve() + } else { + Toast.show({ + type: 'error', + position: 'bottom', + text1: '隐藏域名失败,请重试', + autoHide: false, + bottomOffset: 65 + }) + return Promise.reject() + } + break + // case 'reports': + // res = await client({ + // method: 'post', + // instance: 'local', + // endpoint: `reports`, + // query: { + // domain: id || '' + // } + // }) + + // if (!res.body.error) { + // Toast.show({ + // type: 'success', + // position: 'bottom', + // text1: '隐藏域名成功', + // visibilityTime: 2000, + // autoHide: true, + // bottomOffset: 65 + // }) + // return Promise.resolve() + // } else { + // Toast.show({ + // type: 'error', + // position: 'bottom', + // text1: '隐藏域名失败,请重试', + // autoHide: false, + // bottomOffset: 65 + // }) + // return Promise.reject() + // } + // break + } +} export interface Props { + queryKey: store.QueryKey + accountId: string + domain: string name: string emojis?: mastodon.Emoji[] account: string @@ -14,6 +127,9 @@ export interface Props { } const Header: React.FC = ({ + queryKey, + accountId, + domain, name, emojis, account, @@ -21,7 +137,45 @@ const Header: React.FC = ({ application }) => { const navigation = useNavigation() + const localAccountId = useSelector(state => state.instanceInfo.localAccountId) + const localDomain = useSelector(state => state.instanceInfo.local) const [since, setSince] = useState(relativeTime(created_at)) + const [modalVisible, setModalVisible] = useState(false) + + const queryCache = useQueryCache() + const [mutateAction] = useMutation(fireMutation, { + onMutate: () => { + queryCache.cancelQueries(queryKey) + const prevData = queryCache.getQueryData(queryKey) + return prevData + }, + onSuccess: (newData, params) => { + if (params.type === 'domain_blocks') { + console.log('clearing cache') + queryCache.invalidateQueries(['Following', { page: 'Following' }]) + } + // queryCache.setQueryData(queryKey, (oldData: any) => { + // oldData && + // oldData.map((paging: any) => { + // paging.toots.map( + // (status: mastodon.Status | mastodon.Notification, i: number) => { + // if (status.id === newData.id) { + // paging.toots[i] = newData + // } + // } + // ) + // }) + // return oldData + // }) + return Promise.resolve() + }, + onError: (err, variables, prevData) => { + queryCache.setQueryData(queryKey, prevData) + }, + onSettled: () => { + queryCache.invalidateQueries(queryKey) + } + }) // causing full re-render useEffect(() => { @@ -32,18 +186,26 @@ const Header: React.FC = ({ return ( - + {emojis ? ( ) : ( - {name} + {name} )} - - @{account} - + {accountId !== localAccountId && domain !== localDomain && ( + setModalVisible(true)} + > + + + )} + + @{account} + {since} @@ -63,21 +225,98 @@ const Header: React.FC = ({ )} + + + setModalVisible(false)} + > + + {accountId !== localAccountId && ( + { + setModalVisible(false) + mutateAction({ + id: accountId, + type: 'mute', + stateKey: 'muting' + }) + }} + > + 静音用户 + + )} + {accountId !== localAccountId && ( + { + setModalVisible(false) + mutateAction({ + id: accountId, + type: 'block', + stateKey: 'blocking' + }) + }} + > + 屏蔽用户 + + )} + {domain !== localDomain && ( + { + setModalVisible(false) + mutateAction({ + id: domain, + type: 'domain_blocks' + }) + }} + > + 屏蔽域名 + + )} + {accountId !== localAccountId && ( + { + setModalVisible(false) + mutateAction({ + id: accountId, + type: 'reports' + }) + }} + > + 举报用户 + + )} + + + ) } const styles = StyleSheet.create({ - names: { - flexDirection: 'row' + nameAndAction: { + width: '100%', + flexDirection: 'row', + justifyContent: 'space-between' }, name: { flexDirection: 'row', - marginRight: 8 + marginRight: 8, + fontWeight: '900' + }, + action: { + width: 14, + height: 14, + marginLeft: 8 }, account: { - fontSize: 12, - lineHeight: 14 + lineHeight: 14, + flexShrink: 1 }, meta: { flexDirection: 'row' @@ -92,6 +331,21 @@ const styles = StyleSheet.create({ application: { fontSize: 12, lineHeight: 11 + }, + modalBackground: { + width: '100%', + height: '100%', + backgroundColor: 'rgba(0, 0, 0, 0.75)', + flex: 1, + flexDirection: 'row', + justifyContent: 'center', + alignItems: 'flex-end' + }, + modalSheet: { + width: '100%', + height: '50%', + backgroundColor: 'white', + flex: 1 } }) diff --git a/src/components/StatusInTimeline.tsx b/src/components/StatusInTimeline.tsx index 6f8f0972..f162d670 100644 --- a/src/components/StatusInTimeline.tsx +++ b/src/components/StatusInTimeline.tsx @@ -38,6 +38,9 @@ const StatusInTimeline: React.FC = ({ status, queryKey }) => { />