Skip to content
This repository was archived by the owner on Oct 19, 2024. It is now read-only.

Commit 4cbba77

Browse files
committed
Account actions doen except reports
1 parent c08c25e commit 4cbba77

File tree

2 files changed

+268
-11
lines changed

2 files changed

+268
-11
lines changed

src/components/Status/Header.tsx

Lines changed: 265 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,124 @@
11
import React, { useEffect, useState } from 'react'
2-
import { StyleSheet, Text, View } from 'react-native'
2+
import { Modal, Pressable, StyleSheet, Text, View } from 'react-native'
33
import { useNavigation } from '@react-navigation/native'
4+
import { Feather } from '@expo/vector-icons'
5+
import Toast from 'react-native-toast-message'
6+
import { useMutation, useQueryCache } from 'react-query'
47

58
import Emojis from './Emojis'
69
import relativeTime from 'src/utils/relativeTime'
10+
import client from 'src/api/client'
11+
import { useSelector } from 'react-redux'
12+
13+
const fireMutation = async ({
14+
id,
15+
type,
16+
stateKey
17+
}: {
18+
id: string
19+
type: 'mute' | 'block' | 'domain_blocks' | 'reports'
20+
stateKey?: 'muting' | 'blocking'
21+
}) => {
22+
let res
23+
switch (type) {
24+
case 'mute':
25+
case 'block':
26+
res = await client({
27+
method: 'post',
28+
instance: 'local',
29+
endpoint: `accounts/${id}/${type}`
30+
})
31+
32+
if (res.body[stateKey] === true) {
33+
Toast.show({
34+
type: 'success',
35+
position: 'bottom',
36+
text1: '功能成功',
37+
visibilityTime: 2000,
38+
autoHide: true,
39+
bottomOffset: 65
40+
})
41+
return Promise.resolve()
42+
} else {
43+
Toast.show({
44+
type: 'error',
45+
position: 'bottom',
46+
text1: '请重试',
47+
autoHide: false,
48+
bottomOffset: 65
49+
})
50+
return Promise.reject()
51+
}
52+
break
53+
case 'domain_blocks':
54+
res = await client({
55+
method: 'post',
56+
instance: 'local',
57+
endpoint: `domain_blocks`,
58+
query: {
59+
domain: id || ''
60+
}
61+
})
62+
63+
if (!res.body.error) {
64+
Toast.show({
65+
type: 'success',
66+
position: 'bottom',
67+
text1: '隐藏域名成功',
68+
visibilityTime: 2000,
69+
autoHide: true,
70+
bottomOffset: 65
71+
})
72+
return Promise.resolve()
73+
} else {
74+
Toast.show({
75+
type: 'error',
76+
position: 'bottom',
77+
text1: '隐藏域名失败,请重试',
78+
autoHide: false,
79+
bottomOffset: 65
80+
})
81+
return Promise.reject()
82+
}
83+
break
84+
// case 'reports':
85+
// res = await client({
86+
// method: 'post',
87+
// instance: 'local',
88+
// endpoint: `reports`,
89+
// query: {
90+
// domain: id || ''
91+
// }
92+
// })
93+
94+
// if (!res.body.error) {
95+
// Toast.show({
96+
// type: 'success',
97+
// position: 'bottom',
98+
// text1: '隐藏域名成功',
99+
// visibilityTime: 2000,
100+
// autoHide: true,
101+
// bottomOffset: 65
102+
// })
103+
// return Promise.resolve()
104+
// } else {
105+
// Toast.show({
106+
// type: 'error',
107+
// position: 'bottom',
108+
// text1: '隐藏域名失败,请重试',
109+
// autoHide: false,
110+
// bottomOffset: 65
111+
// })
112+
// return Promise.reject()
113+
// }
114+
// break
115+
}
116+
}
7117

