From 06324ee51a03357654944db6bc03ca5aa76d04f4 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Wed, 4 Jan 2023 22:39:29 +0100 Subject: [PATCH 1/3] Believe #638 can be closed now! --- src/components/Timeline/Conversation.tsx | 5 +- src/components/Timeline/Default.tsx | 14 +- src/components/Timeline/Notifications.tsx | 5 +- src/components/Timeline/Shared/Actions.tsx | 18 +-- src/components/Timeline/Shared/Context.tsx | 1 - .../Timeline/Shared/HeaderAndroid.tsx | 7 +- .../Timeline/Shared/HeaderConversation.tsx | 1 - .../Timeline/Shared/HeaderDefault.tsx | 7 +- .../Timeline/Shared/HeaderNotification.tsx | 3 +- src/components/Timeline/Shared/Poll.tsx | 15 +-- src/components/contextMenu/account.ts | 23 ++-- src/components/contextMenu/instance.ts | 11 +- src/components/contextMenu/status.ts | 32 ++--- src/screens/Compose/index.tsx | 17 +-- src/screens/Tabs/Local/Root.tsx | 2 +- src/screens/Tabs/Me/Bookmarks.tsx | 11 +- src/screens/Tabs/Me/Cconversations.tsx | 11 +- src/screens/Tabs/Me/Favourites.tsx | 11 +- src/screens/Tabs/Me/List/List.tsx | 6 +- src/screens/Tabs/Me/List/index.tsx | 21 +-- src/screens/Tabs/Me/List/menus.tsx | 16 +-- src/screens/Tabs/Notifications/index.tsx | 49 +++---- src/screens/Tabs/Public/Root.tsx | 8 +- src/screens/Tabs/Shared/Account/index.tsx | 24 ++-- src/screens/Tabs/Shared/Attachments.tsx | 1 + src/screens/Tabs/Shared/Hashtag.tsx | 5 +- src/screens/Tabs/Shared/Toot.tsx | 12 +- src/utils/navigation/navigators.ts | 53 ++++---- src/utils/push/useNavigate.ts | 4 +- src/utils/queryHooks/timeline.ts | 32 +---- src/utils/queryHooks/timeline/deleteItem.ts | 34 ++--- src/utils/queryHooks/timeline/editItem.ts | 39 ------ .../timeline/updateStatusProperty.ts | 120 +++++++++--------- src/utils/startup/dev.ts | 6 +- 34 files changed, 278 insertions(+), 346 deletions(-) delete mode 100644 src/utils/queryHooks/timeline/editItem.ts diff --git a/src/components/Timeline/Conversation.tsx b/src/components/Timeline/Conversation.tsx index b32b4e81..3f492e49 100644 --- a/src/components/Timeline/Conversation.tsx +++ b/src/components/Timeline/Conversation.tsx @@ -41,10 +41,7 @@ const TimelineConversation: React.FC = ({ 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 }) } }, []) diff --git a/src/components/Timeline/Default.tsx b/src/components/Timeline/Default.tsx index 89d60d9d..e5caec31 100644 --- a/src/components/Timeline/Default.tsx +++ b/src/components/Timeline/Default.tsx @@ -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 = ({ item, queryKey, - rootQueryKey, highlighted = false, disableDetails = false, disableOnPress = false, @@ -131,8 +129,8 @@ const TimelineDefault: React.FC = ({ 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 = ({ = ({ 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()} /> diff --git a/src/components/Timeline/Notifications.tsx b/src/components/Timeline/Notifications.tsx index 75b7b030..1bc1bbb8 100644 --- a/src/components/Timeline/Notifications.tsx +++ b/src/components/Timeline/Notifications.tsx @@ -154,10 +154,7 @@ const TimelineNotifications: React.FC = ({ 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()} diff --git a/src/components/Timeline/Shared/Actions.tsx b/src/components/Timeline/Shared/Actions.tsx index 73314cc4..509d22a8 100644 --- a/src/components/Timeline/Shared/Actions.tsx +++ b/src/components/Timeline/Shared/Actions.tsx @@ -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>() 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', diff --git a/src/components/Timeline/Shared/Context.tsx b/src/components/Timeline/Shared/Context.tsx index cc23fb8c..7cba7d89 100644 --- a/src/components/Timeline/Shared/Context.tsx +++ b/src/components/Timeline/Shared/Context.tsx @@ -5,7 +5,6 @@ export type HighlightedStatusContextType = {} type StatusContextType = { queryKey?: QueryKeyTimeline - rootQueryKey?: QueryKeyTimeline status?: Mastodon.Status diff --git a/src/components/Timeline/Shared/HeaderAndroid.tsx b/src/components/Timeline/Shared/HeaderAndroid.tsx index 016ec0da..df9f35e9 100644 --- a/src/components/Timeline/Shared/HeaderAndroid.tsx +++ b/src/components/Timeline/Shared/HeaderAndroid.tsx @@ -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 ( diff --git a/src/components/Timeline/Shared/HeaderConversation.tsx b/src/components/Timeline/Shared/HeaderConversation.tsx index 69252478..d09bce7c 100644 --- a/src/components/Timeline/Shared/HeaderConversation.tsx +++ b/src/components/Timeline/Shared/HeaderConversation.tsx @@ -84,7 +84,6 @@ const HeaderConversation = ({ conversation }: Props) => { mutation.mutate({ type: 'deleteItem', source: 'conversations', - queryKey, id: conversation.id }) } diff --git a/src/components/Timeline/Shared/HeaderDefault.tsx b/src/components/Timeline/Shared/HeaderDefault.tsx index 48bf2e03..d69ba2fe 100644 --- a/src/components/Timeline/Shared/HeaderDefault.tsx +++ b/src/components/Timeline/Shared/HeaderDefault.tsx @@ -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 ( diff --git a/src/components/Timeline/Shared/HeaderNotification.tsx b/src/components/Timeline/Shared/HeaderNotification.tsx index 2c63182e..81ac44f9 100644 --- a/src/components/Timeline/Shared/HeaderNotification.tsx +++ b/src/components/Timeline/Shared/HeaderNotification.tsx @@ -41,8 +41,7 @@ const TimelineHeaderNotification: React.FC = ({ notification }) => { type: 'status', openChange, account: status?.account, - ...(status && { status }), - queryKey + ...(status && { status }) }) const mStatus = menuStatus({ status, queryKey }) const mInstance = menuInstance({ status, queryKey }) diff --git a/src/components/Timeline/Shared/Poll.tsx b/src/components/Timeline/Shared/Poll.tsx index d2de4b53..a69862bf 100644 --- a/src/components/Timeline/Shared/Poll.tsx +++ b/src/components/Timeline/Shared/Poll.tsx @@ -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', diff --git a/src/components/contextMenu/account.ts b/src/components/contextMenu/account.ts index dbaf6c09..17dc501e 100644 --- a/src/components/contextMenu/account.ts +++ b/src/components/contextMenu/account.ts @@ -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 & Pick status?: Mastodon.Status - queryKey?: QueryKeyTimeline - rootQueryKey?: QueryKeyTimeline }): ContextMenu[][] => { const navigation = useNavigation>() + 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(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 } }) diff --git a/src/components/contextMenu/instance.ts b/src/components/contextMenu/instance.ts index 2185f717..602a6ec3 100644 --- a/src/components/contextMenu/instance.ts +++ b/src/components/contextMenu/instance.ts @@ -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 }) } }, { diff --git a/src/components/contextMenu/status.ts b/src/components/contextMenu/status.ts index caed4a62..ee172db3 100644 --- a/src/components/contextMenu/status.ts +++ b/src/components/contextMenu/status.ts @@ -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', diff --git a/src/screens/Compose/index.tsx b/src/screens/Compose/index.tsx index b6c74688..33a22249 100644 --- a/src/screens/Compose/index.tsx +++ b/src/screens/Compose/index.tsx @@ -339,24 +339,25 @@ const ScreenCompose: React.FC> = ({ 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 } diff --git a/src/screens/Tabs/Local/Root.tsx b/src/screens/Tabs/Local/Root.tsx index 87426bea..57d65863 100644 --- a/src/screens/Tabs/Local/Root.tsx +++ b/src/screens/Tabs/Local/Root.tsx @@ -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 ) }) + navigation.setParams({ queryKey: queryKey }) }, [mode, queryKey[1], pageLocal, lists]) return ( diff --git a/src/screens/Tabs/Me/Bookmarks.tsx b/src/screens/Tabs/Me/Bookmarks.tsx index 68f904c0..808dc3e1 100644 --- a/src/screens/Tabs/Me/Bookmarks.tsx +++ b/src/screens/Tabs/Me/Bookmarks.tsx @@ -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> = ({ + navigation +}) => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }] + useEffect(() => { + navigation.setParams({ queryKey: queryKey }) + }, []) return ( { +const TabMeConversations: React.FC< + NativeStackScreenProps +> = ({ navigation }) => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Conversations' }] + useEffect(() => { + navigation.setParams({ queryKey: queryKey }) + }, []) return ( { +const TabMeFavourites: React.FC< + NativeStackScreenProps +> = ({ navigation }) => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }] + useEffect(() => { + navigation.setParams({ queryKey: queryKey }) + }, []) return ( > = ({ na return ( - {data?.map((params, index) => ( + {data?.map((list, index) => ( navigation.navigate('Tab-Me-List', params)} + title={list.title} + onPress={() => navigation.navigate('Tab-Me-List', { list })} /> ))} diff --git a/src/screens/Tabs/Me/List/index.tsx b/src/screens/Tabs/Me/List/index.tsx index 7de99133..5fe3cd7b 100644 --- a/src/screens/Tabs/Me/List/index.tsx +++ b/src/screens/Tabs/Me/List/index.tsx @@ -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> = ({ +const TabMeList: React.FC> = ({ 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> = ({ }) 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> = ({ ) }) - }, [params]) + navigation.setParams({ queryKey }) + }, [list]) return ( ({ +export const menuListAccounts = ({ list }: { list: Mastodon.List }) => ({ key: 'list-accounts', - onSelect: () => navigationRef.navigate('Tab-Me-List-Accounts', params), + onSelect: () => navigationRef.navigate('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('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 }) => ({ 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') } ] diff --git a/src/screens/Tabs/Notifications/index.tsx b/src/screens/Tabs/Notifications/index.tsx index 6dfbfcbf..7f60b75a 100644 --- a/src/screens/Tabs/Notifications/index.tsx +++ b/src/screens/Tabs/Notifications/index.tsx @@ -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() -const Root = () => { +const Root: React.FC< + NativeStackScreenProps +> = ({ navigation }) => { + const { t } = useTranslation('screenTabs') + const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Notifications' }] + useEffect(() => { + navigation.setOptions({ + title: t('tabs.notifications.name'), + headerRight: () => ( + navigation.navigate('Tab-Notifications-Filters')} + /> + ) + }) + navigation.setParams({ queryKey }) + }, []) + return ( { ) } -const TabNotifications = ({ navigation }: ScreenTabsScreenProps<'Tab-Notifications'>) => { - const { t } = useTranslation('screenTabs') - +const TabNotifications: React.FC = () => { usePopToTop() return ( - ( - - navigation.navigate('Tab-Notifications', { screen: 'Tab-Notifications-Filters' }) - } - /> - ) - }} - /> + { + const navigation = + useNavigation>() const queryKey: QueryKeyTimeline = ['Timeline', { page }] + useEffect(() => { + navigation.setParams({ queryKey }) + }, []) return ( } }) + const queryClient = useQueryClient() + const [queryKey, setQueryKey] = useState([ + '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 } }) }, [mAccount]) + useEffect(() => { + navigation.setParams({ queryKey }) + }, [queryKey[1]]) const scrollY = useSharedValue(0) - const queryClient = useQueryClient() - const [queryKey, setQueryKey] = useState([ - 'Timeline', - { - page: 'Account', - id: account._remote ? data?.id : account.id, - exclude_reblogs: true, - only_media: false - } - ]) const page = queryKey[1] const [segment, setSegment] = useState(0) diff --git a/src/screens/Tabs/Shared/Attachments.tsx b/src/screens/Tabs/Shared/Attachments.tsx index 022c6306..11f420fe 100644 --- a/src/screens/Tabs/Shared/Attachments.tsx +++ b/src/screens/Tabs/Shared/Attachments.tsx @@ -41,6 +41,7 @@ const TabSharedAttachments: React.FC ) }) + navigation.setParams({ queryKey }) }, []) const queryKey: QueryKeyTimeline = [ diff --git a/src/screens/Tabs/Shared/Hashtag.tsx b/src/screens/Tabs/Shared/Hashtag.tsx index dced90cb..542fe67b 100644 --- a/src/screens/Tabs/Shared/Hashtag.tsx +++ b/src/screens/Tabs/Shared/Hashtag.tsx @@ -17,15 +17,16 @@ const TabSharedHashtag: React.FC params: { hashtag } } }) => { + const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Hashtag', hashtag }] + useEffect(() => { navigation.setOptions({ headerLeft: () => 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') diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index ad999c54..60baf80a 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -21,13 +21,17 @@ import { Path, Svg } from 'react-native-svg' const TabSharedToot: React.FC> = ({ navigation, route: { - params: { toot, rootQueryKey } + params: { toot } } }) => { const { colors } = useTheme() const { t } = useTranslation(['componentTimeline', 'screenTabs']) const [hasRemoteContent, setHasRemoteContent] = useState(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> = ({ ), headerLeft: () => navigation.goBack()} /> }) + navigation.setParams({ toot, queryKey: toot._remote ? queryKey.remote : queryKey.local }) }, [hasRemoteContent]) const flRef = useRef(null) @@ -71,10 +76,6 @@ const TabSharedToot: React.FC> = ({ { ...toot, _level: 0, key: 'cached' } ]) const highlightIndex = useRef(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> = ({ diff --git a/src/utils/navigation/navigators.ts b/src/utils/navigation/navigators.ts index 79237400..86252a1a 100644 --- a/src/utils/navigation/navigators.ts +++ b/src/utils/navigation/navigators.ts @@ -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 '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 = Bo export type TabSharedStackParamList = { 'Tab-Shared-Account': { account: Pick + queryKey?: QueryKeyTimeline } - 'Tab-Shared-Account-In-Lists': { - account: Pick - } - '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 } + '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 status?: Pick } '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 = NativeStackScreenProps 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 = @@ -140,11 +139,11 @@ export type TabNotificationsStackScreenProps 'Tab-Me-List-Edit': | { diff --git a/src/utils/push/useNavigate.ts b/src/utils/push/useNavigate.ts index bd519ca0..79b42ea0 100644 --- a/src/utils/push/useNavigate.ts +++ b/src/utils/push/useNavigate.ts @@ -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) { diff --git a/src/utils/queryHooks/timeline.ts b/src/utils/queryHooks/timeline.ts index 70d204df..d313d423 100644 --- a/src/utils/queryHooks/timeline.ts +++ b/src/utils/queryHooks/timeline.ts @@ -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({ 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 diff --git a/src/utils/queryHooks/timeline/deleteItem.ts b/src/utils/queryHooks/timeline/deleteItem.ts index ac920df2..e872ce3d 100644 --- a/src/utils/queryHooks/timeline/deleteItem.ts +++ b/src/utils/queryHooks/timeline/deleteItem.ts @@ -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 | undefined>(queryKey, old => { +const deleteItem = ( + { id }: MutationVarsTimelineDeleteItem, + navigationState: (QueryKeyTimeline | undefined)[] +) => { + for (const key of navigationState) { + if (!key) continue + + queryClient.setQueryData | 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 | 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 diff --git a/src/utils/queryHooks/timeline/editItem.ts b/src/utils/queryHooks/timeline/editItem.ts deleted file mode 100644 index 22a3542f..00000000 --- a/src/utils/queryHooks/timeline/editItem.ts +++ /dev/null @@ -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 | 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 | 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 diff --git a/src/utils/queryHooks/timeline/updateStatusProperty.ts b/src/utils/queryHooks/timeline/updateStatusProperty.ts index 24b03408..ee096549 100644 --- a/src/utils/queryHooks/timeline/updateStatusProperty.ts +++ b/src/utils/queryHooks/timeline/updateStatusProperty.ts @@ -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 | 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 }) } diff --git a/src/utils/startup/dev.ts b/src/utils/startup/dev.ts index 981c8f7a..8c9dd394 100644 --- a/src/utils/startup/dev.ts +++ b/src/utils/startup/dev.ts @@ -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 }) + // }) } } From bb9fa0c752f2beb1cf28db69cc97f77d21b7abdc Mon Sep 17 00:00:00 2001 From: xmflsct Date: Wed, 4 Jan 2023 23:12:18 +0100 Subject: [PATCH 2/3] Improved history diff --- fastlane/metadata/en-US/release_notes.txt | 1 + fastlane/metadata/zh-Hans/release_notes.txt | 1 + .../Shared/HeaderShared/Application.tsx | 4 +-- src/screens/Tabs/Shared/History.tsx | 35 ++++++++++++++++--- src/screens/Tabs/Shared/Toot.tsx | 4 +-- 5 files changed, 37 insertions(+), 8 deletions(-) diff --git a/fastlane/metadata/en-US/release_notes.txt b/fastlane/metadata/en-US/release_notes.txt index 62516967..87d4f712 100644 --- a/fastlane/metadata/en-US/release_notes.txt +++ b/fastlane/metadata/en-US/release_notes.txt @@ -1,4 +1,5 @@ Enjoy toooting! This version includes following improvements and fixes: +- Auto fetch remote content in conversations! - Allowing adding more context of reports - Option to disable autoplay gif - Hide boosts from users diff --git a/fastlane/metadata/zh-Hans/release_notes.txt b/fastlane/metadata/zh-Hans/release_notes.txt index 8225007b..41ef5bc6 100644 --- a/fastlane/metadata/zh-Hans/release_notes.txt +++ b/fastlane/metadata/zh-Hans/release_notes.txt @@ -1,4 +1,5 @@ toooting愉快!此版本包括以下改进和修复: +- 主动获取对话的远程内容 - 可添加举报细节 - 新增暂停自动播放gif动画选项 - 隐藏用户的转嘟 diff --git a/src/components/Timeline/Shared/HeaderShared/Application.tsx b/src/components/Timeline/Shared/HeaderShared/Application.tsx index 2e021b2f..09d1ddba 100644 --- a/src/components/Timeline/Shared/HeaderShared/Application.tsx +++ b/src/components/Timeline/Shared/HeaderShared/Application.tsx @@ -7,11 +7,11 @@ import { useTranslation } from 'react-i18next' import StatusContext from '../Context' const HeaderSharedApplication: React.FC = () => { - const { status } = useContext(StatusContext) + const { status, isConversation } = useContext(StatusContext) const { colors } = useTheme() const { t } = useTranslation('componentTimeline') - return status?.application?.name && status.application.name !== 'Web' ? ( + return !isConversation && status?.application?.name && status.application.name !== 'Web' ? ( + withoutBoundary + ? prevItem?.poll?.options[index].title + ? diffChars(prevItem?.poll?.options[index].title, option.title) + : undefined + : prevItem?.poll?.options[index].title + ? diffWords(prevItem?.poll?.options[index].title, option.title) + : undefined + ) + : null return ( // @ts-ignore @@ -92,12 +103,28 @@ const ContentView: React.FC<{ paddingTop: StyleConstants.Font.LineHeight.M - StyleConstants.Font.Size.M, marginRight: StyleConstants.Spacing.S }} - name='Circle' + name={item.poll?.multiple ? 'Square' : 'Circle'} size={StyleConstants.Font.Size.M} - color={colors.disabled} + color={ + prevItem?.poll?.multiple !== item.poll?.multiple ? colors.red : colors.disabled + } /> - - + + {changesPoll?.[index]?.length ? ( + changesPoll[index]?.map(({ value, added, removed }, index) => ( + + )) + ) : ( + + )} diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index 60baf80a..3630781e 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -368,7 +368,7 @@ const TabSharedToot: React.FC> = ({ }) : null} {/* > = ({ style={{ position: 'absolute', top: 20, left: 4, color: colors.yellow }} /> */} From feadcc019c292e30fcc4f2c38861523b40a2f328 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Thu, 5 Jan 2023 00:49:10 +0100 Subject: [PATCH 3/3] Updates --- ...t-native-fast-image-npm-8.6.3-03ee2d23c0.patch | 4 ++-- ios/Podfile.lock | 12 ++++++------ src/components/Parse/HTML.tsx | 15 ++++++++++----- src/components/Timeline/Shared/Content.tsx | 4 ++++ src/screens/Tabs/Shared/Account/index.tsx | 3 ++- src/utils/navigation/navigators.ts | 3 ++- yarn.lock | 4 ++-- 7 files changed, 28 insertions(+), 17 deletions(-) diff --git a/.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch b/.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch index a80e96b4..93b92243 100644 --- a/.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch +++ b/.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch @@ -1,5 +1,5 @@ diff --git a/RNFastImage.podspec b/RNFastImage.podspec -index db0fada63fc06191f8620d336d244edde6c3dba3..b23cd91a9d70bdb8abd2f4ba1417c2c35e5a1d4c 100644 +index db0fada63fc06191f8620d336d244edde6c3dba3..b6ffe6c77ab1fd5b821525f6f0b7363a13cba3a0 100644 --- a/RNFastImage.podspec +++ b/RNFastImage.podspec @@ -16,6 +16,6 @@ Pod::Spec.new do |s| @@ -8,7 +8,7 @@ index db0fada63fc06191f8620d336d244edde6c3dba3..b23cd91a9d70bdb8abd2f4ba1417c2c3 s.dependency 'React-Core' - s.dependency 'SDWebImage', '~> 5.11.1' - s.dependency 'SDWebImageWebPCoder', '~> 0.8.4' -+ s.dependency 'SDWebImage', '~> 5.14.2' ++ s.dependency 'SDWebImage', '~> 5.14.3' + s.dependency 'SDWebImageWebPCoder', '~> 0.9.1' end diff --git a/android/build.gradle b/android/build.gradle diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 1620ad57..6aaa6e64 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -398,7 +398,7 @@ PODS: - React-Core - RNFastImage (8.6.3): - React-Core - - SDWebImage (~> 5.14.2) + - SDWebImage (~> 5.14.3) - SDWebImageWebPCoder (~> 0.9.1) - RNGestureHandler (2.8.0): - React-Core @@ -439,9 +439,9 @@ PODS: - React - RNSVG (13.6.0): - React-Core - - SDWebImage (5.14.2): - - SDWebImage/Core (= 5.14.2) - - SDWebImage/Core (5.14.2) + - SDWebImage (5.14.3): + - SDWebImage/Core (= 5.14.3) + - SDWebImage/Core (5.14.3) - SDWebImageWebPCoder (0.9.1): - libwebp (~> 1.0) - SDWebImage/Core (~> 5.13) @@ -769,14 +769,14 @@ SPEC CHECKSUMS: ReactCommon: 349be31adeecffc7986a0de875d7fb0dcf4e251c RNCAsyncStorage: 8616bd5a58af409453ea4e1b246521bb76578d60 RNCClipboard: 2834e1c4af68697089cdd455ee4a4cdd198fa7dd - RNFastImage: c5dd1b551779c5826fe43b7d36788385da2021e2 + RNFastImage: 756ab178acb5e3f11d8b0a931956fbd9da8d6e54 RNGestureHandler: 62232ba8f562f7dea5ba1b3383494eb5bf97a4d3 RNReanimated: ce445c233a6ff5600223484a88ad5704945d972a RNScreens: 34cc502acf1b916c582c60003dc3089fa01dc66d RNSentry: 4c09f4dd9740cb9b33e94303de5b6d0dbeb0737d RNShareMenu: cb9dac548c8bf147d06f0bf07296ad51ea9f5fc3 RNSVG: 3a79c0c4992213e4f06c08e62730c5e7b9e4dc17 - SDWebImage: b9a731e1d6307f44ca703b3976d18c24ca561e84 + SDWebImage: 9c36e66c8ce4620b41a7407698dda44211a96764 SDWebImageWebPCoder: 18503de6621dd2c420d680e33d46bf8e1d5169b0 Sentry: 08884c523575ec0f6690d94ed3ccb0246a1600bf Swime: d7b2c277503b6cea317774aedc2dce05613f8b0b diff --git a/src/components/Parse/HTML.tsx b/src/components/Parse/HTML.tsx index 246f839a..a9e213af 100644 --- a/src/components/Parse/HTML.tsx +++ b/src/components/Parse/HTML.tsx @@ -87,14 +87,14 @@ const ParseHTML: React.FC = ({ return '' } } - const openingMentions = useRef(true) + const prevMentionRemoved = useRef(false) const renderNode = (node: ChildNode, index: number) => { switch (node.type) { case ElementType.Text: let content: string = node.data - if (openingMentions.current) { + if (prevMentionRemoved.current) { + prevMentionRemoved.current = false // Removing empty spaces appeared between tags and mentions if (node.data.trim().length) { - openingMentions.current = false // Removing empty spaces appeared between tags and mentions content = excludeMentions?.current.length ? node.data.replace(new RegExp(/^\s+/), '') : node.data @@ -119,7 +119,6 @@ const ParseHTML: React.FC = ({ const href = node.attribs.href if (classes) { if (classes.includes('hashtag')) { - openingMentions.current = false const tag = href.match(new RegExp(/\/tags?\/(.*)/, 'i'))?.[1].toLowerCase() const paramsHashtag = (params as { hashtag: Mastodon.Tag['name'] } | undefined) ?.hashtag @@ -156,6 +155,7 @@ const ParseHTML: React.FC = ({ matchedMention && excludeMentions?.current.find(eM => eM.id === matchedMention.id) ) { + prevMentionRemoved.current = true return null } const paramsAccount = (params as { account: Mastodon.Account } | undefined)?.account @@ -176,7 +176,6 @@ const ParseHTML: React.FC = ({ } } - openingMentions.current = false const content = node.children.map(child => unwrapNode(child)).join('') const shouldBeTag = status?.tags?.find(tag => `#${tag.name}` === content) return ( @@ -198,6 +197,12 @@ const ParseHTML: React.FC = ({ /> ) break + case 'br': + return ( + + {'\n'} + + ) case 'p': if (index < document.children.length - 1) { return ( diff --git a/src/components/Timeline/Shared/Content.tsx b/src/components/Timeline/Shared/Content.tsx index 3a738fb6..f7b41113 100644 --- a/src/components/Timeline/Shared/Content.tsx +++ b/src/components/Timeline/Shared/Content.tsx @@ -24,6 +24,10 @@ const TimelineContent: React.FC = ({ notificationOwnToot = false, setSpoi return ( + {/* mention.username).join(' - ')} + style={{ color: colors.secondary }} + /> */} {status.spoiler_text?.length ? ( <> } ]) } - } + }, + onError: () => navigation.goBack() } }) diff --git a/src/utils/navigation/navigators.ts b/src/utils/navigation/navigators.ts index 86252a1a..6db71913 100644 --- a/src/utils/navigation/navigators.ts +++ b/src/utils/navigation/navigators.ts @@ -92,7 +92,8 @@ export type ScreenTabsScreenProps = Bo export type TabSharedStackParamList = { 'Tab-Shared-Account': { - account: Pick + account: Partial> & + Pick queryKey?: QueryKeyTimeline } 'Tab-Shared-Account-In-Lists': { account: Pick } diff --git a/yarn.lock b/yarn.lock index a28945f8..67e094aa 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9491,11 +9491,11 @@ __metadata: "react-native-fast-image@patch:react-native-fast-image@npm%3A8.6.3#./.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch::locator=tooot%40workspace%3A.": version: 8.6.3 - resolution: "react-native-fast-image@patch:react-native-fast-image@npm%3A8.6.3#./.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch::version=8.6.3&hash=61017c&locator=tooot%40workspace%3A." + resolution: "react-native-fast-image@patch:react-native-fast-image@npm%3A8.6.3#./.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch::version=8.6.3&hash=d37d57&locator=tooot%40workspace%3A." peerDependencies: react: ^17 || ^18 react-native: ">=0.60.0" - checksum: ffdd0bdf16ef618235bdac64771bb41fb26142737aa98c2c49679025ab1f97e3c8e8d09e23ba2ebe780691f1d11df5e154576f40e057797923a09fa945db8c1b + checksum: e5749406ed7608d606df8a7d298a6adaeefdf1077e5349ceb51b344e1fc9de62923f0af05c753c0baa59f476be6d46aee20a20c92c7840a30d8b473a156dfec5 languageName: node linkType: hard