Notifications working

This commit is contained in:
Zhiyuan Zheng 2020-10-24 18:07:09 +02:00
parent c8b40017d8
commit 8f6c5af0fd
No known key found for this signature in database
GPG Key ID: 078A93AB607D85E0
9 changed files with 150 additions and 38 deletions

View File

@ -5,6 +5,7 @@ import { enableScreens } from 'react-native-screens'
enableScreens()
import React from 'react'
import { Feather } from '@expo/vector-icons'
import store from 'src/stacks/common/store'
import { Provider } from 'react-redux'
import { StatusBar } from 'expo-status-bar'
@ -21,10 +22,39 @@ export default function Index () {
<Provider store={store}>
<StatusBar style='auto' />
<NavigationContainer>
<Tab.Navigator>
<Tab.Navigator
screenOptions={({ route }) => ({
tabBarIcon: ({ focused, color, size }) => {
let name
switch (route.name) {
case 'Local':
name = 'home'
break
case 'Public':
name = 'globe'
break
case 'Post':
name = 'plus'
break
case 'Notifications':
name = 'bell'
break
case 'Me':
name = focused ? 'smile' : 'meh'
break
}
return <Feather name={name} size={size} color={color} />
}
})}
tabBarOptions={{
activeTintColor: 'black',
inactiveTintColor: 'gray',
showLabel: false
}}
>
<Tab.Screen name='Local' component={Local} />
<Tab.Screen name='Public' component={Public} />
{/* <Tab.Screen name='Notifications' component={Notifications} /> */}
<Tab.Screen name='Notifications' component={Notifications} />
<Tab.Screen name='Me' component={Me} />
</Tab.Navigator>
</NavigationContainer>

View File

@ -5,7 +5,7 @@ import HTML from 'react-native-render-html'
import relativeTime from 'src/utils/relativeTime'
export default function TootTimeline ({ item }) {
export default function TootTimeline ({ item, notification }) {
return (
<View style={styles.tootTimeline}>
<View style={styles.header}>
@ -36,7 +36,13 @@ export default function TootTimeline ({ item }) {
</View>
</View>
</View>
{item.content ? <HTML html={item.content} /> : <></>}
{notification ? (
<HTML html={item.status.content} />
) : item.content ? (
<HTML html={item.content} />
) : (
<></>
)}
</View>
)
}
@ -54,7 +60,8 @@ TootTimeline.propTypes = {
website: PropTypes.string
}),
content: PropTypes.string
}).isRequired
}).isRequired,
notification: PropTypes.bool
}
const styles = StyleSheet.create({

View File

@ -5,6 +5,7 @@ import TimelinesCombined from 'src/stacks/common/TimelinesCombined'
export default function Local () {
return (
<TimelinesCombined
page='Local'
route={[
{ title: '关注', timeline: { endpoint: 'home' } },
{ title: '本站', timeline: { endpoint: 'public', local: true } }

View File

@ -1,9 +1,33 @@
import React, { useEffect } from 'react'
import { ActivityIndicator, FlatList, View } from 'react-native'
import { useSelector, useDispatch } from 'react-redux'
import React, { useEffect, useState } from 'react'
import { createNativeStackNavigator } from 'react-native-screens/native-stack'
import { Feather } from '@expo/vector-icons'
import TootTimeline from 'src/components/TootTimeline'
import Timeline from 'src/stacks/common/Timeline'
const Stack = createNativeStackNavigator()
export default function Notifications () {
return <View></View>
const [renderHeader, setRenderHeader] = useState(false)
useEffect(() => {
const nbr = setTimeout(() => setRenderHeader(true), 50)
return
}, [])
return (
<Stack.Navigator
screenOptions={{
statusBarAnimation: 'none',
headerRight: () =>
renderHeader ? (
<Feather name='search' size={24} color='black' />
) : null,
headerTitle: '通知'
}}
>
<Stack.Screen name='Notifications'>
{props => <Timeline endpoint='notifications' {...props} />}
</Stack.Screen>
</Stack.Navigator>
)
}

View File

@ -5,6 +5,7 @@ import TimelinesCombined from 'src/stacks/common/TimelinesCombined'
export default function Public () {
return (
<TimelinesCombined
page='Public'
route={[
{ title: '跨站', timeline: { endpoint: 'public' } },
{ title: '他站', timeline: { remote: true } }

View File

@ -1,11 +1,61 @@
import PropTypes from 'prop-types'
import React, { useEffect } from 'react'
import { ActivityIndicator, FlatList, View } from 'react-native'
import { connect, useSelector, useDispatch } from 'react-redux'
import { useSelector, useDispatch } from 'react-redux'
import TootTimeline from 'src/components/TootTimeline'
import { fetch, getToots, getStatus } from './timelineSlice'
const Default = ({ toots, status, remote, endpoint, local }) => {
return (
<>
<FlatList
data={toots}
keyExtractor={({ id }) => id}
renderItem={TootTimeline}
onRefresh={() =>
dispatch(
fetch({ remote, endpoint, local, id: toots[0].id, newer: true })
)
}
refreshing={status === 'loading'}
onEndReached={() =>
dispatch(
fetch({ remote, endpoint, local, id: toots[toots.length - 1].id })
)
}
onEndReachedThreshold={0.5}
style={{ height: '100%', width: '100%' }}
/>
{status === 'loading' && <ActivityIndicator />}
</>
)
}
const Notifications = ({ toots, status, endpoint }) => {
return (
<>
<FlatList
data={toots}
keyExtractor={({ status: { id } }) => id}
renderItem={({ item }) => (
<TootTimeline item={item} notification={true} />
)}
// onRefresh={() =>
// dispatch(fetch({ endpoint, id: toots[0].status.id, newer: true }))
// }
// refreshing={status === 'loading'}
// onEndReached={() =>
// dispatch(fetch({ endpoint, id: toots[toots.length - 1].status.id }))
// }
onEndReachedThreshold={0.5}
style={{ height: '100%', width: '100%' }}
/>
{status === 'loading' && <ActivityIndicator />}
</>
)
}
export default function Timeline ({ remote, endpoint, local }) {
const dispatch = useDispatch()
const toots = useSelector(state =>
@ -20,34 +70,26 @@ export default function Timeline ({ remote, endpoint, local }) {
dispatch(fetch({ remote, endpoint, local }))
}
}, [status, dispatch])
let content
let content
if (status === 'error') {
content = <Text>Error message</Text>
} else {
content = (
<>
<FlatList
data={toots}
keyExtractor={({ id }) => id}
renderItem={TootTimeline}
onRefresh={() =>
dispatch(
fetch({ remote, endpoint, local, id: toots[0].id, newer: true })
)
}
refreshing={status === 'loading'}
onEndReached={() =>
dispatch(
fetch({ remote, endpoint, local, id: toots[toots.length - 1].id })
)
}
onEndReachedThreshold={0.5}
style={{ height: '100%', width: '100%' }}
if (endpoint === 'notifications') {
content = (
<Notifications toots={toots} status={status} endpoint={endpoint} />
)
} else {
content = (
<Default
toots={toots}
status={status}
remote={remote}
endpoint={endpoint}
local={local}
/>
{status === 'loading' && <ActivityIndicator />}
</>
)
)
}
}
return <View>{content}</View>

View File

@ -9,7 +9,7 @@ import Timeline from './Timeline'
const Stack = createNativeStackNavigator()
export default function TimelinesCombined ({ route }) {
export default function TimelinesCombined ({ page, route }) {
const [segment, setSegment] = useState(0)
const [renderHeader, setRenderHeader] = useState(false)
@ -48,7 +48,7 @@ export default function TimelinesCombined ({ route }) {
) : null
}}
>
<Stack.Screen name='LocalView'>
<Stack.Screen name={page}>
{props => (
<Animated.View
style={{

View File

@ -6,8 +6,8 @@ import timelineSlice from 'src/stacks/common/timelineSlice'
// get site information from local storage and pass to reducers
const preloadedState = {
instanceInfo: {
current: 'social.xmflsct.com',
currentToken: 'qjzJ0IjvZ1apsn0_wBkGcdjKgX7Dao9KEPhGwggPwAo',
current: 'm.cmx.im',
currentToken: 'Cxx19XX2VNHnPy_dr_HCHMh4HvwHEvYwWrrU3r3BNzQ',
remote: 'mastodon.social'
}
}

View File

@ -7,6 +7,7 @@ import { client } from 'src/api/client'
// Local: public/local
// CurrentPublic: public
// RemotePublic: remote
// Notifications: notifications
const checkInstance = ({ remote, endpoint, local }) =>
remote ? 'remote' : `${endpoint}${local ? '/local' : ''}`
@ -16,6 +17,8 @@ export const fetch = createAsyncThunk(
async ({ remote, endpoint, local, id, newer }, { getState }) => {
const instance = remote
? `${getState().instanceInfo.remote}/api/v1/timelines/public`
: endpoint === 'notifications'
? `${getState().instanceInfo.current}/api/v1/${endpoint}`
: `${getState().instanceInfo.current}/api/v1/timelines/${endpoint}`
const query = {
@ -58,6 +61,10 @@ export const timelineSlice = createSlice({
remote: {
toots: [],
status: 'idle'
},
notifications: {
toots: [],
status: 'idle'
}
},
extraReducers: {