diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 00000000..5e6575f2 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,3 @@ +{ + "javascript.inlayHints.functionLikeReturnTypes.enabled": false +} \ No newline at end of file diff --git a/src/App.tsx b/src/App.tsx index 96433aeb..6419e708 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -74,37 +74,6 @@ const App: React.FC = () => { } }, []) - const children = useCallback( - bootstrapped => { - log('log', 'App', 'bootstrapped') - if (bootstrapped) { - log('log', 'App', 'loading actual app :)') - const language = getSettingsLanguage(store.getState()) - if (!language) { - store.dispatch(changeLanguage('en')) - i18n.changeLanguage('en') - } else { - i18n.changeLanguage(language) - } - - return ( - - - - - - - - - - ) - } else { - return null - } - }, - [localCorrupt] - ) - return ( @@ -112,7 +81,33 @@ const App: React.FC = () => { { + log('log', 'App', 'bootstrapped') + if (bootstrapped) { + log('log', 'App', 'loading actual app :)') + const language = getSettingsLanguage(store.getState()) + if (!language) { + store.dispatch(changeLanguage('en')) + i18n.changeLanguage('en') + } else { + i18n.changeLanguage(language) + } + + return ( + + + + + + + + + + ) + } else { + return null + } + }} /> diff --git a/src/Screens.tsx b/src/Screens.tsx index f83cf37c..79d43b5b 100644 --- a/src/Screens.tsx +++ b/src/Screens.tsx @@ -170,6 +170,7 @@ const Screens: React.FC = ({ localCorrupt }) => { } | { data: string | string[]; mimeType: string } ) => { + console.log('item', item) if (instanceActive < 0) { return } @@ -253,6 +254,7 @@ const Screens: React.FC = ({ localCorrupt }) => { if (!text && !media.length) { return } else { + console.log('media', media) navigationRef.navigate('Screen-Compose', { type: 'share', text, media }) } }, diff --git a/src/components/Emojis.tsx b/src/components/Emojis.tsx index 0eafa302..044dce6d 100644 --- a/src/components/Emojis.tsx +++ b/src/components/Emojis.tsx @@ -7,6 +7,7 @@ import { chunk, forEach, groupBy, sortBy } from 'lodash' import React, { Dispatch, MutableRefObject, + PropsWithChildren, SetStateAction, useCallback, useEffect, @@ -57,7 +58,7 @@ export interface Props { maxLength?: number } -const ComponentEmojis: React.FC = ({ +const ComponentEmojis: React.FC = ({ enabled = false, value, setValue, diff --git a/src/components/Emojis/List.tsx b/src/components/Emojis/List.tsx index 48eb8ba3..32a2a931 100644 --- a/src/components/Emojis/List.tsx +++ b/src/components/Emojis/List.tsx @@ -27,18 +27,6 @@ const EmojisList = React.memo( const { emojisState, emojisDispatch } = useContext(EmojisContext) const { colors } = useTheme() - const listHeader = useCallback( - ({ section: { title } }) => ( - - {title} - - ), - [] - ) - const listItem = useCallback( ({ index, item }: { item: Mastodon.Emoji[]; index: number }) => { return ( @@ -112,7 +100,14 @@ const EmojisList = React.memo( keyboardShouldPersistTaps='always' sections={emojisState.emojis} keyExtractor={item => item[0].shortcode} - renderSectionHeader={listHeader} + renderSectionHeader={({ section: { title } }) => ( + + {title} + + )} renderItem={listItem} windowSize={4} /> diff --git a/src/components/Input.tsx b/src/components/Input.tsx index d3f7f34b..5c3752c2 100644 --- a/src/components/Input.tsx +++ b/src/components/Input.tsx @@ -4,7 +4,6 @@ import { useTheme } from '@utils/styles/ThemeManager' import React, { Dispatch, SetStateAction, - useCallback, useEffect, useRef, useState @@ -81,10 +80,6 @@ const Input: React.FC = ({ } : { start: 0, end: 0 } ) - const onSelectionChange = useCallback( - ({ nativeEvent: { selection } }) => (selectionRange.current = selection), - [] - ) const [inputFocused, setInputFocused] = useState(false) useEffect(() => { @@ -128,7 +123,9 @@ const Input: React.FC = ({ : undefined }} onChangeText={setValue} - onSelectionChange={onSelectionChange} + onSelectionChange={({ nativeEvent: { selection } }) => + (selectionRange.current = selection) + } value={value} {...(multiline && { multiline, diff --git a/src/components/Instance.tsx b/src/components/Instance.tsx index 1158fe76..b37361c2 100644 --- a/src/components/Instance.tsx +++ b/src/components/Instance.tsx @@ -88,21 +88,6 @@ const ComponentInstance: React.FC = ({ } }, [domain]) - const onSubmitEditing = useCallback( - ({ nativeEvent: { text } }) => { - analytics('instance_textinput_submit', { match: text === domain }) - if ( - text === domain && - instanceQuery.isSuccess && - instanceQuery.data && - instanceQuery.data.uri - ) { - processUpdate() - } - }, - [domain, instanceQuery.isSuccess, instanceQuery.data] - ) - const requestAuth = useMemo(() => { if ( domain && @@ -180,7 +165,17 @@ const ComponentInstance: React.FC = ({ clearButtonMode='never' keyboardType='url' textContentType='URL' - onSubmitEditing={onSubmitEditing} + onSubmitEditing={({ nativeEvent: { text } }) => { + analytics('instance_textinput_submit', { match: text === domain }) + if ( + text === domain && + instanceQuery.isSuccess && + instanceQuery.data && + instanceQuery.data.uri + ) { + processUpdate() + } + }} placeholder={' ' + t('server.textInput.placeholder')} placeholderTextColor={colors.secondary} returnKeyType='go' diff --git a/src/components/Parse/HTML.tsx b/src/components/Parse/HTML.tsx index 3c1b26f4..51aab5c7 100644 --- a/src/components/Parse/HTML.tsx +++ b/src/components/Parse/HTML.tsx @@ -215,7 +215,7 @@ const ParseHTML = React.memo( } const renderNodeCallback = useCallback( - (node, index) => + (node: any, index: any) => renderNode({ routeParams: route.params, colors, @@ -231,7 +231,7 @@ const ParseHTML = React.memo( }), [] ) - const textComponent = useCallback(({ children }) => { + const textComponent = useCallback(({ children }: any) => { if (children) { return ( { + ({ children }: any) => { const { t } = useTranslation('componentParse') const [expandAllow, setExpandAllow] = useState(false) const [expanded, setExpanded] = useState(highlighted) - const onTextLayout = useCallback(({ nativeEvent }) => { - if ( - numberOfLines === 1 || - nativeEvent.lines.length >= numberOfLines + 5 - ) { - setExpandAllow(true) - } - }, []) - return ( { + if ( + numberOfLines === 1 || + nativeEvent.lines.length >= numberOfLines + 5 + ) { + setExpandAllow(true) + } + }} numberOfLines={ expandAllow ? (expanded ? 999 : numberOfLines) : undefined } diff --git a/src/components/Timeline.tsx b/src/components/Timeline.tsx index 6908a321..2f73d636 100644 --- a/src/components/Timeline.tsx +++ b/src/components/Timeline.tsx @@ -64,17 +64,6 @@ const Timeline: React.FC = ({ ? data.pages?.flatMap(page => [...page.body]) : [] - const ItemSeparatorComponent = useCallback( - ({ leadingItem }) => - queryKey[1].page === 'Toot' && queryKey[1].toot === leadingItem.id ? ( - - ) : ( - - ), - [] - ) const onEndReached = useCallback( () => !disableInfinity && !isFetchingNextPage && fetchNextPage(), [isFetchingNextPage] @@ -151,7 +140,17 @@ const Timeline: React.FC = ({ /> } ListEmptyComponent={} - ItemSeparatorComponent={ItemSeparatorComponent} + ItemSeparatorComponent={({ leadingItem }) => + queryKey[1].page === 'Toot' && queryKey[1].toot === leadingItem.id ? ( + + ) : ( + + ) + } maintainVisibleContentPosition={ isFetching ? { diff --git a/src/components/Timeline/Refresh.tsx b/src/components/Timeline/Refresh.tsx index f5d5ad2a..38cfdcdd 100644 --- a/src/components/Timeline/Refresh.tsx +++ b/src/components/Timeline/Refresh.tsx @@ -9,7 +9,7 @@ import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { RefObject, useCallback, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' -import { FlatList, Platform, StyleSheet, Text, View } from 'react-native' +import { FlatList, LayoutChangeEvent, Platform, StyleSheet, Text, View } from 'react-native' import { Circle } from 'react-native-animated-spinkit' import Animated, { Extrapolate, @@ -169,7 +169,7 @@ const TimelineRefresh: React.FC = ({ const arrowStage = useSharedValue(0) const onLayout = useCallback( - ({ nativeEvent }) => { + ({ nativeEvent }: LayoutChangeEvent) => { if (nativeEvent.layout.x + nativeEvent.layout.width > textRight) { setTextRight(nativeEvent.layout.x + nativeEvent.layout.width) } diff --git a/src/components/mediaSelector.ts b/src/components/mediaSelector.ts index 313bcef2..89404cd2 100644 --- a/src/components/mediaSelector.ts +++ b/src/components/mediaSelector.ts @@ -1,15 +1,8 @@ -import analytics from '@components/analytics' import { ActionSheetOptions } from '@expo/react-native-action-sheet' import { store } from '@root/store' import { getInstanceConfigurationStatusMaxAttachments } from '@utils/slices/instancesSlice' -import { manipulateAsync, SaveFormat } from 'expo-image-manipulator' -import * as ExpoImagePicker from 'expo-image-picker' import i18next from 'i18next' -import { Alert, Linking, Platform } from 'react-native' -import ImagePicker, { - Image, - ImageOrVideo -} from 'react-native-image-crop-picker' +import { Asset, launchImageLibrary } from 'react-native-image-picker' export interface Props { mediaType?: 'photo' | 'video' @@ -28,43 +21,7 @@ const mediaSelector = async ({ maximum, indicateMaximum = false, showActionSheetWithOptions -}: Props): Promise<({ uri: string } & Omit)[]> => { - const checkLibraryPermission = async (): Promise => { - const { status } = - await ExpoImagePicker.requestMediaLibraryPermissionsAsync() - if (status !== 'granted') { - Alert.alert( - i18next.t('componentMediaSelector:library.alert.title'), - i18next.t('componentMediaSelector:library.alert.message'), - [ - { - text: i18next.t('common:buttons.cancel'), - style: 'cancel', - onPress: () => - analytics('mediaSelector_nopermission', { - action: 'cancel' - }) - }, - { - text: i18next.t( - 'componentMediaSelector:library.alert.buttons.settings' - ), - style: 'default', - onPress: () => { - analytics('mediaSelector_nopermission', { - action: 'settings' - }) - Linking.openURL('app-settings:') - } - } - ] - ) - return false - } else { - return true - } - } - +}: Props): Promise => { const _maximum = maximum || getInstanceConfigurationStatusMaxAttachments(store.getState()) || @@ -105,79 +62,30 @@ const mediaSelector = async ({ return new Promise((resolve, reject) => { const selectImage = async () => { - const images = await ImagePicker.openPicker({ + const images = await launchImageLibrary({ mediaType: 'photo', - includeExif: false, - multiple: true, - minFiles: 1, - maxFiles: _maximum, - smartAlbums: ['UserLibrary'], - writeTempFile: false, - loadingLabelText: '' - }).catch(() => {}) + ...(resize && { maxWidth: resize.width, maxHeight: resize.height }), + includeBase64: false, + includeExtra: false, + selectionLimit: _maximum + }) - if (!images) { + if (!images.assets) { return reject() } - // react-native-image-crop-picker may return HEIC as JPG that causes upload failure - if (Platform.OS === 'ios') { - for (const [index, image] of images.entries()) { - if (image.mime === 'image/heic') { - const converted = await manipulateAsync(image.sourceURL!, [], { - base64: false, - compress: 0.8, - format: SaveFormat.JPEG - }) - images[index] = { - ...images[index], - sourceURL: converted.uri, - mime: 'image/jpeg' - } - } - } - } - - if (!resize) { - return resolve( - images.map(image => ({ - ...image, - uri: image.sourceURL || `file://${image.path}` - })) - ) - } else { - const croppedImages: Image[] = [] - for (const image of images) { - const croppedImage = await ImagePicker.openCropper({ - mediaType: 'photo', - path: image.sourceURL || image.path, - width: resize.width, - height: resize.height, - cropperChooseText: i18next.t('common:buttons.apply'), - cropperCancelText: i18next.t('common:buttons.cancel'), - hideBottomControls: true - }).catch(() => {}) - croppedImage && croppedImages.push(croppedImage) - } - return resolve( - croppedImages.map(image => ({ - ...image, - uri: `file://${image.path}` - })) - ) - } + return resolve(images.assets) } const selectVideo = async () => { - const video = await ImagePicker.openPicker({ + const video = await launchImageLibrary({ mediaType: 'video', - includeExif: false, - loadingLabelText: '' - }).catch(() => {}) + includeBase64: false, + includeExtra: false, + selectionLimit: 1 + }) - if (video) { - return resolve([ - { ...video, uri: video.sourceURL || `file://${video.path}` } - ]) + if (video.assets?.[0]) { + return resolve(video.assets) } else { return reject() } @@ -189,10 +97,6 @@ const mediaSelector = async ({ cancelButtonIndex: mediaType ? 1 : 2 }, async buttonIndex => { - if (!(await checkLibraryPermission())) { - return reject() - } - switch (mediaType) { case 'photo': if (buttonIndex === 0) { diff --git a/src/components/mediaTransformation.ts b/src/components/mediaTransformation.ts deleted file mode 100644 index 29bb542d..00000000 --- a/src/components/mediaTransformation.ts +++ /dev/null @@ -1,149 +0,0 @@ -import { store } from '@root/store' -import { getInstanceConfigurationMediaAttachments } from '@utils/slices/instancesSlice' -import { Action, manipulateAsync, SaveFormat } from 'expo-image-manipulator' -import i18next from 'i18next' -import { Platform } from 'react-native' -import ImagePicker from 'react-native-image-crop-picker' - -export interface Props { - type: 'image' | 'video' - uri: string // This can be pure path or uri starting with file:// - mime?: string - transform: { - imageFormat?: SaveFormat.JPEG | SaveFormat.PNG - resize?: boolean - width?: number - height?: number - } -} - -const getFileExtension = (uri: string) => { - const extension = uri.split('.').pop() - // Using mime type standard of jpeg - return extension === 'jpg' ? 'jpeg' : extension -} - -const mediaTransformation = async ({ - type, - uri, - mime, - transform -}: Props): Promise<{ - uri: string - mime: string - width: number - height: number -}> => { - const configurationMediaAttachments = - getInstanceConfigurationMediaAttachments(store.getState()) - - const fileExtension = getFileExtension(uri) - - switch (type) { - case 'image': - if (mime === 'image/gif' || fileExtension === 'gif') { - return Promise.reject('GIFs should not be transformed') - } - let targetFormat: SaveFormat.JPEG | SaveFormat.PNG = SaveFormat.JPEG - - const supportedImageTypes = - configurationMediaAttachments.supported_mime_types.filter(mime => - mime.startsWith('image/') - ) - - // @ts-ignore - const transformations: Action[] = [ - !transform.resize && (transform.width || transform.height) - ? { - resize: { width: transform.width, height: transform.height } - } - : null - ].filter(t => !!t) - - if (mime) { - if ( - mime !== `image/${fileExtension}` || - !supportedImageTypes.includes(mime) - ) { - targetFormat = transform.imageFormat || SaveFormat.JPEG - } else { - targetFormat = mime.split('/').pop() as any - } - } else { - if (!fileExtension) { - return Promise.reject('Unable to get file extension') - } - if (!supportedImageTypes.includes(`image/${fileExtension}`)) { - targetFormat = transform.imageFormat || SaveFormat.JPEG - } else { - targetFormat = fileExtension as any - } - } - - const converted = await manipulateAsync(uri, transformations, { - base64: false, - compress: Platform.OS === 'ios' ? 0.8 : 1, - format: targetFormat - }) - - if (transform.resize) { - const resized = await ImagePicker.openCropper({ - mediaType: 'photo', - path: converted.uri, - width: transform.width, - height: transform.height, - cropperChooseText: i18next.t('common:buttons.apply'), - cropperCancelText: i18next.t('common:buttons.cancel'), - hideBottomControls: true - }) - if (!resized) { - return Promise.reject('Resize failed') - } else { - return { - uri: resized.path, - mime: resized.mime, - width: resized.width, - height: resized.height - } - } - } else { - return { - uri: converted.uri, - mime: transform.imageFormat || SaveFormat.JPEG, - width: converted.width, - height: converted.height - } - } - case 'video': - const supportedVideoTypes = - configurationMediaAttachments.supported_mime_types.filter(mime => - mime.startsWith('video/') - ) - - if (mime) { - if (mime !== `video/${fileExtension}`) { - console.warn('Video mime type and file extension does not match') - } - if (!supportedVideoTypes.includes(mime)) { - return Promise.reject('Video file type is not supported') - } - } else { - if (!fileExtension) { - return Promise.reject('Unable to get file extension') - } - if (!supportedVideoTypes.includes(`video/${fileExtension}`)) { - return Promise.reject('Video file type is not supported') - } - } - - return { - uri: uri, - mime: mime || `video/${fileExtension}`, - width: 0, - height: 0 - } - break - } -} - -export default mediaTransformation diff --git a/src/screens/Announcements.tsx b/src/screens/Announcements.tsx index e38df48c..2b04312b 100644 --- a/src/screens/Announcements.tsx +++ b/src/screens/Announcements.tsx @@ -15,8 +15,15 @@ import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import React, { useCallback, useEffect, useState } from 'react' import { Trans, useTranslation } from 'react-i18next' -import { FormattedRelativeTime } from 'react-intl' -import { Dimensions, Platform, Pressable, StyleSheet, View } from 'react-native' +import { + Dimensions, + NativeScrollEvent, + NativeSyntheticEvent, + Platform, + Pressable, + StyleSheet, + View +} from 'react-native' import { Circle } from 'react-native-animated-spinkit' import FastImage from 'react-native-fast-image' import { FlatList, ScrollView } from 'react-native-gesture-handler' @@ -92,9 +99,7 @@ const ScreenAnnouncements: React.FC< > - ]} + components={[]} /> { + }: NativeSyntheticEvent) => { setIndex(Math.floor(x / width)) }, [] diff --git a/src/screens/Compose.tsx b/src/screens/Compose.tsx index d0695c9d..3a7aa3ab 100644 --- a/src/screens/Compose.tsx +++ b/src/screens/Compose.tsx @@ -150,7 +150,7 @@ const ScreenCompose: React.FC> = ({ for (const m of params.media) { uploadAttachment({ composeDispatch, - media: { ...m, width: 100, height: 100 } + media: { uri: m.uri, fileName: 'temp.jpg', type: m.mime } }) } } diff --git a/src/screens/Compose/DraftsList/Root.tsx b/src/screens/Compose/DraftsList/Root.tsx index 3c1abed3..12c44384 100644 --- a/src/screens/Compose/DraftsList/Root.tsx +++ b/src/screens/Compose/DraftsList/Root.tsx @@ -47,10 +47,6 @@ const ComposeDraftsListRoot: React.FC = ({ timestamp }) => { const [checkingAttachments, setCheckingAttachments] = useState(false) - const removeDraft = useCallback(ts => { - dispatch(removeInstanceDraft(ts)) - }, []) - const renderItem = useCallback( ({ item }: { item: ComposeStateDraft }) => { return ( @@ -144,7 +140,7 @@ const ComposeDraftsListRoot: React.FC = ({ timestamp }) => { }} source={{ uri: - attachment.local?.local_thumbnail || + attachment.local?.thumbnail || attachment.remote?.preview_url }} /> @@ -157,38 +153,6 @@ const ComposeDraftsListRoot: React.FC = ({ timestamp }) => { }, [theme] ) - const renderHiddenItem = useCallback( - ({ item }) => ( - removeDraft(item.timestamp)} - children={ - - } - /> - } - /> - ), - [theme] - ) return ( <> @@ -220,7 +184,35 @@ const ComposeDraftsListRoot: React.FC = ({ timestamp }) => { ( + dispatch(removeInstanceDraft(item.timestamp))} + children={ + + } + /> + } + /> + )} disableRightSwipe={true} rightOpenValue={-actionWidth} // previewRowKey={ diff --git a/src/screens/Compose/EditAttachment/Root.tsx b/src/screens/Compose/EditAttachment/Root.tsx index bff60bd9..24e89f3f 100644 --- a/src/screens/Compose/EditAttachment/Root.tsx +++ b/src/screens/Compose/EditAttachment/Root.tsx @@ -35,7 +35,7 @@ const ComposeEditAttachmentRoot: React.FC = ({ index }) => { video.local ? ({ url: video.local.uri, - preview_url: video.local.local_thumbnail, + preview_url: video.local.thumbnail, blurhash: video.remote?.blurhash } as Mastodon.AttachmentVideo) : (video.remote as Mastodon.AttachmentVideo) diff --git a/src/screens/Compose/Root.tsx b/src/screens/Compose/Root.tsx index f2270d8a..5afeaf54 100644 --- a/src/screens/Compose/Root.tsx +++ b/src/screens/Compose/Root.tsx @@ -4,13 +4,7 @@ import { useSearchQuery } from '@utils/queryHooks/search' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' import { chunk, forEach, groupBy, sortBy } from 'lodash' -import React, { - useCallback, - useContext, - useEffect, - useMemo, - useRef -} from 'react' +import React, { useContext, useEffect, useMemo, useRef } from 'react' import { AccessibilityInfo, findNodeHandle, @@ -147,35 +141,25 @@ const ComposeRoot = React.memo( } }, [isFetching]) - const listItem = useCallback( - ({ item }) => ( - - ), - [composeState] - ) - - const ListFooter = useCallback( - () => ( - - ), - [] - ) - return ( ( + + )} ListEmptyComponent={listEmpty} keyboardShouldPersistTaps='always' ListHeaderComponent={ComposeRootHeader} - ListFooterComponent={ListFooter} + ListFooterComponent={() => ( + + )} ItemSeparatorComponent={ComponentSeparator} // @ts-ignore data={data ? data[composeState.tag?.type] : undefined} diff --git a/src/screens/Compose/Root/Footer/Attachments.tsx b/src/screens/Compose/Root/Footer/Attachments.tsx index 8df70266..da5c7496 100644 --- a/src/screens/Compose/Root/Footer/Attachments.tsx +++ b/src/screens/Compose/Root/Footer/Attachments.tsx @@ -56,9 +56,12 @@ const ComposeAttachments: React.FC = ({ accessibleRefAttachments }) => { }) }, [composeState.attachments.sensitive]) - const calculateWidth = useCallback(item => { + const calculateWidth = useCallback((item: ExtendedAttachment) => { if (item.local) { - return (item.local.width / item.local.height) * DEFAULT_HEIGHT + return ( + ((item.local.width || 100) / (item.local.height || 100)) * + DEFAULT_HEIGHT + ) } else { if (item.remote) { if (item.remote.meta.original.aspect) { @@ -135,7 +138,7 @@ const ComposeAttachments: React.FC = ({ accessibleRefAttachments }) => { {item.remote?.meta?.original?.duration ? ( diff --git a/src/screens/Compose/Root/Footer/Emojis.tsx b/src/screens/Compose/Root/Footer/Emojis.tsx index 552d755d..eb6ee6b2 100644 --- a/src/screens/Compose/Root/Footer/Emojis.tsx +++ b/src/screens/Compose/Root/Footer/Emojis.tsx @@ -42,22 +42,6 @@ const ComposeEmojis: React.FC = ({ accessibleRefEmojis }) => { } }, [composeState.emoji.active]) - const listHeader = useCallback( - ({ section: { title } }) => ( - - {title} - - ), - [] - ) - const listItem = useCallback( ({ index, item }: { item: Mastodon.Emoji[]; index: number }) => { return ( @@ -155,7 +139,18 @@ const ComposeEmojis: React.FC = ({ accessibleRefEmojis }) => { keyboardShouldPersistTaps='always' sections={composeState.emoji.emojis || []} keyExtractor={item => item[0].shortcode} - renderSectionHeader={listHeader} + renderSectionHeader={({ section: { title } }) => ( + + {title} + + )} renderItem={listItem} windowSize={2} /> diff --git a/src/screens/Compose/Root/Footer/addAttachment.ts b/src/screens/Compose/Root/Footer/addAttachment.ts index 63e11904..676e67d9 100644 --- a/src/screens/Compose/Root/Footer/addAttachment.ts +++ b/src/screens/Compose/Root/Footer/addAttachment.ts @@ -7,7 +7,7 @@ import { ActionSheetOptions } from '@expo/react-native-action-sheet' import i18next from 'i18next' import apiInstance from '@api/instance' import mediaSelector from '@components/mediaSelector' -import { ImageOrVideo } from 'react-native-image-crop-picker' +import { Asset } from 'react-native-image-picker' export interface Props { composeDispatch: Dispatch @@ -22,46 +22,40 @@ export const uploadAttachment = async ({ media }: { composeDispatch: Dispatch - media: { uri: string } & Pick + media: Required> }) => { const hash = await Crypto.digestStringAsync( Crypto.CryptoDigestAlgorithm.SHA256, media.uri + Math.random() ) - switch (media.mime.split('/')[0]) { + switch (media.type.split('/')[0]) { case 'image': composeDispatch({ type: 'attachment/upload/start', payload: { - local: { ...media, type: 'image', local_thumbnail: media.uri, hash }, + local: { ...media, thumbnail: media.uri, hash }, uploading: true } }) break case 'video': VideoThumbnails.getThumbnailAsync(media.uri) - .then(({ uri, width, height }) => + .then(({ uri, width, height }) => { + console.log('new', uri, width, height) composeDispatch({ type: 'attachment/upload/start', payload: { - local: { - ...media, - type: 'video', - local_thumbnail: uri, - hash, - width, - height - }, + local: { ...media, thumbnail: uri, hash, width, height }, uploading: true } }) - ) + }) .catch(() => composeDispatch({ type: 'attachment/upload/start', payload: { - local: { ...media, type: 'video', hash }, + local: { ...media, hash }, uploading: true } }) @@ -71,7 +65,7 @@ export const uploadAttachment = async ({ composeDispatch({ type: 'attachment/upload/start', payload: { - local: { ...media, type: 'unknown', hash }, + local: { ...media, hash }, uploading: true } }) @@ -102,8 +96,8 @@ export const uploadAttachment = async ({ const formData = new FormData() formData.append('file', { uri: media.uri, - name: media.uri.match(new RegExp(/.*\/(.*)/))?.[1] || 'file.jpg', - type: media.mime + name: media.fileName, + type: media.type } as any) return apiInstance({ @@ -140,7 +134,8 @@ const chooseAndUploadAttachment = async ({ showActionSheetWithOptions }) for (const media of result) { - uploadAttachment({ composeDispatch, media }) + const requiredMedia = media as Required + uploadAttachment({ composeDispatch, media: requiredMedia }) await new Promise(res => setTimeout(res, 500)) } } diff --git a/src/screens/Compose/Root/Header/TextInput.tsx b/src/screens/Compose/Root/Header/TextInput.tsx index aa0ed691..f107cebf 100644 --- a/src/screens/Compose/Root/Header/TextInput.tsx +++ b/src/screens/Compose/Root/Header/TextInput.tsx @@ -101,15 +101,7 @@ const ComposeTextInput: React.FC = () => { } for (const file of files) { - uploadAttachment({ - composeDispatch, - media: { - uri: file.uri, - mime: file.type, - width: 100, - height: 100 - } - }) + uploadAttachment({ composeDispatch, media: file }) } }} > diff --git a/src/screens/Compose/utils/types.d.ts b/src/screens/Compose/utils/types.d.ts index 586be113..3b89b956 100644 --- a/src/screens/Compose/utils/types.d.ts +++ b/src/screens/Compose/utils/types.d.ts @@ -1,12 +1,8 @@ -import { ImageOrVideo } from 'react-native-image-crop-picker' +import { Asset } from 'react-native-image-picker' export type ExtendedAttachment = { remote?: Mastodon.Attachment - local?: { uri: string } & Pick & { - type: 'image' | 'video' | 'unknown' - local_thumbnail?: string - hash?: string - } + local?: Asset & { thumbnail?: string; hash: string } uploading?: boolean } @@ -121,10 +117,7 @@ export type ComposeAction = } | { type: 'attachment/upload/end' - payload: { - remote: Mastodon.Attachment - local: { uri: string } & Pick - } + payload: { remote: Mastodon.Attachment; local: Asset } } | { type: 'attachment/upload/fail' diff --git a/src/screens/ImageViewer/hooks/usePanResponder.ts b/src/screens/ImageViewer/hooks/usePanResponder.ts index d4ed1fe1..69f0eb9a 100644 --- a/src/screens/ImageViewer/hooks/usePanResponder.ts +++ b/src/screens/ImageViewer/hooks/usePanResponder.ts @@ -50,11 +50,9 @@ const usePanResponder = ({ onLongPress, delayLongPress, onRequestClose -}: Props): Readonly<[ - GestureResponderHandlers, - Animated.Value, - Animated.ValueXY -]> => { +}: Props): Readonly< + [GestureResponderHandlers, Animated.Value, Animated.ValueXY] +> => { let numberInitialTouches = 1 let initialTouches: NativeTouchEvent[] = [] let currentScale = initialScale @@ -137,6 +135,7 @@ const usePanResponder = ({ if (gestureState.numberActiveTouches > 1) return + // @ts-ignore longPressHandlerRef = setTimeout(onLongPress, delayLongPress) }, onStart: ( @@ -150,6 +149,7 @@ const usePanResponder = ({ const tapTS = Date.now() !timer && + // @ts-ignore (timer = setTimeout(() => onRequestClose(), DOUBLE_TAP_DELAY + 50)) // Handle double tap event by calculating diff between first and second taps timestamps @@ -158,6 +158,7 @@ const usePanResponder = ({ ) if (doubleTapToZoomEnabled && isDoubleTapPerformed) { + // @ts-ignore clearTimeout(timer) const isScaled = currentTranslate.x !== initialTranslate.x // currentScale !== initialScale; const { pageX: touchX, pageY: touchY } = event.nativeEvent.touches[0] @@ -291,9 +292,8 @@ const usePanResponder = ({ if (isTapGesture && currentScale > initialScale) { const { x, y } = currentTranslate const { dx, dy } = gestureState - const [topBound, leftBound, bottomBound, rightBound] = getBounds( - currentScale - ) + const [topBound, leftBound, bottomBound, rightBound] = + getBounds(currentScale) let nextTranslateX = x + dx let nextTranslateY = y + dy @@ -357,9 +357,8 @@ const usePanResponder = ({ if (tmpTranslate) { const { x, y } = tmpTranslate - const [topBound, leftBound, bottomBound, rightBound] = getBounds( - currentScale - ) + const [topBound, leftBound, bottomBound, rightBound] = + getBounds(currentScale) let nextTranslateX = x let nextTranslateY = y diff --git a/src/screens/ImageViewer/utils.ts b/src/screens/ImageViewer/utils.ts index 54703ac5..c75a8ae8 100644 --- a/src/screens/ImageViewer/utils.ts +++ b/src/screens/ImageViewer/utils.ts @@ -44,6 +44,7 @@ export const getImageStyles = ( const transform = translate.getTranslateTransform() if (scale) { + // @ts-ignore transform.push({ scale }, { perspective: new Animated.Value(1000) }) } diff --git a/src/screens/Tabs.tsx b/src/screens/Tabs.tsx index 0c18965e..6efb3266 100644 --- a/src/screens/Tabs.tsx +++ b/src/screens/Tabs.tsx @@ -1,10 +1,7 @@ import GracefullyImage from '@components/GracefullyImage' import haptics from '@components/haptics' import Icon from '@components/Icon' -import { - BottomTabNavigationOptions, - createBottomTabNavigator -} from '@react-navigation/bottom-tabs' +import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' import { useAppDispatch } from '@root/store' import { RootStackScreenProps, @@ -15,10 +12,7 @@ import { getInstanceAccount, getInstanceActive } from '@utils/slices/instancesSlice' -import { - getVersionUpdate, - retriveVersionLatest -} from '@utils/slices/appSlice' +import { getVersionUpdate, retriveVersionLatest } from '@utils/slices/appSlice' import { useTheme } from '@utils/styles/ThemeManager' import React, { useCallback, useEffect, useMemo } from 'react' import { Platform } from 'react-native' @@ -32,7 +26,7 @@ const Tab = createBottomTabNavigator() const ScreenTabs = React.memo( ({ navigation }: RootStackScreenProps<'Screen-Tabs'>) => { - const { colors, theme } = useTheme() + const { colors } = useTheme() const instanceActive = useSelector(getInstanceActive) const instanceAccount = useSelector( @@ -40,57 +34,6 @@ const ScreenTabs = React.memo( (prev, next) => prev?.avatarStatic === next?.avatarStatic ) - const screenOptions = useCallback( - ({ route }): BottomTabNavigationOptions => ({ - headerShown: false, - tabBarActiveTintColor: colors.primaryDefault, - tabBarInactiveTintColor: colors.secondary, - tabBarShowLabel: false, - ...(Platform.OS === 'android' && { tabBarHideOnKeyboard: true }), - tabBarStyle: { display: instanceActive !== -1 ? 'flex' : 'none' }, - tabBarIcon: ({ - focused, - color, - size - }: { - focused: boolean - color: string - size: number - }) => { - switch (route.name) { - case 'Tab-Local': - return - case 'Tab-Public': - return - case 'Tab-Compose': - return - case 'Tab-Notifications': - return - case 'Tab-Me': - return ( - - ) - default: - return - } - } - }), - [instanceAccount?.avatarStatic, instanceActive, theme] - ) - const composeListeners = useMemo( () => ({ tabPress: (e: any) => { @@ -132,7 +75,53 @@ const ScreenTabs = React.memo( return ( ({ + headerShown: false, + tabBarActiveTintColor: colors.primaryDefault, + tabBarInactiveTintColor: colors.secondary, + tabBarShowLabel: false, + ...(Platform.OS === 'android' && { tabBarHideOnKeyboard: true }), + tabBarStyle: { display: instanceActive !== -1 ? 'flex' : 'none' }, + tabBarIcon: ({ + focused, + color, + size + }: { + focused: boolean + color: string + size: number + }) => { + switch (route.name) { + case 'Tab-Local': + return + case 'Tab-Public': + return + case 'Tab-Compose': + return + case 'Tab-Notifications': + return + case 'Tab-Me': + return ( + + ) + default: + return + } + } + })} > diff --git a/src/screens/Tabs/Local.tsx b/src/screens/Tabs/Local.tsx index 53cadbb2..30c073fd 100644 --- a/src/screens/Tabs/Local.tsx +++ b/src/screens/Tabs/Local.tsx @@ -44,16 +44,16 @@ const TabLocal = React.memo( ) const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Following' }] - const renderItem = useCallback( - ({ item }) => , - [] - ) const children = useCallback( () => ( ( + + ) + }} /> ), [] diff --git a/src/screens/Tabs/Me/Bookmarks.tsx b/src/screens/Tabs/Me/Bookmarks.tsx index aad868e8..a6bdd1f2 100644 --- a/src/screens/Tabs/Me/Bookmarks.tsx +++ b/src/screens/Tabs/Me/Bookmarks.tsx @@ -1,16 +1,22 @@ import Timeline from '@components/Timeline' import TimelineDefault from '@components/Timeline/Default' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import React, { useCallback } from 'react' +import React from 'react' const TabMeBookmarks = React.memo( () => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Bookmarks' }] - const renderItem = useCallback( - ({ item }) => , - [] + + return ( + ( + + ) + }} + /> ) - return }, () => true ) diff --git a/src/screens/Tabs/Me/Cconversations.tsx b/src/screens/Tabs/Me/Cconversations.tsx index 65eecd6d..48d2410e 100644 --- a/src/screens/Tabs/Me/Cconversations.tsx +++ b/src/screens/Tabs/Me/Cconversations.tsx @@ -1,19 +1,22 @@ import Timeline from '@components/Timeline' import TimelineConversation from '@components/Timeline/Conversation' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import React, { useCallback } from 'react' +import React from 'react' const TabMeConversations = React.memo( () => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Conversations' }] - const renderItem = useCallback( - ({ item }) => ( - - ), - [] - ) - return + return ( + ( + + ) + }} + /> + ) }, () => true ) diff --git a/src/screens/Tabs/Me/Favourites.tsx b/src/screens/Tabs/Me/Favourites.tsx index fe799f19..c712fe4a 100644 --- a/src/screens/Tabs/Me/Favourites.tsx +++ b/src/screens/Tabs/Me/Favourites.tsx @@ -1,17 +1,22 @@ import Timeline from '@components/Timeline' import TimelineDefault from '@components/Timeline/Default' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import React, { useCallback } from 'react' +import React from 'react' const TabMeFavourites = React.memo( () => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Favourites' }] - const renderItem = useCallback( - ({ item }) => , - [] - ) - return + return ( + ( + + ) + }} + /> + ) }, () => true ) diff --git a/src/screens/Tabs/Me/ListsList.tsx b/src/screens/Tabs/Me/ListsList.tsx index ad94eb04..3c76cf85 100644 --- a/src/screens/Tabs/Me/ListsList.tsx +++ b/src/screens/Tabs/Me/ListsList.tsx @@ -2,7 +2,7 @@ import Timeline from '@components/Timeline' import TimelineDefault from '@components/Timeline/Default' import { TabMeStackScreenProps } from '@utils/navigation/navigators' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import React, { useCallback } from 'react' +import React from 'react' const TabMeListsList: React.FC> = ({ route: { @@ -10,12 +10,17 @@ const TabMeListsList: React.FC> = ({ } }) => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'List', list }] - const renderItem = useCallback( - ({ item }) => , - [] - ) - return + return ( + ( + + ) + }} + /> + ) } export default TabMeListsList diff --git a/src/screens/Tabs/Notifications.tsx b/src/screens/Tabs/Notifications.tsx index a6746b4a..32b8f0c2 100644 --- a/src/screens/Tabs/Notifications.tsx +++ b/src/screens/Tabs/Notifications.tsx @@ -43,14 +43,17 @@ const TabNotifications = React.memo( ) const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Notifications' }] - const renderItem = useCallback( - ({ item }) => ( - - ), - [] - ) const children = useCallback( - () => , + () => ( + ( + + ) + }} + /> + ), [] ) diff --git a/src/screens/Tabs/Shared/Account.tsx b/src/screens/Tabs/Shared/Account.tsx index d9562b42..cc1f561d 100644 --- a/src/screens/Tabs/Shared/Account.tsx +++ b/src/screens/Tabs/Shared/Account.tsx @@ -30,18 +30,10 @@ const TabSharedAccount: React.FC< const scrollY = useSharedValue(0) - const onScroll = useCallback(({ nativeEvent }) => { - scrollY.value = nativeEvent.contentOffset.y - }, []) - const [queryKey, setQueryKey] = useState([ 'Timeline', { page: 'Account_Default', account: account.id } ]) - const renderItem = useCallback( - ({ item }) => , - [] - ) const isFetchingTimeline = useIsFetching(queryKey) const fetchedTimeline = useRef(false) useEffect(() => { @@ -97,8 +89,11 @@ const TabSharedAccount: React.FC< queryKey={queryKey} disableRefresh customProps={{ - renderItem, - onScroll, + renderItem: ({ item }) => ( + + ), + onScroll: ({ nativeEvent }) => + (scrollY.value = nativeEvent.contentOffset.y), ListHeaderComponent, maintainVisibleContentPosition: undefined }} diff --git a/src/screens/Tabs/Shared/Account/Information.tsx b/src/screens/Tabs/Shared/Account/Information.tsx index f91d3860..82b47204 100644 --- a/src/screens/Tabs/Shared/Account/Information.tsx +++ b/src/screens/Tabs/Shared/Account/Information.tsx @@ -1,7 +1,7 @@ import { useRoute } from '@react-navigation/native' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' -import React, { useCallback } from 'react' +import React from 'react' import { StyleSheet, View } from 'react-native' import { Placeholder, Fade } from 'rn-placeholder' import AccountInformationAccount from './Information/Account' @@ -19,21 +19,21 @@ export interface Props { const AccountInformation = React.memo( ({ account }: Props) => { - const { colors, theme } = useTheme() + const { colors } = useTheme() const { name } = useRoute() const myInfo = name !== 'Tab-Shared-Account' - const animation = useCallback( - props => ( - - ), - [theme] - ) - return ( - + ( + + )} + > diff --git a/src/screens/Tabs/Shared/Attachments.tsx b/src/screens/Tabs/Shared/Attachments.tsx index 75036656..773b3938 100644 --- a/src/screens/Tabs/Shared/Attachments.tsx +++ b/src/screens/Tabs/Shared/Attachments.tsx @@ -2,11 +2,11 @@ import Timeline from '@components/Timeline' import TimelineDefault from '@components/Timeline/Default' import { TabSharedStackScreenProps } from '@utils/navigation/navigators' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import React, { useCallback } from 'react' +import React from 'react' -const TabSharedAttachments: React.FC> = ({ +const TabSharedAttachments: React.FC< + TabSharedStackScreenProps<'Tab-Shared-Attachments'> +> = ({ route: { params: { account } } @@ -15,11 +15,16 @@ const TabSharedAttachments: React.FC , - [] + return ( + ( + + ) + }} + /> ) - return } export default TabSharedAttachments diff --git a/src/screens/Tabs/Shared/Hashtag.tsx b/src/screens/Tabs/Shared/Hashtag.tsx index 6afd083a..93cd5061 100644 --- a/src/screens/Tabs/Shared/Hashtag.tsx +++ b/src/screens/Tabs/Shared/Hashtag.tsx @@ -2,21 +2,26 @@ import Timeline from '@components/Timeline' import TimelineDefault from '@components/Timeline/Default' import { TabSharedStackScreenProps } from '@utils/navigation/navigators' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import React, { useCallback } from 'react' +import React from 'react' -const TabSharedHashtag: React.FC> = ({ +const TabSharedHashtag: React.FC< + TabSharedStackScreenProps<'Tab-Shared-Hashtag'> +> = ({ route: { params: { hashtag } } }) => { const queryKey: QueryKeyTimeline = ['Timeline', { page: 'Hashtag', hashtag }] - const renderItem = useCallback( - ({ item }) => , - [] + return ( + ( + + ) + }} + /> ) - return } export default TabSharedHashtag diff --git a/src/screens/Tabs/Shared/Search.tsx b/src/screens/Tabs/Shared/Search.tsx index fd5d885c..4f883807 100644 --- a/src/screens/Tabs/Shared/Search.tsx +++ b/src/screens/Tabs/Shared/Search.tsx @@ -139,65 +139,22 @@ const TabSharedSearch: React.FC< ) }, [status]) - const sectionHeader = useCallback( - ({ section: { translation } }) => ( - - - {translation} - - - ), + + const listItem = useCallback( + ({ item, section }: { item: any; section: any }) => { + switch (section.title) { + case 'accounts': + return + case 'hashtags': + return + case 'statuses': + return + default: + return null + } + }, [] ) - const sectionFooter = useCallback( - ({ section: { data, translation } }) => - !data.length ? ( - - - - }} - /> - - - ) : null, - [text] - ) - const listItem = useCallback(({ item, section }) => { - switch (section.title) { - case 'accounts': - return - case 'hashtags': - return - case 'statuses': - return - default: - return null - } - }, []) return ( ( + + + {translation} + + + )} + renderSectionFooter={({ section: { data, translation } }) => + !data.length ? ( + + + + }} + /> + + + ) : null + } keyExtractor={(item, index) => item + index} SectionSeparatorComponent={ComponentSeparator} ItemSeparatorComponent={ComponentSeparator} diff --git a/src/screens/Tabs/Shared/Toot.tsx b/src/screens/Tabs/Shared/Toot.tsx index 63a6a6ea..b238ebad 100644 --- a/src/screens/Tabs/Shared/Toot.tsx +++ b/src/screens/Tabs/Shared/Toot.tsx @@ -3,7 +3,7 @@ import TimelineDefault from '@components/Timeline/Default' import { useNavigation } from '@react-navigation/native' import { TabSharedStackScreenProps } from '@utils/navigation/navigators' import { QueryKeyTimeline } from '@utils/queryHooks/timeline' -import React, { useCallback, useEffect, useRef, useState } from 'react' +import React, { useEffect, useRef, useState } from 'react' import { FlatList } from 'react-native' import { InfiniteQueryObserver, useQueryClient } from 'react-query' @@ -59,43 +59,35 @@ const TabSharedToot: React.FC> = ({ }) }, [scrolled.current]) - // Toot page auto scroll to selected toot - const onScrollToIndexFailed = useCallback( - error => { - const offset = error.averageItemLength * error.index - flRef.current?.scrollToOffset({ offset }) - try { - error.index < itemsLength && - setTimeout( - () => - flRef.current?.scrollToIndex({ - index: error.index, - viewOffset: 100 - }), - 500 - ) - } catch {} - }, - [itemsLength] - ) - - const renderItem = useCallback( - ({ item }) => ( - - ), - [] - ) - return ( ( + + ), + onScrollToIndexFailed: error => { + const offset = error.averageItemLength * error.index + flRef.current?.scrollToOffset({ offset }) + try { + error.index < itemsLength && + setTimeout( + () => + flRef.current?.scrollToIndex({ + index: error.index, + viewOffset: 100 + }), + 500 + ) + } catch {} + } + }} disableRefresh disableInfinity /> diff --git a/src/screens/Tabs/Shared/Users.tsx b/src/screens/Tabs/Shared/Users.tsx index 34134664..187f3b11 100644 --- a/src/screens/Tabs/Shared/Users.tsx +++ b/src/screens/Tabs/Shared/Users.tsx @@ -9,28 +9,20 @@ import { FlatList } from 'react-native-gesture-handler' const TabSharedUsers = React.memo( ({ route: { params } }: TabSharedStackScreenProps<'Tab-Shared-Users'>) => { const queryKey: QueryKeyUsers = ['Users', params] - const { - data, - hasNextPage, - fetchNextPage, - isFetchingNextPage - } = useUsersQuery({ - ...queryKey[1], - options: { - getPreviousPageParam: firstPage => - firstPage.links?.prev && { since_id: firstPage.links.next }, - getNextPageParam: lastPage => - lastPage.links?.next && { max_id: lastPage.links.next } - } - }) + const { data, hasNextPage, fetchNextPage, isFetchingNextPage } = + useUsersQuery({ + ...queryKey[1], + options: { + getPreviousPageParam: firstPage => + firstPage.links?.prev && { since_id: firstPage.links.next }, + getNextPageParam: lastPage => + lastPage.links?.next && { max_id: lastPage.links.next } + } + }) const flattenData = data?.pages ? data.pages.flatMap(page => [...page.body]) : [] - const renderItem = useCallback( - ({ item }) => , - [] - ) const onEndReached = useCallback( () => hasNextPage && !isFetchingNextPage && fetchNextPage(), [hasNextPage, isFetchingNextPage] @@ -41,7 +33,9 @@ const TabSharedUsers = React.memo( windowSize={7} data={flattenData} style={styles.flatList} - renderItem={renderItem} + renderItem={({ item }) => ( + + )} onEndReached={onEndReached} onEndReachedThreshold={0.75} ItemSeparatorComponent={ComponentSeparator} diff --git a/src/utils/accessibility/AccessibilityManager.tsx b/src/utils/accessibility/AccessibilityManager.tsx index 871db497..28ab4ed8 100644 --- a/src/utils/accessibility/AccessibilityManager.tsx +++ b/src/utils/accessibility/AccessibilityManager.tsx @@ -1,4 +1,10 @@ -import React, { createContext, useContext, useEffect, useState } from 'react' +import React, { + createContext, + PropsWithChildren, + useContext, + useEffect, + useState +} from 'react' import { AccessibilityInfo } from 'react-native' type ContextType = { @@ -15,7 +21,7 @@ const AccessibilityContext = createContext({ export const useAccessibility = () => useContext(AccessibilityContext) -const AccessibilityManager: React.FC = ({ children }) => { +const AccessibilityManager: React.FC = ({ children }) => { const [reduceMotionEnabled, setReduceMotionEnabled] = useState(false) const [screenReaderEnabled, setScreenReaderEnabled] = useState(false) const [boldTextEnabled, setBoldTextEnabled] = useState(false) diff --git a/src/utils/styles/ThemeManager.tsx b/src/utils/styles/ThemeManager.tsx index a5d9ea17..21959cab 100644 --- a/src/utils/styles/ThemeManager.tsx +++ b/src/utils/styles/ThemeManager.tsx @@ -1,4 +1,10 @@ -import React, { createContext, useContext, useEffect, useState } from 'react' +import React, { + createContext, + PropsWithChildren, + useContext, + useEffect, + useState +} from 'react' import { Appearance } from 'react-native' import { useSelector } from 'react-redux' import { ColorDefinitions, getColors, Theme } from '@utils/styles/themes' @@ -74,7 +80,7 @@ const determineTheme = ( } } -const ThemeManager: React.FC = ({ children }) => { +const ThemeManager: React.FC = ({ children }) => { const osTheme = useColorSchemeDelay() const userTheme = useSelector(getSettingsTheme) const darkTheme = useSelector(getSettingsDarkTheme)