From d1bddc696afdcd187d103147b2ab253e3e561b4a Mon Sep 17 00:00:00 2001 From: Zhiyuan Zheng Date: Thu, 11 Feb 2021 01:33:31 +0100 Subject: [PATCH] Fixed #19 --- README.md | 1 - .../app/tooot/generated/BasePackageList.java | 1 + .../res/drawable-night/splashscreen_image.png | Bin 70155 -> 70177 bytes .../app/src/main/res/values-night/colors.xml | 2 +- app.config.ts | 4 - ios/Podfile.lock | 6 - .../dark_splashscreen.png | Bin 70155 -> 70177 bytes .../Background.colorset/Contents.json | 6 +- package.json | 5 +- src/@types/app.d.ts | 9 +- src/@types/untyped.d.ts | 1 + src/Screens.tsx | 2 +- src/api/client.ts | 26 ++- src/components/Timeline.tsx | 163 +++++++++--------- src/components/Timeline/Default.tsx | 12 +- .../Timeline/Shared/HeaderNotification.tsx | 2 +- src/i18n/en/system.json | 4 - src/i18n/zh-Hans/system.json | 4 - src/screens/Actions/Status.tsx | 9 +- src/screens/Compose/DraftsList/Root.tsx | 2 +- src/screens/Compose/EditAttachment.tsx | 56 +++--- src/screens/Compose/EditAttachment/Image.tsx | 9 +- src/screens/Compose/EditAttachment/Root.tsx | 11 +- .../Compose/Root/Footer/Attachments.tsx | 7 +- src/screens/Compose/Root/Footer/Emojis.tsx | 2 +- .../Compose/Root/Footer/addAttachment.ts | 4 +- src/screens/Compose/utils/reducer.ts | 2 +- src/screens/ImagesViewer.tsx | 4 + src/screens/Tabs.tsx | 5 +- src/screens/Tabs/Me/Settings/Tooot.tsx | 4 +- src/screens/Tabs/Shared/Account.tsx | 1 + .../Tabs/Shared/Account/Attachments.tsx | 6 +- .../Tabs/Shared/Relationships/List.tsx | 14 +- src/startup/netInfo.ts | 6 +- src/utils/queryHooks/account.ts | 2 +- src/utils/queryHooks/accountCheck.ts | 2 +- src/utils/queryHooks/announcement.ts | 2 +- src/utils/queryHooks/apps.ts | 2 +- src/utils/queryHooks/emojis.ts | 2 +- src/utils/queryHooks/instance.ts | 2 +- src/utils/queryHooks/lists.ts | 2 +- src/utils/queryHooks/relationship.ts | 6 +- src/utils/queryHooks/relationships.ts | 21 ++- src/utils/queryHooks/search.ts | 2 +- src/utils/queryHooks/timeline.ts | 58 +++---- src/utils/queryHooks/timeline/deleteItem.ts | 17 +- .../timeline/updateStatusProperty.ts | 11 +- src/utils/slices/instancesSlice.ts | 10 +- src/utils/styles/themes.ts | 6 +- yarn.lock | 5 + 50 files changed, 271 insertions(+), 269 deletions(-) delete mode 100644 src/i18n/en/system.json delete mode 100644 src/i18n/zh-Hans/system.json diff --git a/README.md b/README.md index 9e10710f..e69de29b 100644 --- a/README.md +++ b/README.md @@ -1 +0,0 @@ -@tooot@xmflsct.com \ No newline at end of file diff --git a/android/app/src/main/java/com/xmflsct/app/tooot/generated/BasePackageList.java b/android/app/src/main/java/com/xmflsct/app/tooot/generated/BasePackageList.java index 07f590fa..dfd10e2d 100644 --- a/android/app/src/main/java/com/xmflsct/app/tooot/generated/BasePackageList.java +++ b/android/app/src/main/java/com/xmflsct/app/tooot/generated/BasePackageList.java @@ -25,6 +25,7 @@ public class BasePackageList { new expo.modules.localization.LocalizationPackage(), new expo.modules.location.LocationPackage(), new expo.modules.permissions.PermissionsPackage(), + new expo.modules.screencapture.ScreenCapturePackage(), new expo.modules.securestore.SecureStorePackage(), new expo.modules.splashscreen.SplashScreenPackage(), new expo.modules.sqlite.SQLitePackage(), diff --git a/android/app/src/main/res/drawable-night/splashscreen_image.png b/android/app/src/main/res/drawable-night/splashscreen_image.png index 83ca55a4a3b5ace827d4f8b005b7837229c7cf8f..8ba9b37af4e8a1babe54e62d38eb84cb97b32933 100644 GIT binary patch literal 70177 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 literal 70155 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

