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