mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Updates
This commit is contained in:
		| @@ -14,6 +14,7 @@ | ||||
|     "@react-native-community/masked-view": "0.1.10", | ||||
|     "@react-native-community/netinfo": "^5.9.7", | ||||
|     "@react-native-community/segmented-control": "2.2.1", | ||||
|     "@react-native-community/viewpager": "4.2.0", | ||||
|     "@react-navigation/bottom-tabs": "^5.11.2", | ||||
|     "@react-navigation/native": "^5.8.10", | ||||
|     "@reduxjs/toolkit": "^1.5.0", | ||||
| @@ -61,6 +62,7 @@ | ||||
|     "react-native-shimmer-placeholder": "^2.0.6", | ||||
|     "react-native-svg": "12.1.0", | ||||
|     "react-native-tab-view": "^2.15.2", | ||||
|     "react-native-tab-view-viewpager-adapter": "^1.1.0", | ||||
|     "react-native-toast-message": "^1.4.2", | ||||
|     "react-navigation": "^4.4.3", | ||||
|     "react-query": "^3.5.6", | ||||
|   | ||||
							
								
								
									
										12
									
								
								src/@types/react-navigation.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										12
									
								
								src/@types/react-navigation.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -14,8 +14,18 @@ declare namespace Nav { | ||||
|     'Screen-Shared-Announcements': { showAll?: boolean } | ||||
|     'Screen-Shared-Compose': | ||||
|       | { | ||||
|           type?: 'reply' | 'conversation' | 'edit' | ||||
|           type: 'reply' | 'conversation' | 'edit' | ||||
|           incomingStatus: Mastodon.Status | ||||
|           queryKey?: [ | ||||
|             'Timeline', | ||||
|             { | ||||
|               page: App.Pages | ||||
|               hashtag?: Mastodon.Tag['name'] | ||||
|               list?: Mastodon.List['id'] | ||||
|               toot?: Mastodon.Status['id'] | ||||
|               account?: Mastodon.Account['id'] | ||||
|             } | ||||
|           ] | ||||
|         } | ||||
|       | undefined | ||||
|     'Screen-Shared-Hashtag': { | ||||
|   | ||||
| @@ -1,10 +1,14 @@ | ||||
| import React from 'react' | ||||
| import React, { useRef } from 'react' | ||||
| import { Dimensions, Modal, StyleSheet, View } from 'react-native' | ||||
| import { useSafeAreaInsets } from 'react-native-safe-area-context' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import Button from '@components/Button' | ||||
| import { PanGestureHandler } from 'react-native-gesture-handler' | ||||
| import { | ||||
|   PanGestureHandler, | ||||
|   State, | ||||
|   TapGestureHandler | ||||
| } from 'react-native-gesture-handler' | ||||
| import Animated, { | ||||
|   Extrapolate, | ||||
|   interpolate, | ||||
| @@ -55,10 +59,17 @@ const BottomSheet: React.FC<Props> = ({ children, visible, handleDismiss }) => { | ||||
|  | ||||
|   return ( | ||||
|     <Modal animated animationType='fade' visible={visible} transparent> | ||||
|       <PanGestureHandler onGestureEvent={onGestureEvent}> | ||||
|       <TapGestureHandler | ||||
|         onHandlerStateChange={({ nativeEvent }) => { | ||||
|           if (nativeEvent.state === State.ACTIVE) { | ||||
|             callDismiss() | ||||
|           } | ||||
|         }} | ||||
|       > | ||||
|         <Animated.View | ||||
|           style={[styles.overlay, { backgroundColor: theme.backgroundOverlay }]} | ||||
|         > | ||||
|           <PanGestureHandler onGestureEvent={onGestureEvent}> | ||||
|             <Animated.View | ||||
|               style={[ | ||||
|                 styles.container, | ||||
| @@ -70,7 +81,10 @@ const BottomSheet: React.FC<Props> = ({ children, visible, handleDismiss }) => { | ||||
|               ]} | ||||
|             > | ||||
|               <View | ||||
|               style={[styles.handle, { backgroundColor: theme.primaryOverlay }]} | ||||
|                 style={[ | ||||
|                   styles.handle, | ||||
|                   { backgroundColor: theme.primaryOverlay } | ||||
|                 ]} | ||||
|               /> | ||||
|               {children} | ||||
|               <Button | ||||
| @@ -80,8 +94,9 @@ const BottomSheet: React.FC<Props> = ({ children, visible, handleDismiss }) => { | ||||
|                 style={styles.button} | ||||
|               /> | ||||
|             </Animated.View> | ||||
|         </Animated.View> | ||||
|           </PanGestureHandler> | ||||
|         </Animated.View> | ||||
|       </TapGestureHandler> | ||||
|     </Modal> | ||||
|   ) | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import Icon from '@components/Icon' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import layoutAnimation from '@utils/styles/layoutAnimation' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import React, { useMemo } from 'react' | ||||
| import React, { useEffect, useMemo, useRef } from 'react' | ||||
| import { Pressable, StyleSheet, Text, View } from 'react-native' | ||||
| import { Chase } from 'react-native-animated-spinkit' | ||||
|  | ||||
| @@ -24,6 +25,15 @@ const HeaderRight: React.FC<Props> = ({ | ||||
| }) => { | ||||
|   const { theme } = useTheme() | ||||
|  | ||||
|   const mounted = useRef(false) | ||||
|   useEffect(() => { | ||||
|     if (mounted.current) { | ||||
|       layoutAnimation() | ||||
|     } else { | ||||
|       mounted.current = true | ||||
|     } | ||||
|   }, [content, loading, disabled]) | ||||
|  | ||||
|   const loadingSpinkit = useMemo( | ||||
|     () => ( | ||||
|       <View style={{ position: 'absolute' }}> | ||||
|   | ||||
| @@ -3,8 +3,9 @@ import { StyleConstants } from '@utils/styles/constants' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import { ColorDefinitions } from '@utils/styles/themes' | ||||
| import React, { useMemo } from 'react' | ||||
| import { Pressable, StyleSheet, Switch, Text, View } from 'react-native' | ||||
| import { StyleSheet, Switch, Text, View } from 'react-native' | ||||
| import { Chase } from 'react-native-animated-spinkit' | ||||
| import { State, TapGestureHandler } from 'react-native-gesture-handler' | ||||
|  | ||||
| export interface Props { | ||||
|   iconFront?: any | ||||
| @@ -54,11 +55,15 @@ const MenuRow: React.FC<Props> = ({ | ||||
|   ) | ||||
|  | ||||
|   return ( | ||||
|     <Pressable | ||||
|       style={styles.base} | ||||
|       onPress={onPress} | ||||
|       disabled={loading} | ||||
|       testID='base' | ||||
|     <View style={styles.base}> | ||||
|       <TapGestureHandler | ||||
|         onHandlerStateChange={({ nativeEvent }) => { | ||||
|           if (nativeEvent.state === State.ACTIVE) { | ||||
|             if (!loading) { | ||||
|               onPress && onPress() | ||||
|             } | ||||
|           } | ||||
|         }} | ||||
|       > | ||||
|         <View style={styles.core}> | ||||
|           <View style={styles.front}> | ||||
| @@ -128,7 +133,8 @@ const MenuRow: React.FC<Props> = ({ | ||||
|             </View> | ||||
|           ) : null} | ||||
|         </View> | ||||
|     </Pressable> | ||||
|       </TapGestureHandler> | ||||
|     </View> | ||||
|   ) | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -9,6 +9,7 @@ import React, { useCallback, useMemo, useState } from 'react' | ||||
| import { Dimensions, Platform, StyleSheet, View } from 'react-native' | ||||
| import { createNativeStackNavigator } from 'react-native-screens/native-stack' | ||||
| import { TabView } from 'react-native-tab-view' | ||||
| import ViewPagerAdapter from 'react-native-tab-view-viewpager-adapter' | ||||
| import { useSelector } from 'react-redux' | ||||
|  | ||||
| const Stack = createNativeStackNavigator< | ||||
| @@ -53,21 +54,6 @@ const Timelines: React.FC<Props> = ({ name, content }) => { | ||||
|     [localActiveIndex] | ||||
|   ) | ||||
|  | ||||
|   const screenComponent = useCallback( | ||||
|     () => ( | ||||
|       <TabView | ||||
|         lazy | ||||
|         swipeEnabled | ||||
|         renderScene={renderScene} | ||||
|         renderTabBar={() => null} | ||||
|         onIndexChange={index => setSegment(index)} | ||||
|         navigationState={{ index: segment, routes }} | ||||
|         initialLayout={{ width: Dimensions.get('window').width }} | ||||
|       /> | ||||
|     ), | ||||
|     [segment, localActiveIndex] | ||||
|   ) | ||||
|  | ||||
|   const screenOptions = useMemo(() => { | ||||
|     if (localActiveIndex === null) { | ||||
|       if (name === 'Public') { | ||||
| @@ -102,6 +88,8 @@ const Timelines: React.FC<Props> = ({ name, content }) => { | ||||
|     } | ||||
|   }, [localActiveIndex, mode, segment]) | ||||
|  | ||||
|   const renderPager = useCallback(props => <ViewPagerAdapter {...props} />, []) | ||||
|  | ||||
|   return ( | ||||
|     <Stack.Navigator | ||||
|       screenOptions={{ headerHideShadow: true, headerTopInsetEnabled: false }} | ||||
| @@ -109,9 +97,21 @@ const Timelines: React.FC<Props> = ({ name, content }) => { | ||||
|       <Stack.Screen | ||||
|         // @ts-ignore | ||||
|         name={`Screen-${name}-Root`} | ||||
|         component={screenComponent} | ||||
|         options={screenOptions} | ||||
|       > | ||||
|         {() => ( | ||||
|           <TabView | ||||
|             lazy | ||||
|             swipeEnabled | ||||
|             renderPager={renderPager} | ||||
|             renderScene={renderScene} | ||||
|             renderTabBar={() => null} | ||||
|             onIndexChange={index => setSegment(index)} | ||||
|             navigationState={{ index: segment, routes }} | ||||
|             initialLayout={{ width: Dimensions.get('window').width }} | ||||
|           /> | ||||
|         )} | ||||
|       </Stack.Screen> | ||||
|  | ||||
|       {sharedScreens(Stack)} | ||||
|     </Stack.Navigator> | ||||
|   | ||||
| @@ -14,9 +14,7 @@ import { FlatList } from 'react-native-gesture-handler' | ||||
| import { useDispatch } from 'react-redux' | ||||
| import { QueryKeyTimeline, useTimelineQuery } from '@utils/queryHooks/timeline' | ||||
| import { findIndex } from 'lodash' | ||||
| import CustomRefreshControl from '@components/CustomRefreshControl' | ||||
| import { InfiniteData, useQueryClient } from 'react-query' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
|  | ||||
| export interface Props { | ||||
|   page: App.Pages | ||||
| @@ -37,8 +35,6 @@ const Timeline: React.FC<Props> = ({ | ||||
|   disableRefresh = false, | ||||
|   disableInfinity = false | ||||
| }) => { | ||||
|   const { theme } = useTheme() | ||||
|  | ||||
|   const queryKeyParams = { | ||||
|     page, | ||||
|     ...(hashtag && { hashtag }), | ||||
| @@ -212,6 +208,7 @@ const Timeline: React.FC<Props> = ({ | ||||
|  | ||||
|   return ( | ||||
|     <FlatList | ||||
|       bounces={!disableRefresh} | ||||
|       ref={flRef} | ||||
|       windowSize={11} | ||||
|       data={flattenData} | ||||
|   | ||||
| @@ -103,7 +103,8 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => { | ||||
|     () => | ||||
|       navigation.navigate('Screen-Shared-Compose', { | ||||
|         type: 'reply', | ||||
|         incomingStatus: status | ||||
|         incomingStatus: status, | ||||
|         queryKey | ||||
|       }), | ||||
|     [] | ||||
|   ) | ||||
|   | ||||
| @@ -10,6 +10,32 @@ export interface Props { | ||||
|   card: Mastodon.Card | ||||
| } | ||||
|  | ||||
| type CancelPromise = ((reason?: Error) => void) | undefined | ||||
| type ImageSize = { width: number; height: number } | ||||
| interface ImageSizeOperation { | ||||
|   start: () => Promise<ImageSize> | ||||
|   cancel: CancelPromise | ||||
| } | ||||
| const getImageSize = (uri: string): ImageSizeOperation => { | ||||
|   let cancel: CancelPromise | ||||
|   const start = (): Promise<ImageSize> => | ||||
|     new Promise<{ width: number; height: number }>((resolve, reject) => { | ||||
|       cancel = reject | ||||
|       Image.getSize( | ||||
|         uri, | ||||
|         (width, height) => { | ||||
|           cancel = undefined | ||||
|           resolve({ width, height }) | ||||
|         }, | ||||
|         error => { | ||||
|           reject(error) | ||||
|         } | ||||
|       ) | ||||
|     }) | ||||
|  | ||||
|   return { start, cancel } | ||||
| } | ||||
|  | ||||
| const TimelineCard: React.FC<Props> = ({ card }) => { | ||||
|   const { theme } = useTheme() | ||||
|  | ||||
| @@ -19,6 +45,26 @@ const TimelineCard: React.FC<Props> = ({ card }) => { | ||||
|       Image.getSize(card.image, () => setImageLoaded(true)) | ||||
|     } | ||||
|   }, []) | ||||
|   useEffect(() => { | ||||
|     let cancel: CancelPromise | ||||
|     const sideEffect = async (): Promise<void> => { | ||||
|       try { | ||||
|         const operation = getImageSize(card.image) | ||||
|         cancel = operation.cancel | ||||
|         await operation.start() | ||||
|       } catch (error) { | ||||
|         if (__DEV__) console.warn(error) | ||||
|       } | ||||
|     } | ||||
|     if (card.image) { | ||||
|       sideEffect() | ||||
|     } | ||||
|     return () => { | ||||
|       if (cancel) { | ||||
|         cancel() | ||||
|       } | ||||
|     } | ||||
|   }) | ||||
|   const cardVisual = useMemo(() => { | ||||
|     if (imageLoaded) { | ||||
|       return <Image source={{ uri: card.image }} style={styles.image} /> | ||||
|   | ||||
| @@ -96,7 +96,8 @@ const HeaderActionsStatus: React.FC<Props> = ({ | ||||
|                   if (res.id) { | ||||
|                     navigation.navigate('Screen-Shared-Compose', { | ||||
|                       type: 'edit', | ||||
|                       incomingStatus: res | ||||
|                       incomingStatus: res, | ||||
|                       queryKey | ||||
|                     }) | ||||
|                   } | ||||
|                 } | ||||
|   | ||||
| @@ -23,7 +23,6 @@ const ScreenMeRoot: React.FC<StackScreenProps< | ||||
| >> = ({ route: { params }, navigation }) => { | ||||
|   useEffect(() => { | ||||
|     if (params && params.navigateAway) { | ||||
|       console.log('oops') | ||||
|       navigation.navigate(params.navigateAway) | ||||
|     } | ||||
|   }, [params]) | ||||
|   | ||||
| @@ -43,8 +43,8 @@ const AccountHeader: React.FC<Props> = ({ account, limitHeight = false }) => { | ||||
|   }, [account]) | ||||
|  | ||||
|   return ( | ||||
|     <Animated.Image | ||||
|       source={{ uri: account?.header }} | ||||
|     <Animated.View | ||||
|       // source={{ uri: account?.header }} | ||||
|       style={[styleHeight, { backgroundColor: theme.disabled }]} | ||||
|     /> | ||||
|   ) | ||||
|   | ||||
| @@ -1,10 +1,11 @@ | ||||
| import Timeline from '@components/Timelines/Timeline' | ||||
| import { useBottomTabBarHeight } from '@react-navigation/bottom-tabs' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
| import React, { useContext } from 'react' | ||||
| import React, { useCallback, useContext } from 'react' | ||||
| import { Dimensions, StyleSheet } from 'react-native' | ||||
| import { useSafeAreaInsets } from 'react-native-safe-area-context' | ||||
| import { TabView } from 'react-native-tab-view' | ||||
| import ViewPagerAdapter from 'react-native-tab-view-viewpager-adapter' | ||||
| import AccountContext from './utils/createContext' | ||||
|  | ||||
| export interface Props { | ||||
| @@ -32,10 +33,13 @@ const AccountToots: React.FC<Props> = ({ id }) => { | ||||
|     return <Timeline page={route.key} account={id} disableRefresh /> | ||||
|   } | ||||
|  | ||||
|   const renderPager = useCallback(props => <ViewPagerAdapter {...props} />, []) | ||||
|  | ||||
|   return ( | ||||
|     <TabView | ||||
|       lazy | ||||
|       swipeEnabled | ||||
|       renderPager={renderPager} | ||||
|       renderScene={renderScene} | ||||
|       renderTabBar={() => null} | ||||
|       initialLayout={{ width: Dimensions.get('window').width }} | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| import { HeaderLeft, HeaderRight } from '@components/Header' | ||||
| import haptics from '@root/components/haptics' | ||||
| import { store } from '@root/store' | ||||
| import layoutAnimation from '@root/utils/styles/layoutAnimation' | ||||
| import formatText from '@screens/Shared/Compose/formatText' | ||||
| import ComposeRoot from '@screens/Shared/Compose/Root' | ||||
| import { QueryKeyTimeline } from '@utils/queryHooks/timeline' | ||||
| @@ -58,11 +57,8 @@ const Compose: React.FC<SharedComposeProp> = ({ | ||||
|   const localAccount = getLocalAccount(store.getState()) | ||||
|   const [composeState, composeDispatch] = useReducer( | ||||
|     composeReducer, | ||||
|     params?.type && params?.incomingStatus | ||||
|       ? composeParseState({ | ||||
|           type: params.type, | ||||
|           incomingStatus: params.incomingStatus | ||||
|         }) | ||||
|     params | ||||
|       ? composeParseState(params) | ||||
|       : { | ||||
|           ...composeInitialState, | ||||
|           visibility: | ||||
| @@ -72,7 +68,6 @@ const Compose: React.FC<SharedComposeProp> = ({ | ||||
|               : 'public' | ||||
|         } | ||||
|   ) | ||||
|   const [isSubmitting, setIsSubmitting] = useState(false) | ||||
|  | ||||
|   useEffect(() => { | ||||
|     switch (params?.type) { | ||||
| @@ -163,8 +158,8 @@ const Compose: React.FC<SharedComposeProp> = ({ | ||||
|         type='text' | ||||
|         content={params?.type ? postButtonText[params.type] : '发嘟嘟'} | ||||
|         onPress={() => { | ||||
|           layoutAnimation() | ||||
|           setIsSubmitting(true) | ||||
|           composeDispatch({ type: 'posting', payload: true }) | ||||
|  | ||||
|           composePost(params, composeState) | ||||
|             .then(() => { | ||||
|               haptics('Success') | ||||
| @@ -173,27 +168,15 @@ const Compose: React.FC<SharedComposeProp> = ({ | ||||
|                 { page: 'Following' } | ||||
|               ] | ||||
|               queryClient.invalidateQueries(queryKey) | ||||
|               if ( | ||||
|                 params?.type && | ||||
|                 (params.type === 'reply' || params.type === 'conversation') | ||||
|               ) { | ||||
|                 queryClient.invalidateQueries( | ||||
|                   [ | ||||
|                     'Toot', | ||||
|                     { | ||||
|                       toot: params.incomingStatus.reblog | ||||
|                         ? params.incomingStatus.reblog.id | ||||
|                         : params.incomingStatus.id | ||||
|                     } | ||||
|                   ], | ||||
|                   { exact: true, active: true } | ||||
|                 ) | ||||
|  | ||||
|               if (params?.queryKey && params.queryKey[1].page === 'Toot') { | ||||
|                 queryClient.invalidateQueries(params.queryKey) | ||||
|               } | ||||
|               navigation.goBack() | ||||
|             }) | ||||
|             .catch(() => { | ||||
|               haptics('Error') | ||||
|               setIsSubmitting(false) | ||||
|               composeDispatch({ type: 'posting', payload: false }) | ||||
|               Alert.alert('发布失败', '', [ | ||||
|                 { | ||||
|                   text: '返回重试' | ||||
| @@ -201,11 +184,11 @@ const Compose: React.FC<SharedComposeProp> = ({ | ||||
|               ]) | ||||
|             }) | ||||
|         }} | ||||
|         loading={isSubmitting} | ||||
|         loading={composeState.posting} | ||||
|         disabled={composeState.text.raw.length < 1 || totalTextCount > 500} | ||||
|       /> | ||||
|     ), | ||||
|     [isSubmitting, totalTextCount, composeState] | ||||
|     [totalTextCount, composeState] | ||||
|   ) | ||||
|  | ||||
|   return ( | ||||
|   | ||||
							
								
								
									
										43
									
								
								src/screens/Shared/Compose/Posting.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/screens/Shared/Compose/Posting.tsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| import React, { useContext } from 'react' | ||||
| import { Modal, StyleSheet, View } from 'react-native' | ||||
| import { useTheme } from '@utils/styles/ThemeManager' | ||||
| import ComposeContext from './utils/createContext' | ||||
| import { Chase } from 'react-native-animated-spinkit' | ||||
| import { StyleConstants } from '@utils/styles/constants' | ||||
|  | ||||
| const ComposePosting = React.memo( | ||||
|   () => { | ||||
|     const { composeState } = useContext(ComposeContext) | ||||
|     const { theme } = useTheme() | ||||
|  | ||||
|     return ( | ||||
|       <Modal | ||||
|         transparent | ||||
|         animationType='fade' | ||||
|         visible={composeState.posting} | ||||
|         children={ | ||||
|           <View | ||||
|             style={[styles.base, { backgroundColor: theme.backgroundOverlay }]} | ||||
|             children={ | ||||
|               <Chase | ||||
|                 size={StyleConstants.Font.Size.L * 2} | ||||
|                 color={theme.primaryOverlay} | ||||
|               /> | ||||
|             } | ||||
|           /> | ||||
|         } | ||||
|       /> | ||||
|     ) | ||||
|   }, | ||||
|   () => true | ||||
| ) | ||||
|  | ||||
| const styles = StyleSheet.create({ | ||||
|   base: { | ||||
|     flex: 1, | ||||
|     justifyContent: 'center', | ||||
|     alignItems: 'center' | ||||
|   } | ||||
| }) | ||||
|  | ||||
| export default ComposePosting | ||||
| @@ -7,6 +7,7 @@ import React, { useCallback, useContext, useEffect, useMemo } from 'react' | ||||
| import { View, FlatList, StyleSheet } from 'react-native' | ||||
| import { Chase } from 'react-native-animated-spinkit' | ||||
| import ComposeActions from './Actions' | ||||
| import ComposePosting from './Posting' | ||||
| import ComposeRootFooter from './Root/Footer' | ||||
| import ComposeRootHeader from './Root/Header' | ||||
| import ComposeRootSuggestion from './Root/Suggestion' | ||||
| @@ -89,6 +90,7 @@ const ComposeRoot: React.FC = () => { | ||||
|         keyExtractor={({ item }) => item.acct || item.name} | ||||
|       /> | ||||
|       <ComposeActions /> | ||||
|       <ComposePosting /> | ||||
|     </View> | ||||
|   ) | ||||
| } | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| import { createRef } from "react" | ||||
| import { ComposeState } from "./types" | ||||
| import { createRef } from 'react' | ||||
| import { ComposeState } from './types' | ||||
|  | ||||
| const composeInitialState: ComposeState = { | ||||
|   posting: false, | ||||
|   spoiler: { | ||||
|     active: false, | ||||
|     count: 0, | ||||
|   | ||||
| @@ -1,10 +1,10 @@ | ||||
| import client from '@root/api/client' | ||||
| import { Props } from '@screens/Shared/Compose' | ||||
| import { ComposeState } from '@screens/Shared/Compose/utils/types' | ||||
| import { SharedComposeProp } from '@screens/Shared/sharedScreens' | ||||
| import * as Crypto from 'expo-crypto' | ||||
|  | ||||
| const composePost = async ( | ||||
|   params: Props['route']['params'], | ||||
|   params: SharedComposeProp['route']['params'], | ||||
|   composeState: ComposeState | ||||
| ) => { | ||||
|   const formData = new FormData() | ||||
| @@ -43,7 +43,7 @@ const composePost = async ( | ||||
|   return client<Mastodon.Status>({ | ||||
|     method: 'post', | ||||
|     instance: 'local', | ||||
|     url: 'statuses', | ||||
|     url: 'statusess', | ||||
|     headers: { | ||||
|       'Idempotency-Key': await Crypto.digestStringAsync( | ||||
|         Crypto.CryptoDigestAlgorithm.SHA256, | ||||
|   | ||||
| @@ -5,6 +5,8 @@ const composeReducer = ( | ||||
|   action: ComposeAction | ||||
| ): ComposeState => { | ||||
|   switch (action.type) { | ||||
|     case 'posting': | ||||
|       return { ...state, posting: action.payload } | ||||
|     case 'spoiler': | ||||
|       return { ...state, spoiler: { ...state.spoiler, ...action.payload } } | ||||
|     case 'text': | ||||
|   | ||||
							
								
								
									
										5
									
								
								src/screens/Shared/Compose/utils/types.d.ts
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										5
									
								
								src/screens/Shared/Compose/utils/types.d.ts
									
									
									
									
										vendored
									
									
								
							| @@ -5,6 +5,7 @@ export type ExtendedAttachment = { | ||||
| } | ||||
|  | ||||
| export type ComposeState = { | ||||
|   posting: boolean | ||||
|   spoiler: { | ||||
|     active: boolean | ||||
|     count: number | ||||
| @@ -62,6 +63,10 @@ export type ComposeState = { | ||||
| } | ||||
|  | ||||
| export type ComposeAction = | ||||
|   | { | ||||
|       type: 'posting' | ||||
|       payload: ComposeState['posting'] | ||||
|     } | ||||
|   | { | ||||
|       type: 'spoiler' | ||||
|       payload: Partial<ComposeState['spoiler']> | ||||
|   | ||||
| @@ -33,7 +33,7 @@ const ScreenSharedRelationships: React.FC<SharedRelationshipsProp> = ({ | ||||
|         ) | ||||
|       }) | ||||
|     return updateHeaderRight() | ||||
|   }, []) | ||||
|   }, [segment, mode]) | ||||
|  | ||||
|   const routes: { | ||||
|     key: SharedRelationshipsProp['route']['params']['initialType'] | ||||
| @@ -55,9 +55,9 @@ const ScreenSharedRelationships: React.FC<SharedRelationshipsProp> = ({ | ||||
|       swipeEnabled | ||||
|       renderScene={renderScene} | ||||
|       renderTabBar={() => null} | ||||
|       initialLayout={{ width: Dimensions.get('window').width }} | ||||
|       navigationState={{ index: segment, routes }} | ||||
|       onIndexChange={index => setSegment(index)} | ||||
|       navigationState={{ index: segment, routes }} | ||||
|       initialLayout={{ width: Dimensions.get('window').width }} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|   | ||||
							
								
								
									
										10
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -1727,6 +1727,11 @@ | ||||
|   resolved "https://registry.yarnpkg.com/@react-native-community/segmented-control/-/segmented-control-2.2.1.tgz#5ca418d78c5f6051353c9586918458713b88a83c" | ||||
|   integrity sha512-BzxFbI9Iqv+31yVqEvCTzJYmwb8jOMTf/UPuC4Hj176tmEPqBpuDaGH+rkAFg1miOco3/43RQxiAZO+mkY40Fg== | ||||
|  | ||||
| "@react-native-community/viewpager@4.2.0": | ||||
|   version "4.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/@react-native-community/viewpager/-/viewpager-4.2.0.tgz#11a4453715eb45cb0f732c98666ce168b800dfa4" | ||||
|   integrity sha512-tptvkyStulE9Jv/LVYSldvydAq3DVOwsfqmy3mTh3NWl1LZwE4gZwZ455jiRmW5StsJ3Q/Od/GGsN0FI8gHAXQ== | ||||
|  | ||||
| "@react-navigation/bottom-tabs@^5.11.2": | ||||
|   version "5.11.2" | ||||
|   resolved "https://registry.yarnpkg.com/@react-navigation/bottom-tabs/-/bottom-tabs-5.11.2.tgz#5b541612fcecdea2a5024a4028da35e4a727bde6" | ||||
| @@ -8280,6 +8285,11 @@ react-native-svg@12.1.0: | ||||
|     css-select "^2.1.0" | ||||
|     css-tree "^1.0.0-alpha.39" | ||||
|  | ||||
| react-native-tab-view-viewpager-adapter@^1.1.0: | ||||
|   version "1.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/react-native-tab-view-viewpager-adapter/-/react-native-tab-view-viewpager-adapter-1.1.0.tgz#d6e085ed1c91a13e714d87395d428f8afc2b3377" | ||||
|   integrity sha512-KLKw+Ay41xAl5F2eRscJd7DHN8JLx06E2lTQJrYAxtBcNKDKfrcYC3wmq7t72DAOBe/6niF0h44c/t/D/AoXsA== | ||||
|  | ||||
| react-native-tab-view@^2.15.2: | ||||
|   version "2.15.2" | ||||
|   resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.15.2.tgz#4bc7832d33a119306614efee667509672a7ee64e" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user