!prcwo7sFb)6Lw`&cS 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 nU}k`wkROEbkt1IO#5gF diff --git a/ios/tooot/RootViewColor.xcassets/Background.colorset/Contents.json b/ios/tooot/RootViewColor.xcassets/Background.colorset/Contents.json index ff4bf220..dd794a6f 100644 --- a/ios/tooot/RootViewColor.xcassets/Background.colorset/Contents.json +++ b/ios/tooot/RootViewColor.xcassets/Background.colorset/Contents.json @@ -23,9 +23,9 @@ "color-space" : "srgb", "components" : { "alpha" : "1.000", - "blue" : "25", - "green" : "25", - "red" : "25" + "blue" : "18", + "green" : "18", + "red" : "18" } }, "idiom" : "universal" diff --git a/package.json b/package.json index d1782c77..9c0f4969 100644 --- a/package.json +++ b/package.json @@ -43,6 +43,7 @@ "expo-video-thumbnails": "~4.4.0", "expo-web-browser": "~8.6.0", "i18next": "^19.8.5", + "li": "^1.3.0", "lodash": "^4.17.20", "react": "16.13.1", "react-dom": "16.13.1", @@ -108,8 +109,8 @@ "versions": { "native": "210201", "major": 0, - "minor": 3, - "patch": 1, + "minor": 4, + "patch": 0, "expo": "40.0.0" } } diff --git a/src/@types/app.d.ts b/src/@types/app.d.ts index 959b393b..489f987e 100644 --- a/src/@types/app.d.ts +++ b/src/@types/app.d.ts @@ -15,10 +15,9 @@ declare namespace App { | 'Favourites' interface IImageInfo { - url: string - width?: number - height?: number - originUrl?: string - props?: any + uri: string + width: number + height: number + type?: 'image' | 'video' } } diff --git a/src/@types/untyped.d.ts b/src/@types/untyped.d.ts index fae6f608..24592684 100644 --- a/src/@types/untyped.d.ts +++ b/src/@types/untyped.d.ts @@ -1,4 +1,5 @@ declare module 'gl-react-blurhash' +declare module 'li' declare module 'react-native-feather' declare module 'react-native-htmlview' declare module 'react-native-toast-message' diff --git a/src/Screens.tsx b/src/Screens.tsx index 49349274..7e0a015a 100644 --- a/src/Screens.tsx +++ b/src/Screens.tsx @@ -90,7 +90,7 @@ const Screens: React.FC = ({ localCorrupt }) => { url: `announcements` }) .then(res => { - if (res?.filter(announcement => !announcement.read).length) { + if (res.body.filter(announcement => !announcement.read).length) { navigationRef.current?.navigate('Screen-Announcements', { showAll: false }) diff --git a/src/api/client.ts b/src/api/client.ts index 52cdac4f..66ea911a 100644 --- a/src/api/client.ts +++ b/src/api/client.ts @@ -1,6 +1,7 @@ import { RootState } from '@root/store' import axios from 'axios' import chalk from 'chalk' +import li from 'li' const ctx = new chalk.Instance({ level: 3 }) @@ -28,7 +29,7 @@ const client = async ({ headers?: { [key: string]: string } body?: FormData onUploadProgress?: (progressEvent: any) => void -}): Promise => { +}): Promise<{ body: T; links: { prev?: string; next?: string } }> => { const { store } = require('@root/store') const state = (store.getState() as RootState).instances const theLocalIndex = @@ -78,7 +79,19 @@ const client = async ({ ...(body && { data: body }), ...(onUploadProgress && { onUploadProgress: onUploadProgress }) }) - .then(response => Promise.resolve(response.data)) + .then(response => { + let prev + let next + if (response.headers.link) { + const headersLinks = li.parse(response.headers.link) + prev = headersLinks.prev?.match(/_id=([0-9]*)/)[1] + next = headersLinks.next?.match(/_id=([0-9]*)/)[1] + } + return Promise.resolve({ + body: response.data, + links: { prev, next } + }) + }) .catch(error => { if (error.response) { // The request was made and the server responded with a status code @@ -97,8 +110,13 @@ const client = async ({ console.error(ctx.bold(' API '), ctx.bold('request'), error) return Promise.reject() } else { - console.error(ctx.bold(' API '), ctx.bold('other'), error.message) - return Promise.reject({ body: error.message }) + console.error( + ctx.bold(' API '), + ctx.bold('internal'), + error.message, + url + ) + return Promise.reject() } }) } diff --git a/src/components/Timeline.tsx b/src/components/Timeline.tsx index 9945d668..afcb7957 100644 --- a/src/components/Timeline.tsx +++ b/src/components/Timeline.tsx @@ -4,7 +4,7 @@ import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline' import { getLocalActiveIndex } from '@utils/slices/instancesSlice' import { StyleConstants } from '@utils/styles/constants' import { findIndex } from 'lodash' -import React, { useCallback, useEffect, useMemo, useRef } from 'react' +import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { FlatListProps, StyleSheet } from 'react-native' import { FlatList } from 'react-native-gesture-handler' import Animated, { @@ -14,6 +14,7 @@ import Animated, { } from 'react-native-reanimated' import { InfiniteData, useQueryClient } from 'react-query' import { useSelector } from 'react-redux' +import haptics from './haptics' import TimelineConversation from './Timeline/Conversation' import TimelineDefault from './Timeline/Default' import TimelineEmpty from './Timeline/Empty' @@ -68,30 +69,18 @@ const Timeline: React.FC = ({ } = useTimelineQuery({ ...queryKeyParams, options: { - getPreviousPageParam: firstPage => { - return Array.isArray(firstPage) && firstPage.length - ? { - direction: 'prev', - id: firstPage[0].last_status - ? firstPage[0].last_status.id - : firstPage[0].id - } - : undefined - }, - getNextPageParam: lastPage => { - return Array.isArray(lastPage) && lastPage.length - ? { - direction: 'next', - id: lastPage[lastPage.length - 1].last_status - ? lastPage[lastPage.length - 1].last_status.id - : lastPage[lastPage.length - 1].id - } - : undefined - } + getPreviousPageParam: firstPage => + firstPage.links?.prev && { + min_id: firstPage.links.prev, + // https://github.com/facebook/react-native/issues/25239#issuecomment-731100372 + limit: '3' + }, + getNextPageParam: lastPage => + lastPage.links?.next && { max_id: lastPage.links.next } } }) - const flattenData = data?.pages ? data.pages.flatMap(d => [...d]) : [] + const flattenData = data?.pages ? data.pages.flatMap(d => [...d.body]) : [] const flRef = useRef>(null) const scrolled = useRef(false) @@ -109,22 +98,30 @@ const Timeline: React.FC = ({ }, [isSuccess, flattenData.length, scrolled]) const keyExtractor = useCallback(({ id }) => id, []) - const renderItem = useCallback(({ item }) => { - switch (page) { - case 'Conversations': - return - case 'Notifications': - return - default: - return ( - - ) - } - }, []) + const renderItem = useCallback( + ({ item }) => { + switch (page) { + case 'Conversations': + return ( + + ) + case 'Notifications': + return ( + + ) + default: + return ( + + ) + } + }, + [data?.pages[0]] + ) const ItemSeparatorComponent = useCallback( ({ leadingItem }) => ( = ({ () => !disableInfinity && !isFetchingNextPage && fetchNextPage(), [isFetchingNextPage] ) - const prevId = useSharedValue(null) - const headerPadding = useAnimatedStyle(() => { - if (hasPreviousPage) { - if (isFetchingPreviousPage) { - return { paddingTop: withTiming(StyleConstants.Spacing.XL) } - } else { - return { paddingTop: withTiming(0) } - } - } else { - return { paddingTop: withTiming(0) } - } - }, [hasPreviousPage, isFetchingPreviousPage]) - const ListHeaderComponent = useMemo( - () => , - [] - ) const ListFooterComponent = useMemo( () => , [hasNextPage] @@ -180,38 +161,60 @@ const Timeline: React.FC = ({ useScrollToTop(flRef) const queryClient = useQueryClient() const scrollY = useSharedValue(0) - const onScroll = useCallback( - ({ nativeEvent }) => (scrollY.value = nativeEvent.contentOffset.y), - [] - ) + const [isFetchingLatest, setIsFetchingLatest] = useState(false) + useEffect(() => { + // https://github.com/facebook/react-native/issues/25239#issuecomment-731100372 + if (isFetchingLatest) { + if (!isFetchingPreviousPage) { + fetchPreviousPage() + } else { + if (data?.pages[0].body.length === 0) { + setIsFetchingLatest(false) + queryClient.setQueryData | undefined>( + queryKey, + data => { + if (data?.pages[0].body.length === 0) { + return { + pages: data.pages.slice(1), + pageParams: data.pageParams.slice(1) + } + } else { + return data + } + } + ) + } + } + } + }, [isFetchingPreviousPage, isFetchingLatest, data?.pages[0].body]) + const onScroll = useCallback(({ nativeEvent }) => { + scrollY.value = nativeEvent.contentOffset.y + }, []) const onResponderRelease = useCallback(() => { if ( scrollY.value <= -StyleConstants.Spacing.XL && - !isFetchingPreviousPage && + !isFetchingLatest && !disableRefresh ) { - queryClient.setQueryData | undefined>( - queryKey, - data => { - if (data?.pages[0].length === 0) { - if (data.pages[1]) { - prevId.value = data.pages[1][0].id - } - return { - pages: data.pages.slice(1), - pageParams: data.pageParams.slice(1) - } - } else { - prevId.value = data?.pages[0][0].id - return data - } - } - ) - // https://github.com/facebook/react-native/issues/25239#issuecomment-731100372 - fetchPreviousPage() - flRef.current?.scrollToOffset({ animated: true, offset: 1 }) + haptics('Light') + setIsFetchingLatest(true) + flRef.current?.scrollToOffset({ + animated: true, + offset: 1 + }) } - }, [scrollY.value, isFetchingPreviousPage, disableRefresh]) + }, [scrollY.value, isFetchingLatest, disableRefresh]) + const headerPadding = useAnimatedStyle(() => { + if (isFetchingLatest) { + return { paddingTop: withTiming(StyleConstants.Spacing.XL) } + } else { + return { paddingTop: withTiming(0) } + } + }, [isFetchingLatest]) + const ListHeaderComponent = useMemo( + () => , + [] + ) return ( <> diff --git a/src/components/Timeline/Default.tsx b/src/components/Timeline/Default.tsx index b602c854..91cb330b 100644 --- a/src/components/Timeline/Default.tsx +++ b/src/components/Timeline/Default.tsx @@ -24,6 +24,7 @@ export interface Props { highlighted?: boolean disableDetails?: boolean disableOnPress?: boolean + pinned: Mastodon.Status['id'][] } // When the poll is long @@ -33,7 +34,8 @@ const TimelineDefault: React.FC = ({ origin, highlighted = false, disableDetails = false, - disableOnPress = false + disableOnPress = false, + pinned }) => { const { theme } = useTheme() const localAccount = useSelector( @@ -73,7 +75,7 @@ const TimelineDefault: React.FC = ({ > {item.reblog ? ( - ) : item.isPinned ? ( + ) : pinned && pinned.includes(item.id) ? ( ) : null} @@ -113,9 +115,11 @@ const TimelineDefault: React.FC = ({ sameAccount={actualStatus.account.id === localAccount?.id} /> ) : null} - {!disableDetails && actualStatus.media_attachments.length > 0 && ( + {!disableDetails && + Array.isArray(actualStatus.media_attachments) && + actualStatus.media_attachments.length ? ( - )} + ) : null} {!disableDetails && actualStatus.card && ( )} diff --git a/src/components/Timeline/Shared/HeaderNotification.tsx b/src/components/Timeline/Shared/HeaderNotification.tsx index 338edab4..3db92160 100644 --- a/src/components/Timeline/Shared/HeaderNotification.tsx +++ b/src/components/Timeline/Shared/HeaderNotification.tsx @@ -46,7 +46,7 @@ const TimelineHeaderNotification: React.FC = ({ onPress={() => navigation.navigate('Screen-Actions', { queryKey, - status, + status: notification.status, url: notification.status?.url || notification.status?.uri, type: 'status' }) diff --git a/src/i18n/en/system.json b/src/i18n/en/system.json deleted file mode 100644 index c0b5f7fe..00000000 --- a/src/i18n/en/system.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "NSCameraUsageDescription": "Allow camera access to upload attachments", - "NSPhotoLibraryUsageDescription": "Allow photo library access to upload attachments" -} \ No newline at end of file diff --git a/src/i18n/zh-Hans/system.json b/src/i18n/zh-Hans/system.json deleted file mode 100644 index 637191f4..00000000 --- a/src/i18n/zh-Hans/system.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "NSCameraUsageDescription": "允许tooot使用相机拍摄上传附件", - "NSPhotoLibraryUsageDescription": "允许tooot读取相册上传附件" -} \ No newline at end of file diff --git a/src/screens/Actions/Status.tsx b/src/screens/Actions/Status.tsx index 169d0970..68954ca7 100644 --- a/src/screens/Actions/Status.tsx +++ b/src/screens/Actions/Status.tsx @@ -100,16 +100,17 @@ const ActionsStatus: React.FC = ({ } ) dismiss() - const res = (await mutation.mutateAsync({ + const res = await mutation.mutateAsync({ type: 'deleteItem', source: 'statuses', queryKey, id: status.id - })) as Mastodon.Status - if (res.id) { + }) + if (res.body.id) { + // @ts-ignore navigation.navigate('Screen-Compose', { type: 'edit', - incomingStatus: res, + incomingStatus: res.body, queryKey }) } diff --git a/src/screens/Compose/DraftsList/Root.tsx b/src/screens/Compose/DraftsList/Root.tsx index b5200064..b289a45f 100644 --- a/src/screens/Compose/DraftsList/Root.tsx +++ b/src/screens/Compose/DraftsList/Root.tsx @@ -64,7 +64,7 @@ const ComposeDraftsListRoot: React.FC = ({ timestamp }) => { url: `media/${attachment.remote?.id}` }) .then(res => { - if (res.id === attachment.remote?.id) { + if (res.body.id === attachment.remote?.id) { tempUploads.push(attachment) } }) diff --git a/src/screens/Compose/EditAttachment.tsx b/src/screens/Compose/EditAttachment.tsx index 21247ef1..b2296e4e 100644 --- a/src/screens/Compose/EditAttachment.tsx +++ b/src/screens/Compose/EditAttachment.tsx @@ -3,15 +3,10 @@ import analytics from '@components/analytics' import haptics from '@components/haptics' import { HeaderCenter, HeaderLeft, HeaderRight } from '@components/Header' import { StackScreenProps } from '@react-navigation/stack' -import React, { - useCallback, - useContext, - useEffect, - useRef, - useState -} from 'react' +import React, { useCallback, useContext, useEffect, useState } from 'react' import { useTranslation } from 'react-i18next' import { Alert, KeyboardAvoidingView, Platform } from 'react-native' +import { useSharedValue } from 'react-native-reanimated' import { SafeAreaView } from 'react-native-safe-area-context' import { createNativeStackNavigator } from 'react-native-screens/native-stack' import ComposeEditAttachmentRoot from './EditAttachment/Root' @@ -39,34 +34,31 @@ const ComposeEditAttachment: React.FC = ({ const [altText, setAltText] = useState( theAttachment.description ) - const focus = useRef({ x: 0, y: 0 }) + const focus = useSharedValue({ + x: theAttachment.meta.focus.x, + y: theAttachment.meta.focus.y + }) useEffect(() => { const unsubscribe = navigation.addListener('beforeRemove', () => { - let needUpdate = false - - if (theAttachment.description !== altText) { - theAttachment.description = altText - needUpdate = true - } - - if (theAttachment.type === 'image') { - if (focus.current.x !== 0 || focus.current.y !== 0) { - theAttachment.meta && - (theAttachment.meta.focus = { - x: focus.current.x > 1 ? 1 : focus.current.x, - y: focus.current.y > 1 ? 1 : focus.current.y - }) - needUpdate = true + composeDispatch({ + type: 'attachment/edit', + payload: { + ...theAttachment, + description: altText, + meta: { + ...theAttachment.meta, + focus: { + x: focus.value.x > 1 ? 1 : focus.value.x, + y: focus.value.y > 1 ? 1 : focus.value.y + } + } } - } - if (needUpdate) { - composeDispatch({ type: 'attachment/edit', payload: theAttachment }) - } + }) }) return unsubscribe - }, [focus, altText]) + }, [focus.value.x, focus.value.y, altText]) const headerLeft = useCallback( () => ( @@ -86,7 +78,7 @@ const ComposeEditAttachment: React.FC = ({ loading={isSubmitting} onPress={() => { analytics('editattachment_confirm_press') - if (!altText && focus.current.x === 0 && focus.current.y === 0) { + if (!altText && focus.value.x === 0 && focus.value.y === 0) { navigation.goBack() return } @@ -95,8 +87,8 @@ const ComposeEditAttachment: React.FC = ({ if (altText) { formData.append('description', altText) } - if (focus.current.x !== 0 || focus.current.y !== 0) { - formData.append('focus', `${focus.current.x},${focus.current.y}`) + if (focus.value.x !== 0 || focus.value.y !== 0) { + formData.append('focus', `${focus.value.x},${focus.value.y}`) } client({ @@ -129,7 +121,7 @@ const ComposeEditAttachment: React.FC = ({ /> ), - [] + [isSubmitting, altText, focus.value.x, focus.value.y] ) const children = useCallback( diff --git a/src/screens/Compose/EditAttachment/Image.tsx b/src/screens/Compose/EditAttachment/Image.tsx index 5b267ae4..7e86c40b 100644 --- a/src/screens/Compose/EditAttachment/Image.tsx +++ b/src/screens/Compose/EditAttachment/Image.tsx @@ -1,6 +1,6 @@ import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' -import React, { MutableRefObject, useContext } from 'react' +import React, { useContext } from 'react' import { useTranslation } from 'react-i18next' import { Dimensions, StyleSheet, Text, View } from 'react-native' import FastImage from 'react-native-fast-image' @@ -18,7 +18,7 @@ import ComposeContext from '../utils/createContext' export interface Props { index: number - focus: MutableRefObject<{ + focus: Animated.SharedValue<{ x: number y: number }> @@ -57,7 +57,7 @@ const ComposeEditAttachmentImage: React.FC = ({ index, focus }) => { 2 ) const updateFocus = ({ x, y }: { x: number; y: number }) => { - focus.current = { x, y } + focus.value = { x, y } } type PanContext = { startX: number @@ -110,7 +110,7 @@ const ComposeEditAttachmentImage: React.FC = ({ index, focus }) => { return ( <> - + = ({ index, focus }) => { } const styles = StyleSheet.create({ + base: { overflow: 'hidden', flex: 1, alignItems: 'center' }, imageFocusText: { ...StyleConstants.FontStyle.M, padding: StyleConstants.Spacing.Global.PagePadding diff --git a/src/screens/Compose/EditAttachment/Root.tsx b/src/screens/Compose/EditAttachment/Root.tsx index 98e5b384..782ea96b 100644 --- a/src/screens/Compose/EditAttachment/Root.tsx +++ b/src/screens/Compose/EditAttachment/Root.tsx @@ -1,21 +1,16 @@ import AttachmentVideo from '@components/Timeline/Shared/Attachment/Video' import { StyleConstants } from '@utils/styles/constants' import { useTheme } from '@utils/styles/ThemeManager' -import React, { - Dispatch, - MutableRefObject, - SetStateAction, - useContext, - useMemo -} from 'react' +import React, { Dispatch, SetStateAction, useContext, useMemo } from 'react' import { useTranslation } from 'react-i18next' import { ScrollView, StyleSheet, Text, TextInput, View } from 'react-native' +import Animated from 'react-native-reanimated' import ComposeContext from '../utils/createContext' import ComposeEditAttachmentImage from './Image' export interface Props { index: number - focus: MutableRefObject<{ + focus: Animated.SharedValue<{ x: number y: number }> diff --git a/src/screens/Compose/Root/Footer/Attachments.tsx b/src/screens/Compose/Root/Footer/Attachments.tsx index 4786ed1f..493ea87b 100644 --- a/src/screens/Compose/Root/Footer/Attachments.tsx +++ b/src/screens/Compose/Root/Footer/Attachments.tsx @@ -32,7 +32,6 @@ const ComposeAttachments: React.FC = () => { const navigation = useNavigation() const flatListRef = useRef(null) - let prevOffsets = useRef() const sensitiveOnPress = useCallback(() => { analytics('compose_attachment_sensitive_press', { @@ -92,7 +91,7 @@ const ComposeAttachments: React.FC = () => { ] : attachmentsOffsets }, [composeState.attachments.uploads.length]) - + let prevOffsets = useRef() useEffect(() => { if ( snapToOffsets.length > @@ -105,7 +104,7 @@ const ComposeAttachments: React.FC = () => { }) } prevOffsets.current = snapToOffsets - }, [snapToOffsets, prevOffsets]) + }, [snapToOffsets, prevOffsets.current]) const renderAttachment = useCallback( ({ item, index }: { item: ExtendedAttachment; index: number }) => { @@ -251,7 +250,7 @@ const ComposeAttachments: React.FC = () => { showsHorizontalScrollIndicator={false} data={composeState.attachments.uploads} keyExtractor={item => - item.local?.url || item.remote?.url || Math.random().toString() + item.local?.uri || item.remote?.url || Math.random().toString() } ListFooterComponent={ composeState.attachments.uploads.length < 4 ? listFooter : null diff --git a/src/screens/Compose/Root/Footer/Emojis.tsx b/src/screens/Compose/Root/Footer/Emojis.tsx index 1775186c..26a017f5 100644 --- a/src/screens/Compose/Root/Footer/Emojis.tsx +++ b/src/screens/Compose/Root/Footer/Emojis.tsx @@ -22,7 +22,7 @@ const SingleEmoji = ({ emoji }: { emoji: Mastodon.Emoji }) => { // type: 'emoji', // payload: { ...composeState.emoji, active: false } // }) - haptics('Success') + haptics('Light') }, [composeState]) const children = useMemo( () => , diff --git a/src/screens/Compose/Root/Footer/addAttachment.ts b/src/screens/Compose/Root/Footer/addAttachment.ts index 3459b56d..8ebee3e9 100644 --- a/src/screens/Compose/Root/Footer/addAttachment.ts +++ b/src/screens/Compose/Root/Footer/addAttachment.ts @@ -113,10 +113,10 @@ const addAttachment = async ({ body: formData }) .then(res => { - if (res.id) { + if (res.body.id) { composeDispatch({ type: 'attachment/upload/end', - payload: { remote: res, local: result } + payload: { remote: res.body, local: result } }) } else { uploadFailed() diff --git a/src/screens/Compose/utils/reducer.ts b/src/screens/Compose/utils/reducer.ts index a4b448c3..e7fecc30 100644 --- a/src/screens/Compose/utils/reducer.ts +++ b/src/screens/Compose/utils/reducer.ts @@ -70,7 +70,7 @@ const composeReducer = ( attachments: { ...state.attachments, uploads: state.attachments.uploads.filter( - upload => upload.local.hash !== action.payload + upload => upload.local?.hash !== action.payload ) } } diff --git a/src/screens/ImagesViewer.tsx b/src/screens/ImagesViewer.tsx index f10d645c..e1a26daa 100644 --- a/src/screens/ImagesViewer.tsx +++ b/src/screens/ImagesViewer.tsx @@ -28,6 +28,10 @@ const ScreenImagesViewer = ({ }, navigation }: ScreenImagesViewerProp) => { + if (imageUrls.length === 0) { + return null + } + const [currentIndex, setCurrentIndex] = useState( findIndex(imageUrls, ['imageIndex', imageIndex]) ) diff --git a/src/screens/Tabs.tsx b/src/screens/Tabs.tsx index b3bfc2d8..e19918c2 100644 --- a/src/screens/Tabs.tsx +++ b/src/screens/Tabs.tsx @@ -145,10 +145,11 @@ const ScreenTabs = React.memo( options: { notifyOnChangeProps: [], select: data => { - if (data.pages[0].length) { + if (data.pages[0].body.length) { dispatch( updateLocalNotification({ - latestTime: data.pages[0][0].created_at + // @ts-ignore + latestTime: data.pages[0].body[0].created_at }) ) } diff --git a/src/screens/Tabs/Me/Settings/Tooot.tsx b/src/screens/Tabs/Me/Settings/Tooot.tsx index 6d55b430..26200673 100644 --- a/src/screens/Tabs/Me/Settings/Tooot.tsx +++ b/src/screens/Tabs/Me/Settings/Tooot.tsx @@ -77,7 +77,9 @@ const SettingsTooot: React.FC = () => { iconBack='ChevronRight' onPress={() => { const foundAccounts = data?.accounts.filter( - account => account.acct === 'tooot@xmflsct.com' + account => + account.acct === 'tooot@xmflsct.com' || + account.url === 'https://social.xmflsct.com/@tooot' ) if (foundAccounts?.length === 1) { navigation.navigate('Screen-Compose', { diff --git a/src/screens/Tabs/Shared/Account.tsx b/src/screens/Tabs/Shared/Account.tsx index 1b46a289..8484c3fb 100644 --- a/src/screens/Tabs/Shared/Account.tsx +++ b/src/screens/Tabs/Shared/Account.tsx @@ -41,6 +41,7 @@ const TabSharedAccount: React.FC = ({ analytics('bottomsheet_open_press', { page: 'account' }) + // @ts-ignore navigation.navigate('Screen-Actions', { type: 'account', account diff --git a/src/screens/Tabs/Shared/Account/Attachments.tsx b/src/screens/Tabs/Shared/Account/Attachments.tsx index 6bfbd24e..4b2c3855 100644 --- a/src/screens/Tabs/Shared/Account/Attachments.tsx +++ b/src/screens/Tabs/Shared/Account/Attachments.tsx @@ -39,7 +39,7 @@ const AccountAttachments = React.memo( page: 'Account_Attachments' as 'Account_Attachments', account: account?.id } - const { data, refetch } = useTimelineQuery({ + const { data, refetch } = useTimelineQuery({ ...queryKeyParams, options: { enabled: false } }) @@ -51,8 +51,8 @@ const AccountAttachments = React.memo( const flattenData = data?.pages ? data.pages - .flatMap(d => [...d]) - .filter(status => !status.sensitive) + .flatMap(d => [...d.body]) + .filter(status => !(status as Mastodon.Status).sensitive) .splice(0, DISPLAY_AMOUNT) : [] diff --git a/src/screens/Tabs/Shared/Relationships/List.tsx b/src/screens/Tabs/Shared/Relationships/List.tsx index 133a4e34..79bf0e22 100644 --- a/src/screens/Tabs/Shared/Relationships/List.tsx +++ b/src/screens/Tabs/Shared/Relationships/List.tsx @@ -26,17 +26,13 @@ const RelationshipsList: React.FC = ({ id, type }) => { type, id, options: { - getNextPageParam: lastPage => { - return lastPage.length - ? { - direction: 'next', - id: lastPage[lastPage.length - 1].id - } - : undefined - } + 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(d => [...d]) : [] + const flattenData = data?.pages ? data.pages.flatMap(d => [...d.body]) : [] const flRef = useRef>(null) diff --git a/src/startup/netInfo.ts b/src/startup/netInfo.ts index 23303628..050fe9c3 100644 --- a/src/startup/netInfo.ts +++ b/src/startup/netInfo.ts @@ -27,7 +27,7 @@ const netInfo = async (): Promise<{ .then(res => { log('log', 'netInfo', 'local credential check passed') if ( - res.id !== + res.body.id !== store.getState().instances.local?.instances[activeIndex].account.id ) { log('error', 'netInfo', 'local id does not match remote id') @@ -36,8 +36,8 @@ const netInfo = async (): Promise<{ } else { store.dispatch( updateLocalAccount({ - acct: res.acct, - avatarStatic: res.avatar_static + acct: res.body.acct, + avatarStatic: res.body.avatar_static }) ) return Promise.resolve({ connected: true }) diff --git a/src/utils/queryHooks/account.ts b/src/utils/queryHooks/account.ts index f13fd2bd..3020b4e0 100644 --- a/src/utils/queryHooks/account.ts +++ b/src/utils/queryHooks/account.ts @@ -11,7 +11,7 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKey }) => { method: 'get', instance: 'local', url: `accounts/${id}` - }) + }).then(res => res.body) } const useAccountQuery = ({ diff --git a/src/utils/queryHooks/accountCheck.ts b/src/utils/queryHooks/accountCheck.ts index 3af6e3be..272d32d1 100644 --- a/src/utils/queryHooks/accountCheck.ts +++ b/src/utils/queryHooks/accountCheck.ts @@ -19,7 +19,7 @@ const queryFunction = async ({ queryKey }: { queryKey: QueryKey }) => { instance: 'local', localIndex: index, url: `accounts/${id}` - }) + }).then(res => res.body) } const useAccountCheckQuery = ({ diff --git a/src/utils/queryHooks/announcement.ts b/src/utils/queryHooks/announcement.ts index a1fbea53..532736a5 100644 --- a/src/utils/queryHooks/announcement.ts +++ b/src/utils/queryHooks/announcement.ts @@ -21,7 +21,7 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKeyAnnouncement }) => { with_dismissed: 'true' } }) - }) + }).then(res => res.body) } const useAnnouncementQuery = ({ diff --git a/src/utils/queryHooks/apps.ts b/src/utils/queryHooks/apps.ts index 80c2e147..3e7d9c0a 100644 --- a/src/utils/queryHooks/apps.ts +++ b/src/utils/queryHooks/apps.ts @@ -25,7 +25,7 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKey }) => { instanceDomain, url: `apps`, body: formData - }) + }).then(res => res.body) } const useAppsQuery = ({ diff --git a/src/utils/queryHooks/emojis.ts b/src/utils/queryHooks/emojis.ts index d0e548c3..79c6bf29 100644 --- a/src/utils/queryHooks/emojis.ts +++ b/src/utils/queryHooks/emojis.ts @@ -9,7 +9,7 @@ const queryFunction = () => { method: 'get', instance: 'local', url: 'custom_emojis' - }) + }).then(res => res.body) } const useEmojisQuery = ({ diff --git a/src/utils/queryHooks/instance.ts b/src/utils/queryHooks/instance.ts index a66f8d22..88161ac3 100644 --- a/src/utils/queryHooks/instance.ts +++ b/src/utils/queryHooks/instance.ts @@ -12,7 +12,7 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKey }) => { instance: 'remote', instanceDomain, url: `instance` - }) + }).then(res => res.body) } const useInstanceQuery = < diff --git a/src/utils/queryHooks/lists.ts b/src/utils/queryHooks/lists.ts index 15439297..dacd76c4 100644 --- a/src/utils/queryHooks/lists.ts +++ b/src/utils/queryHooks/lists.ts @@ -9,7 +9,7 @@ const queryFunction = () => { method: 'get', instance: 'local', url: 'lists' - }) + }).then(res => res.body) } const useListsQuery = ({ diff --git a/src/utils/queryHooks/relationship.ts b/src/utils/queryHooks/relationship.ts index 90fa1d3d..3adac0b6 100644 --- a/src/utils/queryHooks/relationship.ts +++ b/src/utils/queryHooks/relationship.ts @@ -22,7 +22,7 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKeyRelationship }) => { params: { 'id[]': id } - }) + }).then(res => res.body) } const useRelationshipQuery = ({ @@ -61,7 +61,7 @@ const mutationFunction = async (params: MutationVarsRelationship) => { method: 'post', instance: 'local', url: `follow_requests/${params.id}/${params.payload.action}` - }) + }).then(res => res.body) case 'outgoing': return client({ method: 'post', @@ -69,7 +69,7 @@ const mutationFunction = async (params: MutationVarsRelationship) => { url: `accounts/${params.id}/${params.payload.state ? 'un' : ''}${ params.payload.action }` - }) + }).then(res => res.body) } } diff --git a/src/utils/queryHooks/relationships.ts b/src/utils/queryHooks/relationships.ts index f82965f1..f9b8cf77 100644 --- a/src/utils/queryHooks/relationships.ts +++ b/src/utils/queryHooks/relationships.ts @@ -12,18 +12,10 @@ const queryFunction = ({ pageParam }: { queryKey: QueryKey - pageParam?: { direction: 'next'; id: Mastodon.Status['id'] } + pageParam?: { [key: string]: string } }) => { const { type, id } = queryKey[1] - let params: { [key: string]: string } = {} - - if (pageParam) { - switch (pageParam.direction) { - case 'next': - params.max_id = pageParam.id - break - } - } + let params: { [key: string]: string } = { ...pageParam } return client({ method: 'get', @@ -37,7 +29,14 @@ const useRelationshipsQuery = ({ options, ...queryKeyParams }: QueryKey[1] & { - options?: UseInfiniteQueryOptions + options?: UseInfiniteQueryOptions< + { + body: Mastodon.Account[] + links?: { prev?: string; next?: string } + }, + AxiosError, + TData + > }) => { const queryKey: QueryKey = ['Relationships', { ...queryKeyParams }] return useInfiniteQuery(queryKey, queryFunction, options) diff --git a/src/utils/queryHooks/search.ts b/src/utils/queryHooks/search.ts index b5ab2eab..b0c485da 100644 --- a/src/utils/queryHooks/search.ts +++ b/src/utils/queryHooks/search.ts @@ -25,7 +25,7 @@ const queryFunction = ({ queryKey }: { queryKey: QueryKey }) => { instance: 'local', url: 'search', params: { ...(type && { type }), ...(term && { q: term }), limit } - }) + }).then(res => res.body) } const useSearchQuery = ({ diff --git a/src/utils/queryHooks/timeline.ts b/src/utils/queryHooks/timeline.ts index 5e2445ea..da1fd54b 100644 --- a/src/utils/queryHooks/timeline.ts +++ b/src/utils/queryHooks/timeline.ts @@ -28,29 +28,10 @@ const queryFunction = ({ pageParam }: { queryKey: QueryKeyTimeline - pageParam?: { direction: 'prev' | 'next'; id: Mastodon.Status['id'] } + pageParam?: { [key: string]: string } }) => { const { page, account, hashtag, list, toot } = queryKey[1] - let params: { [key: string]: string } = {} - - if (pageParam) { - switch (pageParam.direction) { - case 'prev': - if (page === 'Bookmarks' || page === 'Favourites') { - params.max_id = pageParam.id - } else { - params.min_id = pageParam.id - } - break - case 'next': - if (page === 'Bookmarks' || page === 'Favourites') { - params.min_id = pageParam.id - } else { - params.max_id = pageParam.id - } - break - } - } + let params: { [key: string]: string } = { ...pageParam } switch (page) { case 'Following': @@ -89,7 +70,7 @@ const queryFunction = ({ }) case 'Account_Default': - if (pageParam && pageParam.direction === 'next') { + if (pageParam && pageParam.pointer === 'max_id') { return client({ method: 'get', instance: 'local', @@ -108,10 +89,8 @@ const queryFunction = ({ pinned: 'true' } }).then(async res1 => { - let toots = res1.map(status => { - status.isPinned = true - return status - }) + let pinned: Mastodon.Status['id'][] = [] + res1.body.forEach(status => pinned.push(status.id)) const res2 = await client({ method: 'get', instance: 'local', @@ -120,7 +99,11 @@ const queryFunction = ({ exclude_replies: 'true' } }) - return uniqBy([...toots, ...res2], 'id') + return { + body: uniqBy([...res1.body, ...res2.body], 'id'), + ...(res2.links.next && { links: { max_id: res2.links.next } }), + pinned + } }) } @@ -197,7 +180,9 @@ const queryFunction = ({ instance: 'local', url: `statuses/${toot}/context` }) - return [...res2.ancestors, res1, ...res2.descendants] + return { + body: [...res2.body.ancestors, res1.body, ...res2.body.descendants] + } }) default: return Promise.reject() @@ -210,7 +195,18 @@ const useTimelineQuery = ({ options, ...queryKeyParams }: QueryKeyTimeline[1] & { - options?: UseInfiniteQueryOptions + options?: UseInfiniteQueryOptions< + { + body: + | Mastodon.Status[] + | Mastodon.Notification[] + | Mastodon.Conversation[] + links?: { prev?: string; next?: string } + pinned?: Mastodon.Status['id'][] + }, + AxiosError, + TData + > }) => { const queryKey: QueryKeyTimeline = ['Timeline', { ...queryKeyParams }] return useInfiniteQuery(queryKey, queryFunction, options) @@ -354,7 +350,7 @@ const mutationFunction = async (params: MutationVarsTimeline) => { } type MutationOptionsTimeline = MutationOptions< - Mastodon.Conversation | Mastodon.Notification | Mastodon.Status, + { body: Mastodon.Conversation | Mastodon.Notification | Mastodon.Status }, AxiosError, MutationVarsTimeline > @@ -373,7 +369,7 @@ const useTimelineMutation = ({ onSuccess?: MutationOptionsTimeline['onSuccess'] | boolean }) => { return useMutation< - Mastodon.Conversation | Mastodon.Notification | Mastodon.Status, + { body: Mastodon.Conversation | Mastodon.Notification | Mastodon.Status }, AxiosError, MutationVarsTimeline >(mutationFunction, { diff --git a/src/utils/queryHooks/timeline/deleteItem.ts b/src/utils/queryHooks/timeline/deleteItem.ts index ca8a9ebf..b333196a 100644 --- a/src/utils/queryHooks/timeline/deleteItem.ts +++ b/src/utils/queryHooks/timeline/deleteItem.ts @@ -1,5 +1,5 @@ import { InfiniteData, QueryClient } from 'react-query' -import { QueryKeyTimeline } from '../timeline' +import { QueryKeyTimeline, TimelineData } from '../timeline' const deleteItem = ({ queryClient, @@ -10,16 +10,15 @@ const deleteItem = ({ queryKey: QueryKeyTimeline id: Mastodon.Status['id'] }) => { - queryClient.setQueryData | undefined>( - queryKey, - old => { - if (old) { - old.pages = old.pages.map(page => page.filter(item => item.id !== id)) - } - + queryClient.setQueryData | undefined>(queryKey, old => { + if (old) { + old.pages = old.pages.map(page => { + page.body = page.body.filter((item: Mastodon.Status) => item.id !== id) + return page + }) return old } - ) + }) } export default deleteItem diff --git a/src/utils/queryHooks/timeline/updateStatusProperty.ts b/src/utils/queryHooks/timeline/updateStatusProperty.ts index 0b1e84d0..52602c69 100644 --- a/src/utils/queryHooks/timeline/updateStatusProperty.ts +++ b/src/utils/queryHooks/timeline/updateStatusProperty.ts @@ -32,9 +32,10 @@ const updateStatusProperty = ({ return page } else { if ( - typeof (page as Mastodon.Conversation[])[0].unread === 'boolean' + typeof (page.body as Mastodon.Conversation[])[0].unread === + 'boolean' ) { - const items = page as Mastodon.Conversation[] + const items = page.body as Mastodon.Conversation[] const tootIndex = findIndex(items, ['last_status.id', id]) if (tootIndex >= 0) { foundToot = true @@ -42,16 +43,16 @@ const updateStatusProperty = ({ } return page } else if ( - typeof (page as Mastodon.Notification[])[0].type === 'string' + typeof (page.body as Mastodon.Notification[])[0].type === 'string' ) { - const items = page as Mastodon.Notification[] + const items = page.body as Mastodon.Notification[] const tootIndex = findIndex(items, ['status.id', id]) if (tootIndex >= 0) { foundToot = true updateNotification({ item: items[tootIndex], payload }) } } else { - const items = page as Mastodon.Status[] + const items = page.body as Mastodon.Status[] const tootIndex = findIndex(items, [ reblog ? 'reblog.id' : 'id', id diff --git a/src/utils/slices/instancesSlice.ts b/src/utils/slices/instancesSlice.ts index 50c0f3e9..edd0e457 100644 --- a/src/utils/slices/instancesSlice.ts +++ b/src/utils/slices/instancesSlice.ts @@ -44,13 +44,13 @@ export type InstancesState = { export const updateLocalAccountPreferences = createAsyncThunk( 'instances/updateLocalAccountPreferences', async (): Promise => { - const preferences = await client({ + const res = await client({ method: 'get', instance: 'local', url: `preferences` }) - return Promise.resolve(preferences) + return Promise.resolve(res.body) } ) @@ -73,7 +73,9 @@ export const localAddInstance = createAsyncThunk( const instanceLocal: InstancesState['local'] = store.getState().instances .local - const { id, acct, avatar_static } = await client({ + const { + body: { id, acct, avatar_static } + } = await client({ method: 'get', instance: 'remote', instanceDomain: url, @@ -100,7 +102,7 @@ export const localAddInstance = createAsyncThunk( type = 'add' } - const preferences = await client({ + const { body: preferences } = await client({ method: 'get', instance: 'remote', instanceDomain: url, diff --git a/src/utils/styles/themes.ts b/src/utils/styles/themes.ts index 7d53f4ff..59c812a2 100644 --- a/src/utils/styles/themes.ts +++ b/src/utils/styles/themes.ts @@ -48,15 +48,15 @@ const themeColors: { background: { light: 'rgb(250, 250, 250)', - dark: 'rgb(25, 25, 25)' + dark: 'rgb(18, 18, 18)' }, backgroundGradientStart: { light: 'rgba(250, 250, 250, 0.5)', - dark: 'rgba(25, 25, 25, 0.5)' + dark: 'rgba(18, 18, 18, 0.5)' }, backgroundGradientEnd: { light: 'rgba(250, 250, 250, 1)', - dark: 'rgba(25, 25, 25, 1)' + dark: 'rgba(18, 18, 18, 1)' }, backgroundOverlay: { light: 'rgba(25, 25, 25, 0.5)', diff --git a/yarn.lock b/yarn.lock index 7c0ff3d5..8903c129 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6968,6 +6968,11 @@ levn@~0.3.0: prelude-ls "~1.1.2" type-check "~0.3.2" +li@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/li/-/li-1.3.0.tgz#22c59bcaefaa9a8ef359cf759784e4bf106aea1b" + integrity sha1-IsWbyu+qmo7zWc91l4TkvxBq6hs= + lie@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/lie/-/lie-3.1.1.tgz#9a436b2cc7746ca59de7a41fa469b3efb76bd87e"

