mirror of
				https://github.com/tooot-app/app
				synced 2025-06-05 22:19:13 +02:00 
			
		
		
		
	All timelines working
This commit is contained in:
		
							
								
								
									
										5
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										5
									
								
								package-lock.json
									
									
									
										generated
									
									
									
								
							| @@ -1687,6 +1687,11 @@ | ||||
|       "resolved": "https://registry.npmjs.org/@react-native-community/masked-view/-/masked-view-0.1.10.tgz", | ||||
|       "integrity": "sha512-rk4sWFsmtOw8oyx8SD3KSvawwaK7gRBSEIy2TAwURyGt+3TizssXP1r8nx3zY+R7v2vYYHXZ+k2/GULAT/bcaQ==" | ||||
|     }, | ||||
|     "@react-native-community/segmented-control": { | ||||
|       "version": "2.1.1", | ||||
|       "resolved": "https://registry.npmjs.org/@react-native-community/segmented-control/-/segmented-control-2.1.1.tgz", | ||||
|       "integrity": "sha512-vSrg+DIqX0zGeOb1o6oFLoWFFW8l1UEX/f7/9dXXzWHChF3rIqEpNHC4ONmsLJqWePN4E/n+k+q29z+GbqrqsQ==" | ||||
|     }, | ||||
|     "@react-navigation/bottom-tabs": { | ||||
|       "version": "5.9.2", | ||||
|       "resolved": "https://registry.npmjs.org/@react-navigation/bottom-tabs/-/bottom-tabs-5.9.2.tgz", | ||||
|   | ||||
| @@ -28,7 +28,9 @@ | ||||
|     "react-native-screens": "~2.10.1", | ||||
|     "react-native-web": "~0.13.7", | ||||
|     "react-native-webview": "10.7.0", | ||||
|     "react-redux": "^7.2.1" | ||||
|     "react-redux": "^7.2.1", | ||||
|     "@react-native-community/segmented-control": "2.1.1", | ||||
|     "@expo/vector-icons": "^10.0.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@babel/core": "~7.9.0", | ||||
|   | ||||
| @@ -9,7 +9,7 @@ import store from 'src/stacks/common/store' | ||||
| import { Provider } from 'react-redux' | ||||
| import { StatusBar } from 'expo-status-bar' | ||||
|  | ||||
| import Main from 'src/stacks/Main' | ||||
| import Local from 'src/stacks/Local' | ||||
| import Public from 'src/stacks/Public' | ||||
| import Notifications from 'src/stacks/Notifications' | ||||
| import Me from 'src/stacks/Me' | ||||
| @@ -22,7 +22,7 @@ export default function Index () { | ||||
|       <StatusBar style='auto' /> | ||||
|       <NavigationContainer> | ||||
|         <Tab.Navigator> | ||||
|           <Tab.Screen name='Main' component={Main} /> | ||||
|           <Tab.Screen name='Local' component={Local} /> | ||||
|           <Tab.Screen name='Public' component={Public} /> | ||||
|           {/* <Tab.Screen name='Notifications' component={Notifications} /> */} | ||||
|           <Tab.Screen name='Me' component={Me} /> | ||||
|   | ||||
							
								
								
									
										14
									
								
								src/stacks/Local.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/stacks/Local.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| import React from 'react' | ||||
|  | ||||
| import TimelinesCombined from 'src/stacks/common/TimelinesCombined' | ||||
|  | ||||
| export default function Local () { | ||||
|   return ( | ||||
|     <TimelinesCombined | ||||
|       route={[ | ||||
|         { title: '关注', timeline: { endpoint: 'home' } }, | ||||
|         { title: '本站', timeline: { endpoint: 'public', local: true } } | ||||
|       ]} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
| @@ -1,14 +0,0 @@ | ||||
| import React from 'react' | ||||
| import { createNativeStackNavigator } from 'react-native-screens/native-stack' | ||||
|  | ||||
| import Following from 'src/stacks/Main/Following' | ||||
|  | ||||
| const MainStack = createNativeStackNavigator() | ||||
|  | ||||
| export default function Main () { | ||||
|   return ( | ||||
|     <MainStack.Navigator> | ||||
|       <MainStack.Screen name='Following' component={Following} /> | ||||
|     </MainStack.Navigator> | ||||
|   ) | ||||
| } | ||||
| @@ -1,7 +0,0 @@ | ||||
| import React from 'react' | ||||
|  | ||||
| import Timeline from 'src/stacks/common/Timeline' | ||||
|  | ||||
| export default function Following () { | ||||
|   return <Timeline endpoint='home' /> | ||||
| } | ||||
| @@ -1,14 +1,14 @@ | ||||
| import React from 'react' | ||||
| import { createNativeStackNavigator } from 'react-native-screens/native-stack' | ||||
|  | ||||
| import CurrentPublic from 'src/stacks/Public/CurrentPublic' | ||||
| import TimelinesCombined from 'src/stacks/common/TimelinesCombined' | ||||
|  | ||||
| const PublicStack = createNativeStackNavigator() | ||||
|  | ||||
| export default function PublicTimeline () { | ||||
| export default function Public () { | ||||
|   return ( | ||||
|     <PublicStack.Navigator> | ||||
|       <PublicStack.Screen name='CurrentPublic' component={CurrentPublic} /> | ||||
|     </PublicStack.Navigator> | ||||
|     <TimelinesCombined | ||||
|       route={[ | ||||
|         { title: '跨站', timeline: { endpoint: 'public' } }, | ||||
|         { title: '他站', timeline: { remote: true } } | ||||
|       ]} | ||||
|     /> | ||||
|   ) | ||||
| } | ||||
|   | ||||
| @@ -1,7 +0,0 @@ | ||||
| import React from 'react' | ||||
|  | ||||
| import Timeline from 'src/stacks/common/Timeline' | ||||
|  | ||||
| export default function CurrentPublic () { | ||||
|   return <Timeline endpoint='public' local /> | ||||
| } | ||||
							
								
								
									
										7
									
								
								src/stacks/Public/LocalPublic.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/stacks/Public/LocalPublic.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| import React from 'react' | ||||
|  | ||||
| import Timeline from 'src/stacks/common/Timeline' | ||||
|  | ||||
| export default function LocalPublic () { | ||||
|   return <Timeline endpoint='public' /> | ||||
| } | ||||
| @@ -55,6 +55,6 @@ export default function Timeline ({ remote, endpoint, local }) { | ||||
|  | ||||
| Timeline.propTypes = { | ||||
|   remote: PropTypes.bool, | ||||
|   endpoint: PropTypes.string.isRequired, | ||||
|   endpoint: PropTypes.string, | ||||
|   local: PropTypes.bool | ||||
| } | ||||
|   | ||||
							
								
								
									
										81
									
								
								src/stacks/common/TimelinesCombined.jsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/stacks/common/TimelinesCombined.jsx
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| import React, { useEffect, useRef, useState } from 'react' | ||||
| import PropTypes from 'prop-types' | ||||
| import { Animated, Dimensions, View } from 'react-native' | ||||
| import { createNativeStackNavigator } from 'react-native-screens/native-stack' | ||||
| import SegmentedControl from '@react-native-community/segmented-control' | ||||
| import { Feather } from '@expo/vector-icons' | ||||
|  | ||||
| import Timeline from './Timeline' | ||||
|  | ||||
| const Stack = createNativeStackNavigator() | ||||
|  | ||||
| export default function TimelinesCombined ({ route }) { | ||||
|   const [segment, setSegment] = useState(0) | ||||
|   const [renderHeader, setRenderHeader] = useState(false) | ||||
|  | ||||
|   useEffect(() => { | ||||
|     const nbr = setTimeout(() => setRenderHeader(true), 50) | ||||
|     return | ||||
|   }, []) | ||||
|  | ||||
|   const moveAnimation = useRef(new Animated.Value(0)).current | ||||
|  | ||||
|   return ( | ||||
|     <Stack.Navigator | ||||
|       screenOptions={{ | ||||
|         statusBarAnimation: 'none', | ||||
|         headerRight: () => | ||||
|           renderHeader ? ( | ||||
|             <Feather name='search' size={24} color='black' /> | ||||
|           ) : null, | ||||
|         headerCenter: () => | ||||
|           renderHeader ? ( | ||||
|             <SegmentedControl | ||||
|               values={[route[0].title, route[1].title]} | ||||
|               selectedIndex={segment} | ||||
|               onChange={e => { | ||||
|                 setSegment(e.nativeEvent.selectedSegmentIndex) | ||||
|                 Animated.timing(moveAnimation, { | ||||
|                   toValue: | ||||
|                     -e.nativeEvent.selectedSegmentIndex * | ||||
|                     Dimensions.get('window').width, | ||||
|                   duration: 250, | ||||
|                   useNativeDriver: false | ||||
|                 }).start() | ||||
|               }} | ||||
|               style={{ width: 150, height: 30 }} | ||||
|             /> | ||||
|           ) : null | ||||
|       }} | ||||
|     > | ||||
|       <Stack.Screen name='LocalView'> | ||||
|         {props => ( | ||||
|           <Animated.View | ||||
|             style={{ | ||||
|               flexDirection: 'row', | ||||
|               width: Dimensions.get('window').width * 2, | ||||
|               left: moveAnimation | ||||
|             }} | ||||
|             {...props} | ||||
|           > | ||||
|             <View style={{ width: Dimensions.get('window').width }}> | ||||
|               <Timeline {...route[0].timeline} /> | ||||
|             </View> | ||||
|             <View style={{ width: Dimensions.get('window').width }}> | ||||
|               <Timeline {...route[1].timeline} /> | ||||
|             </View> | ||||
|           </Animated.View> | ||||
|         )} | ||||
|       </Stack.Screen> | ||||
|     </Stack.Navigator> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| TimelinesCombined.propTypes = { | ||||
|   route: PropTypes.arrayOf( | ||||
|     PropTypes.exact({ | ||||
|       title: PropTypes.string.isRequired, | ||||
|       timeline: PropTypes.exact(Timeline.propTypes).isRequired | ||||
|     }) | ||||
|   ).isRequired | ||||
| } | ||||
| @@ -8,7 +8,7 @@ const preloadedState = { | ||||
|   instanceInfo: { | ||||
|     current: 'social.xmflsct.com', | ||||
|     currentToken: 'qjzJ0IjvZ1apsn0_wBkGcdjKgX7Dao9KEPhGwggPwAo', | ||||
|     remote: 'm.cmx.im' | ||||
|     remote: 'mastodon.social' | ||||
|   } | ||||
| } | ||||
|  | ||||
| @@ -17,14 +17,7 @@ const reducer = { | ||||
|   timelines: timelineSlice | ||||
| } | ||||
|  | ||||
| // const middleware = getDefaultMiddleware => | ||||
| //   getDefaultMiddleware({ | ||||
| //     immutableCheck: false, | ||||
| //     serializableCheck: false | ||||
| //   }) | ||||
|  | ||||
| export default configureStore({ | ||||
|   preloadedState, | ||||
|   reducer, | ||||
|   // middleware | ||||
|   reducer | ||||
| }) | ||||
|   | ||||
| @@ -4,8 +4,8 @@ import { client } from 'src/api/client' | ||||
|  | ||||
| // Naming convention | ||||
| // Following:     home | ||||
| // Local:         home/local | ||||
| // CurrentPublic: public/local | ||||
| // Local:         public/local | ||||
| // CurrentPublic: public | ||||
| // RemotePublic:  remote | ||||
|  | ||||
| const checkInstance = ({ remote, endpoint, local }) => | ||||
| @@ -14,8 +14,6 @@ const checkInstance = ({ remote, endpoint, local }) => | ||||
| export const fetch = createAsyncThunk( | ||||
|   'timeline/fetch', | ||||
|   async ({ remote, endpoint, local, id, newer }, { getState }) => { | ||||
|     if (!endpoint) console.error('Missing endpoint') | ||||
|  | ||||
|     const instance = remote | ||||
|       ? `${getState().instanceInfo.remote}/api/v1/timelines/public` | ||||
|       : `${getState().instanceInfo.current}/api/v1/timelines/${endpoint}` | ||||
| @@ -37,6 +35,11 @@ export const fetch = createAsyncThunk( | ||||
|   } | ||||
| ) | ||||
|  | ||||
| export const getToots = state => instance => | ||||
|   state.timelines[checkInstance(instance)].toots | ||||
| export const getStatus = state => instance => | ||||
|   state.timelines[checkInstance(instance)].status | ||||
|  | ||||
| export const timelineSlice = createSlice({ | ||||
|   name: 'timeline', | ||||
|   initialState: { | ||||
| @@ -44,11 +47,11 @@ export const timelineSlice = createSlice({ | ||||
|       toots: [], | ||||
|       status: 'idle' | ||||
|     }, | ||||
|     'home/local': { | ||||
|     'public/local': { | ||||
|       toots: [], | ||||
|       status: 'idle' | ||||
|     }, | ||||
|     'public/local': { | ||||
|     public: { | ||||
|       toots: [], | ||||
|       status: 'idle' | ||||
|     }, | ||||
| @@ -74,9 +77,4 @@ export const timelineSlice = createSlice({ | ||||
|   } | ||||
| }) | ||||
|  | ||||
| export const getToots = state => instance => | ||||
|   state.timelines[checkInstance(instance)].toots | ||||
| export const getStatus = state => instance => | ||||
|   state.timelines[checkInstance(instance)].status | ||||
|  | ||||
| export default timelineSlice.reducer | ||||
|   | ||||
		Reference in New Issue
	
	Block a user