import client from '@api/client' import haptics from '@components/haptics' import Icon from '@components/Icon' import { toast, toastConfig } from '@components/toast' import { BottomTabNavigationOptions, createBottomTabNavigator } from '@react-navigation/bottom-tabs' import { getFocusedRouteNameFromRoute, NavigationContainer, NavigationContainerRef } from '@react-navigation/native' import ScreenLocal from '@screens/Local' import ScreenMe from '@screens/Me' import ScreenNotifications from '@screens/Notifications' import ScreenPublic from '@screens/Public' import { useTimelineQuery } from '@utils/queryHooks/timeline' import { getLocalAccount, getLocalActiveIndex, getLocalNotification, localUpdateAccountPreferences, localUpdateNotification } from '@utils/slices/instancesSlice' import { useTheme } from '@utils/styles/ThemeManager' import { themes } from '@utils/styles/themes' import * as Analytics from 'expo-firebase-analytics' import React, { createRef, useCallback, useEffect, useMemo, useRef } from 'react' import { useTranslation } from 'react-i18next' import { Image, Platform, StatusBar } from 'react-native' import Toast from 'react-native-toast-message' import { useDispatch, useSelector } from 'react-redux' const Tab = createBottomTabNavigator() export interface Props { localCorrupt?: string } export const navigationRef = createRef() const Index: React.FC = ({ localCorrupt }) => { const dispatch = useDispatch() const localActiveIndex = useSelector(getLocalActiveIndex) const { mode, theme } = useTheme() enum barStyle { light = 'dark-content', dark = 'light-content' } const routeNameRef = useRef() // 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]) // On launch display login credentials corrupt information const { t } = useTranslation('common') useEffect(() => { const showLocalCorrect = localCorrupt ? toast({ type: 'error', message: t('index.localCorrupt'), description: localCorrupt.length ? localCorrupt : undefined, autoHide: false }) : undefined return showLocalCorrect }, [localCorrupt]) // On launch check if there is any unread announcements useEffect(() => { console.log('Checking announcements') localActiveIndex !== null && client({ method: 'get', instance: 'local', url: `announcements` }) .then(res => { if (res?.filter(announcement => !announcement.read).length) { navigationRef.current?.navigate('Screen-Shared-Announcements', { showAll: false }) } }) .catch(() => {}) }, []) // On launch check if there is any unread noficiations const queryNotification = useTimelineQuery({ page: 'Notifications', options: { enabled: localActiveIndex !== null ? true : false, refetchInterval: 1000 * 60, refetchIntervalInBackground: true } }) const prevNotification = useSelector(getLocalNotification) useEffect(() => { if (queryNotification.data?.pages) { const flattenData = queryNotification.data.pages.flatMap(d => [...d]) const latestNotificationTime = flattenData.length ? (flattenData[0] as Mastodon.Notification).created_at : undefined if (!prevNotification || !prevNotification.latestTime) { dispatch( localUpdateNotification({ unread: false }) ) } else if ( latestNotificationTime && new Date(prevNotification.latestTime) < new Date(latestNotificationTime) ) { dispatch( localUpdateNotification({ unread: true, latestTime: latestNotificationTime }) ) } } }, [queryNotification.data?.pages]) // Lazily update users's preferences, for e.g. composing default visibility useEffect(() => { if (localActiveIndex !== null) { dispatch(localUpdateAccountPreferences()) } }, []) // 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 localAccount = useSelector(getLocalAccount) const tabNavigatorScreenOptions = useCallback( ({ route }): BottomTabNavigationOptions => ({ tabBarIcon: ({ focused, color, size }: { focused: boolean color: string size: number }) => { switch (route.name) { case 'Screen-Local': return case 'Screen-Public': return case 'Screen-Post': return case 'Screen-Notifications': return case 'Screen-Me': return localActiveIndex !== null ? ( ) : ( ) default: return } }, ...(Platform.OS === 'android' && { tabBarVisible: getFocusedRouteNameFromRoute(route) !== 'Screen-Shared-Compose' && getFocusedRouteNameFromRoute(route) !== 'Screen-Shared-Announcements' && getFocusedRouteNameFromRoute(route) !== 'Screen-Shared-ImagesViewer' && getFocusedRouteNameFromRoute(route) !== 'Screen-Me-Switch' }) }), [localActiveIndex, localAccount] ) const tabNavigatorTabBarOptions = useMemo( () => ({ activeTintColor: theme.primary, inactiveTintColor: localActiveIndex !== null ? theme.secondary : theme.disabled, showLabel: false, ...(Platform.OS === 'android' && { keyboardHidesTabBar: true }) }), [theme, localActiveIndex] ) const tabScreenLocalListeners = useCallback( () => ({ tabPress: (e: any) => { if (!(localActiveIndex !== null)) { e.preventDefault() } } }), [localActiveIndex] ) const tabScreenComposeListeners = useMemo( () => ({ tabPress: (e: any) => { e.preventDefault() if (localActiveIndex !== null) { haptics('Medium') navigationRef.current?.navigate('Screen-Shared-Compose') } } }), [localActiveIndex] ) const tabScreenComposeComponent = useCallback(() => null, []) const tabScreenNotificationsListeners = useCallback( () => ({ tabPress: (e: any) => { if (!(localActiveIndex !== null)) { e.preventDefault() } } }), [localActiveIndex] ) return ( <> {Platform.OS === 'ios' ? ( ) : null} ) } export default React.memo(Index, () => true)