tooot/src/components/contextMenu/account.tsx

239 lines
7.5 KiB
TypeScript

import haptics from '@components/haptics'
import { displayMessage } from '@components/Message'
import { useNavigation } from '@react-navigation/native'
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
import { TabSharedStackParamList } from '@utils/navigation/navigators'
import {
QueryKeyRelationship,
useRelationshipMutation,
useRelationshipQuery
} from '@utils/queryHooks/relationship'
import {
MutationVarsTimelineUpdateAccountProperty,
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
import { getInstanceAccount } from '@utils/slices/instancesSlice'
import { useTheme } from '@utils/styles/ThemeManager'
import { useEffect, useState } from 'react'
import { useTranslation } from 'react-i18next'
import { Platform } from 'react-native'
import { useQueryClient } from 'react-query'
import { useSelector } from 'react-redux'
const menuAccount = ({
type,
openChange,
account,
queryKey,
rootQueryKey
}: {
type: 'status' | 'account' // Where the action is coming from
openChange: boolean
account?: Pick<Mastodon.Account, 'id' | 'username'>
queryKey?: QueryKeyTimeline
rootQueryKey?: QueryKeyTimeline
}): ContextMenu[][] => {
if (!account) return []
const navigation =
useNavigation<NativeStackNavigationProp<TabSharedStackParamList, any, undefined>>()
const { theme } = useTheme()
const { t } = useTranslation('componentContextMenu')
const menus: ContextMenu[][] = [[]]
const instanceAccount = useSelector(getInstanceAccount, (prev, next) => prev.id === next.id)
const ownAccount = instanceAccount?.id === account.id
const [enabled, setEnabled] = useState(openChange)
useEffect(() => {
if (!ownAccount && enabled === false && openChange === true) {
setEnabled(true)
}
}, [openChange, enabled])
const { data, isFetching } = useRelationshipQuery({ id: account.id, options: { enabled } })
const queryClient = useQueryClient()
const timelineMutation = useTimelineMutation({
onSuccess: (_, params) => {
queryClient.refetchQueries(['Relationship', { id: account.id }])
const theParams = params as MutationVarsTimelineUpdateAccountProperty
displayMessage({
theme,
type: 'success',
message: t('common:message.success.message', {
function: t(`account.${theParams.payload.property}.action`, {
...(theParams.payload.property !== 'reports' && {
context: (theParams.payload.currentValue || false).toString()
})
})
})
})
},
onError: (err: any, params) => {
const theParams = params as MutationVarsTimelineUpdateAccountProperty
displayMessage({
theme,
type: 'error',
message: t('common:message.error.message', {
function: t(`account.${theParams.payload.property}.action`, {
...(theParams.payload.property !== 'reports' && {
context: (theParams.payload.currentValue || false).toString()
})
})
}),
...(err.status &&
typeof err.status === 'number' &&
err.data &&
err.data.error &&
typeof err.data.error === 'string' && {
description: err.data.error
})
})
},
onSettled: () => {
queryKey && queryClient.invalidateQueries(queryKey)
rootQueryKey && queryClient.invalidateQueries(rootQueryKey)
}
})
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id: account.id }]
const relationshipMutation = useRelationshipMutation({
onSuccess: (res, { payload: { action } }) => {
haptics('Success')
queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [res])
if (action === 'block') {
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Following' }]
queryClient.invalidateQueries(queryKey)
}
},
onError: (err: any, { payload: { action } }) => {
displayMessage({
theme,
type: 'error',
message: t('common:message.error.message', {
function: t(`${action}.function`)
}),
...(err.status &&
typeof err.status === 'number' &&
err.data &&
err.data.error &&
typeof err.data.error === 'string' && {
description: err.data.error
})
})
}
})
if (!ownAccount && Platform.OS !== 'android' && type !== 'account') {
menus[0].push({
key: 'account-following',
item: {
onSelect: () =>
data &&
relationshipMutation.mutate({
id: account.id,
type: 'outgoing',
payload: { action: 'follow', state: !data?.requested ? data.following : true }
}),
disabled: !data || isFetching,
destructive: false,
hidden: false
},
title: !data?.requested
? t('account.following.action', {
context: (data?.following || false).toString()
})
: t('componentRelationship:button.requested'),
icon: !data?.requested
? data?.following
? 'person.badge.minus'
: 'person.badge.plus'
: 'person.badge.minus'
})
}
if (!ownAccount) {
menus[0].push({
key: 'account-list',
item: {
onSelect: () => navigation.navigate('Tab-Shared-Account-In-Lists', { account }),
disabled: Platform.OS !== 'android' ? !data || isFetching : false,
destructive: false,
hidden: isFetching ? false : !data?.following
},
title: t('account.inLists'),
icon: 'checklist'
})
menus[0].push({
key: 'account-mute',
item: {
onSelect: () =>
timelineMutation.mutate({
type: 'updateAccountProperty',
queryKey,
id: account.id,
payload: { property: 'mute', currentValue: data?.muting }
}),
disabled: Platform.OS !== 'android' ? !data || isFetching : false,
destructive: false,
hidden: false
},
title: t('account.mute.action', {
context: (data?.muting || false).toString()
}),
icon: data?.muting ? 'eye' : 'eye.slash'
})
}
!ownAccount &&
menus.push([
{
key: 'account-block',
item: {
onSelect: () =>
timelineMutation.mutate({
type: 'updateAccountProperty',
queryKey,
id: account.id,
payload: { property: 'block', currentValue: data?.blocking }
}),
disabled: Platform.OS !== 'android' ? !data || isFetching : false,
destructive: !data?.blocking,
hidden: false
},
title: t('account.block.action', {
context: (data?.blocking || false).toString()
}),
icon: data?.blocking ? 'checkmark.circle' : 'xmark.circle'
},
{
key: 'account-reports',
item: {
onSelect: () => {
timelineMutation.mutate({
type: 'updateAccountProperty',
queryKey,
id: account.id,
payload: { property: 'reports' }
})
timelineMutation.mutate({
type: 'updateAccountProperty',
queryKey,
id: account.id,
payload: { property: 'block', currentValue: false }
})
},
disabled: false,
destructive: true,
hidden: false
},
title: t('account.reports.action'),
icon: 'flag'
}
])
return menus
}
export default menuAccount