mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	Restructure some files
This commit is contained in:
		
							
								
								
									
										5
									
								
								App.tsx
									
									
									
									
									
								
							
							
						
						
									
										5
									
								
								App.tsx
									
									
									
									
									
								
							| @@ -1,3 +1,4 @@ | |||||||
|  | import 'react-native-gesture-handler' | ||||||
| import NetInfo from '@react-native-community/netinfo' | import NetInfo from '@react-native-community/netinfo' | ||||||
| import client from '@root/api/client' | import client from '@root/api/client' | ||||||
| import Index from '@root/Index' | import Index from '@root/Index' | ||||||
| @@ -5,9 +6,9 @@ import { persistor, store } from '@root/store' | |||||||
| import { resetLocal } from '@root/utils/slices/instancesSlice' | import { resetLocal } from '@root/utils/slices/instancesSlice' | ||||||
| import ThemeManager from '@utils/styles/ThemeManager' | import ThemeManager from '@utils/styles/ThemeManager' | ||||||
| import chalk from 'chalk' | import chalk from 'chalk' | ||||||
|  | import * as Analytics from 'expo-firebase-analytics' | ||||||
| import * as SplashScreen from 'expo-splash-screen' | import * as SplashScreen from 'expo-splash-screen' | ||||||
| import React, { useCallback, useEffect, useState } from 'react' | import React, { useCallback, useEffect, useState } from 'react' | ||||||
| import { Platform, Text } from 'react-native' |  | ||||||
| import { enableScreens } from 'react-native-screens' | import { enableScreens } from 'react-native-screens' | ||||||
| import { onlineManager, QueryClient, QueryClientProvider } from 'react-query' | import { onlineManager, QueryClient, QueryClientProvider } from 'react-query' | ||||||
| import { Provider } from 'react-redux' | import { Provider } from 'react-redux' | ||||||
| @@ -30,6 +31,8 @@ const startingLog = (type: 'log' | 'warn' | 'error', message: string) => { | |||||||
| } | } | ||||||
|  |  | ||||||
| if (__DEV__) { | if (__DEV__) { | ||||||
|  |   Analytics.setDebugModeEnabled(true) | ||||||
|  |  | ||||||
|   startingLog('log', 'initializing wdyr') |   startingLog('log', 'initializing wdyr') | ||||||
|   const whyDidYouRender = require('@welldone-software/why-did-you-render') |   const whyDidYouRender = require('@welldone-software/why-did-you-render') | ||||||
|   whyDidYouRender(React, { |   whyDidYouRender(React, { | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ export default (): ExpoConfig => ({ | |||||||
|   description: 'This is a description', |   description: 'This is a description', | ||||||
|   slug: 'mastodon-app', |   slug: 'mastodon-app', | ||||||
|   privacy: 'hidden', |   privacy: 'hidden', | ||||||
|   version: '1.0.0', |   version: '0.1.0', | ||||||
|   platforms: ['ios'], |   platforms: ['ios'], | ||||||
|   orientation: 'portrait', |   orientation: 'portrait', | ||||||
|   userInterfaceStyle: 'automatic', |   userInterfaceStyle: 'automatic', | ||||||
| @@ -33,6 +33,18 @@ export default (): ExpoConfig => ({ | |||||||
|   //   } |   //   } | ||||||
|   // }, |   // }, | ||||||
|   assetBundlePatterns: ['assets/*'], |   assetBundlePatterns: ['assets/*'], | ||||||
|  |   hooks: { | ||||||
|  |     postPublish: [ | ||||||
|  |       { | ||||||
|  |         file: 'sentry-expo/upload-sourcemaps' | ||||||
|  |         // config: { | ||||||
|  |         //   organization: "your sentry organization's short name here", | ||||||
|  |         //   project: "your sentry project's name here", | ||||||
|  |         //   authToken: 'your auth token here' | ||||||
|  |         // } | ||||||
|  |       } | ||||||
|  |     ] | ||||||
|  |   }, | ||||||
|   web: { |   web: { | ||||||
|     config: { |     config: { | ||||||
|       firebase: { |       firebase: { | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								package.json
									
									
									
									
									
								
							| @@ -17,7 +17,7 @@ | |||||||
|     "@react-navigation/bottom-tabs": "^5.11.2", |     "@react-navigation/bottom-tabs": "^5.11.2", | ||||||
|     "@react-navigation/native": "^5.8.10", |     "@react-navigation/native": "^5.8.10", | ||||||
|     "@reduxjs/toolkit": "^1.5.0", |     "@reduxjs/toolkit": "^1.5.0", | ||||||
|     "axios": "^0.21.0", |     "axios": "^0.21.1", | ||||||
|     "buffer": "^6.0.3", |     "buffer": "^6.0.3", | ||||||
|     "expo": "^40.0.0", |     "expo": "^40.0.0", | ||||||
|     "expo-auth-session": "~3.0.0", |     "expo-auth-session": "~3.0.0", | ||||||
| @@ -45,7 +45,7 @@ | |||||||
|     "pretty-bytes": "^5.5.0", |     "pretty-bytes": "^5.5.0", | ||||||
|     "react": "16.13.1", |     "react": "16.13.1", | ||||||
|     "react-dom": "16.13.1", |     "react-dom": "16.13.1", | ||||||
|     "react-i18next": "^11.8.4", |     "react-i18next": "^11.8.5", | ||||||
|     "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.0.tar.gz", |     "react-native": "https://github.com/expo/react-native/archive/sdk-40.0.0.tar.gz", | ||||||
|     "react-native-animated-spinkit": "^1.4.2", |     "react-native-animated-spinkit": "^1.4.2", | ||||||
|     "react-native-expo-image-cache": "^4.1.0", |     "react-native-expo-image-cache": "^4.1.0", | ||||||
| @@ -58,9 +58,9 @@ | |||||||
|     "react-native-shimmer-placeholder": "^2.0.6", |     "react-native-shimmer-placeholder": "^2.0.6", | ||||||
|     "react-native-svg": "12.1.0", |     "react-native-svg": "12.1.0", | ||||||
|     "react-native-tab-view": "^2.15.2", |     "react-native-tab-view": "^2.15.2", | ||||||
|     "react-native-toast-message": "^1.3.4", |     "react-native-toast-message": "^1.4.2", | ||||||
|     "react-navigation": "^4.4.3", |     "react-navigation": "^4.4.3", | ||||||
|     "react-query": "^3.3.2", |     "react-query": "^3.5.6", | ||||||
|     "react-redux": "^7.2.2", |     "react-redux": "^7.2.2", | ||||||
|     "redux-persist": "^6.0.0", |     "redux-persist": "^6.0.0", | ||||||
|     "redux-persist-expo-securestore": "^2.0.0", |     "redux-persist-expo-securestore": "^2.0.0", | ||||||
| @@ -87,13 +87,13 @@ | |||||||
|     "@types/react-navigation": "^3.4.0", |     "@types/react-navigation": "^3.4.0", | ||||||
|     "@types/react-redux": "^7.1.12", |     "@types/react-redux": "^7.1.12", | ||||||
|     "@types/react-test-renderer": "^17.0.0", |     "@types/react-test-renderer": "^17.0.0", | ||||||
|     "@welldone-software/why-did-you-render": "^6.0.3", |     "@welldone-software/why-did-you-render": "^6.0.4", | ||||||
|     "babel-plugin-module-resolver": "^4.1.0", |     "babel-plugin-module-resolver": "^4.1.0", | ||||||
|     "chalk": "^4.1.0", |     "chalk": "^4.1.0", | ||||||
|     "jest": "^26.6.3", |     "jest": "^26.6.3", | ||||||
|     "jest-expo": "^40.0.1", |     "jest-expo": "^40.0.1", | ||||||
|     "react-test-renderer": "^16.13.1", |     "react-test-renderer": "^16.13.1", | ||||||
|     "typescript": "~4.0.0" |     "typescript": "~4.1.3" | ||||||
|   }, |   }, | ||||||
|   "jest": { |   "jest": { | ||||||
|     "preset": "jest-expo", |     "preset": "jest-expo", | ||||||
|   | |||||||
							
								
								
									
										254
									
								
								src/Index.tsx
									
									
									
									
									
								
							
							
						
						
									
										254
									
								
								src/Index.tsx
									
									
									
									
									
								
							| @@ -1,37 +1,30 @@ | |||||||
| import 'react-native-gesture-handler' | import client from '@api/client' | ||||||
|  | import { Feather } from '@expo/vector-icons' | ||||||
| import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' | import { createBottomTabNavigator } from '@react-navigation/bottom-tabs' | ||||||
| import { | import { | ||||||
|   NavigationContainer, |   NavigationContainer, | ||||||
|   NavigationContainerRef |   NavigationContainerRef | ||||||
| } from '@react-navigation/native' | } from '@react-navigation/native' | ||||||
|  |  | ||||||
| import * as Analytics from 'expo-firebase-analytics' |  | ||||||
| import React, { useEffect, useRef, useState } from 'react' |  | ||||||
| import { StatusBar } from 'react-native' |  | ||||||
| import Toast from 'react-native-toast-message' |  | ||||||
| import { Feather } from '@expo/vector-icons' |  | ||||||
|  |  | ||||||
| import ScreenLocal from '@screens/Local' | import ScreenLocal from '@screens/Local' | ||||||
| import ScreenPublic from '@screens/Public' | import ScreenPublic from '@screens/Public' | ||||||
| import ScreenNotifications from '@screens/Notifications' | import ScreenNotifications from '@screens/Notifications' | ||||||
| import ScreenMe from '@screens/Me' | import ScreenMe from '@screens/Me' | ||||||
|  | import { timelineFetch } from '@utils/fetches/timelineFetch' | ||||||
| import { themes } from '@utils/styles/themes' |  | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' |  | ||||||
| import getCurrentTab from '@utils/getCurrentTab' |  | ||||||
| import { toast, toastConfig } from '@components/toast' |  | ||||||
| import { useTranslation } from 'react-i18next' |  | ||||||
| import { useDispatch, useSelector } from 'react-redux' |  | ||||||
| import { | import { | ||||||
|   getLocalNotification, |   getLocalNotification, | ||||||
|   getLocalUrl, |   getLocalUrl, | ||||||
|   updateLocalAccountPreferences, |   updateLocalAccountPreferences, | ||||||
|   updateNotification |   updateNotification | ||||||
| } from '@utils/slices/instancesSlice' | } from '@utils/slices/instancesSlice' | ||||||
|  | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
|  | import { themes } from '@utils/styles/themes' | ||||||
|  | import { toast, toastConfig } from '@components/toast' | ||||||
|  | import * as Analytics from 'expo-firebase-analytics' | ||||||
|  | import React, { useCallback, useEffect, useMemo, useRef } from 'react' | ||||||
|  | import { StatusBar } from 'react-native' | ||||||
|  | import Toast from 'react-native-toast-message' | ||||||
|  | import { useDispatch, useSelector } from 'react-redux' | ||||||
| import { useInfiniteQuery } from 'react-query' | import { useInfiniteQuery } from 'react-query' | ||||||
| import client from './api/client' |  | ||||||
| import { timelineFetch } from './utils/fetches/timelineFetch' |  | ||||||
| import { useNetInfo } from '@react-native-community/netinfo' |  | ||||||
|  |  | ||||||
| const Tab = createBottomTabNavigator<RootStackParamList>() | const Tab = createBottomTabNavigator<RootStackParamList>() | ||||||
|  |  | ||||||
| @@ -50,25 +43,27 @@ export interface Props { | |||||||
| const Index: React.FC<Props> = ({ localCorrupt }) => { | const Index: React.FC<Props> = ({ localCorrupt }) => { | ||||||
|   const dispatch = useDispatch() |   const dispatch = useDispatch() | ||||||
|   const localInstance = useSelector(getLocalUrl) |   const localInstance = useSelector(getLocalUrl) | ||||||
|   const { i18n } = useTranslation() |  | ||||||
|   const { mode, theme } = useTheme() |   const { mode, theme } = useTheme() | ||||||
|   enum barStyle { |   enum barStyle { | ||||||
|     light = 'dark-content', |     light = 'dark-content', | ||||||
|     dark = 'light-content' |     dark = 'light-content' | ||||||
|   } |   } | ||||||
|  |  | ||||||
|   const isConnected = useNetInfo().isConnected |   const routeNameRef = useRef<string | undefined>() | ||||||
|   const [firstRender, setFirstRender] = useState(false) |   const navigationRef = useRef<NavigationContainerRef>(null) | ||||||
|   useEffect(() => { |  | ||||||
|     if (firstRender) { |   // const isConnected = useNetInfo().isConnected | ||||||
|       // bug in netInfo on first render as false |   // const [firstRender, setFirstRender] = useState(false) | ||||||
|       if (isConnected !== false) { |   // useEffect(() => { | ||||||
|         toast({ type: 'error', content: '手机🈚️网络', autoHide: false }) |   //   if (firstRender) { | ||||||
|       } |   //     // bug in netInfo on first render as false | ||||||
|     } else { |   //     if (isConnected !== false) { | ||||||
|       setFirstRender(true) |   //       toast({ type: 'error', content: '手机🈚️网络', autoHide: false }) | ||||||
|     } |   //     } | ||||||
|   }, [isConnected, firstRender]) |   //   } else { | ||||||
|  |   //     setFirstRender(true) | ||||||
|  |   //   } | ||||||
|  |   // }, [isConnected, firstRender]) | ||||||
|  |  | ||||||
|   // On launch display login credentials corrupt information |   // On launch display login credentials corrupt information | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
| @@ -84,8 +79,8 @@ const Index: React.FC<Props> = ({ localCorrupt }) => { | |||||||
|   }, [localCorrupt]) |   }, [localCorrupt]) | ||||||
|  |  | ||||||
|   // On launch check if there is any unread announcements |   // On launch check if there is any unread announcements | ||||||
|   const navigationRef = useRef<NavigationContainerRef>(null) |  | ||||||
|   useEffect(() => { |   useEffect(() => { | ||||||
|  |     console.log('Checking announcements') | ||||||
|     localInstance && |     localInstance && | ||||||
|       client({ |       client({ | ||||||
|         method: 'get', |         method: 'get', | ||||||
| @@ -99,7 +94,7 @@ const Index: React.FC<Props> = ({ localCorrupt }) => { | |||||||
|             }) |             }) | ||||||
|           } |           } | ||||||
|         }) |         }) | ||||||
|         .catch(() => null) |         .catch(() => {}) | ||||||
|   }, []) |   }, []) | ||||||
|  |  | ||||||
|   // On launch check if there is any unread noficiations |   // On launch check if there is any unread noficiations | ||||||
| @@ -145,104 +140,149 @@ const Index: React.FC<Props> = ({ localCorrupt }) => { | |||||||
|     } |     } | ||||||
|   }, []) |   }, []) | ||||||
|  |  | ||||||
|  |   // Callbacks | ||||||
|  |   const navigationContainerOnReady = useCallback( | ||||||
|  |     () => | ||||||
|  |       (routeNameRef.current = navigationRef.current?.getCurrentRoute()?.name), | ||||||
|  |     [] | ||||||
|  |   ) | ||||||
|  |   const navigationContainerOnStateChange = useCallback(() => { | ||||||
|  |     const previousRouteName = routeNameRef.current | ||||||
|  |     const currentRouteName = navigationRef.current?.getCurrentRoute()?.name | ||||||
|  |  | ||||||
|  |     if (previousRouteName !== currentRouteName) { | ||||||
|  |       Analytics.setCurrentScreen(currentRouteName) | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     routeNameRef.current = currentRouteName | ||||||
|  |   }, []) | ||||||
|  |   const tabNavigatorScreenOptions = useCallback( | ||||||
|  |     ({ route }) => ({ | ||||||
|  |       tabBarIcon: ({ | ||||||
|  |         focused, | ||||||
|  |         color, | ||||||
|  |         size | ||||||
|  |       }: { | ||||||
|  |         focused: boolean | ||||||
|  |         color: string | ||||||
|  |         size: number | ||||||
|  |       }) => { | ||||||
|  |         let name: any | ||||||
|  |         let updateColor: string = color | ||||||
|  |         switch (route.name) { | ||||||
|  |           case 'Screen-Local': | ||||||
|  |             name = 'home' | ||||||
|  |             break | ||||||
|  |           case 'Screen-Public': | ||||||
|  |             name = 'globe' | ||||||
|  |             !focused && (updateColor = theme.secondary) | ||||||
|  |             break | ||||||
|  |           case 'Screen-Post': | ||||||
|  |             name = 'plus' | ||||||
|  |             break | ||||||
|  |           case 'Screen-Notifications': | ||||||
|  |             name = 'bell' | ||||||
|  |             break | ||||||
|  |           case 'Screen-Me': | ||||||
|  |             name = focused ? 'meh' : 'smile' | ||||||
|  |             !focused && (updateColor = theme.secondary) | ||||||
|  |             break | ||||||
|  |           default: | ||||||
|  |             name = 'alert-octagon' | ||||||
|  |             break | ||||||
|  |         } | ||||||
|  |         return <Feather name={name} size={size} color={updateColor} /> | ||||||
|  |       } | ||||||
|  |     }), | ||||||
|  |     [] | ||||||
|  |   ) | ||||||
|  |   const tabNavigatorTabBarOptions = useMemo( | ||||||
|  |     () => ({ | ||||||
|  |       activeTintColor: theme.primary, | ||||||
|  |       inactiveTintColor: localInstance ? theme.secondary : theme.disabled, | ||||||
|  |       showLabel: false | ||||||
|  |     }), | ||||||
|  |     [] | ||||||
|  |   ) | ||||||
|  |   const tabScreenLocalListeners = useCallback( | ||||||
|  |     () => ({ | ||||||
|  |       tabPress: (e: any) => { | ||||||
|  |         if (!localInstance) { | ||||||
|  |           e.preventDefault() | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }), | ||||||
|  |     [] | ||||||
|  |   ) | ||||||
|  |   const tabScreenComposeListeners = useCallback( | ||||||
|  |     ({ navigation }) => ({ | ||||||
|  |       tabPress: (e: any) => { | ||||||
|  |         e.preventDefault() | ||||||
|  |         if (localInstance) { | ||||||
|  |           navigation.navigate('Screen-Shared-Compose') | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }), | ||||||
|  |     [] | ||||||
|  |   ) | ||||||
|  |   const tabScreenComposeComponent = useCallback(() => null, []) | ||||||
|  |   const tabScreenNotificationsListeners = useCallback( | ||||||
|  |     () => ({ | ||||||
|  |       tabPress: (e: any) => { | ||||||
|  |         if (!localInstance) { | ||||||
|  |           e.preventDefault() | ||||||
|  |         } | ||||||
|  |       } | ||||||
|  |     }), | ||||||
|  |     [] | ||||||
|  |   ) | ||||||
|  |   const tabScreenNotificationsOptions = useMemo( | ||||||
|  |     () => ({ | ||||||
|  |       tabBarBadge: prevNotification && prevNotification.unread ? '' : undefined, | ||||||
|  |       tabBarBadgeStyle: { | ||||||
|  |         transform: [{ scale: 0.5 }], | ||||||
|  |         backgroundColor: theme.red | ||||||
|  |       } | ||||||
|  |     }), | ||||||
|  |     [] | ||||||
|  |   ) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <> |     <> | ||||||
|       <StatusBar barStyle={barStyle[mode]} /> |       <StatusBar barStyle={barStyle[mode]} /> | ||||||
|       <NavigationContainer |       <NavigationContainer | ||||||
|         ref={navigationRef} |         ref={navigationRef} | ||||||
|         theme={themes[mode]} |         theme={themes[mode]} | ||||||
|         key={i18n.language} |         // key={i18n.language} | ||||||
|         onStateChange={state => { |         onReady={navigationContainerOnReady} | ||||||
|           Analytics.setCurrentScreen(state?.routes[state.index].name) |         onStateChange={navigationContainerOnStateChange} | ||||||
|         }} |  | ||||||
|       > |       > | ||||||
|         <Tab.Navigator |         <Tab.Navigator | ||||||
|           initialRouteName={localInstance ? 'Screen-Local' : 'Screen-Public'} |           initialRouteName={localInstance ? 'Screen-Local' : 'Screen-Public'} | ||||||
|           screenOptions={({ route }) => ({ |           screenOptions={tabNavigatorScreenOptions} | ||||||
|             tabBarIcon: ({ focused, color, size }) => { |           tabBarOptions={tabNavigatorTabBarOptions} | ||||||
|               let name: any |  | ||||||
|               let updateColor: string = color |  | ||||||
|               switch (route.name) { |  | ||||||
|                 case 'Screen-Local': |  | ||||||
|                   name = 'home' |  | ||||||
|                   break |  | ||||||
|                 case 'Screen-Public': |  | ||||||
|                   name = 'globe' |  | ||||||
|                   !focused && (updateColor = theme.secondary) |  | ||||||
|                   break |  | ||||||
|                 case 'Screen-Post': |  | ||||||
|                   name = 'plus' |  | ||||||
|                   break |  | ||||||
|                 case 'Screen-Notifications': |  | ||||||
|                   name = 'bell' |  | ||||||
|                   break |  | ||||||
|                 case 'Screen-Me': |  | ||||||
|                   name = focused ? 'meh' : 'smile' |  | ||||||
|                   !focused && (updateColor = theme.secondary) |  | ||||||
|                   break |  | ||||||
|                 default: |  | ||||||
|                   name = 'alert-octagon' |  | ||||||
|                   break |  | ||||||
|               } |  | ||||||
|               return <Feather name={name} size={size} color={updateColor} /> |  | ||||||
|             } |  | ||||||
|           })} |  | ||||||
|           tabBarOptions={{ |  | ||||||
|             activeTintColor: theme.primary, |  | ||||||
|             inactiveTintColor: localInstance ? theme.secondary : theme.disabled, |  | ||||||
|             showLabel: false |  | ||||||
|           }} |  | ||||||
|         > |         > | ||||||
|           <Tab.Screen |           <Tab.Screen | ||||||
|             name='Screen-Local' |             name='Screen-Local' | ||||||
|             component={ScreenLocal} |             component={ScreenLocal} | ||||||
|             listeners={({ navigation }) => ({ |             listeners={tabScreenLocalListeners} | ||||||
|               tabPress: e => { |  | ||||||
|                 if (!localInstance) { |  | ||||||
|                   e.preventDefault() |  | ||||||
|                 } |  | ||||||
|               } |  | ||||||
|             })} |  | ||||||
|           /> |           /> | ||||||
|           <Tab.Screen name='Screen-Public' component={ScreenPublic} /> |           <Tab.Screen name='Screen-Public' component={ScreenPublic} /> | ||||||
|           <Tab.Screen |           <Tab.Screen | ||||||
|             name='Screen-Post' |             name='Screen-Post' | ||||||
|             listeners={({ navigation }) => ({ |             component={tabScreenComposeComponent} | ||||||
|               tabPress: e => { |             listeners={tabScreenComposeListeners} | ||||||
|                 e.preventDefault() |           /> | ||||||
|                 if (localInstance) { |  | ||||||
|                   navigation.navigate(getCurrentTab(navigation), { |  | ||||||
|                     screen: 'Screen-Shared-Compose' |  | ||||||
|                   }) |  | ||||||
|                 } |  | ||||||
|               } |  | ||||||
|             })} |  | ||||||
|           > |  | ||||||
|             {() => null} |  | ||||||
|           </Tab.Screen> |  | ||||||
|           <Tab.Screen |           <Tab.Screen | ||||||
|             name='Screen-Notifications' |             name='Screen-Notifications' | ||||||
|             component={ScreenNotifications} |             component={ScreenNotifications} | ||||||
|             options={{ |             listeners={tabScreenNotificationsListeners} | ||||||
|               tabBarBadge: |             options={tabScreenNotificationsOptions} | ||||||
|                 prevNotification && prevNotification.unread ? '' : undefined, |  | ||||||
|               tabBarBadgeStyle: { |  | ||||||
|                 transform: [{ scale: 0.5 }], |  | ||||||
|                 backgroundColor: theme.red |  | ||||||
|               } |  | ||||||
|             }} |  | ||||||
|             listeners={() => ({ |  | ||||||
|               tabPress: e => { |  | ||||||
|                 if (!localInstance) { |  | ||||||
|                   e.preventDefault() |  | ||||||
|                 } |  | ||||||
|               } |  | ||||||
|             })} |  | ||||||
|           /> |           /> | ||||||
|           <Tab.Screen name='Screen-Me' component={ScreenMe} /> |           <Tab.Screen name='Screen-Me' component={ScreenMe} /> | ||||||
|         </Tab.Navigator> |         </Tab.Navigator> | ||||||
|  |  | ||||||
|         <Toast ref={(ref: any) => Toast.setRef(ref)} config={toastConfig} /> |         <Toast ref={Toast.setRef} config={toastConfig} /> | ||||||
|       </NavigationContainer> |       </NavigationContainer> | ||||||
|     </> |     </> | ||||||
|   ) |   ) | ||||||
|   | |||||||
| @@ -3,7 +3,7 @@ import { StyleConstants } from '@utils/styles/constants' | |||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
| import { ColorDefinitions } from '@utils/styles/themes' | import { ColorDefinitions } from '@utils/styles/themes' | ||||||
| import React, { useMemo } from 'react' | import React, { useMemo } from 'react' | ||||||
| import { Pressable, StyleSheet, Text, View } from 'react-native' | import { Pressable, StyleSheet, Switch, Text, View } from 'react-native' | ||||||
| import { Chase } from 'react-native-animated-spinkit' | import { Chase } from 'react-native-animated-spinkit' | ||||||
|  |  | ||||||
| export interface Props { | export interface Props { | ||||||
| @@ -11,8 +11,13 @@ export interface Props { | |||||||
|   iconFrontColor?: ColorDefinitions |   iconFrontColor?: ColorDefinitions | ||||||
|  |  | ||||||
|   title: string |   title: string | ||||||
|  |   description?: string | ||||||
|   content?: string |   content?: string | ||||||
|  |  | ||||||
|  |   switchValue?: boolean | ||||||
|  |   switchDisabled?: boolean | ||||||
|  |   switchOnValueChange?: () => void | ||||||
|  |  | ||||||
|   iconBack?: 'chevron-right' | 'check' |   iconBack?: 'chevron-right' | 'check' | ||||||
|   iconBackColor?: ColorDefinitions |   iconBackColor?: ColorDefinitions | ||||||
|  |  | ||||||
| @@ -24,7 +29,11 @@ const MenuRow: React.FC<Props> = ({ | |||||||
|   iconFront, |   iconFront, | ||||||
|   iconFrontColor = 'primary', |   iconFrontColor = 'primary', | ||||||
|   title, |   title, | ||||||
|  |   description, | ||||||
|   content, |   content, | ||||||
|  |   switchValue, | ||||||
|  |   switchDisabled, | ||||||
|  |   switchOnValueChange, | ||||||
|   iconBack, |   iconBack, | ||||||
|   iconBackColor = 'secondary', |   iconBackColor = 'secondary', | ||||||
|   loading = false, |   loading = false, | ||||||
| @@ -61,45 +70,59 @@ const MenuRow: React.FC<Props> = ({ | |||||||
|               style={styles.iconFront} |               style={styles.iconFront} | ||||||
|             /> |             /> | ||||||
|           )} |           )} | ||||||
|           <Text |           <View style={styles.main}> | ||||||
|             style={[styles.text, { color: theme.primary }]} |             <Text | ||||||
|             numberOfLines={1} |               style={[styles.title, { color: theme.primary }]} | ||||||
|           > |               numberOfLines={1} | ||||||
|             {title} |             > | ||||||
|           </Text> |               {title} | ||||||
|         </View> |             </Text> | ||||||
|         {(content || iconBack) && ( |             {description ? ( | ||||||
|           <View style={styles.back}> |               <Text style={[styles.description, { color: theme.secondary }]}> | ||||||
|             {content && content.length ? ( |                 {description} | ||||||
|               <> |               </Text> | ||||||
|                 <Text |  | ||||||
|                   style={[ |  | ||||||
|                     styles.content, |  | ||||||
|                     { |  | ||||||
|                       color: theme.secondary, |  | ||||||
|                       opacity: !iconBack && loading ? 0 : 1 |  | ||||||
|                     } |  | ||||||
|                   ]} |  | ||||||
|                   numberOfLines={1} |  | ||||||
|                 > |  | ||||||
|                   {content} |  | ||||||
|                 </Text> |  | ||||||
|                 {loading && !iconBack && loadingSpinkit} |  | ||||||
|               </> |  | ||||||
|             ) : null} |             ) : null} | ||||||
|             {iconBack && ( |  | ||||||
|               <> |  | ||||||
|                 <Feather |  | ||||||
|                   name={iconBack} |  | ||||||
|                   size={StyleConstants.Font.Size.M + 2} |  | ||||||
|                   color={theme[iconBackColor]} |  | ||||||
|                   style={[styles.iconBack, { opacity: loading ? 0 : 1 }]} |  | ||||||
|                 /> |  | ||||||
|                 {loading && loadingSpinkit} |  | ||||||
|               </> |  | ||||||
|             )} |  | ||||||
|           </View> |           </View> | ||||||
|         )} |         </View> | ||||||
|  |  | ||||||
|  |         <View style={styles.back}> | ||||||
|  |           {content && content.length ? ( | ||||||
|  |             <> | ||||||
|  |               <Text | ||||||
|  |                 style={[ | ||||||
|  |                   styles.content, | ||||||
|  |                   { | ||||||
|  |                     color: theme.secondary, | ||||||
|  |                     opacity: !iconBack && loading ? 0 : 1 | ||||||
|  |                   } | ||||||
|  |                 ]} | ||||||
|  |                 numberOfLines={1} | ||||||
|  |               > | ||||||
|  |                 {content} | ||||||
|  |               </Text> | ||||||
|  |               {loading && !iconBack && loadingSpinkit} | ||||||
|  |             </> | ||||||
|  |           ) : null} | ||||||
|  |           {switchValue !== undefined ? ( | ||||||
|  |             <Switch | ||||||
|  |               value={switchValue} | ||||||
|  |               onValueChange={switchOnValueChange} | ||||||
|  |               disabled={switchDisabled} | ||||||
|  |               trackColor={{ true: theme.blue, false: theme.disabled }} | ||||||
|  |             /> | ||||||
|  |           ) : null} | ||||||
|  |           {iconBack ? ( | ||||||
|  |             <> | ||||||
|  |               <Feather | ||||||
|  |                 name={iconBack} | ||||||
|  |                 size={StyleConstants.Font.Size.M + 2} | ||||||
|  |                 color={theme[iconBackColor]} | ||||||
|  |                 style={[styles.iconBack, { opacity: loading ? 0 : 1 }]} | ||||||
|  |               /> | ||||||
|  |               {loading && loadingSpinkit} | ||||||
|  |             </> | ||||||
|  |           ) : null} | ||||||
|  |         </View> | ||||||
|       </View> |       </View> | ||||||
|     </Pressable> |     </Pressable> | ||||||
|   ) |   ) | ||||||
| @@ -131,10 +154,16 @@ const styles = StyleSheet.create({ | |||||||
|   iconFront: { |   iconFront: { | ||||||
|     marginRight: 8 |     marginRight: 8 | ||||||
|   }, |   }, | ||||||
|   text: { |   main: { | ||||||
|     flex: 1, |     flex: 1 | ||||||
|  |   }, | ||||||
|  |   title: { | ||||||
|     ...StyleConstants.FontStyle.M |     ...StyleConstants.FontStyle.M | ||||||
|   }, |   }, | ||||||
|  |   description: { | ||||||
|  |     ...StyleConstants.FontStyle.S, | ||||||
|  |     marginTop: StyleConstants.Spacing.XS | ||||||
|  |   }, | ||||||
|   content: { |   content: { | ||||||
|     ...StyleConstants.FontStyle.M |     ...StyleConstants.FontStyle.M | ||||||
|   }, |   }, | ||||||
|   | |||||||
| @@ -76,6 +76,7 @@ const renderNode = ({ | |||||||
|       } |       } | ||||||
|     } else { |     } else { | ||||||
|       const domain = href.split(new RegExp(/:\/\/(.[^\/]+)/)) |       const domain = href.split(new RegExp(/:\/\/(.[^\/]+)/)) | ||||||
|  |       // Need example here | ||||||
|       const content = node.children && node.children[0].data |       const content = node.children && node.children[0].data | ||||||
|       const shouldBeTag = |       const shouldBeTag = | ||||||
|         tags && tags.filter(tag => `#${tag.name}` === content).length > 0 |         tags && tags.filter(tag => `#${tag.name}` === content).length > 0 | ||||||
|   | |||||||
| @@ -9,7 +9,6 @@ import sharedScreens from '@screens/Shared/sharedScreens' | |||||||
| import { getLocalUrl, getRemoteUrl } from '@utils/slices/instancesSlice' | import { getLocalUrl, getRemoteUrl } from '@utils/slices/instancesSlice' | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
| import { useNavigation } from '@react-navigation/native' | import { useNavigation } from '@react-navigation/native' | ||||||
| import getCurrentTab from '@utils/getCurrentTab' |  | ||||||
| import { HeaderRight } from './Header' | import { HeaderRight } from './Header' | ||||||
| import { TabView } from 'react-native-tab-view' | import { TabView } from 'react-native-tab-view' | ||||||
|  |  | ||||||
| @@ -28,9 +27,7 @@ const Timelines: React.FC<Props> = ({ name, content }) => { | |||||||
|   const [segment, setSegment] = useState(0) |   const [segment, setSegment] = useState(0) | ||||||
|  |  | ||||||
|   const onPressSearch = useCallback(() => { |   const onPressSearch = useCallback(() => { | ||||||
|     navigation.navigate(getCurrentTab(navigation), { |     navigation.navigate('Screen-Shared-Search') | ||||||
|       screen: 'Screen-Shared-Search' |  | ||||||
|     }) |  | ||||||
|   }, []) |   }, []) | ||||||
|  |  | ||||||
|   const routes = content |   const routes = content | ||||||
|   | |||||||
| @@ -8,7 +8,6 @@ import { useTheme } from '@utils/styles/ThemeManager' | |||||||
| import { toast } from '@components/toast' | import { toast } from '@components/toast' | ||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| import { useNavigation } from '@react-navigation/native' | import { useNavigation } from '@react-navigation/native' | ||||||
| import getCurrentTab from '@utils/getCurrentTab' |  | ||||||
| import { findIndex } from 'lodash' | import { findIndex } from 'lodash' | ||||||
| import { TimelineData } from '../../Timeline' | import { TimelineData } from '../../Timeline' | ||||||
|  |  | ||||||
| @@ -124,13 +123,10 @@ const TimelineActions: React.FC<Props> = ({ queryKey, status, reblog }) => { | |||||||
|  |  | ||||||
|   const onPressReply = useCallback( |   const onPressReply = useCallback( | ||||||
|     () => |     () => | ||||||
|       navigation.navigate(getCurrentTab(navigation), { |       navigation.navigate('Screen-Shared-Compose', { | ||||||
|         screen: 'Screen-Shared-Compose', |         type: 'reply', | ||||||
|         params: { |         incomingStatus: status, | ||||||
|           type: 'reply', |         visibilityLock: status.visibility === 'direct' | ||||||
|           incomingStatus: status, |  | ||||||
|           visibilityLock: status.visibility === 'direct' |  | ||||||
|         } |  | ||||||
|       }), |       }), | ||||||
|     [] |     [] | ||||||
|   ) |   ) | ||||||
|   | |||||||
| @@ -5,7 +5,6 @@ import { useMutation, useQueryClient } from 'react-query' | |||||||
| import client from '@api/client' | import client from '@api/client' | ||||||
| import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu' | import { MenuContainer, MenuHeader, MenuRow } from '@components/Menu' | ||||||
| import { toast } from '@components/toast' | import { toast } from '@components/toast' | ||||||
| import getCurrentTab from '@utils/getCurrentTab' |  | ||||||
| import { TimelineData } from '@root/components/Timelines/Timeline' | import { TimelineData } from '@root/components/Timelines/Timeline' | ||||||
| import { findIndex } from 'lodash' | import { findIndex } from 'lodash' | ||||||
|  |  | ||||||
| @@ -155,9 +154,9 @@ const HeaderDefaultActionsStatus: React.FC<Props> = ({ | |||||||
|                     .then(res => { |                     .then(res => { | ||||||
|                       queryClient.invalidateQueries(queryKey) |                       queryClient.invalidateQueries(queryKey) | ||||||
|                       setBottomSheetVisible(false) |                       setBottomSheetVisible(false) | ||||||
|                       navigation.navigate(getCurrentTab(navigation), { |                       navigation.navigate('Screen-Shared-Compose', { | ||||||
|                         screen: 'Screen-Shared-Compose', |                         type: 'edit', | ||||||
|                         params: { type: 'edit', incomingStatus: res.body } |                         incomingStatus: res.body | ||||||
|                       }) |                       }) | ||||||
|                     }) |                     }) | ||||||
|                     .catch(() => { |                     .catch(() => { | ||||||
|   | |||||||
| @@ -63,7 +63,7 @@ const ToastBase = ({ config }: { config: Config }) => { | |||||||
|     <SafeAreaView |     <SafeAreaView | ||||||
|       style={[ |       style={[ | ||||||
|         styles.base, |         styles.base, | ||||||
|         { backgroundColor: theme.background, shadowColor: theme.primary } |         { backgroundColor: theme.background, borderBottomColor: theme.primary } | ||||||
|       ]} |       ]} | ||||||
|     > |     > | ||||||
|       <View style={styles.container}> |       <View style={styles.container}> | ||||||
| @@ -97,15 +97,14 @@ const toastConfig = { | |||||||
| const styles = StyleSheet.create({ | const styles = StyleSheet.create({ | ||||||
|   base: { |   base: { | ||||||
|     width: '100%', |     width: '100%', | ||||||
|     shadowOpacity: 1, |     borderBottomWidth: 1 | ||||||
|     shadowRadius: 6 |  | ||||||
|   }, |   }, | ||||||
|   container: { |   container: { | ||||||
|     flex: 1, |     flex: 1, | ||||||
|     flexDirection: 'row', |     flexDirection: 'row', | ||||||
|     justifyContent: 'center', |     justifyContent: 'center', | ||||||
|     alignItems: 'center', |     alignItems: 'center', | ||||||
|     padding: StyleConstants.Spacing.M |     padding: StyleConstants.Spacing.L | ||||||
|   }, |   }, | ||||||
|   texts: { |   texts: { | ||||||
|     marginLeft: StyleConstants.Spacing.S |     marginLeft: StyleConstants.Spacing.S | ||||||
|   | |||||||
| @@ -29,6 +29,10 @@ export default { | |||||||
|     cache: { |     cache: { | ||||||
|       heading: '清空缓存' |       heading: '清空缓存' | ||||||
|     }, |     }, | ||||||
|  |     analytics: { | ||||||
|  |       heading: '帮助我们改进', | ||||||
|  |       description: '允许我们收集不与用户相关联的使用信息' | ||||||
|  |     }, | ||||||
|     copyrights: { |     copyrights: { | ||||||
|       heading: '版权信息' |       heading: '版权信息' | ||||||
|     }, |     }, | ||||||
|   | |||||||
| @@ -1,20 +1,22 @@ | |||||||
| import prettyBytes from 'pretty-bytes' |  | ||||||
| import React, { useEffect, useState } from 'react' |  | ||||||
| import { useTranslation } from 'react-i18next' |  | ||||||
| import { ActionSheetIOS, StyleSheet, Text } from 'react-native' |  | ||||||
| import { CacheManager } from 'react-native-expo-image-cache' |  | ||||||
| import { useDispatch, useSelector } from 'react-redux' |  | ||||||
| import { MenuContainer, MenuRow } from '@components/Menu' | import { MenuContainer, MenuRow } from '@components/Menu' | ||||||
| import { | import { | ||||||
|  |   changeAnalytics, | ||||||
|   changeBrowser, |   changeBrowser, | ||||||
|   changeLanguage, |   changeLanguage, | ||||||
|   changeTheme, |   changeTheme, | ||||||
|  |   getSettingsAnalytics, | ||||||
|   getSettingsBrowser, |   getSettingsBrowser, | ||||||
|   getSettingsLanguage, |   getSettingsLanguage, | ||||||
|   getSettingsTheme |   getSettingsTheme | ||||||
| } from '@utils/slices/settingsSlice' | } from '@utils/slices/settingsSlice' | ||||||
| import { StyleConstants } from '@utils/styles/constants' | import { StyleConstants } from '@utils/styles/constants' | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
|  | import prettyBytes from 'pretty-bytes' | ||||||
|  | import React, { useEffect, useState } from 'react' | ||||||
|  | import { useTranslation } from 'react-i18next' | ||||||
|  | import { ActionSheetIOS, StyleSheet, Text } from 'react-native' | ||||||
|  | import { CacheManager } from 'react-native-expo-image-cache' | ||||||
|  | import { useDispatch, useSelector } from 'react-redux' | ||||||
|  |  | ||||||
| const ScreenMeSettings: React.FC = () => { | const ScreenMeSettings: React.FC = () => { | ||||||
|   const { t, i18n } = useTranslation('meSettings') |   const { t, i18n } = useTranslation('meSettings') | ||||||
| @@ -22,6 +24,7 @@ const ScreenMeSettings: React.FC = () => { | |||||||
|   const settingsLanguage = useSelector(getSettingsLanguage) |   const settingsLanguage = useSelector(getSettingsLanguage) | ||||||
|   const settingsTheme = useSelector(getSettingsTheme) |   const settingsTheme = useSelector(getSettingsTheme) | ||||||
|   const settingsBrowser = useSelector(getSettingsBrowser) |   const settingsBrowser = useSelector(getSettingsBrowser) | ||||||
|  |   const settingsAnalytics = useSelector(getSettingsAnalytics) | ||||||
|   const dispatch = useDispatch() |   const dispatch = useDispatch() | ||||||
|  |  | ||||||
|   const [cacheSize, setCacheSize] = useState<number>() |   const [cacheSize, setCacheSize] = useState<number>() | ||||||
| @@ -132,6 +135,14 @@ const ScreenMeSettings: React.FC = () => { | |||||||
|             setCacheSize(0) |             setCacheSize(0) | ||||||
|           }} |           }} | ||||||
|         /> |         /> | ||||||
|  |         <MenuRow | ||||||
|  |           title={t('content.analytics.heading')} | ||||||
|  |           description={t('content.analytics.description')} | ||||||
|  |           switchValue={settingsAnalytics} | ||||||
|  |           switchOnValueChange={() => | ||||||
|  |             dispatch(changeAnalytics(!settingsAnalytics)) | ||||||
|  |           } | ||||||
|  |         /> | ||||||
|         <MenuRow |         <MenuRow | ||||||
|           title={t('content.copyrights.heading')} |           title={t('content.copyrights.heading')} | ||||||
|           iconBack='chevron-right' |           iconBack='chevron-right' | ||||||
|   | |||||||
| @@ -3,7 +3,6 @@ import client from '@root/api/client' | |||||||
| import Button from '@root/components/Button' | import Button from '@root/components/Button' | ||||||
| import { toast } from '@root/components/toast' | import { toast } from '@root/components/toast' | ||||||
| import { relationshipFetch } from '@root/utils/fetches/relationshipFetch' | import { relationshipFetch } from '@root/utils/fetches/relationshipFetch' | ||||||
| import getCurrentTab from '@root/utils/getCurrentTab' |  | ||||||
| import { StyleConstants } from '@root/utils/styles/constants' | import { StyleConstants } from '@root/utils/styles/constants' | ||||||
| import { useTheme } from '@root/utils/styles/ThemeManager' | import { useTheme } from '@root/utils/styles/ThemeManager' | ||||||
| import React, { useEffect, useMemo } from 'react' | import React, { useEffect, useMemo } from 'react' | ||||||
| @@ -130,12 +129,9 @@ const AccountInformationActions: React.FC<Props> = ({ account }) => { | |||||||
|           content='mail' |           content='mail' | ||||||
|           round |           round | ||||||
|           onPress={() => |           onPress={() => | ||||||
|             navigation.navigate(getCurrentTab(navigation), { |             navigation.navigate('Screen-Shared-Compose', { | ||||||
|               screen: 'Screen-Shared-Compose', |               type: 'conversation', | ||||||
|               params: { |               incomingStatus: { account } | ||||||
|                 type: 'conversation', |  | ||||||
|                 incomingStatus: { account } |  | ||||||
|               } |  | ||||||
|             }) |             }) | ||||||
|           } |           } | ||||||
|           style={styles.actionConversation} |           style={styles.actionConversation} | ||||||
|   | |||||||
| @@ -63,14 +63,14 @@ const AccountNav: React.FC<Props> = ({ accountState, scrollY, account }) => { | |||||||
|             <Emojis |             <Emojis | ||||||
|               content={account?.display_name || account?.username} |               content={account?.display_name || account?.username} | ||||||
|               emojis={account.emojis} |               emojis={account.emojis} | ||||||
|               size='L' |               size='M' | ||||||
|               fontBold={true} |               fontBold={true} | ||||||
|             /> |             /> | ||||||
|           ) : ( |           ) : ( | ||||||
|             <Text |             <Text | ||||||
|               style={{ |               style={{ | ||||||
|                 color: theme.primary, |                 color: theme.primary, | ||||||
|                 ...StyleConstants.FontStyle.L, |                 ...StyleConstants.FontStyle.M, | ||||||
|                 fontWeight: StyleConstants.Font.Weight.Bold |                 fontWeight: StyleConstants.Font.Weight.Bold | ||||||
|               }} |               }} | ||||||
|             > |             > | ||||||
|   | |||||||
| @@ -1,3 +1,12 @@ | |||||||
|  | import client from '@api/client' | ||||||
|  | import { HeaderLeft, HeaderRight } from '@components/Header' | ||||||
|  | import { store } from '@root/store' | ||||||
|  | import formatText from '@screens/Shared/Compose/formatText' | ||||||
|  | import ComposeRoot from '@screens/Shared/Compose/Root' | ||||||
|  | import { getLocalAccountPreferences } from '@utils/slices/instancesSlice' | ||||||
|  | import { StyleConstants } from '@utils/styles/constants' | ||||||
|  | import { useTheme } from '@utils/styles/ThemeManager' | ||||||
|  | import * as Crypto from 'expo-crypto' | ||||||
| import React, { | import React, { | ||||||
|   createContext, |   createContext, | ||||||
|   createRef, |   createRef, | ||||||
| @@ -10,7 +19,6 @@ import React, { | |||||||
|   useState |   useState | ||||||
| } from 'react' | } from 'react' | ||||||
| import { | import { | ||||||
|   ActivityIndicator, |  | ||||||
|   Alert, |   Alert, | ||||||
|   Keyboard, |   Keyboard, | ||||||
|   KeyboardAvoidingView, |   KeyboardAvoidingView, | ||||||
| @@ -20,19 +28,7 @@ import { | |||||||
| } from 'react-native' | } from 'react-native' | ||||||
| import { SafeAreaView } from 'react-native-safe-area-context' | import { SafeAreaView } from 'react-native-safe-area-context' | ||||||
| import { createNativeStackNavigator } from 'react-native-screens/native-stack' | import { createNativeStackNavigator } from 'react-native-screens/native-stack' | ||||||
| import * as Crypto from 'expo-crypto' |  | ||||||
|  |  | ||||||
| import { store } from '@root/store' |  | ||||||
| import ComposeRoot from '@screens/Shared/Compose/Root' |  | ||||||
| import client from '@api/client' |  | ||||||
| import { getLocalAccountPreferences } from '@utils/slices/instancesSlice' |  | ||||||
| import { HeaderLeft, HeaderRight } from '@components/Header' |  | ||||||
| import { StyleConstants } from '@utils/styles/constants' |  | ||||||
| import { useTheme } from '@utils/styles/ThemeManager' |  | ||||||
| import formatText from '@screens/Shared/Compose/formatText' |  | ||||||
| import { useQueryClient } from 'react-query' | import { useQueryClient } from 'react-query' | ||||||
| import Toast from 'react-native-toast-message' |  | ||||||
| import { toastConfig } from '@root/components/toast' |  | ||||||
|  |  | ||||||
| const Stack = createNativeStackNavigator() | const Stack = createNativeStackNavigator() | ||||||
|  |  | ||||||
| @@ -583,6 +579,15 @@ const Compose: React.FC<Props> = ({ route: { params }, navigation }) => { | |||||||
|     [isSubmitting, rawCount, totalTextCount] |     [isSubmitting, rawCount, totalTextCount] | ||||||
|   ) |   ) | ||||||
|  |  | ||||||
|  |   const screenComponent = useCallback( | ||||||
|  |     () => ( | ||||||
|  |       <ComposeContext.Provider value={{ composeState, composeDispatch }}> | ||||||
|  |         <ComposeRoot /> | ||||||
|  |       </ComposeContext.Provider> | ||||||
|  |     ), | ||||||
|  |     [] | ||||||
|  |   ) | ||||||
|  |  | ||||||
|   return ( |   return ( | ||||||
|     <KeyboardAvoidingView behavior='padding' style={{ flex: 1 }}> |     <KeyboardAvoidingView behavior='padding' style={{ flex: 1 }}> | ||||||
|       <SafeAreaView |       <SafeAreaView | ||||||
| @@ -591,17 +596,10 @@ const Compose: React.FC<Props> = ({ route: { params }, navigation }) => { | |||||||
|       > |       > | ||||||
|         <Stack.Navigator> |         <Stack.Navigator> | ||||||
|           <Stack.Screen |           <Stack.Screen | ||||||
|             name='PostMain' |             name='Screen-Shared-Compose-Root' | ||||||
|             options={{ headerLeft, headerCenter, headerRight }} |             options={{ headerLeft, headerCenter, headerRight }} | ||||||
|           > |             component={screenComponent} | ||||||
|             {() => ( |           /> | ||||||
|               <ComposeContext.Provider |  | ||||||
|                 value={{ composeState, composeDispatch }} |  | ||||||
|               > |  | ||||||
|                 <ComposeRoot /> |  | ||||||
|               </ComposeContext.Provider> |  | ||||||
|             )} |  | ||||||
|           </Stack.Screen> |  | ||||||
|         </Stack.Navigator> |         </Stack.Navigator> | ||||||
|       </SafeAreaView> |       </SafeAreaView> | ||||||
|     </KeyboardAvoidingView> |     </KeyboardAvoidingView> | ||||||
|   | |||||||
| @@ -1,8 +0,0 @@ | |||||||
| const getCurrentTab = (navigation: any) => { |  | ||||||
|   const { length, [length - 1]: last } = |  | ||||||
|     navigation.dangerouslyGetState().history || |  | ||||||
|     navigation.dangerouslyGetParent()?.dangerouslyGetState().history |  | ||||||
|   return `Screen-${last.key.split(new RegExp(/Screen-(.*?)-/))[1]}` |  | ||||||
| } |  | ||||||
|  |  | ||||||
| export default getCurrentTab |  | ||||||
| @@ -1,61 +1,28 @@ | |||||||
| import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' | import { createAsyncThunk, createSlice, PayloadAction } from '@reduxjs/toolkit' | ||||||
|  |  | ||||||
| import { RootState } from '@root/store' | import { RootState } from '@root/store' | ||||||
| // import client from 'src/api/client' | import * as Analytics from 'expo-firebase-analytics' | ||||||
|  |  | ||||||
| export type SettingsState = { | export type SettingsState = { | ||||||
|   language: 'zh' | 'en' | undefined |   language: 'zh' | 'en' | undefined | ||||||
|   theme: 'light' | 'dark' | 'auto' |   theme: 'light' | 'dark' | 'auto' | ||||||
|   browser: 'internal' | 'external' |   browser: 'internal' | 'external' | ||||||
|  |   analytics: boolean | ||||||
| } | } | ||||||
|  |  | ||||||
| const initialState = { | const initialState = { | ||||||
|   language: undefined, |   language: undefined, | ||||||
|   theme: 'auto', |   theme: 'auto', | ||||||
|   browser: 'internal' |   browser: 'internal', | ||||||
|  |   analytics: false | ||||||
| } | } | ||||||
|  |  | ||||||
| // export const updateLocal = createAsyncThunk( | export const changeAnalytics = createAsyncThunk( | ||||||
| //   'instances/updateLocal', |   'settings/changeAnalytics', | ||||||
| //   async ({ |   async (newValue: SettingsState['analytics']) => { | ||||||
| //     url, |     await Analytics.setAnalyticsCollectionEnabled(newValue) | ||||||
| //     token |     return newValue | ||||||
| //   }: { |   } | ||||||
| //     url?: InstancesState['local']['url'] | ) | ||||||
| //     token?: InstancesState['local']['token'] |  | ||||||
| //   }) => { |  | ||||||
| //     if (!url || !token) { |  | ||||||
| //       return initialStateLocal |  | ||||||
| //     } |  | ||||||
|  |  | ||||||
| //     const { |  | ||||||
| //       body: { id } |  | ||||||
| //     } = await client({ |  | ||||||
| //       method: 'get', |  | ||||||
| //       instance: 'remote', |  | ||||||
| //       instanceUrl: url, |  | ||||||
| //       endpoint: `accounts/verify_credentials`, |  | ||||||
| //       headers: { Authorization: `Bearer ${token}` } |  | ||||||
| //     }) |  | ||||||
|  |  | ||||||
| //     const { body: preferences } = await client({ |  | ||||||
| //       method: 'get', |  | ||||||
| //       instance: 'remote', |  | ||||||
| //       instanceUrl: url, |  | ||||||
| //       endpoint: `preferences`, |  | ||||||
| //       headers: { Authorization: `Bearer ${token}` } |  | ||||||
| //     }) |  | ||||||
|  |  | ||||||
| //     return { |  | ||||||
| //       url, |  | ||||||
| //       token, |  | ||||||
| //       account: { |  | ||||||
| //         id, |  | ||||||
| //         preferences |  | ||||||
| //       } |  | ||||||
| //     } |  | ||||||
| //   } |  | ||||||
| // ) |  | ||||||
|  |  | ||||||
| const settingsSlice = createSlice({ | const settingsSlice = createSlice({ | ||||||
|   name: 'settings', |   name: 'settings', | ||||||
| @@ -79,17 +46,19 @@ const settingsSlice = createSlice({ | |||||||
|     ) => { |     ) => { | ||||||
|       state.browser = action.payload |       state.browser = action.payload | ||||||
|     } |     } | ||||||
|  |   }, | ||||||
|  |   extraReducers: builder => { | ||||||
|  |     builder.addCase(changeAnalytics.fulfilled, (state, action) => { | ||||||
|  |       state.analytics = action.payload | ||||||
|  |     }) | ||||||
|   } |   } | ||||||
|   // extraReducers: builder => { |  | ||||||
|   //   builder.addCase(updateLocal.fulfilled, (state, action) => { |  | ||||||
|   //     state.local = action.payload |  | ||||||
|   //   }) |  | ||||||
|   // } |  | ||||||
| }) | }) | ||||||
|  |  | ||||||
| export const getSettingsLanguage = (state: RootState) => state.settings.language | export const getSettingsLanguage = (state: RootState) => state.settings.language | ||||||
| export const getSettingsTheme = (state: RootState) => state.settings.theme | export const getSettingsTheme = (state: RootState) => state.settings.theme | ||||||
| export const getSettingsBrowser = (state: RootState) => state.settings.browser | export const getSettingsBrowser = (state: RootState) => state.settings.browser | ||||||
|  | export const getSettingsAnalytics = (state: RootState) => | ||||||
|  |   state.settings.analytics | ||||||
|  |  | ||||||
| export const { | export const { | ||||||
|   changeLanguage, |   changeLanguage, | ||||||
|   | |||||||
							
								
								
									
										30
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -2262,7 +2262,7 @@ | |||||||
|     invariant "^2.2.4" |     invariant "^2.2.4" | ||||||
|     lodash "^4.5.0" |     lodash "^4.5.0" | ||||||
|  |  | ||||||
| "@welldone-software/why-did-you-render@^6.0.3": | "@welldone-software/why-did-you-render@^6.0.4": | ||||||
|   version "6.0.4" |   version "6.0.4" | ||||||
|   resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-6.0.4.tgz#f8787a603b94fe0ef8aa824aecefd72b0a6c9e2a" |   resolved "https://registry.yarnpkg.com/@welldone-software/why-did-you-render/-/why-did-you-render-6.0.4.tgz#f8787a603b94fe0ef8aa824aecefd72b0a6c9e2a" | ||||||
|   integrity sha512-hOExlpwqPK/A0XRqgg42jSpbOb6AJBdgrI/X3BRj65ItQks0KS/nIT8HWPt8rR+BJb6OD5bm+vc1pcWSmxwd6A== |   integrity sha512-hOExlpwqPK/A0XRqgg42jSpbOb6AJBdgrI/X3BRj65ItQks0KS/nIT8HWPt8rR+BJb6OD5bm+vc1pcWSmxwd6A== | ||||||
| @@ -2609,7 +2609,7 @@ aws4@^1.8.0: | |||||||
|   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" |   resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.11.0.tgz#d61f46d83b2519250e2784daf5b09479a8b41c59" | ||||||
|   integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== |   integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== | ||||||
|  |  | ||||||
| axios@^0.21.0: | axios@^0.21.1: | ||||||
|   version "0.21.1" |   version "0.21.1" | ||||||
|   resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" |   resolved "https://registry.yarnpkg.com/axios/-/axios-0.21.1.tgz#22563481962f4d6bde9a76d516ef0e5d3c09b2b8" | ||||||
|   integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== |   integrity sha512-dKQiRHxGD9PPRIUNIWvZhPTPpl1rf/OxTYKsqKUDjBwYylTvV7SjSHJb9ratfyzM6wCdLCOYLzs73qpg5c4iGA== | ||||||
| @@ -8078,10 +8078,10 @@ react-dom@16.13.1: | |||||||
|     prop-types "^15.6.2" |     prop-types "^15.6.2" | ||||||
|     scheduler "^0.19.1" |     scheduler "^0.19.1" | ||||||
|  |  | ||||||
| react-i18next@^11.8.4: | react-i18next@^11.8.5: | ||||||
|   version "11.8.4" |   version "11.8.5" | ||||||
|   resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.4.tgz#5407d2edcaa704c38e4034e7ac06413914ed6e6d" |   resolved "https://registry.yarnpkg.com/react-i18next/-/react-i18next-11.8.5.tgz#a093335822e36252cda6efc0f55facef6253643f" | ||||||
|   integrity sha512-QlPJfX+Roi+jEQ6frBSsLHHH+VWbUoCl6wZDT8XHMd6PsSgepjgD2sZf/h7F46JnHeuy0U+SxY3TtrJF+aDIyg== |   integrity sha512-2jY/8NkhNv2KWBnZuhHxTn13aMxAbvhiDUNskm+1xVVnrPId78l8fA7fCyVeO3XU1kptM0t4MtvxV1Nu08cjLw== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@babel/runtime" "^7.3.1" |     "@babel/runtime" "^7.3.1" | ||||||
|     html-parse-stringify2 "2.0.1" |     html-parse-stringify2 "2.0.1" | ||||||
| @@ -8186,7 +8186,7 @@ react-native-tab-view@^2.15.2: | |||||||
|   resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.15.2.tgz#4bc7832d33a119306614efee667509672a7ee64e" |   resolved "https://registry.yarnpkg.com/react-native-tab-view/-/react-native-tab-view-2.15.2.tgz#4bc7832d33a119306614efee667509672a7ee64e" | ||||||
|   integrity sha512-2hxLkBnZtEKFDyfvNO5EUywhy3f/EiLOBO8SWqKj4BMBTO0QwnybaPE5MVF00Fhz+VA4+h/iI40Dkrrtq70dGg== |   integrity sha512-2hxLkBnZtEKFDyfvNO5EUywhy3f/EiLOBO8SWqKj4BMBTO0QwnybaPE5MVF00Fhz+VA4+h/iI40Dkrrtq70dGg== | ||||||
|  |  | ||||||
| react-native-toast-message@^1.3.4: | react-native-toast-message@^1.4.2: | ||||||
|   version "1.4.2" |   version "1.4.2" | ||||||
|   resolved "https://registry.yarnpkg.com/react-native-toast-message/-/react-native-toast-message-1.4.2.tgz#bda453dd7259587f2c5b3a1684ee5461569fe191" |   resolved "https://registry.yarnpkg.com/react-native-toast-message/-/react-native-toast-message-1.4.2.tgz#bda453dd7259587f2c5b3a1684ee5461569fe191" | ||||||
|   integrity sha512-Hp/APBQu/TCLlnMhwhqaosWiC/HgpVYXG2WGF2Zd2GF93nOcH516BUoDC0rvbncGx11IBUrUtt14RRm6LrcL6g== |   integrity sha512-Hp/APBQu/TCLlnMhwhqaosWiC/HgpVYXG2WGF2Zd2GF93nOcH516BUoDC0rvbncGx11IBUrUtt14RRm6LrcL6g== | ||||||
| @@ -8234,10 +8234,10 @@ react-navigation@*, react-navigation@^4.4.3: | |||||||
|     "@react-navigation/core" "^3.7.9" |     "@react-navigation/core" "^3.7.9" | ||||||
|     "@react-navigation/native" "^3.8.3" |     "@react-navigation/native" "^3.8.3" | ||||||
|  |  | ||||||
| react-query@^3.3.2: | react-query@^3.5.6: | ||||||
|   version "3.5.5" |   version "3.5.6" | ||||||
|   resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.5.5.tgz#50bae84066e1f61dc9a14ee7db8ea1a224535698" |   resolved "https://registry.yarnpkg.com/react-query/-/react-query-3.5.6.tgz#ea52404002e91e6ce39d49bf4ae96bf62554cd23" | ||||||
|   integrity sha512-WYZcHcAs5K5lPGT6CI8fz3lU62S8IfZhvB1K4aZH27wg9T6CWei+y7IRyZwti9X18LX134O4olgEuNth9LEX+w== |   integrity sha512-Fv184wu9FWg35PkgyZmEveveeRr+6+rqefVWf2vI3fhmWywjo2uBUA3GHwKMKCEI7Xb6T+6SyQt23pXhJQle0w== | ||||||
|   dependencies: |   dependencies: | ||||||
|     "@babel/runtime" "^7.5.5" |     "@babel/runtime" "^7.5.5" | ||||||
|     match-sorter "^6.0.2" |     match-sorter "^6.0.2" | ||||||
| @@ -9512,10 +9512,10 @@ typedarray@^0.0.6: | |||||||
|   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" |   resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" | ||||||
|   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= |   integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= | ||||||
|  |  | ||||||
| typescript@~4.0.0: | typescript@~4.1.3: | ||||||
|   version "4.0.5" |   version "4.1.3" | ||||||
|   resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.0.5.tgz#ae9dddfd1069f1cb5beb3ef3b2170dd7c1332389" |   resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.1.3.tgz#519d582bd94cba0cf8934c7d8e8467e473f53bb7" | ||||||
|   integrity sha512-ywmr/VrTVCmNTJ6iV2LwIrfG1P+lv6luD8sUJs+2eI9NLGigaN+nUQc13iHqisq7bra9lnmUSYqbJvegraBOPQ== |   integrity sha512-B3ZIOf1IKeH2ixgHhj6la6xdwR9QrLC5d1VKeCSY4tvkqhF2eqd9O7txNlS0PO3GrBAFIdr3L1ndNwteUbZLYg== | ||||||
|  |  | ||||||
| ua-parser-js@^0.7.18, ua-parser-js@^0.7.19: | ua-parser-js@^0.7.18, ua-parser-js@^0.7.19: | ||||||
|   version "0.7.23" |   version "0.7.23" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user