From 18ad22302d736edca2c33b450837c338985e4013 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Mon, 16 Jan 2023 18:50:18 +0100 Subject: [PATCH 1/6] Attempt to fix #644 --- ...ve-ios-context-menu-npm-1.15.1-0034bfa5ba.patch | 14 ++++++++++++++ package.json | 3 ++- 2 files changed, 16 insertions(+), 1 deletion(-) create mode 100644 .yarn/patches/react-native-ios-context-menu-npm-1.15.1-0034bfa5ba.patch diff --git a/.yarn/patches/react-native-ios-context-menu-npm-1.15.1-0034bfa5ba.patch b/.yarn/patches/react-native-ios-context-menu-npm-1.15.1-0034bfa5ba.patch new file mode 100644 index 00000000..5e62a401 --- /dev/null +++ b/.yarn/patches/react-native-ios-context-menu-npm-1.15.1-0034bfa5ba.patch @@ -0,0 +1,14 @@ +diff --git a/src/functions/Helpers.ts b/src/functions/Helpers.ts +index e04486540494891ab07ec130b686dc4acddf2d0c..265e6ac11439276a1c52c222dfc4c50daf1689ae 100644 +--- a/src/functions/Helpers.ts ++++ b/src/functions/Helpers.ts +@@ -77,7 +77,8 @@ export function getNativeNodeHandle(nativeRef: React.Component){ + const nodeHandle = findNodeHandle(nativeRef); + + if(nodeHandle == null){ +- throw new Error('Unable to get the node handle for the native ref.'); ++ return 0 ++ // throw new Error('Unable to get the node handle for the native ref.'); + }; + + return nodeHandle; diff --git a/package.json b/package.json index 2dfb17f7..14f3da27 100644 --- a/package.json +++ b/package.json @@ -119,6 +119,7 @@ "react-native-fast-image@^8.6.3": "patch:react-native-fast-image@npm%3A8.6.3#./.yarn/patches/react-native-fast-image-npm-8.6.3-03ee2d23c0.patch", "expo-av@^13.0.2": "patch:expo-av@npm%3A13.0.2#./.yarn/patches/expo-av-npm-13.0.2-7a651776f1.patch", "react-native-share-menu@^6.0.0": "patch:react-native-share-menu@npm%3A6.0.0#./.yarn/patches/react-native-share-menu-npm-6.0.0-f1094c3204.patch", - "@types/react-native-share-menu@^5.0.2": "patch:@types/react-native-share-menu@npm%3A5.0.2#./.yarn/patches/@types-react-native-share-menu-npm-5.0.2-373df17ecc.patch" + "@types/react-native-share-menu@^5.0.2": "patch:@types/react-native-share-menu@npm%3A5.0.2#./.yarn/patches/@types-react-native-share-menu-npm-5.0.2-373df17ecc.patch", + "react-native-ios-context-menu@^1.15.1": "patch:react-native-ios-context-menu@npm%3A1.15.1#./.yarn/patches/react-native-ios-context-menu-npm-1.15.1-0034bfa5ba.patch" } } From 74e794a215149b567c6fb74c11b8f19d5ebd4108 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Mon, 16 Jan 2023 18:56:15 +0100 Subject: [PATCH 2/6] Fix some Sentry reported crashes --- src/screens/Tabs/Me/Root/Collections.tsx | 6 +++--- src/utils/helpers/removeHTML.ts | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/screens/Tabs/Me/Root/Collections.tsx b/src/screens/Tabs/Me/Root/Collections.tsx index 8e99c785..ffe0e532 100644 --- a/src/screens/Tabs/Me/Root/Collections.tsx +++ b/src/screens/Tabs/Me/Root/Collections.tsx @@ -60,7 +60,7 @@ const Collections: React.FC = () => { title={t('screenTabs:me.stacks.favourites.name')} onPress={() => navigation.navigate('Tab-Me-Favourites')} /> - {pageMe.lists?.shown ? ( + {pageMe?.lists?.shown ? ( { onPress={() => navigation.navigate('Tab-Me-List-List')} /> ) : null} - {pageMe.followedTags?.shown ? ( + {pageMe?.followedTags?.shown ? ( { onPress={() => navigation.navigate('Tab-Me-FollowedTags')} /> ) : null} - {pageMe.announcements?.shown ? ( + {pageMe?.announcements?.shown ? ( { + if (!text) return '' + let raw: string = '' const parser = new htmlparser2.Parser({ From 196f51bfca7cc45b4826693f8f0259897d34f554 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Mon, 16 Jan 2023 22:11:41 +0100 Subject: [PATCH 3/6] Refine account switching Part of #663 --- src/App.tsx | 34 ++--------- src/components/Instance/index.tsx | 14 +++-- src/screens/index.tsx | 24 +------- src/utils/helpers/featureCheck.ts | 8 +-- src/utils/startup/netInfo.ts | 54 +---------------- src/utils/storage/actions.ts | 97 ++++++++++++++++++++++--------- 6 files changed, 89 insertions(+), 142 deletions(-) diff --git a/src/App.tsx b/src/App.tsx index 427e18ad..c1d671e2 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -10,13 +10,7 @@ import log from '@utils/startup/log' import netInfo from '@utils/startup/netInfo' import push from '@utils/startup/push' import sentry from '@utils/startup/sentry' -import { storage } from '@utils/storage' -import { - getGlobalStorage, - removeAccount, - setAccount, - setGlobalStorage -} from '@utils/storage/actions' +import { getGlobalStorage, setAccount, setGlobalStorage } from '@utils/storage/actions' import { migrateFromAsyncStorage, versionStorageGlobal } from '@utils/storage/migrations/toMMKV' import ThemeManager from '@utils/styles/ThemeManager' import * as Localization from 'expo-localization' @@ -24,7 +18,6 @@ import * as SplashScreen from 'expo-splash-screen' import React, { useCallback, useEffect, useState } from 'react' import { LogBox, Platform } from 'react-native' import { GestureHandlerRootView } from 'react-native-gesture-handler' -import { MMKV } from 'react-native-mmkv' import { SafeAreaProvider } from 'react-native-safe-area-context' import { enableFreeze } from 'react-native-screens' import i18n from './i18n' @@ -36,6 +29,7 @@ Platform.select({ dev() sentry() +netInfo() audio() push() enableFreeze(true) @@ -46,7 +40,6 @@ SplashScreen.preventAutoHideAsync() const App: React.FC = () => { log('log', 'App', 'rendering App') const [appIsReady, setAppIsReady] = useState(false) - const [localCorrupt, setLocalCorrupt] = useState() const [hasMigrated, setHasMigrated] = useState(versionStorageGlobal !== undefined) @@ -61,36 +54,19 @@ const App: React.FC = () => { log('log', 'App', 'loading from MMKV') const account = getGlobalStorage.string('account.active') if (account) { - const storageAccount = new MMKV({ id: account }) - const token = storageAccount.getString('auth.token') - if (token) { - log('log', 'App', `Binding storage of ${account}`) - storage.account = storageAccount - } else { - log('log', 'App', `Token not found for ${account}`) - removeAccount(account) - } + await setAccount(account) } else { log('log', 'App', 'No active account available') const accounts = getGlobalStorage.object('accounts') if (accounts?.length) { log('log', 'App', `Setting active account ${accounts[accounts.length - 1]}`) - setAccount(accounts[accounts.length - 1]) + await setAccount(accounts[accounts.length - 1]) } else { setGlobalStorage('account.active', undefined) } } } - let netInfoRes = undefined - try { - netInfoRes = await netInfo() - } catch {} - - if (netInfoRes && netInfoRes.corrupted && netInfoRes.corrupted.length) { - setLocalCorrupt(netInfoRes.corrupted) - } - log('log', 'App', `locale: ${Localization.locale}`) const language = getLanguage() if (!language) { @@ -124,7 +100,7 @@ const App: React.FC = () => { - + diff --git a/src/components/Instance/index.tsx b/src/components/Instance/index.tsx index 9b53312d..5d8e829d 100644 --- a/src/components/Instance/index.tsx +++ b/src/components/Instance/index.tsx @@ -193,10 +193,12 @@ const ComponentInstance: React.FC = ({ } }) - const scopes = featureCheck('deprecate_auth_follow') - ? ['read', 'write', 'push'] - : ['read', 'write', 'follow', 'push'] const processUpdate = useCallback(() => { + const scopes = () => + featureCheck('deprecate_auth_follow', instanceQuery.data?.version) + ? ['read', 'write', 'push'] + : ['read', 'write', 'follow', 'push'] + if (domain) { const accounts = getGlobalStorage.object('accounts') if (accounts?.filter(account => account.startsWith(`${domain}/`)).length) { @@ -210,15 +212,15 @@ const ComponentInstance: React.FC = ({ }, { text: t('common:buttons.continue'), - onPress: () => appsMutation.mutate({ domain, scopes }) + onPress: () => appsMutation.mutate({ domain, scopes: scopes() }) } ] ) } else { - appsMutation.mutate({ domain, scopes }) + appsMutation.mutate({ domain, scopes: scopes() }) } } - }, [domain]) + }, [domain, instanceQuery.data?.version]) return ( () -export interface Props { - localCorrupt?: string -} - -const Screens: React.FC = ({ localCorrupt }) => { +const Screens: React.FC = () => { const { t, i18n } = useTranslation([ 'common', 'screens', @@ -64,24 +60,6 @@ const Screens: React.FC = ({ localCorrupt }) => { return () => screenshotListener.remove() }, []) - // On launch display login credentials corrupt information - useEffect(() => { - const showLocalCorrect = () => { - if (localCorrupt) { - displayMessage({ - message: t('screens:localCorrupt.message'), - description: localCorrupt.length ? localCorrupt : undefined, - type: 'danger' - }) - // @ts-ignore - navigationRef.navigate('Screen-Tabs', { - screen: 'Tab-Me' - }) - } - } - return showLocalCorrect() - }, [localCorrupt]) - // Lazily update users's preferences, for e.g. composing default visibility useInstanceQuery({ options: { enabled: !!accountActive } }) useProfileQuery({ options: { enabled: !!accountActive } }) diff --git a/src/utils/helpers/featureCheck.ts b/src/utils/helpers/featureCheck.ts index ff6f4310..83acf784 100644 --- a/src/utils/helpers/featureCheck.ts +++ b/src/utils/helpers/featureCheck.ts @@ -51,8 +51,6 @@ const features = [ } ] -export const featureCheck = (feature: string): boolean => { - const version = getAccountStorage.string('version') - return !!features.filter(f => f.feature === feature).filter(f => parseFloat(version) >= f.version) - ?.length -} +export const featureCheck = (feature: string, v?: string): boolean => + (features.find(f => f.feature === feature)?.version || 999) <= + parseFloat(v || getAccountStorage.string('version')) diff --git a/src/utils/startup/netInfo.ts b/src/utils/startup/netInfo.ts index d20e558f..800e8af7 100644 --- a/src/utils/startup/netInfo.ts +++ b/src/utils/startup/netInfo.ts @@ -1,67 +1,15 @@ import NetInfo from '@react-native-community/netinfo' import { onlineManager } from '@tanstack/react-query' -import apiInstance from '@utils/api/instance' -import { storage } from '@utils/storage' -import { getAccountStorage, removeAccount, setAccountStorage } from '@utils/storage/actions' import log from './log' -const netInfo = async (): Promise<{ - connected?: boolean - corrupted?: string -} | void> => { +const netInfo = () => { log('log', 'netInfo', 'initializing') - const netInfo = await NetInfo.fetch() - onlineManager.setEventListener(setOnline => { return NetInfo.addEventListener(state => { setOnline(!!state.isConnected) }) }) - - if (netInfo.isConnected) { - log('log', 'netInfo', 'network connected') - if (storage.account) { - const domain = getAccountStorage.string('auth.domain') - const id = getAccountStorage.string('auth.account.id') - const account = `${domain}/${id}` - log('log', 'netInfo', 'checking locally stored credentials') - - let resVerify: Mastodon.Account - try { - resVerify = await apiInstance({ - method: 'get', - url: `accounts/verify_credentials` - }).then(res => res.body) - } catch (error: any) { - log('error', 'netInfo', 'local credential check failed') - if (error?.status && error.status == 401) { - removeAccount(account) - } - return Promise.resolve({ corrupted: error.data?.error }) - } - - log('log', 'netInfo', 'local credential check passed') - if (resVerify.id !== id) { - log('error', 'netInfo', 'local id does not match remote id') - removeAccount(account) - return Promise.resolve({ connected: true, corrupted: '' }) - } else { - setAccountStorage([ - { key: 'auth.account.acct', value: resVerify.acct }, - { key: 'auth.account.avatar_static', value: resVerify.avatar_static } - ]) - - return Promise.resolve({ connected: true }) - } - } else { - log('log', 'netInfo', 'no local credential found') - return Promise.resolve() - } - } else { - log('warn', 'netInfo', 'network not connected') - return Promise.resolve() - } } export default netInfo diff --git a/src/utils/storage/actions.ts b/src/utils/storage/actions.ts index 584c4005..d0383e1f 100644 --- a/src/utils/storage/actions.ts +++ b/src/utils/storage/actions.ts @@ -1,4 +1,9 @@ +import { displayMessage } from '@components/Message' +import i18n from '@i18n/index' +import apiGeneral from '@utils/api/general' +import navigationRef from '@utils/navigation/navigationRef' import { queryClient } from '@utils/queryHooks' +import log from '@utils/startup/log' import { storage } from '@utils/storage' import { Platform } from 'react-native' import { @@ -222,10 +227,72 @@ export const generateAccountKey = ({ }) => `${domain}/${id}` export const setAccount = async (account: string) => { - storage.account = new MMKV({ id: account }) - setGlobalStorage('account.active', account) - await queryClient.resetQueries() - queryClient.clear() + const temp = new MMKV({ id: account }) + const token = temp.getString('auth.token') + const domain = temp.getString('auth.domain') + + if (!token || !domain) { + await removeAccount(account) + return + } + + await apiGeneral({ + method: 'get', + domain, + url: 'api/v1/accounts/verify_credentials', + headers: { + Authorization: `Bearer ${token}` + } + }) + .then(res => res.body) + .then(async a => { + temp.set('auth.account.acct', a.acct) + temp.set('auth.account.avatar_static', a.avatar_static) + + log('log', 'setAccount', `binding storage of ${account}`) + await queryClient.resetQueries() + queryClient.clear() + + storage.account = temp + setGlobalStorage('account.active', account) + }) + .catch(async error => { + if (error?.status && error.status == 401) { + log('log', 'setAccount', `unauthorised ${account}`) + await removeAccount(account) + } + }) +} + +export const removeAccount = async (account: string) => { + displayMessage({ + message: i18n.t('screens:localCorrupt.message'), + type: 'danger' + }) + // @ts-ignore + navigationRef.navigate('Screen-Tabs', { screen: 'Tab-Me' }) + + const currAccounts: NonNullable = + getGlobalStorage.object('accounts') || [] + const nextAccounts: NonNullable = currAccounts.filter( + a => a !== account + ) + + storage.global.set('accounts', JSON.stringify(nextAccounts)) + + if (nextAccounts.length) { + log('log', 'removeAccount', `trying next account ${nextAccounts[nextAccounts.length - 1]}`) + await setAccount(nextAccounts[nextAccounts.length - 1]) + } else { + log('log', 'removeAccount', 'setting to undefined') + await queryClient.resetQueries() + queryClient.clear() + + storage.account = undefined + setGlobalStorage('account.active', undefined) + } + + new MMKV({ id: account }).clearAll() } export type ReadableAccountType = { @@ -263,25 +330,3 @@ export const getReadableAccounts = (withoutActive: boolean = false): ReadableAcc }) || [] ).filter(a => a.acct.length) } - -export const removeAccount = async (account: string) => { - const currAccounts: NonNullable = JSON.parse( - storage.global.getString('accounts') || '[]' - ) - const nextAccounts: NonNullable = currAccounts.filter( - a => a !== account - ) - - storage.global.set('accounts', JSON.stringify(nextAccounts)) - - if (nextAccounts.length) { - await setAccount(nextAccounts[nextAccounts.length - 1]) - } else { - storage.account = undefined - setGlobalStorage('account.active', undefined) - queryClient.clear() - } - - const temp = new MMKV({ id: account }) - temp.clearAll() -} From adb7a765b424a2c23a7fe916fd969863853c4503 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Mon, 16 Jan 2023 22:22:19 +0100 Subject: [PATCH 4/6] Fix #663 Properly revoke token when actively logging out --- src/screens/Tabs/Me/Root/Logout.tsx | 2 +- src/utils/storage/actions.ts | 36 +++++++++++++++++++++++++---- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/src/screens/Tabs/Me/Root/Logout.tsx b/src/screens/Tabs/Me/Root/Logout.tsx index fc11cdc8..25375653 100644 --- a/src/screens/Tabs/Me/Root/Logout.tsx +++ b/src/screens/Tabs/Me/Root/Logout.tsx @@ -32,7 +32,7 @@ const Logout: React.FC = () => { onPress: () => { if (accountActive) { haptics('Light') - removeAccount(accountActive) + removeAccount(accountActive, false) } } }, diff --git a/src/utils/storage/actions.ts b/src/utils/storage/actions.ts index d0383e1f..d25dd945 100644 --- a/src/utils/storage/actions.ts +++ b/src/utils/storage/actions.ts @@ -264,14 +264,40 @@ export const setAccount = async (account: string) => { }) } -export const removeAccount = async (account: string) => { - displayMessage({ - message: i18n.t('screens:localCorrupt.message'), - type: 'danger' - }) +export const removeAccount = async (account: string, warning: boolean = true) => { + const temp = new MMKV({ id: account }) + + if (warning) { + const acct = temp.getString('auth.account.acct') + const domain = temp.getString('auth.account.domain') + displayMessage({ + message: i18n.t('screens:localCorrupt.message'), + ...(acct && domain && { description: `@${acct}@${domain}` }), + type: 'danger' + }) + } // @ts-ignore navigationRef.navigate('Screen-Tabs', { screen: 'Tab-Me' }) + const revokeDetails = { + domain: temp.getString('auth.domain'), + client_id: temp.getString('auth.clientId'), + client_secret: temp.getString('auth.clientSecret'), + token: temp.getString('auth.token') + } + if ( + revokeDetails.domain && + revokeDetails.client_id && + revokeDetails.client_secret && + revokeDetails.token + ) { + const body = new FormData() + body.append('client_id', revokeDetails.client_id) + body.append('client_secret', revokeDetails.client_secret) + body.append('token', revokeDetails.token) + apiGeneral({ method: 'post', domain: revokeDetails.domain, url: '/oauth/revoke', body }) + } + const currAccounts: NonNullable = getGlobalStorage.object('accounts') || [] const nextAccounts: NonNullable = currAccounts.filter( From c2a180f4f5bd072fd145c65fec90c944d896fe5e Mon Sep 17 00:00:00 2001 From: xmflsct Date: Mon, 16 Jan 2023 22:36:49 +0100 Subject: [PATCH 5/6] Fix popToTop dev warning --- src/screens/Tabs/Local/index.tsx | 2 +- src/screens/Tabs/Notifications/index.tsx | 2 +- src/screens/Tabs/Public/index.tsx | 2 +- src/utils/navigation/usePopToTop.ts | 11 +++++++---- 4 files changed, 10 insertions(+), 7 deletions(-) diff --git a/src/screens/Tabs/Local/index.tsx b/src/screens/Tabs/Local/index.tsx index a018b8a2..5c133c94 100644 --- a/src/screens/Tabs/Local/index.tsx +++ b/src/screens/Tabs/Local/index.tsx @@ -8,7 +8,7 @@ import Root from './Root' const Stack = createNativeStackNavigator() const TabLocal: React.FC = () => { - usePopToTop() + usePopToTop('Tab-Local-Root') return ( diff --git a/src/screens/Tabs/Notifications/index.tsx b/src/screens/Tabs/Notifications/index.tsx index 7f60b75a..06d1688b 100644 --- a/src/screens/Tabs/Notifications/index.tsx +++ b/src/screens/Tabs/Notifications/index.tsx @@ -44,7 +44,7 @@ const Root: React.FC< } const TabNotifications: React.FC = () => { - usePopToTop() + usePopToTop('Tab-Notifications-Root') return ( diff --git a/src/screens/Tabs/Public/index.tsx b/src/screens/Tabs/Public/index.tsx index a4cf7392..3135b4b5 100644 --- a/src/screens/Tabs/Public/index.tsx +++ b/src/screens/Tabs/Public/index.tsx @@ -8,7 +8,7 @@ import Root from './Root' const Stack = createNativeStackNavigator() const TabPublic: React.FC = () => { - usePopToTop() + usePopToTop('Tab-Public-Root') return ( diff --git a/src/utils/navigation/usePopToTop.ts b/src/utils/navigation/usePopToTop.ts index d16ccc49..1c99df13 100644 --- a/src/utils/navigation/usePopToTop.ts +++ b/src/utils/navigation/usePopToTop.ts @@ -1,15 +1,18 @@ -import { StackActions, useFocusEffect, useNavigation } from '@react-navigation/native' +import { StackActions } from '@react-navigation/native' import { useGlobalStorage } from '@utils/storage/actions' import { useEffect } from 'react' +import navigationRef from './navigationRef' // Mostly used when switching account and sub pages were still querying the old instance -const usePopToTop = () => { - const navigation = useNavigation() +const usePopToTop = (name: string) => { const [accountActive] = useGlobalStorage.string('account.active') useEffect(() => { - navigation.dispatch(StackActions.popToTop()) + const currentRoute = navigationRef.getCurrentRoute() + if (currentRoute && currentRoute.name !== name) { + navigationRef.dispatch(StackActions.popToTop()) + } }, [accountActive]) } From a131b1277ce2b603caf44dd13a9b83672894e855 Mon Sep 17 00:00:00 2001 From: xmflsct Date: Mon, 16 Jan 2023 22:52:30 +0100 Subject: [PATCH 6/6] Fix local content not loaded With the new prepend approach --- src/screens/Tabs/Shared/Toot.tsx | 102 +++++++++++++++++-------------- 1 file changed, 55 insertions(+), 47 deletions(-) diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index e40147e0..6210521c 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -74,8 +74,55 @@ const TabSharedToot: React.FC> = ({ const PREV_PER_BATCH = 1 const ancestorsCache = useRef<(Mastodon.Status & { _level?: number; key?: string })[]>() const loaded = useRef(false) + const prependContent = async () => { + loaded.current = true + + if (ancestorsCache.current?.length) { + switch (Platform.OS) { + case 'ios': + for (let [] of Array( + Math.ceil(ancestorsCache.current.length / PREV_PER_BATCH) + ).entries()) { + await new Promise(promise => setTimeout(promise, 64)) + queryClient.setQueryData<{ pages: { body: Mastodon.Status[] }[] }>( + queryKey.local, + old => { + const insert = ancestorsCache.current?.slice(-PREV_PER_BATCH) + ancestorsCache.current = ancestorsCache.current?.slice(0, -PREV_PER_BATCH) + if (insert) { + old?.pages[0].body.unshift(...insert) + } + + return old + } + ) + } + break + default: + queryClient.setQueryData<{ pages: { body: Mastodon.Status[] }[] }>( + queryKey.local, + old => { + ancestorsCache.current && old?.pages[0].body.unshift(...ancestorsCache.current) + + return old + } + ) + + setTimeout(() => { + flRef.current?.scrollToIndex({ + index: ancestorsCache.current?.length || 0, + viewOffset: 50 + }) + }, 50) + break + } + } + } const match = urlMatcher(toot.url || toot.uri) + const remoteQueryEnabled = + ['public', 'unlisted'].includes(toot.visibility) && + match?.domain !== getAccountStorage.string('auth.domain') const query = useQuery<{ pages: { body: (Mastodon.Status & { _level?: number; key?: string })[] }[] }>( @@ -115,11 +162,15 @@ const TabSharedToot: React.FC> = ({ enabled: !toot._remote, staleTime: 0, refetchOnMount: true, - onSuccess: data => { + onSuccess: async data => { if (data.pages[0].body.length < 1) { navigation.goBack() return } + + if (!remoteQueryEnabled) { + await prependContent() + } } } ) @@ -192,12 +243,10 @@ const TabSharedToot: React.FC> = ({ }) }, { - enabled: - (toot._remote ? true : query.isFetched) && - ['public', 'unlisted'].includes(toot.visibility) && - match?.domain !== getAccountStorage.string('auth.domain'), + enabled: (toot._remote ? true : query.isFetched) && remoteQueryEnabled, staleTime: 0, refetchOnMount: true, + retry: false, onSuccess: async data => { if ((query.data?.pages[0].body.length || 0) < 1 && data.length < 1) { navigation.goBack() @@ -245,48 +294,7 @@ const TabSharedToot: React.FC> = ({ } }, onSettled: async () => { - loaded.current = true - - if (ancestorsCache.current?.length) { - switch (Platform.OS) { - case 'ios': - for (let [] of Array( - Math.ceil(ancestorsCache.current.length / PREV_PER_BATCH) - ).entries()) { - await new Promise(promise => setTimeout(promise, 64)) - queryClient.setQueryData<{ pages: { body: Mastodon.Status[] }[] }>( - queryKey.local, - old => { - const insert = ancestorsCache.current?.slice(-PREV_PER_BATCH) - ancestorsCache.current = ancestorsCache.current?.slice(0, -PREV_PER_BATCH) - if (insert) { - old?.pages[0].body.unshift(...insert) - } - - return old - } - ) - } - break - default: - queryClient.setQueryData<{ pages: { body: Mastodon.Status[] }[] }>( - queryKey.local, - old => { - ancestorsCache.current && old?.pages[0].body.unshift(...ancestorsCache.current) - - return old - } - ) - - setTimeout(() => { - flRef.current?.scrollToIndex({ - index: ancestorsCache.current?.length || 0, - viewOffset: 50 - }) - }, 50) - break - } - } + await prependContent() } } )