MainTabsNavigator.tsx 6.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160
  1. /* Copyright (C) Click & Push Accessibility, Inc - All Rights Reserved
  2. * Unauthorized copying of this file, via any medium is strictly prohibited
  3. * Proprietary and confidential
  4. * Written and maintained by the Click & Push Development team
  5. * <dev@clicknpush.ca>, January 2022
  6. */
  7. import { FontAwesome } from '@expo/vector-icons';
  8. import { BottomTabBarOptions, BottomTabNavigationProp, createBottomTabNavigator } from "@react-navigation/bottom-tabs";
  9. import { observer } from "mobx-react";
  10. import React, { useEffect } from "react";
  11. import { AppState, Platform, SafeAreaView, View, Text, Alert } from 'react-native';
  12. import OutdoorMap from "../components/Map/MainMapComponent/OutdoorMap";
  13. import Profile from "../components/Profile/Profile";
  14. import { colors, SECURESTORE_NOTIFTOKEN } from "../utils/GlobalUtils";
  15. import {check, checkMultiple, PERMISSIONS, requestMultiple} from 'react-native-permissions'
  16. import { Feed } from '../components/Feed/Feed';
  17. import { getItemAsync } from 'expo-secure-store';
  18. import Constants from 'expo-constants';
  19. import * as Notifications from 'expo-notifications'
  20. import { NavigationContainerRef, RouteProp } from '@react-navigation/native';
  21. import { QueryClient, useQuery } from 'react-query';
  22. import { useProfile } from '../hooks/useProfile';
  23. import { NotifType } from '../types';
  24. import Badge from '../components/Badge';
  25. import MapNavigator from './MapNavigator';
  26. import { useAuth } from '../lib/auth/AuthContext';
  27. Notifications.setNotificationHandler({
  28. handleNotification: async () => ({
  29. shouldShowAlert: true,
  30. shouldPlaySound: false,
  31. shouldSetBadge: false,
  32. }),
  33. });
  34. const MainTabs = createBottomTabNavigator();
  35. const tabBarOptions: BottomTabBarOptions = {
  36. //keyboardHidesTabBar: true,
  37. activeTintColor: 'white',
  38. activeBackgroundColor: '#e35555',
  39. inactiveTintColor: "lightgray",
  40. style: {backgroundColor: colors.red, height: 60, justifyContent: 'center'},
  41. labelStyle: {marginBottom: 7},
  42. iconStyle: {marginBottom: 7}
  43. }
  44. /**
  45. * Permitted screens for the Auth tabs navigator.
  46. * @category Navigation
  47. * @typedef
  48. */
  49. export type AuthTabsParamList = {
  50. Map: {selectedLandmark: string, selectedLandmarks: string[]},
  51. Profile: React.FC,
  52. }
  53. export type AuthTabsNavigationProp = BottomTabNavigationProp<AuthTabsParamList>
  54. export const navigationRef = React.createRef<NavigationContainerRef>()
  55. export const navigate = (name: string, params?) => {
  56. navigationRef.current.navigate(name, params)
  57. }
  58. /**
  59. * The root navigator for all authorized screens ({@link Map}, {@link Profile}). It uses a [React Navigation Bottom Tabs Navigator]{@link https://reactnavigation.org/docs/bottom-tab-navigator/} the main navigation mechanism.
  60. * @category Navigation
  61. * @component
  62. */
  63. const AuthorizedNavigator: React.FC = () => {
  64. const { userId } = useAuth()
  65. const { profile, toggleTipsAsync, notifications, markNotificationAsRead, refetchNotifications } = useProfile(userId)
  66. /**
  67. * If the user has their preferences configured to show tips, show them on page load. Recheck every time show_tips changes
  68. */
  69. useEffect(() => {
  70. const showTip = () => {
  71. if (profile?.show_tips) {
  72. console.log('[Profile]: User has tips configured, showing tips.')
  73. Alert.alert(
  74. 'Welcome!',
  75. "There are 3 ways to add a landmark to the map: \n\n - Press and hold where you'd like to add it on the map \n\n - Press the add button to add a landmark at your current location \n\n - Press the mic button and use voice commands.",
  76. [{text: "Don't show this again", onPress: async () => await toggleTipsAsync()}, {text: 'Ok'}]
  77. )
  78. }
  79. else {
  80. console.log('[Profile]: User does not have tips configured, not showing tips')
  81. }
  82. }
  83. showTip();
  84. }, [profile?.show_tips])
  85. const handleNotificationInteraction = async (notifData: any) => {
  86. await markNotificationAsRead(notifData.notif_id)
  87. await refetchNotifications()
  88. if (notifData?.notif_type as NotifType == 'landmark-like' || notifData?.notif_type as NotifType == 'near-landmark')
  89. navigate('Map', {selectedLandmark: notifData.landmark_id})
  90. if (notifData?.notif_type as NotifType == 'near-landmarks')
  91. navigate('Map', {selectedLandmarks: notifData.landmarks})
  92. }
  93. useEffect(() => {
  94. const notifReceivedSubscription = Notifications.addNotificationReceivedListener(async notification => {
  95. await refetchNotifications()
  96. })
  97. const notifResponseReceivedSubscription = Notifications.addNotificationResponseReceivedListener(async response => {
  98. const notifData = response.notification.request.content.data
  99. handleNotificationInteraction(notifData)
  100. });
  101. return () => {
  102. notifReceivedSubscription.remove()
  103. notifResponseReceivedSubscription.remove()
  104. };
  105. }, [])
  106. const getIconSize = (focused: boolean): number => {
  107. if (focused) {
  108. return 20
  109. }
  110. else {
  111. return 17
  112. }
  113. }
  114. const renderFeedBadge = () => {
  115. const newNotifAmount = notifications?.filter(notif => !notif.read).length
  116. return newNotifAmount > 0 ? <Badge positioning={{top: 8, left: 13,}} value={newNotifAmount}/> : null
  117. }
  118. return(
  119. <SafeAreaView style={{height: '100%'}}>
  120. {/* <AdMobBanner adUnitID="ca-app-pub-3940256099942544/6300978111" /> */}
  121. <MainTabs.Navigator
  122. sceneContainerStyle={{flex:1}}
  123. initialRouteName="Map"
  124. tabBarOptions={tabBarOptions}>
  125. <MainTabs.Screen name="Map" component={MapNavigator} options={{tabBarIcon: ({color, focused}) => (<FontAwesome name={focused ? 'map' : 'map-o'} size={getIconSize(focused)} color={color} style={{position: 'absolute', top: 10}}/>)}}/>
  126. <MainTabs.Screen name="Feed" options={{tabBarIcon: ({color, focused}) => (
  127. <View style={{position: 'absolute', top: 10}}>
  128. <FontAwesome name={focused ? 'bell' : 'bell-o'} size={getIconSize(focused)} color={color} />
  129. {renderFeedBadge()}
  130. </View>
  131. )}}>
  132. {() => <Feed notifications={notifications} handleNotifInteraction={handleNotificationInteraction} />}
  133. </MainTabs.Screen>
  134. <MainTabs.Screen name="Profile" component={Profile} options={{tabBarIcon: ({color, focused}) => (<FontAwesome name={focused ? 'user' : 'user-o'} size={getIconSize(focused)} color={color} style={{position: 'absolute', top: 10}}/>)}} />
  135. </MainTabs.Navigator>
  136. </SafeAreaView>
  137. )
  138. }
  139. export default observer(AuthorizedNavigator);