8118
export interface Props {
119+
queryKey: store.QueryKey
120+
accountId: string
121+
domain: string
9122
name: string
10123
emojis?: mastodon.Emoji[]
11124
account: string
@@ -14,14 +127,55 @@ export interface Props {
14127
}
15128

16129
const Header: React.FC<Props> = ({
130+
queryKey,
131+
accountId,
132+
domain,
17133
name,
18134
emojis,
19135
account,
20136
created_at,
21137
application
22138
}) => {
23139
const navigation = useNavigation()
140+
const localAccountId = useSelector(state => state.instanceInfo.localAccountId)
141+
const localDomain = useSelector(state => state.instanceInfo.local)
24142
const [since, setSince] = useState(relativeTime(created_at))
143+
const [modalVisible, setModalVisible] = useState(false)
144+
145+
const queryCache = useQueryCache()
146+
const [mutateAction] = useMutation(fireMutation, {
147+
onMutate: () => {
148+
queryCache.cancelQueries(queryKey)
149+
const prevData = queryCache.getQueryData(queryKey)
150+
return prevData
151+
},
152+
onSuccess: (newData, params) => {
153+
if (params.type === 'domain_blocks') {
154+
console.log('clearing cache')
155+
queryCache.invalidateQueries(['Following', { page: 'Following' }])
156+
}
157+
// queryCache.setQueryData(queryKey, (oldData: any) => {
158+
// oldData &&
159+
// oldData.map((paging: any) => {
160+
// paging.toots.map(
161+
// (status: mastodon.Status | mastodon.Notification, i: number) => {
162+
// if (status.id === newData.id) {
163+
// paging.toots[i] = newData
164+
// }
165+
// }
166+
// )
167+
// })
168+
// return oldData
169+
// })
170+
return Promise.resolve()
171+
},
172+
onError: (err, variables, prevData) => {
173+
queryCache.setQueryData(queryKey, prevData)
174+
},
175+
onSettled: () => {
176+
queryCache.invalidateQueries(queryKey)
177+
}
178+
})
25179

26180
// causing full re-render
27181
useEffect(() => {
@@ -32,18 +186,26 @@ const Header: React.FC<Props> = ({
32186

33187
return (
34188
<View>
35-
<View style={styles.names}>
189+
<View style={styles.nameAndAction}>
36190
<View style={styles.name}>
37191
{emojis ? (
38192
<Emojis content={name} emojis={emojis} dimension={14} />
39193
) : (
40-
<Text>{name}</Text>
194+
<Text numberOfLines={1}>{name}</Text>
41195
)}
42196
</View>
43-
<Text style={styles.account} numberOfLines={1}>
44-
@{account}
45-
</Text>
197+
{accountId !== localAccountId && domain !== localDomain && (
198+
<Pressable
199+
style={styles.action}
200+
onPress={() => setModalVisible(true)}
201+
>
202+
<Feather name='more-horizontal' color='gray' />
203+
</Pressable>
204+
)}
46205
</View>
206+
<Text style={styles.account} numberOfLines={1}>
207+
@{account}
208+
</Text>
47209
<View style={styles.meta}>
48210
<View>
49211
<Text style={styles.created_at}>{since}</Text>
@@ -63,21 +225,98 @@ const Header: React.FC<Props> = ({
63225
</View>
64226
)}
65227
</View>
228+
229+
<Modal
230+
animationType='fade'
231+
presentationStyle='overFullScreen'
232+
transparent
233+
visible={modalVisible}
234+
>
235+
<Pressable
236+
style={styles.modalBackground}
237+
onPress={() => setModalVisible(false)}
238+
>
239+
<View style={styles.modalSheet}>
240+
{accountId !== localAccountId && (
241+
<Pressable
242+
onPress={() => {
243+
setModalVisible(false)
244+
mutateAction({
245+
id: accountId,
246+
type: 'mute',
247+
stateKey: 'muting'
248+
})
249+
}}
250+
>
251+
<Text>静音用户</Text>
252+
</Pressable>
253+
)}
254+
{accountId !== localAccountId && (
255+
<Pressable
256+
onPress={() => {
257+
setModalVisible(false)
258+
mutateAction({
259+
id: accountId,
260+
type: 'block',
261+
stateKey: 'blocking'
262+
})
263+
}}
264+
>
265+
<Text>屏蔽用户</Text>
266+
</Pressable>
267+
)}
268+
{domain !== localDomain && (
269+
<Pressable
270+
onPress={() => {
271+
setModalVisible(false)
272+
mutateAction({
273+
id: domain,
274+
type: 'domain_blocks'
275+
})
276+
}}
277+
>
278+
<Text>屏蔽域名</Text>
279+
</Pressable>
280+
)}
281+
{accountId !== localAccountId && (
282+
<Pressable
283+
onPress={() => {
284+
setModalVisible(false)
285+
mutateAction({
286+
id: accountId,
287+
type: 'reports'
288+
})
289+
}}
290+
>
291+
<Text>举报用户</Text>
292+
</Pressable>
293+
)}
294+
</View>
295+
</Pressable>
296+
</Modal>
66297
</View>
67298
)
68299
}
69300

70301
const styles = StyleSheet.create({
71-
names: {
72-
flexDirection: 'row'
302+
nameAndAction: {
303+
width: '100%',
304+
flexDirection: 'row',
305+
justifyContent: 'space-between'
73306
},
74307
name: {
75308
flexDirection: 'row',
76-
marginRight: 8
309+
marginRight: 8,
310+
fontWeight: '900'
311+
},
312+
action: {
313+
width: 14,
314+
height: 14,
315+
marginLeft: 8
77316
},
78317
account: {
79-
fontSize: 12,
80-
lineHeight: 14
318+
lineHeight: 14,
319+
flexShrink: 1
81320
},
82321
meta: {
83322
flexDirection: 'row'
@@ -92,6 +331,21 @@ const styles = StyleSheet.create({
92331
application: {
93332
fontSize: 12,
94333
lineHeight: 11
334+
},
335+
modalBackground: {
336+
width: '100%',
337+
height: '100%',
338+
backgroundColor: 'rgba(0, 0, 0, 0.75)',
339+
flex: 1,
340+
flexDirection: 'row',
341+
justifyContent: 'center',
342+
alignItems: 'flex-end'
343+
},
344+
modalSheet: {
345+
width: '100%',
346+
height: '50%',
347+
backgroundColor: 'white',
348+
flex: 1
95349
}
96350
})
97351

src/components/StatusInTimeline.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,9 @@ const StatusInTimeline: React.FC<Props> = ({ status, queryKey }) => {
3838
/>
3939
<View style={styles.details}>
4040
<Header
41+
queryKey={queryKey}
42+
accountId={actualStatus.account.id}
43+
domain={actualStatus.uri.split(new RegExp(/\/\/(.*?)\//))[1]}
4144
name={
4245
actualStatus.account.display_name ||
4346
actualStatus.account.username

0 commit comments

Comments
 (0)