2020-12-29 16:19:04 +01:00
|
|
|
import client from '@api/client'
|
2021-01-04 10:50:24 +01:00
|
|
|
import haptics from '@components/haptics'
|
2021-01-03 02:00:26 +01:00
|
|
|
import Icon from '@components/Icon'
|
2021-01-04 10:50:24 +01:00
|
|
|
import { toast, toastConfig } from '@components/toast'
|
2021-01-07 22:18:14 +01:00
|
|
|
import {
|
|
|
|
BottomTabNavigationOptions,
|
|
|
|
createBottomTabNavigator
|
|
|
|
} from '@react-navigation/bottom-tabs'
|
2020-12-23 01:31:11 +01:00
|
|
|
import {
|
2021-01-14 00:43:35 +01:00
|
|
|
getFocusedRouteNameFromRoute,
|
2020-12-23 01:31:11 +01:00
|
|
|
NavigationContainer,
|
|
|
|
NavigationContainerRef
|
|
|
|
} from '@react-navigation/native'
|
2020-12-13 14:04:25 +01:00
|
|
|
import ScreenLocal from '@screens/Local'
|
|
|
|
import ScreenMe from '@screens/Me'
|
2021-01-04 10:50:24 +01:00
|
|
|
import ScreenNotifications from '@screens/Notifications'
|
|
|
|
import ScreenPublic from '@screens/Public'
|
2021-01-11 21:36:57 +01:00
|
|
|
import { useTimelineQuery } from '@utils/queryHooks/timeline'
|
2020-12-22 01:09:34 +01:00
|
|
|
import {
|
2021-01-23 02:41:50 +01:00
|
|
|
getLocalAccount,
|
2021-01-07 19:13:09 +01:00
|
|
|
getLocalActiveIndex,
|
2020-12-24 10:28:51 +01:00
|
|
|
getLocalNotification,
|
2021-01-07 19:13:09 +01:00
|
|
|
localUpdateAccountPreferences,
|
|
|
|
localUpdateNotification
|
2020-12-22 01:09:34 +01:00
|
|
|
} from '@utils/slices/instancesSlice'
|
2020-12-29 16:19:04 +01:00
|
|
|
import { useTheme } from '@utils/styles/ThemeManager'
|
|
|
|
import { themes } from '@utils/styles/themes'
|
|
|
|
import * as Analytics from 'expo-firebase-analytics'
|
2021-01-07 19:13:09 +01:00
|
|
|
import React, {
|
|
|
|
createRef,
|
|
|
|
useCallback,
|
|
|
|
useEffect,
|
|
|
|
useMemo,
|
|
|
|
useRef
|
|
|
|
} from 'react'
|
2021-01-24 02:25:43 +01:00
|
|
|
import { useTranslation } from 'react-i18next'
|
2021-01-23 02:41:50 +01:00
|
|
|
import { Image, Platform, StatusBar } from 'react-native'
|
2020-12-29 16:19:04 +01:00
|
|
|
import Toast from 'react-native-toast-message'
|
2021-01-04 10:50:24 +01:00
|
|
|
import { useDispatch, useSelector } from 'react-redux'
|
2020-11-23 00:07:32 +01:00
|
|
|
|
2021-01-07 22:18:14 +01:00
|
|
|
const Tab = createBottomTabNavigator<Nav.RootStackParamList>()
|
2020-10-23 09:22:17 +02:00
|
|
|
|
2020-12-22 00:50:47 +01:00
|
|
|
export interface Props {
|
2021-01-03 02:00:26 +01:00
|
|
|
localCorrupt?: string
|
2020-12-22 00:50:47 +01:00
|
|
|
}
|
|
|
|
|
2021-01-07 19:13:09 +01:00
|
|
|
export const navigationRef = createRef<NavigationContainerRef>()
|
|
|
|
|
2020-12-29 01:09:22 +01:00
|
|
|
const Index: React.FC<Props> = ({ localCorrupt }) => {
|
2020-12-22 01:09:34 +01:00
|
|
|
const dispatch = useDispatch()
|
2021-01-07 19:13:09 +01:00
|
|
|
const localActiveIndex = useSelector(getLocalActiveIndex)
|
2020-11-23 00:07:32 +01:00
|
|
|
const { mode, theme } = useTheme()
|
2020-11-29 18:08:31 +01:00
|
|
|
enum barStyle {
|
|
|
|
light = 'dark-content',
|
|
|
|
dark = 'light-content'
|
|
|
|
}
|
2020-11-23 00:07:32 +01:00
|
|
|
|
2020-12-29 16:19:04 +01:00
|
|
|
const routeNameRef = useRef<string | undefined>()
|
|
|
|
|
|
|
|
// const isConnected = useNetInfo().isConnected
|
|
|
|
// const [firstRender, setFirstRender] = useState(false)
|
|
|
|
// useEffect(() => {
|
|
|
|
// if (firstRender) {
|
|
|
|
// // bug in netInfo on first render as false
|
|
|
|
// if (isConnected !== false) {
|
|
|
|
// toast({ type: 'error', content: '手机🈚️网络', autoHide: false })
|
|
|
|
// }
|
|
|
|
// } else {
|
|
|
|
// setFirstRender(true)
|
|
|
|
// }
|
|
|
|
// }, [isConnected, firstRender])
|
2020-12-28 23:20:18 +01:00
|
|
|
|
2020-12-24 10:28:51 +01:00
|
|
|
// On launch display login credentials corrupt information
|
2021-01-24 02:25:43 +01:00
|
|
|
const { t } = useTranslation('common')
|
2020-12-22 00:50:47 +01:00
|
|
|
useEffect(() => {
|
|
|
|
const showLocalCorrect = localCorrupt
|
|
|
|
? toast({
|
|
|
|
type: 'error',
|
2021-01-24 02:25:43 +01:00
|
|
|
message: t('index.localCorrupt'),
|
2021-01-03 02:00:26 +01:00
|
|
|
description: localCorrupt.length ? localCorrupt : undefined,
|
2020-12-22 00:50:47 +01:00
|
|
|
autoHide: false
|
|
|
|
})
|
|
|
|
: undefined
|
|
|
|
return showLocalCorrect
|
|
|
|
}, [localCorrupt])
|
|
|
|
|
2020-12-24 10:28:51 +01:00
|
|
|
// On launch check if there is any unread announcements
|
2020-12-22 01:09:34 +01:00
|
|
|
useEffect(() => {
|
2020-12-29 16:19:04 +01:00
|
|
|
console.log('Checking announcements')
|
2021-01-07 19:13:09 +01:00
|
|
|
localActiveIndex !== null &&
|
|
|
|
client<Mastodon.Announcement[]>({
|
2020-12-24 10:28:51 +01:00
|
|
|
method: 'get',
|
|
|
|
instance: 'local',
|
|
|
|
url: `announcements`
|
|
|
|
})
|
2021-01-07 19:13:09 +01:00
|
|
|
.then(res => {
|
|
|
|
if (res?.filter(announcement => !announcement.read).length) {
|
2020-12-25 21:51:46 +01:00
|
|
|
navigationRef.current?.navigate('Screen-Shared-Announcements', {
|
|
|
|
showAll: false
|
|
|
|
})
|
2020-12-24 10:28:51 +01:00
|
|
|
}
|
|
|
|
})
|
2020-12-29 16:19:04 +01:00
|
|
|
.catch(() => {})
|
2020-12-22 01:09:34 +01:00
|
|
|
}, [])
|
|
|
|
|
2020-12-24 10:28:51 +01:00
|
|
|
// On launch check if there is any unread noficiations
|
2021-01-11 21:36:57 +01:00
|
|
|
const queryNotification = useTimelineQuery({
|
2021-01-07 19:13:09 +01:00
|
|
|
page: 'Notifications',
|
|
|
|
options: {
|
|
|
|
enabled: localActiveIndex !== null ? true : false,
|
2021-01-04 14:55:34 +01:00
|
|
|
refetchInterval: 1000 * 60,
|
|
|
|
refetchIntervalInBackground: true
|
|
|
|
}
|
2021-01-07 19:13:09 +01:00
|
|
|
})
|
2020-12-24 10:28:51 +01:00
|
|
|
const prevNotification = useSelector(getLocalNotification)
|
2020-12-23 01:31:11 +01:00
|
|
|
useEffect(() => {
|
2020-12-24 10:28:51 +01:00
|
|
|
if (queryNotification.data?.pages) {
|
2021-01-11 21:36:57 +01:00
|
|
|
const flattenData = queryNotification.data.pages.flatMap(d => [...d])
|
2020-12-24 10:28:51 +01:00
|
|
|
const latestNotificationTime = flattenData.length
|
2021-01-07 22:18:14 +01:00
|
|
|
? (flattenData[0] as Mastodon.Notification).created_at
|
2020-12-24 10:28:51 +01:00
|
|
|
: undefined
|
|
|
|
|
|
|
|
if (!prevNotification || !prevNotification.latestTime) {
|
|
|
|
dispatch(
|
2021-01-07 19:13:09 +01:00
|
|
|
localUpdateNotification({
|
2021-01-23 02:41:50 +01:00
|
|
|
unread: false
|
2020-12-24 10:28:51 +01:00
|
|
|
})
|
|
|
|
)
|
|
|
|
} else if (
|
|
|
|
latestNotificationTime &&
|
|
|
|
new Date(prevNotification.latestTime) < new Date(latestNotificationTime)
|
|
|
|
) {
|
|
|
|
dispatch(
|
2021-01-07 19:13:09 +01:00
|
|
|
localUpdateNotification({
|
2020-12-24 10:28:51 +01:00
|
|
|
unread: true,
|
|
|
|
latestTime: latestNotificationTime
|
|
|
|
})
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}, [queryNotification.data?.pages])
|
|
|
|
|
|
|
|
// Lazily update users's preferences, for e.g. composing default visibility
|
|
|
|
useEffect(() => {
|
2021-01-07 19:13:09 +01:00
|
|
|
if (localActiveIndex !== null) {
|
|
|
|
dispatch(localUpdateAccountPreferences())
|
2020-12-24 10:28:51 +01:00
|
|
|
}
|
2020-12-23 01:31:11 +01:00
|
|
|
}, [])
|
|
|
|
|
2020-12-29 16:19:04 +01:00
|
|
|
// 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
|
|
|
|
}, [])
|
2021-01-23 02:41:50 +01:00
|
|
|
const localAccount = useSelector(getLocalAccount)
|
2020-12-29 16:19:04 +01:00
|
|
|
const tabNavigatorScreenOptions = useCallback(
|
2021-01-07 22:18:14 +01:00
|
|
|
({ route }): BottomTabNavigationOptions => ({
|
2020-12-29 16:19:04 +01:00
|
|
|
tabBarIcon: ({
|
|
|
|
focused,
|
|
|
|
color,
|
|
|
|
size
|
|
|
|
}: {
|
|
|
|
focused: boolean
|
|
|
|
color: string
|
|
|
|
size: number
|
|
|
|
}) => {
|
|
|
|
switch (route.name) {
|
|
|
|
case 'Screen-Local':
|
2021-01-23 02:41:50 +01:00
|
|
|
return <Icon name='Home' size={size} color={color} />
|
2020-12-29 16:19:04 +01:00
|
|
|
case 'Screen-Public':
|
2021-01-26 12:17:25 +01:00
|
|
|
return <Icon name='Globe' size={size} color={color} />
|
2020-12-29 16:19:04 +01:00
|
|
|
case 'Screen-Post':
|
2021-01-23 02:41:50 +01:00
|
|
|
return <Icon name='Plus' size={size} color={color} />
|
2020-12-29 16:19:04 +01:00
|
|
|
case 'Screen-Notifications':
|
2021-01-23 02:41:50 +01:00
|
|
|
return <Icon name='Bell' size={size} color={color} />
|
2020-12-29 16:19:04 +01:00
|
|
|
case 'Screen-Me':
|
2021-01-23 02:41:50 +01:00
|
|
|
return localActiveIndex !== null ? (
|
|
|
|
<Image
|
|
|
|
source={{ uri: localAccount?.avatarStatic }}
|
|
|
|
style={{
|
2021-01-24 02:25:43 +01:00
|
|
|
width: size,
|
|
|
|
height: size,
|
2021-01-23 02:41:50 +01:00
|
|
|
borderRadius: size,
|
|
|
|
borderWidth: focused ? 2 : 0,
|
|
|
|
borderColor: focused ? theme.secondary : color
|
|
|
|
}}
|
|
|
|
/>
|
|
|
|
) : (
|
|
|
|
<Icon
|
|
|
|
name={focused ? 'Meh' : 'Smile'}
|
|
|
|
size={size}
|
|
|
|
color={!focused ? theme.secondary : color}
|
|
|
|
/>
|
|
|
|
)
|
2020-12-29 16:19:04 +01:00
|
|
|
default:
|
2021-01-23 02:41:50 +01:00
|
|
|
return <Icon name='AlertOctagon' size={size} color={color} />
|
2020-12-29 16:19:04 +01:00
|
|
|
}
|
2021-01-14 00:43:35 +01:00
|
|
|
},
|
|
|
|
...(Platform.OS === 'android' && {
|
|
|
|
tabBarVisible:
|
|
|
|
getFocusedRouteNameFromRoute(route) !== 'Screen-Shared-Compose' &&
|
|
|
|
getFocusedRouteNameFromRoute(route) !==
|
|
|
|
'Screen-Shared-Announcements' &&
|
|
|
|
getFocusedRouteNameFromRoute(route) !==
|
|
|
|
'Screen-Shared-ImagesViewer' &&
|
|
|
|
getFocusedRouteNameFromRoute(route) !== 'Screen-Me-Switch'
|
|
|
|
})
|
2020-12-29 16:19:04 +01:00
|
|
|
}),
|
2021-01-23 02:41:50 +01:00
|
|
|
[localActiveIndex, localAccount]
|
2020-12-29 16:19:04 +01:00
|
|
|
)
|
|
|
|
const tabNavigatorTabBarOptions = useMemo(
|
|
|
|
() => ({
|
|
|
|
activeTintColor: theme.primary,
|
2021-01-07 19:13:09 +01:00
|
|
|
inactiveTintColor:
|
|
|
|
localActiveIndex !== null ? theme.secondary : theme.disabled,
|
2021-01-14 00:43:35 +01:00
|
|
|
showLabel: false,
|
|
|
|
...(Platform.OS === 'android' && { keyboardHidesTabBar: true })
|
2020-12-29 16:19:04 +01:00
|
|
|
}),
|
2021-01-07 19:13:09 +01:00
|
|
|
[theme, localActiveIndex]
|
2020-12-29 16:19:04 +01:00
|
|
|
)
|
|
|
|
const tabScreenLocalListeners = useCallback(
|
|
|
|
() => ({
|
|
|
|
tabPress: (e: any) => {
|
2021-01-07 19:13:09 +01:00
|
|
|
if (!(localActiveIndex !== null)) {
|
2020-12-29 16:19:04 +01:00
|
|
|
e.preventDefault()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}),
|
2021-01-07 19:13:09 +01:00
|
|
|
[localActiveIndex]
|
2020-12-29 16:19:04 +01:00
|
|
|
)
|
2021-01-04 10:50:24 +01:00
|
|
|
const tabScreenComposeListeners = useMemo(
|
|
|
|
() => ({
|
2020-12-29 16:19:04 +01:00
|
|
|
tabPress: (e: any) => {
|
|
|
|
e.preventDefault()
|
2021-01-07 19:13:09 +01:00
|
|
|
if (localActiveIndex !== null) {
|
2021-01-04 10:50:24 +01:00
|
|
|
haptics('Medium')
|
|
|
|
navigationRef.current?.navigate('Screen-Shared-Compose')
|
2020-12-29 16:19:04 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}),
|
2021-01-07 19:13:09 +01:00
|
|
|
[localActiveIndex]
|
2020-12-29 16:19:04 +01:00
|
|
|
)
|
|
|
|
const tabScreenComposeComponent = useCallback(() => null, [])
|
|
|
|
const tabScreenNotificationsListeners = useCallback(
|
|
|
|
() => ({
|
|
|
|
tabPress: (e: any) => {
|
2021-01-07 19:13:09 +01:00
|
|
|
if (!(localActiveIndex !== null)) {
|
2020-12-29 16:19:04 +01:00
|
|
|
e.preventDefault()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}),
|
2021-01-07 19:13:09 +01:00
|
|
|
[localActiveIndex]
|
2020-12-29 16:19:04 +01:00
|
|
|
)
|
2020-10-23 09:22:17 +02:00
|
|
|
return (
|
2020-11-29 18:08:31 +01:00
|
|
|
<>
|
2021-01-13 01:03:46 +01:00
|
|
|
<StatusBar barStyle={barStyle[mode]} backgroundColor={theme.background} />
|
2020-12-23 01:31:11 +01:00
|
|
|
<NavigationContainer
|
|
|
|
ref={navigationRef}
|
|
|
|
theme={themes[mode]}
|
2020-12-29 16:19:04 +01:00
|
|
|
onReady={navigationContainerOnReady}
|
|
|
|
onStateChange={navigationContainerOnStateChange}
|
2020-12-23 01:31:11 +01:00
|
|
|
>
|
2020-11-29 18:08:31 +01:00
|
|
|
<Tab.Navigator
|
2021-01-07 19:13:09 +01:00
|
|
|
initialRouteName={
|
2021-01-26 12:17:25 +01:00
|
|
|
localActiveIndex !== null ? 'Screen-Local' : 'Screen-Me'
|
2021-01-07 19:13:09 +01:00
|
|
|
}
|
2020-12-29 16:19:04 +01:00
|
|
|
screenOptions={tabNavigatorScreenOptions}
|
|
|
|
tabBarOptions={tabNavigatorTabBarOptions}
|
2020-11-22 00:46:23 +01:00
|
|
|
>
|
2020-12-13 21:09:21 +01:00
|
|
|
<Tab.Screen
|
|
|
|
name='Screen-Local'
|
|
|
|
component={ScreenLocal}
|
2020-12-29 16:19:04 +01:00
|
|
|
listeners={tabScreenLocalListeners}
|
2020-12-13 21:09:21 +01:00
|
|
|
/>
|
2020-11-29 18:08:31 +01:00
|
|
|
<Tab.Screen name='Screen-Public' component={ScreenPublic} />
|
|
|
|
<Tab.Screen
|
|
|
|
name='Screen-Post'
|
2020-12-29 16:19:04 +01:00
|
|
|
component={tabScreenComposeComponent}
|
|
|
|
listeners={tabScreenComposeListeners}
|
|
|
|
/>
|
2020-11-29 18:08:31 +01:00
|
|
|
<Tab.Screen
|
|
|
|
name='Screen-Notifications'
|
|
|
|
component={ScreenNotifications}
|
2020-12-29 16:19:04 +01:00
|
|
|
listeners={tabScreenNotificationsListeners}
|
2021-01-12 00:12:44 +01:00
|
|
|
options={
|
|
|
|
prevNotification && prevNotification.unread
|
|
|
|
? {
|
|
|
|
tabBarBadge: '',
|
|
|
|
tabBarBadgeStyle: {
|
|
|
|
transform: [{ scale: 0.5 }],
|
|
|
|
backgroundColor: theme.red
|
|
|
|
}
|
|
|
|
}
|
|
|
|
: {
|
|
|
|
tabBarBadgeStyle: {
|
|
|
|
transform: [{ scale: 0.5 }],
|
|
|
|
backgroundColor: theme.red
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-11-29 18:08:31 +01:00
|
|
|
/>
|
|
|
|
<Tab.Screen name='Screen-Me' component={ScreenMe} />
|
|
|
|
</Tab.Navigator>
|
2020-11-06 00:59:33 +01:00
|
|
|
|
2021-01-14 00:43:35 +01:00
|
|
|
{Platform.OS === 'ios' ? (
|
|
|
|
<Toast ref={Toast.setRef} config={toastConfig} />
|
|
|
|
) : null}
|
2020-11-29 18:08:31 +01:00
|
|
|
</NavigationContainer>
|
|
|
|
</>
|
2020-10-23 09:22:17 +02:00
|
|
|
)
|
|
|
|
}
|
2020-12-29 01:09:22 +01:00
|
|
|
|
|
|
|
export default React.memo(Index, () => true)
|