mirror of
https://github.com/tooot-app/app
synced 2025-04-21 05:37:37 +02:00
Believe #638 can be closed now!
This commit is contained in:
parent
62a6594f91
commit
06324ee51a
@ -41,10 +41,7 @@ const TimelineConversation: React.FC<Props> = ({ conversation, queryKey, highlig
|
|||||||
const onPress = useCallback(() => {
|
const onPress = useCallback(() => {
|
||||||
if (conversation.last_status) {
|
if (conversation.last_status) {
|
||||||
conversation.unread && mutate()
|
conversation.unread && mutate()
|
||||||
navigation.push('Tab-Shared-Toot', {
|
navigation.push('Tab-Shared-Toot', { toot: conversation.last_status })
|
||||||
toot: conversation.last_status,
|
|
||||||
rootQueryKey: queryKey
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ import TimelineTranslate from './Shared/Translate'
|
|||||||
export interface Props {
|
export interface Props {
|
||||||
item: Mastodon.Status & { _pinned?: boolean } // For account page, internal property
|
item: Mastodon.Status & { _pinned?: boolean } // For account page, internal property
|
||||||
queryKey?: QueryKeyTimeline
|
queryKey?: QueryKeyTimeline
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
highlighted?: boolean
|
highlighted?: boolean
|
||||||
disableDetails?: boolean
|
disableDetails?: boolean
|
||||||
disableOnPress?: boolean
|
disableOnPress?: boolean
|
||||||
@ -43,7 +42,6 @@ export interface Props {
|
|||||||
const TimelineDefault: React.FC<Props> = ({
|
const TimelineDefault: React.FC<Props> = ({
|
||||||
item,
|
item,
|
||||||
queryKey,
|
queryKey,
|
||||||
rootQueryKey,
|
|
||||||
highlighted = false,
|
highlighted = false,
|
||||||
disableDetails = false,
|
disableDetails = false,
|
||||||
disableOnPress = false,
|
disableOnPress = false,
|
||||||
@ -131,8 +129,8 @@ const TimelineDefault: React.FC<Props> = ({
|
|||||||
url: status.url || status.uri,
|
url: status.url || status.uri,
|
||||||
rawContent
|
rawContent
|
||||||
})
|
})
|
||||||
const mStatus = menuStatus({ status, queryKey, rootQueryKey })
|
const mStatus = menuStatus({ status, queryKey })
|
||||||
const mInstance = menuInstance({ status, queryKey, rootQueryKey })
|
const mInstance = menuInstance({ status, queryKey })
|
||||||
|
|
||||||
if (!ownAccount) {
|
if (!ownAccount) {
|
||||||
let filterResults: FilteredProps['filterResults'] = []
|
let filterResults: FilteredProps['filterResults'] = []
|
||||||
@ -163,7 +161,6 @@ const TimelineDefault: React.FC<Props> = ({
|
|||||||
<StatusContext.Provider
|
<StatusContext.Provider
|
||||||
value={{
|
value={{
|
||||||
queryKey,
|
queryKey,
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
ownAccount,
|
ownAccount,
|
||||||
spoilerHidden,
|
spoilerHidden,
|
||||||
@ -188,12 +185,7 @@ const TimelineDefault: React.FC<Props> = ({
|
|||||||
accessible={highlighted ? false : true}
|
accessible={highlighted ? false : true}
|
||||||
style={mainStyle}
|
style={mainStyle}
|
||||||
disabled={highlighted}
|
disabled={highlighted}
|
||||||
onPress={() =>
|
onPress={() => navigation.push('Tab-Shared-Toot', { toot: status })}
|
||||||
navigation.push('Tab-Shared-Toot', {
|
|
||||||
toot: status,
|
|
||||||
rootQueryKey: queryKey
|
|
||||||
})
|
|
||||||
}
|
|
||||||
onLongPress={() => {}}
|
onLongPress={() => {}}
|
||||||
children={main()}
|
children={main()}
|
||||||
/>
|
/>
|
||||||
|
@ -154,10 +154,7 @@ const TimelineNotifications: React.FC<Props> = ({ notification, queryKey }) => {
|
|||||||
}}
|
}}
|
||||||
onPress={() =>
|
onPress={() =>
|
||||||
notification.status &&
|
notification.status &&
|
||||||
navigation.push('Tab-Shared-Toot', {
|
navigation.push('Tab-Shared-Toot', { toot: notification.status })
|
||||||
toot: notification.status,
|
|
||||||
rootQueryKey: queryKey
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
onLongPress={() => {}}
|
onLongPress={() => {}}
|
||||||
children={main()}
|
children={main()}
|
||||||
|
@ -6,7 +6,7 @@ import { useNavigation } from '@react-navigation/native'
|
|||||||
import { StackNavigationProp } from '@react-navigation/stack'
|
import { StackNavigationProp } from '@react-navigation/stack'
|
||||||
import { useQueryClient } from '@tanstack/react-query'
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
import { androidActionSheetStyles } from '@utils/helpers/androidActionSheetStyles'
|
import { androidActionSheetStyles } from '@utils/helpers/androidActionSheetStyles'
|
||||||
import { RootStackParamList } from '@utils/navigation/navigators'
|
import { RootStackParamList, useNavState } from '@utils/navigation/navigators'
|
||||||
import {
|
import {
|
||||||
MutationVarsTimelineUpdateStatusProperty,
|
MutationVarsTimelineUpdateStatusProperty,
|
||||||
QueryKeyTimeline,
|
QueryKeyTimeline,
|
||||||
@ -22,10 +22,10 @@ import { Pressable, StyleSheet, View } from 'react-native'
|
|||||||
import StatusContext from './Context'
|
import StatusContext from './Context'
|
||||||
|
|
||||||
const TimelineActions: React.FC = () => {
|
const TimelineActions: React.FC = () => {
|
||||||
const { queryKey, rootQueryKey, status, ownAccount, highlighted, disableDetails } =
|
const { queryKey, status, ownAccount, highlighted, disableDetails } = useContext(StatusContext)
|
||||||
useContext(StatusContext)
|
|
||||||
if (!queryKey || !status || disableDetails) return null
|
if (!queryKey || !status || disableDetails) return null
|
||||||
|
|
||||||
|
const navigationState = useNavState()
|
||||||
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>()
|
const navigation = useNavigation<StackNavigationProp<RootStackParamList>>()
|
||||||
const { t } = useTranslation(['common', 'componentTimeline'])
|
const { t } = useTranslation(['common', 'componentTimeline'])
|
||||||
const { colors, theme } = useTheme()
|
const { colors, theme } = useTheme()
|
||||||
@ -87,7 +87,7 @@ const TimelineActions: React.FC = () => {
|
|||||||
type: 'reply',
|
type: 'reply',
|
||||||
incomingStatus: status,
|
incomingStatus: status,
|
||||||
accts,
|
accts,
|
||||||
queryKey
|
navigationState
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const { showActionSheetWithOptions } = useActionSheet()
|
const { showActionSheetWithOptions } = useActionSheet()
|
||||||
@ -109,8 +109,6 @@ const TimelineActions: React.FC = () => {
|
|||||||
case 0:
|
case 0:
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'reblogged',
|
type: 'reblogged',
|
||||||
@ -122,8 +120,6 @@ const TimelineActions: React.FC = () => {
|
|||||||
case 1:
|
case 1:
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'reblogged',
|
type: 'reblogged',
|
||||||
@ -138,8 +134,6 @@ const TimelineActions: React.FC = () => {
|
|||||||
} else {
|
} else {
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'reblogged',
|
type: 'reblogged',
|
||||||
@ -152,8 +146,6 @@ const TimelineActions: React.FC = () => {
|
|||||||
const onPressFavourite = () => {
|
const onPressFavourite = () => {
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'favourited',
|
type: 'favourited',
|
||||||
@ -164,8 +156,6 @@ const TimelineActions: React.FC = () => {
|
|||||||
const onPressBookmark = () => {
|
const onPressBookmark = () => {
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'bookmarked',
|
type: 'bookmarked',
|
||||||
|
@ -5,7 +5,6 @@ export type HighlightedStatusContextType = {}
|
|||||||
|
|
||||||
type StatusContextType = {
|
type StatusContextType = {
|
||||||
queryKey?: QueryKeyTimeline
|
queryKey?: QueryKeyTimeline
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
|
|
||||||
status?: Mastodon.Status
|
status?: Mastodon.Status
|
||||||
|
|
||||||
|
@ -10,7 +10,7 @@ import * as DropdownMenu from 'zeego/dropdown-menu'
|
|||||||
import StatusContext from './Context'
|
import StatusContext from './Context'
|
||||||
|
|
||||||
const TimelineHeaderAndroid: React.FC = () => {
|
const TimelineHeaderAndroid: React.FC = () => {
|
||||||
const { queryKey, rootQueryKey, status, disableDetails, disableOnPress, rawContent } =
|
const { queryKey, status, disableDetails, disableOnPress, rawContent } =
|
||||||
useContext(StatusContext)
|
useContext(StatusContext)
|
||||||
|
|
||||||
if (Platform.OS !== 'android' || !status || disableDetails || disableOnPress) return null
|
if (Platform.OS !== 'android' || !status || disableDetails || disableOnPress) return null
|
||||||
@ -28,10 +28,9 @@ const TimelineHeaderAndroid: React.FC = () => {
|
|||||||
type: 'status',
|
type: 'status',
|
||||||
openChange,
|
openChange,
|
||||||
account: status.account,
|
account: status.account,
|
||||||
...(status && { status }),
|
...(status && { status })
|
||||||
queryKey
|
|
||||||
})
|
})
|
||||||
const mStatus = menuStatus({ status, queryKey, rootQueryKey })
|
const mStatus = menuStatus({ status, queryKey })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ position: 'absolute', top: 0, right: 0 }}>
|
<View style={{ position: 'absolute', top: 0, right: 0 }}>
|
||||||
|
@ -84,7 +84,6 @@ const HeaderConversation = ({ conversation }: Props) => {
|
|||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'deleteItem',
|
type: 'deleteItem',
|
||||||
source: 'conversations',
|
source: 'conversations',
|
||||||
queryKey,
|
|
||||||
id: conversation.id
|
id: conversation.id
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ import HeaderSharedReplies from './HeaderShared/Replies'
|
|||||||
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
import HeaderSharedVisibility from './HeaderShared/Visibility'
|
||||||
|
|
||||||
const TimelineHeaderDefault: React.FC = () => {
|
const TimelineHeaderDefault: React.FC = () => {
|
||||||
const { queryKey, rootQueryKey, status, disableDetails, rawContent, isRemote } =
|
const { queryKey, status, disableDetails, rawContent, isRemote } =
|
||||||
useContext(StatusContext)
|
useContext(StatusContext)
|
||||||
if (!status) return null
|
if (!status) return null
|
||||||
|
|
||||||
@ -35,10 +35,9 @@ const TimelineHeaderDefault: React.FC = () => {
|
|||||||
type: 'status',
|
type: 'status',
|
||||||
openChange,
|
openChange,
|
||||||
account: status.account,
|
account: status.account,
|
||||||
...(status && { status }),
|
...(status && { status })
|
||||||
queryKey
|
|
||||||
})
|
})
|
||||||
const mStatus = menuStatus({ status, queryKey, rootQueryKey })
|
const mStatus = menuStatus({ status, queryKey })
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<View style={{ flex: 1, flexDirection: 'row' }}>
|
<View style={{ flex: 1, flexDirection: 'row' }}>
|
||||||
|
@ -41,8 +41,7 @@ const TimelineHeaderNotification: React.FC<Props> = ({ notification }) => {
|
|||||||
type: 'status',
|
type: 'status',
|
||||||
openChange,
|
openChange,
|
||||||
account: status?.account,
|
account: status?.account,
|
||||||
...(status && { status }),
|
...(status && { status })
|
||||||
queryKey
|
|
||||||
})
|
})
|
||||||
const mStatus = menuStatus({ status, queryKey })
|
const mStatus = menuStatus({ status, queryKey })
|
||||||
const mInstance = menuInstance({ status, queryKey })
|
const mInstance = menuInstance({ status, queryKey })
|
||||||
|
@ -6,6 +6,7 @@ import { ParseEmojis } from '@components/Parse'
|
|||||||
import RelativeTime from '@components/RelativeTime'
|
import RelativeTime from '@components/RelativeTime'
|
||||||
import CustomText from '@components/Text'
|
import CustomText from '@components/Text'
|
||||||
import { useQueryClient } from '@tanstack/react-query'
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
|
import { useNavState } from '@utils/navigation/navigators'
|
||||||
import {
|
import {
|
||||||
MutationVarsTimelineUpdateStatusProperty,
|
MutationVarsTimelineUpdateStatusProperty,
|
||||||
useTimelineMutation
|
useTimelineMutation
|
||||||
@ -20,8 +21,7 @@ import { Pressable, View } from 'react-native'
|
|||||||
import StatusContext from './Context'
|
import StatusContext from './Context'
|
||||||
|
|
||||||
const TimelinePoll: React.FC = () => {
|
const TimelinePoll: React.FC = () => {
|
||||||
const { queryKey, rootQueryKey, status, ownAccount, spoilerHidden, disableDetails } =
|
const { queryKey, status, ownAccount, spoilerHidden, disableDetails } = useContext(StatusContext)
|
||||||
useContext(StatusContext)
|
|
||||||
if (!queryKey || !status || !status.poll) return null
|
if (!queryKey || !status || !status.poll) return null
|
||||||
const poll = status.poll
|
const poll = status.poll
|
||||||
|
|
||||||
@ -30,17 +30,20 @@ const TimelinePoll: React.FC = () => {
|
|||||||
|
|
||||||
const [allOptions, setAllOptions] = useState(new Array(status.poll.options.length).fill(false))
|
const [allOptions, setAllOptions] = useState(new Array(status.poll.options.length).fill(false))
|
||||||
|
|
||||||
|
const navigationState = useNavState()
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const mutation = useTimelineMutation({
|
const mutation = useTimelineMutation({
|
||||||
onSuccess: ({ body }, params) => {
|
onSuccess: ({ body }, params) => {
|
||||||
const theParams = params as MutationVarsTimelineUpdateStatusProperty
|
const theParams = params as MutationVarsTimelineUpdateStatusProperty
|
||||||
queryClient.cancelQueries(queryKey)
|
queryClient.cancelQueries(queryKey)
|
||||||
rootQueryKey && queryClient.cancelQueries(rootQueryKey)
|
|
||||||
|
|
||||||
haptics('Success')
|
haptics('Success')
|
||||||
switch (theParams.payload.type) {
|
switch (theParams.payload.type) {
|
||||||
case 'poll':
|
case 'poll':
|
||||||
updateStatusProperty({ ...theParams, poll: body as unknown as Mastodon.Poll })
|
updateStatusProperty(
|
||||||
|
{ ...theParams, poll: body as unknown as Mastodon.Poll },
|
||||||
|
navigationState
|
||||||
|
)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -74,8 +77,6 @@ const TimelinePoll: React.FC = () => {
|
|||||||
onPress={() =>
|
onPress={() =>
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'poll',
|
type: 'poll',
|
||||||
@ -98,8 +99,6 @@ const TimelinePoll: React.FC = () => {
|
|||||||
onPress={() =>
|
onPress={() =>
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'poll',
|
type: 'poll',
|
||||||
|
@ -3,7 +3,7 @@ import { displayMessage } from '@components/Message'
|
|||||||
import { useNavigation } from '@react-navigation/native'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
||||||
import { useQueryClient } from '@tanstack/react-query'
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
import { TabSharedStackParamList } from '@utils/navigation/navigators'
|
import { TabSharedStackParamList, useNavState } from '@utils/navigation/navigators'
|
||||||
import { useAccountQuery } from '@utils/queryHooks/account'
|
import { useAccountQuery } from '@utils/queryHooks/account'
|
||||||
import {
|
import {
|
||||||
QueryKeyRelationship,
|
QueryKeyRelationship,
|
||||||
@ -12,7 +12,6 @@ import {
|
|||||||
} from '@utils/queryHooks/relationship'
|
} from '@utils/queryHooks/relationship'
|
||||||
import {
|
import {
|
||||||
MutationVarsTimelineUpdateAccountProperty,
|
MutationVarsTimelineUpdateAccountProperty,
|
||||||
QueryKeyTimeline,
|
|
||||||
useTimelineMutation
|
useTimelineMutation
|
||||||
} from '@utils/queryHooks/timeline'
|
} from '@utils/queryHooks/timeline'
|
||||||
import { useAccountStorage } from '@utils/storage/actions'
|
import { useAccountStorage } from '@utils/storage/actions'
|
||||||
@ -24,19 +23,16 @@ const menuAccount = ({
|
|||||||
type,
|
type,
|
||||||
openChange,
|
openChange,
|
||||||
account,
|
account,
|
||||||
status,
|
status
|
||||||
queryKey,
|
|
||||||
rootQueryKey
|
|
||||||
}: {
|
}: {
|
||||||
type: 'status' | 'account' // Where the action is coming from
|
type: 'status' | 'account' // Where the action is coming from
|
||||||
openChange: boolean
|
openChange: boolean
|
||||||
account?: Partial<Mastodon.Account> & Pick<Mastodon.Account, 'id' | 'username' | 'acct' | 'url'>
|
account?: Partial<Mastodon.Account> & Pick<Mastodon.Account, 'id' | 'username' | 'acct' | 'url'>
|
||||||
status?: Mastodon.Status
|
status?: Mastodon.Status
|
||||||
queryKey?: QueryKeyTimeline
|
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
}): ContextMenu[][] => {
|
}): ContextMenu[][] => {
|
||||||
const navigation =
|
const navigation =
|
||||||
useNavigation<NativeStackNavigationProp<TabSharedStackParamList, any, undefined>>()
|
useNavigation<NativeStackNavigationProp<TabSharedStackParamList, any, undefined>>()
|
||||||
|
const navState = useNavState()
|
||||||
const { t } = useTranslation(['common', 'componentContextMenu', 'componentRelationship'])
|
const { t } = useTranslation(['common', 'componentContextMenu', 'componentRelationship'])
|
||||||
|
|
||||||
const menus: ContextMenu[][] = [[]]
|
const menus: ContextMenu[][] = [[]]
|
||||||
@ -101,8 +97,9 @@ const menuAccount = ({
|
|||||||
})
|
})
|
||||||
},
|
},
|
||||||
onSettled: () => {
|
onSettled: () => {
|
||||||
queryKey && queryClient.invalidateQueries(queryKey)
|
for (const key of navState) {
|
||||||
rootQueryKey && queryClient.invalidateQueries(rootQueryKey)
|
queryClient.invalidateQueries(key)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id: actualAccount?.id }]
|
const queryKeyRelationship: QueryKeyRelationship = ['Relationship', { id: actualAccount?.id }]
|
||||||
@ -111,8 +108,10 @@ const menuAccount = ({
|
|||||||
haptics('Success')
|
haptics('Success')
|
||||||
queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [res])
|
queryClient.setQueryData<Mastodon.Relationship[]>(queryKeyRelationship, [res])
|
||||||
if (action === 'block') {
|
if (action === 'block') {
|
||||||
const queryKey = ['Timeline', { page: 'Following' }]
|
queryClient.invalidateQueries({
|
||||||
queryClient.invalidateQueries({ queryKey, exact: false })
|
queryKey: ['Timeline', { page: 'Following' }],
|
||||||
|
exact: false
|
||||||
|
})
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onError: (err: any, { payload: { action } }) => {
|
onError: (err: any, { payload: { action } }) => {
|
||||||
@ -203,7 +202,6 @@ const menuAccount = ({
|
|||||||
actualAccount &&
|
actualAccount &&
|
||||||
timelineMutation.mutate({
|
timelineMutation.mutate({
|
||||||
type: 'updateAccountProperty',
|
type: 'updateAccountProperty',
|
||||||
queryKey,
|
|
||||||
id: actualAccount.id,
|
id: actualAccount.id,
|
||||||
payload: { property: 'mute', currentValue: data?.muting }
|
payload: { property: 'mute', currentValue: data?.muting }
|
||||||
}),
|
}),
|
||||||
@ -236,7 +234,6 @@ const menuAccount = ({
|
|||||||
actualAccount &&
|
actualAccount &&
|
||||||
timelineMutation.mutate({
|
timelineMutation.mutate({
|
||||||
type: 'updateAccountProperty',
|
type: 'updateAccountProperty',
|
||||||
queryKey,
|
|
||||||
id: actualAccount.id,
|
id: actualAccount.id,
|
||||||
payload: { property: 'block', currentValue: data?.blocking }
|
payload: { property: 'block', currentValue: data?.blocking }
|
||||||
})
|
})
|
||||||
|
@ -8,12 +8,10 @@ import parse from 'url-parse'
|
|||||||
|
|
||||||
const menuInstance = ({
|
const menuInstance = ({
|
||||||
status,
|
status,
|
||||||
queryKey,
|
queryKey
|
||||||
rootQueryKey
|
|
||||||
}: {
|
}: {
|
||||||
status?: Mastodon.Status
|
status?: Mastodon.Status
|
||||||
queryKey?: QueryKeyTimeline
|
queryKey?: QueryKeyTimeline
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
}): ContextMenu[][] => {
|
}): ContextMenu[][] => {
|
||||||
if (!status || !queryKey) return []
|
if (!status || !queryKey) return []
|
||||||
|
|
||||||
@ -29,7 +27,6 @@ const menuInstance = ({
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
queryClient.invalidateQueries(queryKey)
|
queryClient.invalidateQueries(queryKey)
|
||||||
rootQueryKey && queryClient.invalidateQueries(rootQueryKey)
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -51,11 +48,7 @@ const menuInstance = ({
|
|||||||
text: t('common:buttons.confirm'),
|
text: t('common:buttons.confirm'),
|
||||||
style: 'destructive',
|
style: 'destructive',
|
||||||
onPress: () => {
|
onPress: () => {
|
||||||
mutation.mutate({
|
mutation.mutate({ type: 'domainBlock', domain: instance })
|
||||||
type: 'domainBlock',
|
|
||||||
queryKey,
|
|
||||||
domain: instance
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -4,7 +4,7 @@ import { NativeStackNavigationProp } from '@react-navigation/native-stack'
|
|||||||
import { useQueryClient } from '@tanstack/react-query'
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
import apiInstance from '@utils/api/instance'
|
import apiInstance from '@utils/api/instance'
|
||||||
import { featureCheck } from '@utils/helpers/featureCheck'
|
import { featureCheck } from '@utils/helpers/featureCheck'
|
||||||
import { RootStackParamList } from '@utils/navigation/navigators'
|
import { RootStackParamList, useNavState } from '@utils/navigation/navigators'
|
||||||
import {
|
import {
|
||||||
MutationVarsTimelineUpdateStatusProperty,
|
MutationVarsTimelineUpdateStatusProperty,
|
||||||
QueryKeyTimeline,
|
QueryKeyTimeline,
|
||||||
@ -17,12 +17,10 @@ import { Alert } from 'react-native'
|
|||||||
|
|
||||||
const menuStatus = ({
|
const menuStatus = ({
|
||||||
status,
|
status,
|
||||||
queryKey,
|
queryKey
|
||||||
rootQueryKey
|
|
||||||
}: {
|
}: {
|
||||||
status?: Mastodon.Status
|
status?: Mastodon.Status
|
||||||
queryKey?: QueryKeyTimeline
|
queryKey?: QueryKeyTimeline
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
}): ContextMenu[][] => {
|
}): ContextMenu[][] => {
|
||||||
if (!status || !queryKey) return []
|
if (!status || !queryKey) return []
|
||||||
|
|
||||||
@ -30,6 +28,8 @@ const menuStatus = ({
|
|||||||
const { theme } = useTheme()
|
const { theme } = useTheme()
|
||||||
const { t } = useTranslation(['common', 'componentContextMenu'])
|
const { t } = useTranslation(['common', 'componentContextMenu'])
|
||||||
|
|
||||||
|
const navigationState = useNavState()
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const mutation = useTimelineMutation({
|
const mutation = useTimelineMutation({
|
||||||
onMutate: true,
|
onMutate: true,
|
||||||
@ -90,8 +90,7 @@ const menuStatus = ({
|
|||||||
spoiler_text: res.body.spoiler_text
|
spoiler_text: res.body.spoiler_text
|
||||||
},
|
},
|
||||||
...(replyToStatus && { replyToStatus }),
|
...(replyToStatus && { replyToStatus }),
|
||||||
queryKey,
|
navigationState
|
||||||
rootQueryKey
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
@ -122,18 +121,13 @@ const menuStatus = ({
|
|||||||
}).then(res => res.body)
|
}).then(res => res.body)
|
||||||
}
|
}
|
||||||
mutation
|
mutation
|
||||||
.mutateAsync({
|
.mutateAsync({ type: 'deleteItem', source: 'statuses', id: status.id })
|
||||||
type: 'deleteItem',
|
|
||||||
source: 'statuses',
|
|
||||||
queryKey,
|
|
||||||
id: status.id
|
|
||||||
})
|
|
||||||
.then(res => {
|
.then(res => {
|
||||||
navigation.navigate('Screen-Compose', {
|
navigation.navigate('Screen-Compose', {
|
||||||
type: 'deleteEdit',
|
type: 'deleteEdit',
|
||||||
incomingStatus: res.body as Mastodon.Status,
|
incomingStatus: res.body as Mastodon.Status,
|
||||||
...(replyToStatus && { replyToStatus }),
|
...(replyToStatus && { replyToStatus }),
|
||||||
queryKey
|
navigationState
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -162,13 +156,7 @@ const menuStatus = ({
|
|||||||
text: t('common:buttons.confirm'),
|
text: t('common:buttons.confirm'),
|
||||||
style: 'destructive',
|
style: 'destructive',
|
||||||
onPress: async () => {
|
onPress: async () => {
|
||||||
mutation.mutate({
|
mutation.mutate({ type: 'deleteItem', source: 'statuses', id: status.id })
|
||||||
type: 'deleteItem',
|
|
||||||
source: 'statuses',
|
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
id: status.id
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -193,8 +181,6 @@ const menuStatus = ({
|
|||||||
onSelect: () =>
|
onSelect: () =>
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'muted',
|
type: 'muted',
|
||||||
@ -218,8 +204,6 @@ const menuStatus = ({
|
|||||||
// Also note that reblogs cannot be pinned.
|
// Also note that reblogs cannot be pinned.
|
||||||
mutation.mutate({
|
mutation.mutate({
|
||||||
type: 'updateStatusProperty',
|
type: 'updateStatusProperty',
|
||||||
queryKey,
|
|
||||||
rootQueryKey,
|
|
||||||
status,
|
status,
|
||||||
payload: {
|
payload: {
|
||||||
type: 'pinned',
|
type: 'pinned',
|
||||||
|
@ -339,24 +339,25 @@ const ScreenCompose: React.FC<RootStackScreenProps<'Screen-Compose'>> = ({
|
|||||||
StoreReview?.isAvailableAsync()
|
StoreReview?.isAvailableAsync()
|
||||||
.then(() => StoreReview.requestReview())
|
.then(() => StoreReview.requestReview())
|
||||||
.catch(() => {})
|
.catch(() => {})
|
||||||
|
setGlobalStorage('app.count_till_store_review', (currentCount || 0) + 1)
|
||||||
} else {
|
} else {
|
||||||
setGlobalStorage('app.count_till_store_review', (currentCount || 0) + 1)
|
setGlobalStorage('app.count_till_store_review', (currentCount || 0) + 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (params?.type) {
|
switch (params?.type) {
|
||||||
case 'edit':
|
case undefined:
|
||||||
mutateTimeline.mutate({
|
case 'conversation':
|
||||||
type: 'editItem',
|
queryClient.invalidateQueries({
|
||||||
queryKey: params.queryKey,
|
queryKey: ['Timeline', { page: 'Following' }],
|
||||||
rootQueryKey: params.rootQueryKey,
|
exact: false
|
||||||
status: res
|
|
||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
case 'edit': // doesn't work
|
||||||
case 'deleteEdit':
|
case 'deleteEdit':
|
||||||
case 'reply':
|
case 'reply':
|
||||||
if (params?.queryKey && params.queryKey[1].page === 'Toot') {
|
for (const navState of params.navigationState) {
|
||||||
queryClient.invalidateQueries(params.queryKey)
|
navState && queryClient.invalidateQueries(navState)
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -5,7 +5,6 @@ import Timeline from '@components/Timeline'
|
|||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
||||||
import { TabLocalStackParamList } from '@utils/navigation/navigators'
|
import { TabLocalStackParamList } from '@utils/navigation/navigators'
|
||||||
import usePopToTop from '@utils/navigation/usePopToTop'
|
|
||||||
import { useListsQuery } from '@utils/queryHooks/lists'
|
import { useListsQuery } from '@utils/queryHooks/lists'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import { setAccountStorage, useAccountStorage } from '@utils/storage/actions'
|
import { setAccountStorage, useAccountStorage } from '@utils/storage/actions'
|
||||||
@ -176,6 +175,7 @@ const Root: React.FC<NativeStackScreenProps<TabLocalStackParamList, 'Tab-Local-R
|
|||||||
/>
|
/>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
navigation.setParams({ queryKey: queryKey })
|
||||||
}, [mode, queryKey[1], pageLocal, lists])
|
}, [mode, queryKey[1], pageLocal, lists])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
import Timeline from '@components/Timeline'
|
import Timeline from '@components/Timeline'
|
||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
||||||
|
import { TabMeStackParamList } from '@utils/navigation/navigators'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import React from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
|
||||||
const TabMeBookmarks = () => {
|
const TabMeBookmarks: React.FC<NativeStackScreenProps<TabMeStackParamList, 'Tab-Me-Bookmarks'>> = ({
|
||||||
|
navigation
|
||||||
|
}) => {
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }]
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }]
|
||||||
|
useEffect(() => {
|
||||||
|
navigation.setParams({ queryKey: queryKey })
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
import Timeline from '@components/Timeline'
|
import Timeline from '@components/Timeline'
|
||||||
import TimelineConversation from '@components/Timeline/Conversation'
|
import TimelineConversation from '@components/Timeline/Conversation'
|
||||||
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
||||||
|
import { TabMeStackParamList } from '@utils/navigation/navigators'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import React from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
|
||||||
const TabMeConversations = () => {
|
const TabMeConversations: React.FC<
|
||||||
|
NativeStackScreenProps<TabMeStackParamList, 'Tab-Me-Conversations'>
|
||||||
|
> = ({ navigation }) => {
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Conversations' }]
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Conversations' }]
|
||||||
|
useEffect(() => {
|
||||||
|
navigation.setParams({ queryKey: queryKey })
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
|
@ -1,10 +1,17 @@
|
|||||||
import Timeline from '@components/Timeline'
|
import Timeline from '@components/Timeline'
|
||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
||||||
|
import { TabMeStackParamList } from '@utils/navigation/navigators'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import React from 'react'
|
import React, { useEffect } from 'react'
|
||||||
|
|
||||||
const TabMeFavourites = () => {
|
const TabMeFavourites: React.FC<
|
||||||
|
NativeStackScreenProps<TabMeStackParamList, 'Tab-Me-Favourites'>
|
||||||
|
> = ({ navigation }) => {
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }]
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }]
|
||||||
|
useEffect(() => {
|
||||||
|
navigation.setParams({ queryKey: queryKey })
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
|
@ -23,13 +23,13 @@ const TabMeListList: React.FC<TabMeStackScreenProps<'Tab-Me-List-List'>> = ({ na
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuContainer>
|
<MenuContainer>
|
||||||
{data?.map((params, index) => (
|
{data?.map((list, index) => (
|
||||||
<MenuRow
|
<MenuRow
|
||||||
key={index}
|
key={index}
|
||||||
iconFront='List'
|
iconFront='List'
|
||||||
iconBack='ChevronRight'
|
iconBack='ChevronRight'
|
||||||
title={params.title}
|
title={list.title}
|
||||||
onPress={() => navigation.navigate('Tab-Me-List', params)}
|
onPress={() => navigation.navigate('Tab-Me-List', { list })}
|
||||||
/>
|
/>
|
||||||
))}
|
))}
|
||||||
</MenuContainer>
|
</MenuContainer>
|
||||||
|
@ -2,8 +2,9 @@ import Icon from '@components/Icon'
|
|||||||
import { displayMessage } from '@components/Message'
|
import { displayMessage } from '@components/Message'
|
||||||
import Timeline from '@components/Timeline'
|
import Timeline from '@components/Timeline'
|
||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
||||||
import { useQueryClient } from '@tanstack/react-query'
|
import { useQueryClient } from '@tanstack/react-query'
|
||||||
import { TabMeStackScreenProps } from '@utils/navigation/navigators'
|
import { TabMeStackParamList } from '@utils/navigation/navigators'
|
||||||
import { QueryKeyLists, useListsMutation } from '@utils/queryHooks/lists'
|
import { QueryKeyLists, useListsMutation } from '@utils/queryHooks/lists'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import { StyleConstants } from '@utils/styles/constants'
|
import { StyleConstants } from '@utils/styles/constants'
|
||||||
@ -13,13 +14,16 @@ import { useTranslation } from 'react-i18next'
|
|||||||
import * as DropdownMenu from 'zeego/dropdown-menu'
|
import * as DropdownMenu from 'zeego/dropdown-menu'
|
||||||
import { menuListAccounts, menuListDelete, menuListEdit } from './menus'
|
import { menuListAccounts, menuListDelete, menuListEdit } from './menus'
|
||||||
|
|
||||||
const TabMeList: React.FC<TabMeStackScreenProps<'Tab-Me-List'>> = ({
|
const TabMeList: React.FC<NativeStackScreenProps<TabMeStackParamList, 'Tab-Me-List'>> = ({
|
||||||
navigation,
|
navigation,
|
||||||
route: { key, params }
|
route: {
|
||||||
|
key,
|
||||||
|
params: { list }
|
||||||
|
}
|
||||||
}) => {
|
}) => {
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { t } = useTranslation(['common', 'screenTabs'])
|
const { t } = useTranslation(['common', 'screenTabs'])
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'List', list: params.id }]
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'List', list: list.id }]
|
||||||
|
|
||||||
const queryKeyLists: QueryKeyLists = ['Lists']
|
const queryKeyLists: QueryKeyLists = ['Lists']
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
@ -39,9 +43,9 @@ const TabMeList: React.FC<TabMeStackScreenProps<'Tab-Me-List'>> = ({
|
|||||||
})
|
})
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const listAccounts = menuListAccounts({ params })
|
const listAccounts = menuListAccounts({ list })
|
||||||
const listEdit = menuListEdit({ params, key })
|
const listEdit = menuListEdit({ list, key })
|
||||||
const listDelete = menuListDelete({ params, mutation })
|
const listDelete = menuListDelete({ list, mutation })
|
||||||
|
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
headerRight: () => (
|
headerRight: () => (
|
||||||
@ -67,7 +71,8 @@ const TabMeList: React.FC<TabMeStackScreenProps<'Tab-Me-List'>> = ({
|
|||||||
</DropdownMenu.Root>
|
</DropdownMenu.Root>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
}, [params])
|
navigation.setParams({ queryKey })
|
||||||
|
}, [list])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
|
@ -3,19 +3,19 @@ import navigationRef from '@utils/navigation/navigationRef'
|
|||||||
import i18next from 'i18next'
|
import i18next from 'i18next'
|
||||||
import { Alert } from 'react-native'
|
import { Alert } from 'react-native'
|
||||||
|
|
||||||
export const menuListAccounts = ({ params }: { params: Mastodon.List }) => ({
|
export const menuListAccounts = ({ list }: { list: Mastodon.List }) => ({
|
||||||
key: 'list-accounts',
|
key: 'list-accounts',
|
||||||
onSelect: () => navigationRef.navigate<any>('Tab-Me-List-Accounts', params),
|
onSelect: () => navigationRef.navigate<any>('Tab-Me-List-Accounts', list),
|
||||||
title: i18next.t('screenTabs:me.listAccounts.heading'),
|
title: i18next.t('screenTabs:me.listAccounts.heading'),
|
||||||
icon: 'person.crop.circle.fill.badge.checkmark'
|
icon: 'person.crop.circle.fill.badge.checkmark'
|
||||||
})
|
})
|
||||||
|
|
||||||
export const menuListEdit = ({ params, key }: { params: Mastodon.List; key: string }) => ({
|
export const menuListEdit = ({ list, key }: { list: Mastodon.List; key: string }) => ({
|
||||||
key: 'list-edit',
|
key: 'list-edit',
|
||||||
onSelect: () =>
|
onSelect: () =>
|
||||||
navigationRef.navigate<any>('Tab-Me-List-Edit', {
|
navigationRef.navigate<any>('Tab-Me-List-Edit', {
|
||||||
type: 'edit',
|
type: 'edit',
|
||||||
payload: params,
|
payload: list,
|
||||||
key
|
key
|
||||||
}),
|
}),
|
||||||
title: i18next.t('screenTabs:me.listEdit.heading'),
|
title: i18next.t('screenTabs:me.listEdit.heading'),
|
||||||
@ -23,22 +23,22 @@ export const menuListEdit = ({ params, key }: { params: Mastodon.List; key: stri
|
|||||||
})
|
})
|
||||||
|
|
||||||
export const menuListDelete = ({
|
export const menuListDelete = ({
|
||||||
params,
|
list,
|
||||||
mutation
|
mutation
|
||||||
}: {
|
}: {
|
||||||
params: Mastodon.List
|
list: Mastodon.List
|
||||||
mutation: UseMutationResult<any, any, unknown, unknown>
|
mutation: UseMutationResult<any, any, unknown, unknown>
|
||||||
}) => ({
|
}) => ({
|
||||||
key: 'list-delete',
|
key: 'list-delete',
|
||||||
onSelect: () =>
|
onSelect: () =>
|
||||||
Alert.alert(
|
Alert.alert(
|
||||||
i18next.t('screenTabs:me.listDelete.confirm.title', { list: params.title.slice(0, 20) }),
|
i18next.t('screenTabs:me.listDelete.confirm.title', { list: list.title.slice(0, 20) }),
|
||||||
i18next.t('screenTabs:me.listDelete.confirm.message'),
|
i18next.t('screenTabs:me.listDelete.confirm.message'),
|
||||||
[
|
[
|
||||||
{
|
{
|
||||||
text: i18next.t('common:buttons.delete'),
|
text: i18next.t('common:buttons.delete'),
|
||||||
style: 'destructive',
|
style: 'destructive',
|
||||||
onPress: () => mutation.mutate({ type: 'delete', payload: params })
|
onPress: () => mutation.mutate({ type: 'delete', payload: list })
|
||||||
},
|
},
|
||||||
{ text: i18next.t('common:buttons.cancel') }
|
{ text: i18next.t('common:buttons.cancel') }
|
||||||
]
|
]
|
||||||
|
@ -1,19 +1,38 @@
|
|||||||
import { HeaderRight } from '@components/Header'
|
import { HeaderRight } from '@components/Header'
|
||||||
import Timeline from '@components/Timeline'
|
import Timeline from '@components/Timeline'
|
||||||
import TimelineNotifications from '@components/Timeline/Notifications'
|
import TimelineNotifications from '@components/Timeline/Notifications'
|
||||||
import { createNativeStackNavigator } from '@react-navigation/native-stack'
|
import { createNativeStackNavigator, NativeStackScreenProps } from '@react-navigation/native-stack'
|
||||||
import { ScreenTabsScreenProps, TabNotificationsStackParamList } from '@utils/navigation/navigators'
|
import { TabNotificationsStackParamList } from '@utils/navigation/navigators'
|
||||||
import usePopToTop from '@utils/navigation/usePopToTop'
|
import usePopToTop from '@utils/navigation/usePopToTop'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import React from 'react'
|
import React, { useEffect } from 'react'
|
||||||
import { useTranslation } from 'react-i18next'
|
import { useTranslation } from 'react-i18next'
|
||||||
import TabShared from '../Shared'
|
import TabShared from '../Shared'
|
||||||
import TabNotificationsFilters from './Filters'
|
import TabNotificationsFilters from './Filters'
|
||||||
|
|
||||||
const Stack = createNativeStackNavigator<TabNotificationsStackParamList>()
|
const Stack = createNativeStackNavigator<TabNotificationsStackParamList>()
|
||||||
|
|
||||||
const Root = () => {
|
const Root: React.FC<
|
||||||
|
NativeStackScreenProps<TabNotificationsStackParamList, 'Tab-Notifications-Root'>
|
||||||
|
> = ({ navigation }) => {
|
||||||
|
const { t } = useTranslation('screenTabs')
|
||||||
|
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Notifications' }]
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Notifications' }]
|
||||||
|
useEffect(() => {
|
||||||
|
navigation.setOptions({
|
||||||
|
title: t('tabs.notifications.name'),
|
||||||
|
headerRight: () => (
|
||||||
|
<HeaderRight
|
||||||
|
accessibilityLabel={t('notifications.filters.accessibilityLabel')}
|
||||||
|
accessibilityHint={t('notifications.filters.accessibilityHint')}
|
||||||
|
content='Filter'
|
||||||
|
onPress={() => navigation.navigate('Tab-Notifications-Filters')}
|
||||||
|
/>
|
||||||
|
)
|
||||||
|
})
|
||||||
|
navigation.setParams({ queryKey })
|
||||||
|
}, [])
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
queryKey={queryKey}
|
queryKey={queryKey}
|
||||||
@ -24,30 +43,12 @@ const Root = () => {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const TabNotifications = ({ navigation }: ScreenTabsScreenProps<'Tab-Notifications'>) => {
|
const TabNotifications: React.FC = () => {
|
||||||
const { t } = useTranslation('screenTabs')
|
|
||||||
|
|
||||||
usePopToTop()
|
usePopToTop()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack.Navigator screenOptions={{ headerShadowVisible: false }}>
|
<Stack.Navigator screenOptions={{ headerShadowVisible: false }}>
|
||||||
<Stack.Screen
|
<Stack.Screen name='Tab-Notifications-Root' component={Root} />
|
||||||
name='Tab-Notifications-Root'
|
|
||||||
component={Root}
|
|
||||||
options={{
|
|
||||||
title: t('tabs.notifications.name'),
|
|
||||||
headerRight: () => (
|
|
||||||
<HeaderRight
|
|
||||||
accessibilityLabel={t('notifications.filters.accessibilityLabel')}
|
|
||||||
accessibilityHint={t('notifications.filters.accessibilityHint')}
|
|
||||||
content='Filter'
|
|
||||||
onPress={() =>
|
|
||||||
navigation.navigate('Tab-Notifications', { screen: 'Tab-Notifications-Filters' })
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
)
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
<Stack.Screen
|
<Stack.Screen
|
||||||
name='Tab-Notifications-Filters'
|
name='Tab-Notifications-Filters'
|
||||||
component={TabNotificationsFilters}
|
component={TabNotificationsFilters}
|
||||||
|
@ -2,7 +2,8 @@ import { HeaderRight } from '@components/Header'
|
|||||||
import Timeline from '@components/Timeline'
|
import Timeline from '@components/Timeline'
|
||||||
import TimelineDefault from '@components/Timeline/Default'
|
import TimelineDefault from '@components/Timeline/Default'
|
||||||
import SegmentedControl from '@react-native-community/segmented-control'
|
import SegmentedControl from '@react-native-community/segmented-control'
|
||||||
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
import { useNavigation } from '@react-navigation/native'
|
||||||
|
import { NativeStackNavigationProp, NativeStackScreenProps } from '@react-navigation/native-stack'
|
||||||
import { TabPublicStackParamList } from '@utils/navigation/navigators'
|
import { TabPublicStackParamList } from '@utils/navigation/navigators'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
import { getGlobalStorage, setGlobalStorage } from '@utils/storage/actions'
|
import { getGlobalStorage, setGlobalStorage } from '@utils/storage/actions'
|
||||||
@ -14,7 +15,12 @@ import { Dimensions } from 'react-native'
|
|||||||
import { SceneMap, TabView } from 'react-native-tab-view'
|
import { SceneMap, TabView } from 'react-native-tab-view'
|
||||||
|
|
||||||
const Route = ({ route: { key: page } }: { route: any }) => {
|
const Route = ({ route: { key: page } }: { route: any }) => {
|
||||||
|
const navigation =
|
||||||
|
useNavigation<NativeStackNavigationProp<TabPublicStackParamList, 'Tab-Public-Root'>>()
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page }]
|
const queryKey: QueryKeyTimeline = ['Timeline', { page }]
|
||||||
|
useEffect(() => {
|
||||||
|
navigation.setParams({ queryKey })
|
||||||
|
}, [])
|
||||||
return (
|
return (
|
||||||
<Timeline
|
<Timeline
|
||||||
queryKey={queryKey}
|
queryKey={queryKey}
|
||||||
|
@ -51,6 +51,17 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const queryClient = useQueryClient()
|
||||||
|
const [queryKey, setQueryKey] = useState<QueryKeyTimeline>([
|
||||||
|
'Timeline',
|
||||||
|
{
|
||||||
|
page: 'Account',
|
||||||
|
id: account._remote ? data?.id : account.id,
|
||||||
|
exclude_reblogs: true,
|
||||||
|
only_media: false
|
||||||
|
}
|
||||||
|
])
|
||||||
|
|
||||||
const mShare = menuShare({ type: 'account', url: data?.url })
|
const mShare = menuShare({ type: 'account', url: data?.url })
|
||||||
const mAccount = menuAccount({ type: 'account', openChange: true, account: data })
|
const mAccount = menuAccount({ type: 'account', openChange: true, account: data })
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -97,19 +108,12 @@ const TabSharedAccount: React.FC<TabSharedStackScreenProps<'Tab-Shared-Account'>
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}, [mAccount])
|
}, [mAccount])
|
||||||
|
useEffect(() => {
|
||||||
|
navigation.setParams({ queryKey })
|
||||||
|
}, [queryKey[1]])
|
||||||
|
|
||||||
const scrollY = useSharedValue(0)
|
const scrollY = useSharedValue(0)
|
||||||
|
|
||||||
const queryClient = useQueryClient()
|
|
||||||
const [queryKey, setQueryKey] = useState<QueryKeyTimeline>([
|
|
||||||
'Timeline',
|
|
||||||
{
|
|
||||||
page: 'Account',
|
|
||||||
id: account._remote ? data?.id : account.id,
|
|
||||||
exclude_reblogs: true,
|
|
||||||
only_media: false
|
|
||||||
}
|
|
||||||
])
|
|
||||||
const page = queryKey[1]
|
const page = queryKey[1]
|
||||||
|
|
||||||
const [segment, setSegment] = useState<number>(0)
|
const [segment, setSegment] = useState<number>(0)
|
||||||
|
@ -41,6 +41,7 @@ const TabSharedAttachments: React.FC<TabSharedStackScreenProps<'Tab-Shared-Attac
|
|||||||
</CustomText>
|
</CustomText>
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
navigation.setParams({ queryKey })
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const queryKey: QueryKeyTimeline = [
|
const queryKey: QueryKeyTimeline = [
|
||||||
|
@ -17,15 +17,16 @@ const TabSharedHashtag: React.FC<TabSharedStackScreenProps<'Tab-Shared-Hashtag'>
|
|||||||
params: { hashtag }
|
params: { hashtag }
|
||||||
}
|
}
|
||||||
}) => {
|
}) => {
|
||||||
|
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Hashtag', hashtag }]
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />,
|
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />,
|
||||||
title: `#${decodeURIComponent(hashtag)}`
|
title: `#${decodeURIComponent(hashtag)}`
|
||||||
})
|
})
|
||||||
|
navigation.setParams({ queryKey: queryKey })
|
||||||
}, [])
|
}, [])
|
||||||
|
|
||||||
const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Hashtag', hashtag }]
|
|
||||||
|
|
||||||
const { t } = useTranslation(['common', 'screenTabs'])
|
const { t } = useTranslation(['common', 'screenTabs'])
|
||||||
|
|
||||||
const canFollowTags = featureCheck('follow_tags')
|
const canFollowTags = featureCheck('follow_tags')
|
||||||
|
@ -21,13 +21,17 @@ import { Path, Svg } from 'react-native-svg'
|
|||||||
const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
|
const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
|
||||||
navigation,
|
navigation,
|
||||||
route: {
|
route: {
|
||||||
params: { toot, rootQueryKey }
|
params: { toot }
|
||||||
}
|
}
|
||||||
}) => {
|
}) => {
|
||||||
const { colors } = useTheme()
|
const { colors } = useTheme()
|
||||||
const { t } = useTranslation(['componentTimeline', 'screenTabs'])
|
const { t } = useTranslation(['componentTimeline', 'screenTabs'])
|
||||||
|
|
||||||
const [hasRemoteContent, setHasRemoteContent] = useState<boolean>(false)
|
const [hasRemoteContent, setHasRemoteContent] = useState<boolean>(false)
|
||||||
|
const queryKey: { local: QueryKeyTimeline; remote: QueryKeyTimeline } = {
|
||||||
|
local: ['Timeline', { page: 'Toot', toot: toot.id, remote: false }],
|
||||||
|
remote: ['Timeline', { page: 'Toot', toot: toot.id, remote: true }]
|
||||||
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
navigation.setOptions({
|
navigation.setOptions({
|
||||||
@ -61,6 +65,7 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
|
|||||||
),
|
),
|
||||||
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
headerLeft: () => <HeaderLeft onPress={() => navigation.goBack()} />
|
||||||
})
|
})
|
||||||
|
navigation.setParams({ toot, queryKey: toot._remote ? queryKey.remote : queryKey.local })
|
||||||
}, [hasRemoteContent])
|
}, [hasRemoteContent])
|
||||||
|
|
||||||
const flRef = useRef<FlatList>(null)
|
const flRef = useRef<FlatList>(null)
|
||||||
@ -71,10 +76,6 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
|
|||||||
{ ...toot, _level: 0, key: 'cached' }
|
{ ...toot, _level: 0, key: 'cached' }
|
||||||
])
|
])
|
||||||
const highlightIndex = useRef<number>(0)
|
const highlightIndex = useRef<number>(0)
|
||||||
const queryKey: { local: QueryKeyTimeline; remote: QueryKeyTimeline } = {
|
|
||||||
local: ['Timeline', { page: 'Toot', toot: toot.id, remote: false }],
|
|
||||||
remote: ['Timeline', { page: 'Toot', toot: toot.id, remote: true }]
|
|
||||||
}
|
|
||||||
const queryLocal = useQuery(
|
const queryLocal = useQuery(
|
||||||
queryKey.local,
|
queryKey.local,
|
||||||
async () => {
|
async () => {
|
||||||
@ -280,7 +281,6 @@ const TabSharedToot: React.FC<TabSharedStackScreenProps<'Tab-Shared-Toot'>> = ({
|
|||||||
<TimelineDefault
|
<TimelineDefault
|
||||||
item={item}
|
item={item}
|
||||||
queryKey={item._remote ? queryKey.remote : queryKey.local}
|
queryKey={item._remote ? queryKey.remote : queryKey.local}
|
||||||
rootQueryKey={rootQueryKey}
|
|
||||||
highlighted={toot.id === item.id || item.id === 'cached'}
|
highlighted={toot.id === item.id || item.id === 'cached'}
|
||||||
isConversation={toot.id !== item.id && item.id !== 'cached'}
|
isConversation={toot.id !== item.id && item.id !== 'cached'}
|
||||||
/>
|
/>
|
||||||
|
@ -1,10 +1,19 @@
|
|||||||
import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'
|
import { BottomTabScreenProps } from '@react-navigation/bottom-tabs'
|
||||||
import { NavigatorScreenParams } from '@react-navigation/native'
|
import { NavigatorScreenParams, useNavigationState } from '@react-navigation/native'
|
||||||
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
import { NativeStackScreenProps } from '@react-navigation/native-stack'
|
||||||
import { StackNavigationProp } from '@react-navigation/stack'
|
import { StackNavigationProp } from '@react-navigation/stack'
|
||||||
import { ComposeState } from '@screens/Compose/utils/types'
|
import { ComposeState } from '@screens/Compose/utils/types'
|
||||||
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
import { QueryKeyTimeline } from '@utils/queryHooks/timeline'
|
||||||
|
|
||||||
|
export const useNavState = () =>
|
||||||
|
useNavigationState(state =>
|
||||||
|
state.routes.map(
|
||||||
|
route => (route.params as { queryKey?: QueryKeyTimeline } | undefined)?.queryKey
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.filter(key => key?.[0] === 'Timeline')
|
||||||
|
.reverse()
|
||||||
|
|
||||||
export type RootStackParamList = {
|
export type RootStackParamList = {
|
||||||
'Screen-Tabs': NavigatorScreenParams<ScreenTabsStackParamList>
|
'Screen-Tabs': NavigatorScreenParams<ScreenTabsStackParamList>
|
||||||
'Screen-Announcements': { showAll: boolean }
|
'Screen-Announcements': { showAll: boolean }
|
||||||
@ -13,20 +22,19 @@ export type RootStackParamList = {
|
|||||||
type: 'edit'
|
type: 'edit'
|
||||||
incomingStatus: Mastodon.Status
|
incomingStatus: Mastodon.Status
|
||||||
replyToStatus?: Mastodon.Status
|
replyToStatus?: Mastodon.Status
|
||||||
queryKey?: QueryKeyTimeline
|
navigationState: (QueryKeyTimeline | undefined)[]
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'deleteEdit'
|
type: 'deleteEdit'
|
||||||
incomingStatus: Mastodon.Status
|
incomingStatus: Mastodon.Status
|
||||||
replyToStatus?: Mastodon.Status
|
replyToStatus?: Mastodon.Status
|
||||||
queryKey?: QueryKeyTimeline
|
navigationState: (QueryKeyTimeline | undefined)[]
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'reply'
|
type: 'reply'
|
||||||
incomingStatus: Mastodon.Status
|
incomingStatus: Mastodon.Status
|
||||||
accts: Mastodon.Account['acct'][]
|
accts: Mastodon.Account['acct'][]
|
||||||
queryKey?: QueryKeyTimeline
|
navigationState: (QueryKeyTimeline | undefined)[]
|
||||||
}
|
}
|
||||||
| {
|
| {
|
||||||
type: 'conversation'
|
type: 'conversation'
|
||||||
@ -85,27 +93,18 @@ export type ScreenTabsScreenProps<T extends keyof ScreenTabsStackParamList> = Bo
|
|||||||
export type TabSharedStackParamList = {
|
export type TabSharedStackParamList = {
|
||||||
'Tab-Shared-Account': {
|
'Tab-Shared-Account': {
|
||||||
account: Pick<Mastodon.Account, 'id' | 'username' | 'acct' | 'url' | '_remote'>
|
account: Pick<Mastodon.Account, 'id' | 'username' | 'acct' | 'url' | '_remote'>
|
||||||
|
queryKey?: QueryKeyTimeline
|
||||||
}
|
}
|
||||||
'Tab-Shared-Account-In-Lists': {
|
'Tab-Shared-Account-In-Lists': { account: Pick<Mastodon.Account, 'id' | 'username'> }
|
||||||
account: Pick<Mastodon.Account, 'id' | 'username'>
|
'Tab-Shared-Attachments': { account: Mastodon.Account; queryKey?: QueryKeyTimeline }
|
||||||
}
|
'Tab-Shared-Hashtag': { hashtag: Mastodon.Tag['name']; queryKey?: QueryKeyTimeline }
|
||||||
'Tab-Shared-Attachments': { account: Mastodon.Account }
|
'Tab-Shared-History': { status: Mastodon.Status; detectedLanguage: string }
|
||||||
'Tab-Shared-Hashtag': {
|
|
||||||
hashtag: Mastodon.Tag['name']
|
|
||||||
}
|
|
||||||
'Tab-Shared-History': {
|
|
||||||
status: Mastodon.Status
|
|
||||||
detectedLanguage: string
|
|
||||||
}
|
|
||||||
'Tab-Shared-Report': {
|
'Tab-Shared-Report': {
|
||||||
account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'>
|
account: Pick<Mastodon.Account, 'id' | 'acct' | 'username' | 'url'>
|
||||||
status?: Pick<Mastodon.Status, 'id' | '_remote' | 'uri'>
|
status?: Pick<Mastodon.Status, 'id' | '_remote' | 'uri'>
|
||||||
}
|
}
|
||||||
'Tab-Shared-Search': undefined
|
'Tab-Shared-Search': undefined
|
||||||
'Tab-Shared-Toot': {
|
'Tab-Shared-Toot': { toot: Mastodon.Status; queryKey?: QueryKeyTimeline }
|
||||||
toot: Mastodon.Status
|
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
}
|
|
||||||
'Tab-Shared-Users':
|
'Tab-Shared-Users':
|
||||||
| {
|
| {
|
||||||
reference: 'accounts'
|
reference: 'accounts'
|
||||||
@ -124,15 +123,15 @@ export type TabSharedStackScreenProps<T extends keyof TabSharedStackParamList> =
|
|||||||
NativeStackScreenProps<TabSharedStackParamList, T>
|
NativeStackScreenProps<TabSharedStackParamList, T>
|
||||||
|
|
||||||
export type TabLocalStackParamList = {
|
export type TabLocalStackParamList = {
|
||||||
'Tab-Local-Root': undefined
|
'Tab-Local-Root': { queryKey?: QueryKeyTimeline }
|
||||||
} & TabSharedStackParamList
|
} & TabSharedStackParamList
|
||||||
|
|
||||||
export type TabPublicStackParamList = {
|
export type TabPublicStackParamList = {
|
||||||
'Tab-Public-Root': undefined
|
'Tab-Public-Root': { queryKey?: QueryKeyTimeline }
|
||||||
} & TabSharedStackParamList
|
} & TabSharedStackParamList
|
||||||
|
|
||||||
export type TabNotificationsStackParamList = {
|
export type TabNotificationsStackParamList = {
|
||||||
'Tab-Notifications-Root': undefined
|
'Tab-Notifications-Root': { queryKey?: QueryKeyTimeline }
|
||||||
'Tab-Notifications-Filters': undefined
|
'Tab-Notifications-Filters': undefined
|
||||||
} & TabSharedStackParamList
|
} & TabSharedStackParamList
|
||||||
export type TabNotificationsStackScreenProps<T extends keyof TabNotificationsStackParamList> =
|
export type TabNotificationsStackScreenProps<T extends keyof TabNotificationsStackParamList> =
|
||||||
@ -140,11 +139,11 @@ export type TabNotificationsStackScreenProps<T extends keyof TabNotificationsSta
|
|||||||
|
|
||||||
export type TabMeStackParamList = {
|
export type TabMeStackParamList = {
|
||||||
'Tab-Me-Root': undefined
|
'Tab-Me-Root': undefined
|
||||||
'Tab-Me-Bookmarks': undefined
|
'Tab-Me-Bookmarks': { queryKey?: QueryKeyTimeline }
|
||||||
'Tab-Me-Conversations': undefined
|
'Tab-Me-Conversations': { queryKey?: QueryKeyTimeline }
|
||||||
'Tab-Me-Favourites': undefined
|
'Tab-Me-Favourites': { queryKey?: QueryKeyTimeline }
|
||||||
'Tab-Me-FollowedTags': undefined
|
'Tab-Me-FollowedTags': undefined
|
||||||
'Tab-Me-List': Mastodon.List
|
'Tab-Me-List': { list: Mastodon.List; queryKey?: QueryKeyTimeline }
|
||||||
'Tab-Me-List-Accounts': Omit<Mastodon.List, 'replies_policy'>
|
'Tab-Me-List-Accounts': Omit<Mastodon.List, 'replies_policy'>
|
||||||
'Tab-Me-List-Edit':
|
'Tab-Me-List-Edit':
|
||||||
| {
|
| {
|
||||||
|
@ -4,9 +4,7 @@ import navigationRef from '@utils/navigation/navigationRef'
|
|||||||
const pushUseNavigate = (id?: Mastodon.Notification['id']) => {
|
const pushUseNavigate = (id?: Mastodon.Notification['id']) => {
|
||||||
navigationRef.navigate('Screen-Tabs', {
|
navigationRef.navigate('Screen-Tabs', {
|
||||||
screen: 'Tab-Notifications',
|
screen: 'Tab-Notifications',
|
||||||
params: {
|
params: { screen: 'Tab-Notifications-Root', params: {} }
|
||||||
screen: 'Tab-Notifications-Root'
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if (!id) {
|
if (!id) {
|
||||||
|
@ -9,13 +9,13 @@ import {
|
|||||||
import { PagedResponse } from '@utils/api/helpers'
|
import { PagedResponse } from '@utils/api/helpers'
|
||||||
import apiInstance from '@utils/api/instance'
|
import apiInstance from '@utils/api/instance'
|
||||||
import { featureCheck } from '@utils/helpers/featureCheck'
|
import { featureCheck } from '@utils/helpers/featureCheck'
|
||||||
|
import { useNavState } from '@utils/navigation/navigators'
|
||||||
import { queryClient } from '@utils/queryHooks'
|
import { queryClient } from '@utils/queryHooks'
|
||||||
import { getAccountStorage } from '@utils/storage/actions'
|
import { getAccountStorage } from '@utils/storage/actions'
|
||||||
import { AxiosError } from 'axios'
|
import { AxiosError } from 'axios'
|
||||||
import { uniqBy } from 'lodash'
|
import { uniqBy } from 'lodash'
|
||||||
import { searchLocalStatus } from './search'
|
import { searchLocalStatus } from './search'
|
||||||
import deleteItem from './timeline/deleteItem'
|
import deleteItem from './timeline/deleteItem'
|
||||||
import editItem from './timeline/editItem'
|
|
||||||
import updateStatusProperty from './timeline/updateStatusProperty'
|
import updateStatusProperty from './timeline/updateStatusProperty'
|
||||||
|
|
||||||
export type QueryKeyTimeline = [
|
export type QueryKeyTimeline = [
|
||||||
@ -248,8 +248,6 @@ enum MapPropertyToUrl {
|
|||||||
export type MutationVarsTimelineUpdateStatusProperty = {
|
export type MutationVarsTimelineUpdateStatusProperty = {
|
||||||
// This is status in general, including "status" inside conversation and notification
|
// This is status in general, including "status" inside conversation and notification
|
||||||
type: 'updateStatusProperty'
|
type: 'updateStatusProperty'
|
||||||
queryKey: QueryKeyTimeline
|
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
status: Mastodon.Status
|
status: Mastodon.Status
|
||||||
payload:
|
payload:
|
||||||
| {
|
| {
|
||||||
@ -279,7 +277,6 @@ export type MutationVarsTimelineUpdateStatusProperty = {
|
|||||||
export type MutationVarsTimelineUpdateAccountProperty = {
|
export type MutationVarsTimelineUpdateAccountProperty = {
|
||||||
// This is status in general, including "status" inside conversation and notification
|
// This is status in general, including "status" inside conversation and notification
|
||||||
type: 'updateAccountProperty'
|
type: 'updateAccountProperty'
|
||||||
queryKey?: QueryKeyTimeline
|
|
||||||
id: Mastodon.Account['id']
|
id: Mastodon.Account['id']
|
||||||
payload: {
|
payload: {
|
||||||
property: 'mute' | 'block' | 'reports'
|
property: 'mute' | 'block' | 'reports'
|
||||||
@ -287,34 +284,22 @@ export type MutationVarsTimelineUpdateAccountProperty = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MutationVarsTimelineEditItem = {
|
|
||||||
// This is for editing status
|
|
||||||
type: 'editItem'
|
|
||||||
queryKey?: QueryKeyTimeline
|
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
status: Mastodon.Status
|
|
||||||
}
|
|
||||||
|
|
||||||
export type MutationVarsTimelineDeleteItem = {
|
export type MutationVarsTimelineDeleteItem = {
|
||||||
// This is for deleting status and conversation
|
// This is for deleting status and conversation
|
||||||
type: 'deleteItem'
|
type: 'deleteItem'
|
||||||
source: 'statuses' | 'conversations'
|
source: 'statuses' | 'conversations'
|
||||||
queryKey?: QueryKeyTimeline
|
|
||||||
rootQueryKey?: QueryKeyTimeline
|
|
||||||
id: Mastodon.Status['id']
|
id: Mastodon.Status['id']
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MutationVarsTimelineDomainBlock = {
|
export type MutationVarsTimelineDomainBlock = {
|
||||||
// This is for deleting status and conversation
|
// This is for deleting status and conversation
|
||||||
type: 'domainBlock'
|
type: 'domainBlock'
|
||||||
queryKey: QueryKeyTimeline
|
|
||||||
domain: string
|
domain: string
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MutationVarsTimeline =
|
export type MutationVarsTimeline =
|
||||||
| MutationVarsTimelineUpdateStatusProperty
|
| MutationVarsTimelineUpdateStatusProperty
|
||||||
| MutationVarsTimelineUpdateAccountProperty
|
| MutationVarsTimelineUpdateAccountProperty
|
||||||
| MutationVarsTimelineEditItem
|
|
||||||
| MutationVarsTimelineDeleteItem
|
| MutationVarsTimelineDeleteItem
|
||||||
| MutationVarsTimelineDomainBlock
|
| MutationVarsTimelineDomainBlock
|
||||||
|
|
||||||
@ -380,8 +365,6 @@ const mutationFunction = async (params: MutationVarsTimeline) => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
case 'editItem':
|
|
||||||
return { body: params.status }
|
|
||||||
case 'deleteItem':
|
case 'deleteItem':
|
||||||
return apiInstance<Mastodon.Conversation>({
|
return apiInstance<Mastodon.Conversation>({
|
||||||
method: 'delete',
|
method: 'delete',
|
||||||
@ -415,6 +398,8 @@ const useTimelineMutation = ({
|
|||||||
onSettled?: MutationOptionsTimeline['onSettled']
|
onSettled?: MutationOptionsTimeline['onSettled']
|
||||||
onSuccess?: MutationOptionsTimeline['onSuccess']
|
onSuccess?: MutationOptionsTimeline['onSuccess']
|
||||||
}) => {
|
}) => {
|
||||||
|
const navigationState = useNavState()
|
||||||
|
|
||||||
return useMutation<
|
return useMutation<
|
||||||
{ body: Mastodon.Conversation | Mastodon.Notification | Mastodon.Status },
|
{ body: Mastodon.Conversation | Mastodon.Notification | Mastodon.Status },
|
||||||
AxiosError,
|
AxiosError,
|
||||||
@ -425,19 +410,16 @@ const useTimelineMutation = ({
|
|||||||
onSuccess,
|
onSuccess,
|
||||||
...(onMutate && {
|
...(onMutate && {
|
||||||
onMutate: params => {
|
onMutate: params => {
|
||||||
queryClient.cancelQueries(params.queryKey)
|
queryClient.cancelQueries(navigationState[0])
|
||||||
const oldData = params.queryKey && queryClient.getQueryData(params.queryKey)
|
const oldData = navigationState[0] && queryClient.getQueryData(navigationState[0])
|
||||||
|
|
||||||
haptics('Light')
|
haptics('Light')
|
||||||
switch (params.type) {
|
switch (params.type) {
|
||||||
case 'updateStatusProperty':
|
case 'updateStatusProperty':
|
||||||
updateStatusProperty(params)
|
updateStatusProperty(params, navigationState)
|
||||||
break
|
|
||||||
case 'editItem':
|
|
||||||
editItem(params)
|
|
||||||
break
|
break
|
||||||
case 'deleteItem':
|
case 'deleteItem':
|
||||||
deleteItem(params)
|
deleteItem(params, navigationState)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
return oldData
|
return oldData
|
||||||
|
@ -1,29 +1,31 @@
|
|||||||
import { InfiniteData } from '@tanstack/react-query'
|
import { InfiniteData } from '@tanstack/react-query'
|
||||||
import { queryClient } from '@utils/queryHooks'
|
import { queryClient } from '@utils/queryHooks'
|
||||||
import { MutationVarsTimelineDeleteItem } from '../timeline'
|
import { MutationVarsTimelineDeleteItem, QueryKeyTimeline, TimelineData } from '../timeline'
|
||||||
|
|
||||||
const deleteItem = ({ queryKey, rootQueryKey, id }: MutationVarsTimelineDeleteItem) => {
|
const deleteItem = (
|
||||||
queryKey &&
|
{ id }: MutationVarsTimelineDeleteItem,
|
||||||
queryClient.setQueryData<InfiniteData<any> | undefined>(queryKey, old => {
|
navigationState: (QueryKeyTimeline | undefined)[]
|
||||||
|
) => {
|
||||||
|
for (const key of navigationState) {
|
||||||
|
if (!key) continue
|
||||||
|
|
||||||
|
queryClient.setQueryData<InfiniteData<TimelineData> | undefined>(key, old => {
|
||||||
if (old) {
|
if (old) {
|
||||||
|
let foundToot: boolean = false
|
||||||
old.pages = old.pages.map(page => {
|
old.pages = old.pages.map(page => {
|
||||||
page.body = page.body.filter((item: Mastodon.Status) => item.id !== id)
|
if (foundToot) return page
|
||||||
|
|
||||||
|
page.body = (page.body as Mastodon.Status[]).filter(
|
||||||
|
(item: Mastodon.Status) => item.id !== id
|
||||||
|
)
|
||||||
|
|
||||||
return page
|
return page
|
||||||
})
|
})
|
||||||
return old
|
|
||||||
}
|
}
|
||||||
})
|
|
||||||
|
|
||||||
rootQueryKey &&
|
|
||||||
queryClient.setQueryData<InfiniteData<any> | undefined>(rootQueryKey, old => {
|
|
||||||
if (old) {
|
|
||||||
old.pages = old.pages.map(page => {
|
|
||||||
page.body = page.body.filter((item: Mastodon.Status) => item.id !== id)
|
|
||||||
return page
|
|
||||||
})
|
|
||||||
return old
|
return old
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export default deleteItem
|
export default deleteItem
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
import { InfiniteData } from '@tanstack/react-query'
|
|
||||||
import { queryClient } from '@utils/queryHooks'
|
|
||||||
import { MutationVarsTimelineEditItem } from '../timeline'
|
|
||||||
|
|
||||||
const editItem = ({ queryKey, rootQueryKey, status }: MutationVarsTimelineEditItem) => {
|
|
||||||
queryKey &&
|
|
||||||
queryClient.setQueryData<InfiniteData<any> | undefined>(queryKey, old => {
|
|
||||||
if (old) {
|
|
||||||
old.pages = old.pages.map(page => {
|
|
||||||
page.body = page.body.map((item: Mastodon.Status) => {
|
|
||||||
if (item.id === status.id) {
|
|
||||||
item = status
|
|
||||||
}
|
|
||||||
return item
|
|
||||||
})
|
|
||||||
return page
|
|
||||||
})
|
|
||||||
return old
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
rootQueryKey &&
|
|
||||||
queryClient.setQueryData<InfiniteData<any> | undefined>(rootQueryKey, old => {
|
|
||||||
if (old) {
|
|
||||||
old.pages = old.pages.map(page => {
|
|
||||||
page.body = page.body.map((item: Mastodon.Status) => {
|
|
||||||
if (item.id === status.id) {
|
|
||||||
item = status
|
|
||||||
}
|
|
||||||
return item
|
|
||||||
})
|
|
||||||
return page
|
|
||||||
})
|
|
||||||
return old
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
export default editItem
|
|
@ -1,72 +1,78 @@
|
|||||||
import { InfiniteData } from '@tanstack/react-query'
|
import { InfiniteData } from '@tanstack/react-query'
|
||||||
import { queryClient } from '@utils/queryHooks'
|
import { queryClient } from '@utils/queryHooks'
|
||||||
import { MutationVarsTimelineUpdateStatusProperty, TimelineData } from '../timeline'
|
import {
|
||||||
|
MutationVarsTimelineUpdateStatusProperty,
|
||||||
|
QueryKeyTimeline,
|
||||||
|
TimelineData
|
||||||
|
} from '../timeline'
|
||||||
|
|
||||||
const updateStatusProperty = ({
|
const updateStatusProperty = (
|
||||||
queryKey,
|
{ status, payload, poll }: MutationVarsTimelineUpdateStatusProperty & { poll?: Mastodon.Poll },
|
||||||
rootQueryKey,
|
navigationState: (QueryKeyTimeline | undefined)[]
|
||||||
status,
|
) => {
|
||||||
payload,
|
const update = (to?: Mastodon.Status): boolean => {
|
||||||
poll
|
if (!to) return false
|
||||||
}: MutationVarsTimelineUpdateStatusProperty & { poll?: Mastodon.Poll }) => {
|
|
||||||
for (const key of [queryKey, rootQueryKey]) {
|
|
||||||
if (!key) continue
|
|
||||||
|
|
||||||
queryClient.setQueryData<InfiniteData<TimelineData> | undefined>(key, old => {
|
|
||||||
if (old) {
|
|
||||||
let foundToot: Mastodon.Status | undefined = undefined
|
|
||||||
old.pages = old.pages.map(page => {
|
|
||||||
if (foundToot) {
|
|
||||||
return page
|
|
||||||
} else {
|
|
||||||
if (typeof (page.body as Mastodon.Conversation[])[0].unread === 'boolean') {
|
|
||||||
foundToot = (page.body as Mastodon.Conversation[]).find(({ last_status }) =>
|
|
||||||
last_status?.reblog
|
|
||||||
? last_status.reblog.id === status.id
|
|
||||||
: last_status?.id === status.id
|
|
||||||
)?.last_status
|
|
||||||
} else if (typeof (page.body as Mastodon.Notification[])[0].type === 'string') {
|
|
||||||
foundToot = (page.body as Mastodon.Notification[]).find(no =>
|
|
||||||
no.status?.reblog ? no.status.reblog.id === status.id : no.status?.id === status.id
|
|
||||||
)?.status
|
|
||||||
} else {
|
|
||||||
foundToot = (page.body as Mastodon.Status[]).find(toot =>
|
|
||||||
toot.reblog ? toot.reblog.id === status.id : toot.id === status.id
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return page
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
if (foundToot) {
|
|
||||||
const toot = foundToot as Mastodon.Status
|
|
||||||
enum MapPropertyToCount {
|
enum MapPropertyToCount {
|
||||||
favourited = 'favourites_count',
|
favourited = 'favourites_count',
|
||||||
reblogged = 'reblogs_count'
|
reblogged = 'reblogs_count'
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (payload.type) {
|
switch (payload.type) {
|
||||||
case 'poll':
|
case 'poll':
|
||||||
toot.poll = poll
|
to.poll = poll
|
||||||
break
|
return true
|
||||||
default:
|
default:
|
||||||
toot[payload.type] = payload.to
|
to[payload.type] = payload.to
|
||||||
switch (payload.type) {
|
switch (payload.type) {
|
||||||
case 'favourited':
|
case 'favourited':
|
||||||
case 'reblogged':
|
case 'reblogged':
|
||||||
if (payload.to) {
|
if (payload.to) {
|
||||||
toot[MapPropertyToCount[payload.type]]++
|
to[MapPropertyToCount[payload.type]]++
|
||||||
} else {
|
} else {
|
||||||
toot[MapPropertyToCount[payload.type]]--
|
to[MapPropertyToCount[payload.type]]--
|
||||||
}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const key of navigationState) {
|
||||||
|
if (!key) continue
|
||||||
|
|
||||||
|
queryClient.setQueryData<InfiniteData<TimelineData> | undefined>(key, old => {
|
||||||
|
if (old) {
|
||||||
|
let updated: boolean = false
|
||||||
|
old.pages = old.pages.map(page => {
|
||||||
|
if (updated) return page
|
||||||
|
|
||||||
|
if (typeof (page.body as Mastodon.Conversation[])[0].unread === 'boolean') {
|
||||||
|
;(page.body as Mastodon.Conversation[]).forEach(({ last_status }) => {
|
||||||
|
if (last_status?.reblog?.id === status.id) {
|
||||||
|
updated = update(last_status.reblog)
|
||||||
|
} else if (last_status?.id === status.id) {
|
||||||
|
updated = update(last_status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else if (typeof (page.body as Mastodon.Notification[])[0].type === 'string') {
|
||||||
|
;(page.body as Mastodon.Notification[]).forEach(no => {
|
||||||
|
if (no.status?.reblog?.id === status.id) {
|
||||||
|
updated = update(no.status.reblog)
|
||||||
|
} else if (no.status?.id === status.id) {
|
||||||
|
updated = update(no.status)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
;(page.body as Mastodon.Status[]).forEach(toot => {
|
||||||
|
if (toot.reblog?.id === status.id) {
|
||||||
|
updated = update(toot.reblog)
|
||||||
|
} else if (toot.id === status.id) {
|
||||||
|
updated = update(toot)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return page
|
||||||
|
})
|
||||||
|
}
|
||||||
return old
|
return old
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -5,8 +5,8 @@ export const dev = () => {
|
|||||||
if (__DEV__) {
|
if (__DEV__) {
|
||||||
log('log', 'dev', 'loading tools')
|
log('log', 'dev', 'loading tools')
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import('react-query-native-devtools').then(({ addPlugin }) => {
|
// import('react-query-native-devtools').then(({ addPlugin }) => {
|
||||||
addPlugin({ queryClient })
|
// addPlugin({ queryClient })
|
||||||
})
|
// })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user