diff --git a/src/App.tsx b/src/App.tsx index 35b5aff7..fda43418 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -16,6 +16,7 @@ import * as SplashScreen from 'expo-splash-screen' import React, { useCallback, useEffect, useState } from 'react' import { AppState, LogBox, Platform } from 'react-native' import { GestureHandlerRootView } from 'react-native-gesture-handler' +import { enableFreeze } from 'react-native-screens' import { QueryClientProvider } from 'react-query' import { Provider } from 'react-redux' import { PersistGate } from 'redux-persist/integration/react' @@ -29,6 +30,7 @@ dev() sentry() audio() push() +enableFreeze() const App: React.FC = () => { log('log', 'App', 'rendering App') diff --git a/src/Screens.tsx b/src/Screens.tsx index 8397144b..392bc8d8 100644 --- a/src/Screens.tsx +++ b/src/Screens.tsx @@ -136,7 +136,7 @@ const Screens: React.FC = ({ localCorrupt }) => { } if (previousRoute?.name !== currentRoute?.name) { - Analytics.setCurrentScreen(currentRoute?.name) + Analytics.logEvent('screen_view', { screen_name: currentRoute?.name }) Sentry.Native.setContext('page', { previous: previousRoute, current: currentRoute diff --git a/src/api/instance.ts b/src/api/instance.ts index 2bc8c7ad..6805e160 100644 --- a/src/api/instance.ts +++ b/src/api/instance.ts @@ -21,6 +21,11 @@ export type Params = { > } +export type InstanceResponse = { + body: T + links: { prev?: string; next?: string } +} + const apiInstance = async ({ method, version = 'v1', @@ -29,7 +34,7 @@ const apiInstance = async ({ headers, body, extras -}: Params): Promise<{ body: T; links: { prev?: string; next?: string } }> => { +}: Params): Promise> => { const { store } = require('@root/store') const state = store.getState() as RootState const instanceActive = state.instances.instances.findIndex( diff --git a/src/components/Timeline/Shared/Translate.tsx b/src/components/Timeline/Shared/Translate.tsx index 3745ef04..59a0b501 100644 --- a/src/components/Timeline/Shared/Translate.tsx +++ b/src/components/Timeline/Shared/Translate.tsx @@ -47,7 +47,6 @@ const TimelineTranslate = React.memo( const [enabled, setEnabled] = useState(false) const { refetch, data, isLoading, isSuccess, isError } = useTranslateQuery({ - uri: status.uri, source: status.language, target: settingsLanguage, text, diff --git a/src/screens/Tabs.tsx b/src/screens/Tabs.tsx index 35b27236..7f83015f 100644 --- a/src/screens/Tabs.tsx +++ b/src/screens/Tabs.tsx @@ -31,7 +31,7 @@ const Tab = createBottomTabNavigator() const ScreenTabs = React.memo( ({ navigation }: RootStackScreenProps<'Screen-Tabs'>) => { - const { mode, theme } = useTheme() + const { theme } = useTheme() const instanceActive = useSelector(getInstanceActive) const instanceAccount = useSelector( diff --git a/src/screens/Tabs/Me/Profile/Name.tsx b/src/screens/Tabs/Me/Profile/Name.tsx index 129ef780..b841c9b0 100644 --- a/src/screens/Tabs/Me/Profile/Name.tsx +++ b/src/screens/Tabs/Me/Profile/Name.tsx @@ -10,9 +10,11 @@ import { Alert, StyleSheet } from 'react-native' import FlashMessage from 'react-native-flash-message' import { ScrollView } from 'react-native-gesture-handler' -const TabMeProfileName: React.FC & { messageRef: RefObject }> = ({ +const TabMeProfileName: React.FC< + TabMeProfileStackScreenProps<'Tab-Me-Profile-Name'> & { + messageRef: RefObject + } +> = ({ messageRef, route: { params: { display_name } @@ -91,7 +93,8 @@ const TabMeProfileName: React.FC diff --git a/src/screens/Tabs/Me/Settings/App.tsx b/src/screens/Tabs/Me/Settings/App.tsx index 8da8619a..a8852885 100644 --- a/src/screens/Tabs/Me/Settings/App.tsx +++ b/src/screens/Tabs/Me/Settings/App.tsx @@ -64,6 +64,7 @@ const SettingsApp: React.FC = () => { cancelButtonIndex: options.length - 1 }, buttonIndex => { + if (!buttonIndex) return if (buttonIndex < options.length - 1) { analytics('settings_language_press', { current: i18n.language, diff --git a/src/screens/Tabs/Me/SettingsFontsize.tsx b/src/screens/Tabs/Me/SettingsFontsize.tsx index c604dd97..88571805 100644 --- a/src/screens/Tabs/Me/SettingsFontsize.tsx +++ b/src/screens/Tabs/Me/SettingsFontsize.tsx @@ -32,9 +32,9 @@ export const mapFontsizeToName = (size: SettingsState['fontsize']) => { } } -const TabMeSettingsFontsize: React.FC> = () => { +const TabMeSettingsFontsize: React.FC< + TabMeStackScreenProps<'Tab-Me-Settings-Fontsize'> +> = () => { const { mode, theme } = useTheme() const { t } = useTranslation('screenTabs') const initialSize = useSelector(getSettingsFontsize) @@ -113,7 +113,12 @@ const TabMeSettingsFontsize: React.FC - + > = ({ +const TabSharedSearch: React.FC< + TabSharedStackScreenProps<'Tab-Shared-Search'> +> = ({ route: { params: { text } } @@ -33,7 +33,13 @@ const TabSharedSearch: React.FC({ term: text, options: { enabled: text !== undefined, diff --git a/src/utils/accessibility/AccessibilityManager.tsx b/src/utils/accessibility/AccessibilityManager.tsx index 52eec5b4..7ad74782 100644 --- a/src/utils/accessibility/AccessibilityManager.tsx +++ b/src/utils/accessibility/AccessibilityManager.tsx @@ -33,24 +33,18 @@ const AccessibilityManager: React.FC = ({ children }) => { useEffect(() => { loadAccessibilityInfo() - AccessibilityInfo.addEventListener( + const reduceMotionSubscription = AccessibilityInfo.addEventListener( 'reduceMotionChanged', handleReduceMotionChanged ) - AccessibilityInfo.addEventListener( + const screenReaderSubscription = AccessibilityInfo.addEventListener( 'screenReaderChanged', handleScreenReaderEnabled ) return () => { - AccessibilityInfo.removeEventListener( - 'reduceMotionChanged', - handleReduceMotionChanged - ) - AccessibilityInfo.removeEventListener( - 'screenReaderChanged', - handleScreenReaderEnabled - ) + reduceMotionSubscription.remove() + screenReaderSubscription.remove() } }, []) diff --git a/src/utils/queryHooks/account.ts b/src/utils/queryHooks/account.ts index 5efcc437..45ab11df 100644 --- a/src/utils/queryHooks/account.ts +++ b/src/utils/queryHooks/account.ts @@ -1,10 +1,10 @@ import apiInstance from '@api/instance' import { AxiosError } from 'axios' -import { useQuery, UseQueryOptions } from 'react-query' +import { QueryFunctionContext, useQuery, UseQueryOptions } from 'react-query' export type QueryKeyAccount = ['Account', { id: Mastodon.Account['id'] }] -const queryFunction = ({ queryKey }: { queryKey: QueryKeyAccount }) => { +const queryFunction = ({ queryKey }: QueryFunctionContext) => { const { id } = queryKey[1] return apiInstance({ @@ -13,11 +13,11 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKeyAccount }) => { }).then(res => res.body) } -const useAccountQuery = ({ +const useAccountQuery = ({ options, ...queryKeyParams }: QueryKeyAccount[1] & { - options?: UseQueryOptions + options?: UseQueryOptions }) => { const queryKey: QueryKeyAccount = ['Account', { ...queryKeyParams }] return useQuery(queryKey, queryFunction, options) diff --git a/src/utils/queryHooks/announcement.ts b/src/utils/queryHooks/announcement.ts index 5278affd..3f003041 100644 --- a/src/utils/queryHooks/announcement.ts +++ b/src/utils/queryHooks/announcement.ts @@ -1,6 +1,7 @@ import apiInstance from '@api/instance' import { AxiosError } from 'axios' import { + QueryFunctionContext, useMutation, UseMutationOptions, useQuery, @@ -9,7 +10,9 @@ import { type QueryKeyAnnouncement = ['Announcements', { showAll?: boolean }] -const queryFunction = ({ queryKey }: { queryKey: QueryKeyAnnouncement }) => { +const queryFunction = ({ + queryKey +}: QueryFunctionContext) => { const { showAll } = queryKey[1] return apiInstance({ @@ -23,11 +26,11 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKeyAnnouncement }) => { }).then(res => res.body) } -const useAnnouncementQuery = ({ +const useAnnouncementQuery = ({ options, ...queryKeyParams }: QueryKeyAnnouncement[1] & { - options?: UseQueryOptions + options?: UseQueryOptions }) => { const queryKey: QueryKeyAnnouncement = [ 'Announcements', diff --git a/src/utils/queryHooks/apps.ts b/src/utils/queryHooks/apps.ts index b890eb99..601f0b50 100644 --- a/src/utils/queryHooks/apps.ts +++ b/src/utils/queryHooks/apps.ts @@ -1,11 +1,11 @@ import apiGeneral from '@api/general' import { AxiosError } from 'axios' import * as AuthSession from 'expo-auth-session' -import { useQuery, UseQueryOptions } from 'react-query' +import { QueryFunctionContext, useQuery, UseQueryOptions } from 'react-query' -export type QueryKey = ['Apps', { domain?: string }] +export type QueryKeyApps = ['Apps', { domain?: string }] -const queryFunction = ({ queryKey }: { queryKey: QueryKey }) => { +const queryFunction = ({ queryKey }: QueryFunctionContext) => { const redirectUri = AuthSession.makeRedirectUri({ native: 'tooot://instance-auth', useProxy: false @@ -27,13 +27,13 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKey }) => { }).then(res => res.body) } -const useAppsQuery = ({ +const useAppsQuery = ({ options, ...queryKeyParams -}: QueryKey[1] & { - options?: UseQueryOptions +}: QueryKeyApps[1] & { + options?: UseQueryOptions }) => { - const queryKey: QueryKey = ['Apps', { ...queryKeyParams }] + const queryKey: QueryKeyApps = ['Apps', { ...queryKeyParams }] return useQuery(queryKey, queryFunction, options) } diff --git a/src/utils/queryHooks/emojis.ts b/src/utils/queryHooks/emojis.ts index 47765647..891bd509 100644 --- a/src/utils/queryHooks/emojis.ts +++ b/src/utils/queryHooks/emojis.ts @@ -2,21 +2,22 @@ import apiInstance from '@api/instance' import { AxiosError } from 'axios' import { useQuery, UseQueryOptions } from 'react-query' -type QueryKey = ['Emojis'] +type QueryKeyEmojis = ['Emojis'] -const queryFunction = () => { - return apiInstance({ +const queryFunction = async () => { + const res = await apiInstance({ method: 'get', url: 'custom_emojis' - }).then(res => res.body) + }) + return res.body } -const useEmojisQuery = ({ +const useEmojisQuery = ({ options }: { - options?: UseQueryOptions + options?: UseQueryOptions }) => { - const queryKey: QueryKey = ['Emojis'] + const queryKey: QueryKeyEmojis = ['Emojis'] return useQuery(queryKey, queryFunction, options) } diff --git a/src/utils/queryHooks/instance.ts b/src/utils/queryHooks/instance.ts index ad7a892c..c1785683 100644 --- a/src/utils/queryHooks/instance.ts +++ b/src/utils/queryHooks/instance.ts @@ -1,10 +1,12 @@ import apiGeneral from '@api/general' import { AxiosError } from 'axios' -import { useQuery, UseQueryOptions } from 'react-query' +import { QueryFunctionContext, useQuery, UseQueryOptions } from 'react-query' -export type QueryKey = ['Instance', { domain?: string }] +export type QueryKeyInstance = ['Instance', { domain?: string }] -const queryFunction = async ({ queryKey }: { queryKey: QueryKey }) => { +const queryFunction = async ({ + queryKey +}: QueryFunctionContext) => { const { domain } = queryKey[1] if (!domain) { return Promise.reject() @@ -18,19 +20,16 @@ const queryFunction = async ({ queryKey }: { queryKey: QueryKey }) => { return res.body } -const useInstanceQuery = < - TData = Mastodon.Instance & { publicAllow?: boolean } ->({ +const useInstanceQuery = ({ options, ...queryKeyParams -}: QueryKey[1] & { +}: QueryKeyInstance[1] & { options?: UseQueryOptions< Mastodon.Instance & { publicAllow?: boolean }, - AxiosError, - TData + AxiosError > }) => { - const queryKey: QueryKey = ['Instance', { ...queryKeyParams }] + const queryKey: QueryKeyInstance = ['Instance', { ...queryKeyParams }] return useQuery(queryKey, queryFunction, options) } diff --git a/src/utils/queryHooks/lists.ts b/src/utils/queryHooks/lists.ts index 251ce84a..c1d381de 100644 --- a/src/utils/queryHooks/lists.ts +++ b/src/utils/queryHooks/lists.ts @@ -4,17 +4,18 @@ import { useQuery, UseQueryOptions } from 'react-query' export type QueryKey = ['Lists'] -const queryFunction = () => { - return apiInstance({ +const queryFunction = async () => { + const res = await apiInstance({ method: 'get', url: 'lists' - }).then(res => res.body) + }) + return res.body } -const useListsQuery = ({ +const useListsQuery = ({ options }: { - options?: UseQueryOptions + options?: UseQueryOptions }) => { const queryKey: QueryKey = ['Lists'] return useQuery(queryKey, queryFunction, options) diff --git a/src/utils/queryHooks/profile.ts b/src/utils/queryHooks/profile.ts index a6b1a1dc..1f9d194b 100644 --- a/src/utils/queryHooks/profile.ts +++ b/src/utils/queryHooks/profile.ts @@ -14,17 +14,18 @@ type AccountWithSource = Mastodon.Account & type QueryKeyProfile = ['Profile'] const queryKey: QueryKeyProfile = ['Profile'] -const queryFunction = () => { - return apiInstance({ +const queryFunction = async () => { + const res = await apiInstance({ method: 'get', url: `accounts/verify_credentials` - }).then(res => res.body) + }) + return res.body } -const useProfileQuery = ({ +const useProfileQuery = ({ options }: { - options?: UseQueryOptions + options?: UseQueryOptions }) => { return useQuery(queryKey, queryFunction, options) } diff --git a/src/utils/queryHooks/relationship.ts b/src/utils/queryHooks/relationship.ts index 0663da8d..1671449e 100644 --- a/src/utils/queryHooks/relationship.ts +++ b/src/utils/queryHooks/relationship.ts @@ -1,6 +1,7 @@ import apiInstance from '@api/instance' import { AxiosError } from 'axios' import { + QueryFunctionContext, useMutation, UseMutationOptions, useQuery, @@ -12,7 +13,9 @@ export type QueryKeyRelationship = [ { id: Mastodon.Account['id'] } ] -const queryFunction = ({ queryKey }: { queryKey: QueryKeyRelationship }) => { +const queryFunction = ({ + queryKey +}: QueryFunctionContext) => { const { id } = queryKey[1] return apiInstance({ diff --git a/src/utils/queryHooks/search.ts b/src/utils/queryHooks/search.ts index 0ea5d5e7..f15e17d2 100644 --- a/src/utils/queryHooks/search.ts +++ b/src/utils/queryHooks/search.ts @@ -1,8 +1,8 @@ import apiInstance from '@api/instance' import { AxiosError } from 'axios' -import { useQuery, UseQueryOptions } from 'react-query' +import { QueryFunctionContext, useQuery, UseQueryOptions } from 'react-query' -export type QueryKey = [ +export type QueryKeySearch = [ 'Search', { type?: 'accounts' | 'hashtags' | 'statuses' @@ -17,9 +17,11 @@ export type SearchResult = { statuses: Mastodon.Status[] } -const queryFunction = ({ queryKey }: { queryKey: QueryKey }) => { +const queryFunction = async ({ + queryKey +}: QueryFunctionContext) => { const { type, term, limit = 20 } = queryKey[1] - return apiInstance({ + const res = await apiInstance({ version: 'v2', method: 'get', url: 'search', @@ -29,16 +31,17 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKey }) => { limit, resolve: true } - }).then(res => res.body) + }) + return res.body } -const useSearchQuery = ({ +const useSearchQuery = ({ options, ...queryKeyParams -}: QueryKey[1] & { - options?: UseQueryOptions +}: QueryKeySearch[1] & { + options?: UseQueryOptions }) => { - const queryKey: QueryKey = ['Search', { ...queryKeyParams }] + const queryKey: QueryKeySearch = ['Search', { ...queryKeyParams }] return useQuery(queryKey, queryFunction, options) } diff --git a/src/utils/queryHooks/timeline.ts b/src/utils/queryHooks/timeline.ts index 99756cf3..7384ecaa 100644 --- a/src/utils/queryHooks/timeline.ts +++ b/src/utils/queryHooks/timeline.ts @@ -1,4 +1,4 @@ -import apiInstance from '@api/instance' +import apiInstance, { InstanceResponse } from '@api/instance' import haptics from '@components/haptics' import queryClient from '@helpers/queryClient' import { store } from '@root/store' @@ -7,6 +7,7 @@ import { AxiosError } from 'axios' import { uniqBy } from 'lodash' import { MutationOptions, + QueryFunctionContext, useInfiniteQuery, UseInfiniteQueryOptions, useMutation @@ -28,10 +29,7 @@ export type QueryKeyTimeline = [ const queryFunction = async ({ queryKey, pageParam -}: { - queryKey: QueryKeyTimeline - pageParam?: { [key: string]: string } -}) => { +}: QueryFunctionContext) => { const { page, account, hashtag, list, toot } = queryKey[1] let params: { [key: string]: string } = { ...pageParam } @@ -191,21 +189,15 @@ const queryFunction = async ({ type Unpromise> = T extends Promise ? U : never export type TimelineData = Unpromise> -const useTimelineQuery = ({ +const useTimelineQuery = ({ options, ...queryKeyParams }: QueryKeyTimeline[1] & { options?: UseInfiniteQueryOptions< - { - body: - | Mastodon.Status[] - | Mastodon.Notification[] - | Mastodon.Conversation[] - links?: { prev?: string; next?: string } - pinned?: Mastodon.Status['id'][] - }, - AxiosError, - TData + InstanceResponse< + Mastodon.Status[] | Mastodon.Notification[] | Mastodon.Conversation[] + >, + AxiosError > }) => { const queryKey: QueryKeyTimeline = ['Timeline', { ...queryKeyParams }] diff --git a/src/utils/queryHooks/translate.ts b/src/utils/queryHooks/translate.ts index 64aec663..1ea1060c 100644 --- a/src/utils/queryHooks/translate.ts +++ b/src/utils/queryHooks/translate.ts @@ -1,7 +1,7 @@ import apiTooot from '@api/tooot' import haptics from '@components/haptics' import { AxiosError } from 'axios' -import { useQuery, UseQueryOptions } from 'react-query' +import { QueryFunctionContext, useQuery, UseQueryOptions } from 'react-query' type Translations = { provider: string @@ -18,7 +18,9 @@ export type QueryKeyTranslate = [ } ] -const queryFunction = async ({ queryKey }: { queryKey: QueryKeyTranslate }) => { +const queryFunction = async ({ + queryKey +}: QueryFunctionContext) => { const { source, target, text } = queryKey[1] const res = await apiTooot({ @@ -34,7 +36,7 @@ const useTranslateQuery = ({ options, ...queryKeyParams }: QueryKeyTranslate[1] & { - options?: UseQueryOptions + options?: UseQueryOptions }) => { const queryKey: QueryKeyTranslate = ['Translate', { ...queryKeyParams }] return useQuery(queryKey, queryFunction, { ...options, retry: false }) diff --git a/src/utils/queryHooks/users.ts b/src/utils/queryHooks/users.ts index fd5c2150..10ce5b59 100644 --- a/src/utils/queryHooks/users.ts +++ b/src/utils/queryHooks/users.ts @@ -1,7 +1,11 @@ -import apiInstance from '@api/instance' +import apiInstance, { InstanceResponse } from '@api/instance' import { TabSharedStackParamList } from '@utils/navigation/navigators' import { AxiosError } from 'axios' -import { useInfiniteQuery, UseInfiniteQueryOptions } from 'react-query' +import { + QueryFunctionContext, + useInfiniteQuery, + UseInfiniteQueryOptions +} from 'react-query' export type QueryKeyUsers = [ 'Users', @@ -11,10 +15,7 @@ export type QueryKeyUsers = [ const queryFunction = ({ queryKey, pageParam -}: { - queryKey: QueryKeyUsers - pageParam?: { [key: string]: string } -}) => { +}: QueryFunctionContext) => { const { reference, id, type } = queryKey[1] let params: { [key: string]: string } = { ...pageParam } @@ -30,15 +31,8 @@ const useUsersQuery = ({ ...queryKeyParams }: QueryKeyUsers[1] & { options?: UseInfiniteQueryOptions< - { - body: Mastodon.Account[] - links?: { prev?: string; next?: string } - }, - AxiosError, - { - body: Mastodon.Account[] - links?: { prev?: string; next?: string } - } + InstanceResponse, + AxiosError > }) => { const queryKey: QueryKeyUsers = ['Users', { ...queryKeyParams }] diff --git a/src/utils/slices/instances/add.ts b/src/utils/slices/instances/add.ts index 41d8cb81..69135a33 100644 --- a/src/utils/slices/instances/add.ts +++ b/src/utils/slices/instances/add.ts @@ -99,7 +99,7 @@ const addInstance = createAsyncThunk( mention: { loading: false, value: true }, poll: { loading: false, value: true } }, - keys: undefined + keys: { auth: undefined, public: undefined, private: undefined } }, drafts: [] }