tooot/src/components/Timeline/Shared/Actions.tsx

316 lines
9.4 KiB
TypeScript
Raw Normal View History

2021-01-24 02:25:43 +01:00
import analytics from '@components/analytics'
import Icon from '@components/Icon'
2021-02-28 22:49:55 +01:00
import { displayMessage } from '@components/Message'
2020-12-07 12:31:40 +01:00
import { useNavigation } from '@react-navigation/native'
2021-01-11 21:36:57 +01:00
import {
MutationVarsTimelineUpdateStatusProperty,
QueryKeyTimeline,
useTimelineMutation
} from '@utils/queryHooks/timeline'
2021-01-01 16:48:16 +01:00
import { StyleConstants } from '@utils/styles/constants'
import { useTheme } from '@utils/styles/ThemeManager'
import React, { useCallback, useMemo } from 'react'
2021-01-01 23:10:47 +01:00
import { useTranslation } from 'react-i18next'
2021-01-19 01:13:45 +01:00
import { Pressable, StyleSheet, Text, View } from 'react-native'
2021-01-11 21:36:57 +01:00
import { useQueryClient } from 'react-query'
export interface Props {
2021-01-07 19:13:09 +01:00
queryKey: QueryKeyTimeline
2021-02-13 01:26:02 +01:00
rootQueryKey?: QueryKeyTimeline
2021-03-16 23:15:37 +01:00
highlighted: boolean
status: Mastodon.Status
2021-01-24 02:25:43 +01:00
accts: Mastodon.Account['acct'][] // When replying to conversations
2020-12-19 18:21:37 +01:00
reblog: boolean
}
2021-03-06 21:01:38 +01:00
const TimelineActions = React.memo(
2021-03-16 23:15:37 +01:00
({ queryKey, rootQueryKey, highlighted, status, accts, reblog }: Props) => {
2021-03-06 21:01:38 +01:00
const navigation = useNavigation()
const { t } = useTranslation('componentTimeline')
const { mode, theme } = useTheme()
const iconColor = theme.secondary
const iconColorAction = (state: boolean) =>
state ? theme.primaryDefault : theme.secondary
2020-11-23 00:07:32 +01:00
2021-03-06 21:01:38 +01:00
const queryClient = useQueryClient()
const mutation = useTimelineMutation({
queryClient,
onMutate: true,
onSuccess: (_, params) => {
const theParams = params as MutationVarsTimelineUpdateStatusProperty
if (
// Un-bookmark from bookmarks page
(queryKey[1].page === 'Bookmarks' &&
theParams.payload.property === 'bookmarked') ||
// Un-favourite from favourites page
(queryKey[1].page === 'Favourites' &&
theParams.payload.property === 'favourited') ||
// Un-reblog from following page
(queryKey[1].page === 'Following' &&
theParams.payload.property === 'reblogged' &&
theParams.payload.currentValue === true)
) {
queryClient.invalidateQueries(queryKey)
} else if (
2021-01-13 01:03:46 +01:00
theParams.payload.property === 'reblogged' &&
2021-03-06 21:01:38 +01:00
queryKey[1].page !== 'Following'
) {
// When reblogged, update cache of following page
const tempQueryKey: QueryKeyTimeline = [
'Timeline',
{ page: 'Following' }
]
queryClient.invalidateQueries(tempQueryKey)
} else if (theParams.payload.property === 'favourited') {
// When favourited, update favourited page
const tempQueryKey: QueryKeyTimeline = [
'Timeline',
{ page: 'Favourites' }
]
queryClient.invalidateQueries(tempQueryKey)
} else if (theParams.payload.property === 'bookmarked') {
// When bookmarked, update bookmark page
const tempQueryKey: QueryKeyTimeline = [
'Timeline',
{ page: 'Bookmarks' }
]
queryClient.invalidateQueries(tempQueryKey)
}
},
onError: (err: any, params, oldData) => {
const correctParam = params as MutationVarsTimelineUpdateStatusProperty
displayMessage({
mode,
type: 'error',
message: t('common:toastMessage.error.message', {
function: t(
`shared.actions.${correctParam.payload.property}.function`
)
}),
...(err.status &&
typeof err.status === 'number' &&
err.data &&
err.data.error &&
typeof err.data.error === 'string' && {
description: err.data.error
})
})
2021-01-12 00:12:44 +01:00
queryClient.invalidateQueries(queryKey)
2021-01-24 02:25:43 +01:00
}
})
2020-11-28 17:07:30 +01:00
2021-03-06 21:01:38 +01:00
const onPressReply = useCallback(() => {
analytics('timeline_shared_actions_reply_press', {
page: queryKey[1].page,
count: status.replies_count
})
navigation.navigate('Screen-Compose', {
type: 'reply',
incomingStatus: status,
accts,
queryKey
})
}, [status.replies_count])
const onPressReblog = useCallback(() => {
analytics('timeline_shared_actions_reblog_press', {
page: queryKey[1].page,
count: status.reblogs_count,
current: status.reblogged
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
rootQueryKey,
id: status.id,
reblog,
payload: {
property: 'reblogged',
currentValue: status.reblogged,
propertyCount: 'reblogs_count',
countValue: status.reblogs_count
}
})
}, [status.reblogged, status.reblogs_count])
const onPressFavourite = useCallback(() => {
analytics('timeline_shared_actions_favourite_press', {
page: queryKey[1].page,
count: status.favourites_count,
current: status.favourited
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
rootQueryKey,
id: status.id,
reblog,
payload: {
property: 'favourited',
currentValue: status.favourited,
propertyCount: 'favourites_count',
countValue: status.favourites_count
}
})
}, [status.favourited, status.favourites_count])
const onPressBookmark = useCallback(() => {
analytics('timeline_shared_actions_bookmark_press', {
page: queryKey[1].page,
current: status.bookmarked
})
mutation.mutate({
type: 'updateStatusProperty',
queryKey,
rootQueryKey,
id: status.id,
reblog,
payload: {
property: 'bookmarked',
currentValue: status.bookmarked,
propertyCount: undefined,
countValue: undefined
}
})
}, [status.bookmarked])
const childrenReply = useMemo(
() => (
<>
<Icon
name='MessageCircle'
color={iconColor}
size={StyleConstants.Font.Size.L}
/>
{status.replies_count > 0 && (
<Text
style={{
color: theme.secondary,
fontSize: StyleConstants.Font.Size.M,
marginLeft: StyleConstants.Spacing.XS
}}
>
{status.replies_count}
</Text>
)}
</>
),
[status.replies_count]
)
const childrenReblog = useMemo(() => {
const color = (state: boolean) => (state ? theme.green : theme.secondary)
return (
2021-03-06 21:01:38 +01:00
<>
<Icon
name='Repeat'
color={
status.visibility === 'private' || status.visibility === 'direct'
? theme.disabled
: color(status.reblogged)
2021-03-06 21:01:38 +01:00
}
size={StyleConstants.Font.Size.L}
/>
{status.reblogs_count > 0 && (
<Text
style={{
color: color(status.reblogged),
2021-03-06 21:01:38 +01:00
fontSize: StyleConstants.Font.Size.M,
marginLeft: StyleConstants.Spacing.XS
}}
>
{status.reblogs_count}
</Text>
)}
</>
)
}, [status.reblogged, status.reblogs_count])
const childrenFavourite = useMemo(() => {
const color = (state: boolean) => (state ? theme.red : theme.secondary)
return (
2021-03-06 21:01:38 +01:00
<>
<Icon
name='Heart'
color={color(status.favourited)}
2021-03-06 21:01:38 +01:00
size={StyleConstants.Font.Size.L}
/>
{status.favourites_count > 0 && (
<Text
style={{
color: color(status.favourited),
2021-03-06 21:01:38 +01:00
fontSize: StyleConstants.Font.Size.M,
marginLeft: StyleConstants.Spacing.XS,
marginTop: 0
}}
>
{status.favourites_count}
</Text>
)}
</>
)
}, [status.favourited, status.favourites_count])
const childrenBookmark = useMemo(() => {
const color = (state: boolean) => (state ? theme.yellow : theme.secondary)
return (
2021-01-20 00:39:39 +01:00
<Icon
2021-03-06 21:01:38 +01:00
name='Bookmark'
color={color(status.bookmarked)}
2021-01-20 00:39:39 +01:00
size={StyleConstants.Font.Size.L}
/>
)
}, [status.bookmarked])
2020-11-28 17:07:30 +01:00
2021-03-06 21:01:38 +01:00
return (
2021-03-16 23:15:37 +01:00
<View
style={{
paddingLeft: highlighted
? 0
: StyleConstants.Avatar.M + StyleConstants.Spacing.S
}}
>
2021-03-06 21:01:38 +01:00
<View style={styles.actions}>
<Pressable
style={styles.action}
onPress={onPressReply}
children={childrenReply}
/>
2021-03-06 21:01:38 +01:00
<Pressable
style={styles.action}
onPress={onPressReblog}
children={childrenReblog}
disabled={
status.visibility === 'private' || status.visibility === 'direct'
}
/>
2021-03-06 21:01:38 +01:00
<Pressable
style={styles.action}
onPress={onPressFavourite}
children={childrenFavourite}
/>
2021-03-06 21:01:38 +01:00
<Pressable
style={styles.action}
onPress={onPressBookmark}
children={childrenBookmark}
/>
</View>
2021-03-16 23:15:37 +01:00
</View>
2021-03-06 21:01:38 +01:00
)
},
() => true
)
const styles = StyleSheet.create({
actions: {
2021-01-23 02:41:50 +01:00
flexDirection: 'row'
},
action: {
2021-01-19 01:13:45 +01:00
flex: 1,
flexDirection: 'row',
2021-01-01 16:48:16 +01:00
justifyContent: 'center',
2021-01-20 00:39:39 +01:00
alignItems: 'center',
2021-03-15 00:18:44 +01:00
minHeight: StyleConstants.Font.Size.L + StyleConstants.Spacing.S * 4,
marginHorizontal: StyleConstants.Spacing.S
}
})
2020-12-03 01:28:56 +01:00
export default TimelineActions