!prcwo7sFb)6Lw`&cS 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 nU}k`wkROEbkt1IO#5gF diff --git a/android/app/src/main/res/values-night/colors.xml b/android/app/src/main/res/values-night/colors.xml index 55096642..9c941a17 100644 --- a/android/app/src/main/res/values-night/colors.xml +++ b/android/app/src/main/res/values-night/colors.xml @@ -1,5 +1,5 @@ - #191919 + #121212 diff --git a/app.config.ts b/app.config.ts index b99e6197..bf7bb859 100644 --- a/app.config.ts +++ b/app.config.ts @@ -30,10 +30,6 @@ export default (): ExpoConfig => ({ } ] }, - locales: { - en: './src/i18n/en/system.json', - zh: './src/i18n/zh-Hans/system.json' - }, android: { versionCode: 4, package: 'com.xmflsct.app.tooot', diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d2315a0a..58ec9d41 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -450,8 +450,6 @@ PODS: - RNSentry (2.1.1): - React-Core - Sentry (= 6.0.9) - - RNSharedElement (0.7.0): - - React - RNSVG (12.1.0): - React - SDWebImage (5.10.3): @@ -551,7 +549,6 @@ DEPENDENCIES: - RNReanimated (from `../node_modules/react-native-reanimated`) - RNScreens (from `../node_modules/react-native-screens`) - "RNSentry (from `../node_modules/@sentry/react-native`)" - - RNSharedElement (from `../node_modules/react-native-shared-element`) - RNSVG (from `../node_modules/react-native-svg`) - UMAppLoader (from `../node_modules/unimodules-app-loader/ios`) - UMBarCodeScannerInterface (from `../node_modules/unimodules-barcode-scanner-interface/ios`) @@ -721,8 +718,6 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native-screens" RNSentry: :path: "../node_modules/@sentry/react-native" - RNSharedElement: - :path: "../node_modules/react-native-shared-element" RNSVG: :path: "../node_modules/react-native-svg" UMAppLoader: @@ -835,7 +830,6 @@ SPEC CHECKSUMS: RNReanimated: e8a1520b15df106c96214161078c69e4a23b8b29 RNScreens: b6c9607e6fe47c1b6e2f1910d2acd46dd7ecea3a RNSentry: 6b46b6fc1d715a378fbaa5d7d43bc9ce99b500e5 - RNSharedElement: 00b1a1420d213a34459bb9a5aacabb38107d7948 RNSVG: ce9d996113475209013317e48b05c21ee988d42e SDWebImage: e378178472b735e84b007bfb55514c97948a0598 SDWebImageWebPCoder: d0dac55073088d24b2ac1b191a71a8f8d0adac21 diff --git a/ios/tooot/Images.xcassets/SplashScreen.imageset/dark_splashscreen.png b/ios/tooot/Images.xcassets/SplashScreen.imageset/dark_splashscreen.png index 83ca55a4a3b5ace827d4f8b005b7837229c7cf8f..8ba9b37af4e8a1babe54e62d38eb84cb97b32933 100644 GIT binary patch literal 70177 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 literal 70155 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