Skip to content

Commit

Permalink
feat: adds dynamic tabs (#2348)
Browse files Browse the repository at this point in the history
* feat: adds dynamic tabs

* moved bottom tabs

* fix

* update podfile

* apollosconfig tabs

* fixed

* removed tabs from template

* dont need to prop spread here

* include android search fix

* podfile

Co-authored-by: Vincent Wilson <vince@classyh.at>
  • Loading branch information
redreceipt and vinnyjth committed May 5, 2022
1 parent 2ad3fcb commit 4671c1a
Show file tree
Hide file tree
Showing 10 changed files with 240 additions and 92 deletions.
4 changes: 2 additions & 2 deletions package.json
Expand Up @@ -19,8 +19,8 @@
"nuke:cache": "watchman watch-del-all",
"postinstall": "lerna run build --parallel",
"generate-stories": "lerna run generate-stories",
"storybook": "yarn && yarn generate-stories && (cd ApollosStorybook && yarn && yarn prestart && yarn ios)",
"app": "yarn && (cd templates/mobile && yarn && yarn prestart && yarn ios)"
"app": "yarn && (cd templates/mobile && yarn && yarn prestart && yarn ios)",
"storybook": "yarn && yarn generate-stories && (cd ApollosStorybook && yarn && yarn prestart && yarn ios)"
},
"resolutions": {
"babel-core": "7.0.0-bridge.0"
Expand Down
1 change: 1 addition & 0 deletions packages/apollos-ui-connected/package.json
Expand Up @@ -65,6 +65,7 @@
},
"dependencies": {
"@gorhom/bottom-sheet": "3.4.1",
"@react-navigation/bottom-tabs": "^5.11.8",
"apollo-upload-client": "^17.0.0",
"graphql": "^16.3.0",
"graphql-tag": "2.9.2",
Expand Down
@@ -1,23 +1,19 @@
import { useEffect } from 'react';
import React, { useEffect, useMemo } from 'react';
import PropTypes from 'prop-types';
import { Image, View } from 'react-native';
import { View } from 'react-native';
import { useNavigation } from '@react-navigation/native';
import { createNativeStackNavigator } from 'react-native-screens/native-stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
import ApollosConfig from '@apollosproject/config';
import {
NavigationService,
withTheme,
useTheme,
Icon,
Touchable,
} from '@apollosproject/ui-kit';
import { useApolloClient } from '@apollo/client';
import {
createFeatureFeedTab,
UserAvatarConnected,
ConnectScreenConnected,
} from '@apollosproject/ui-connected';
import { UserAvatarConnected } from '@apollosproject/ui-connected';
import { checkOnboardingStatusAndNavigate } from '@apollosproject/ui-onboarding';
import createTab from './createTab';

const HeaderLogo = () => {
const theme = useTheme();
Expand Down Expand Up @@ -75,54 +71,9 @@ const tabBarIcon = (name) => {
return TabBarIcon;
};

// we nest stack inside of tabs so we can use all the fancy native header features
const HomeTab = createFeatureFeedTab({
screenOptions: {
headerHideShadow: true,
headerCenter: HeaderLogo,
headerRight: SearchButton,
headerLeft: ProfileButton,
headerLargeTitle: false,
},
tabName: 'Home',
feedName: 'HOME',
});

const ReadTab = createFeatureFeedTab({
options: {
headerLeft: ProfileButton,
},
tabName: 'Read',
feedName: 'READ',
});

const WatchTab = createFeatureFeedTab({
options: {
headerLeft: ProfileButton,
},
tabName: 'Watch',
feedName: 'WATCH',
});

const PrayTab = createFeatureFeedTab({
options: {
headerLeft: ProfileButton,
},
tabName: 'Pray',
feedName: 'PRAY',
});

const ConnectTab = createFeatureFeedTab({
options: {
headerLeft: ProfileButton,
},
tabName: 'Connect',
feedName: 'CONNECT',
});

const { Navigator, Screen } = createBottomTabNavigator();

const TabNavigator = () => {
const Tabs = ({ tabs }) => {
const client = useApolloClient();
// this is only used by the tab loaded first
// if there is a new version of the onboarding flow,
Expand All @@ -134,35 +85,56 @@ const TabNavigator = () => {
navigateHome: false,
});
}, [client]);
return (
<Navigator lazy>
<Screen
name="Home"
component={HomeTab}
options={{ tabBarIcon: tabBarIcon('home') }}
/>
<Screen
name="Read"
component={ReadTab}
options={{ tabBarIcon: tabBarIcon('sections') }}
/>
<Screen
name="Watch"
component={WatchTab}
options={{ tabBarIcon: tabBarIcon('video') }}
/>
<Screen
name="Pray"
component={PrayTab}
options={{ tabBarIcon: tabBarIcon('like') }}
/>
<Screen
name="Connect"
component={ConnectTab}
options={{ tabBarIcon: tabBarIcon('profile') }}
/>
</Navigator>
const tabNavs = useMemo(
() =>
tabs.map(({ title, icon, feed }) => ({
title,
icon,
component: createTab({
featureFeedId: feed.id,
options: {
...(ApollosConfig.TABS[title]?.showLogo
? { headerCenter: HeaderLogo }
: {}),
...(ApollosConfig.TABS[title]?.showSearch
? { headerRight: SearchButton }
: {}),
...(ApollosConfig.TABS[title]?.showProfile
? { headerLeft: ProfileButton }
: {}),
...(ApollosConfig.TABS[title] ?? {}),
},
title,
}),
})),
[tabs]
);
return tabNavs.length ? (
<Navigator>
{tabNavs.map(({ title, icon, component }) => (
<Screen
key={title}
name={title}
component={component}
options={{ tabBarIcon: tabBarIcon(icon) }}
/>
))}
</Navigator>
) : null;
};

Tabs.propTypes = {
tabs: PropTypes.arrayOf(
PropTypes.shape({
title: PropTypes.string,
icon: PropTypes.string,
feed: PropTypes.shape({ id: PropTypes.string }),
})
),
};

Tabs.defaultProps = {
tabs: [],
};

export default TabNavigator;
export default Tabs;
90 changes: 90 additions & 0 deletions packages/apollos-ui-connected/src/TabsConnected/createTab.js
@@ -0,0 +1,90 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import { useNavigation, useRoute } from '@react-navigation/native';

import { BackgroundView } from '@apollosproject/ui-kit';

import { createNativeStackNavigator } from 'react-native-screens/native-stack';
import RockAuthedWebBrowser from '../RockAuthedWebBrowser';
import FeaturesFeedConnected from '../FeaturesFeedConnected';

import ContentFeed from '../ContentFeedConnected';
import TagFilterConnected from '../TagFilterConnected';

const Tab = ({ useTagFilter, feedViewProps, additionalFeatures }) => {
const navigation = useNavigation();
const route = useRoute();
const [filteredTags, setFilteredTags] = useState([]);
return (
<>
{useTagFilter ? (
<TagFilterConnected
filteredTags={filteredTags}
setFilteredTags={setFilteredTags}
/>
) : null}
<RockAuthedWebBrowser>
{(openUrl) => (
<BackgroundView>
<FeaturesFeedConnected
openUrl={openUrl}
featureFeedId={route.params.featureFeedId}
navigation={navigation}
feedViewProps={feedViewProps}
additionalFeatures={additionalFeatures}
/>
</BackgroundView>
)}
</RockAuthedWebBrowser>
</>
);
};

Tab.propTypes = {
useTagFilter: PropTypes.bool,
feedViewProps: PropTypes.shape({}),
additionalFeatures: PropTypes.shape({}),
};

Tab.defaultProps = {
useTagFilter: false,
feedViewProps: {},
additionalFeatures: {},
};

export const createTab = ({ featureFeedId, title, screenOptions, options }) => {
const TabStack = createNativeStackNavigator();
const TabNav = () => (
<TabStack.Navigator
screenOptions={{
headerHideShadow: true,
headerLargeTitle: true,
...screenOptions,
}}
>
<TabStack.Screen
name={title}
component={Tab}
options={options}
initialParams={{ featureFeedId }}
/>
<TabStack.Screen
component={ContentFeed}
name="ContentFeed"
options={({ route }) => ({
title: route?.params?.itemTitle || 'Content Feed',
})}
/>
<TabStack.Screen
component={FeaturesFeedConnected}
name="FeatureFeed"
options={({ route }) => ({
title: route?.params?.title || 'Feed',
})}
/>
</TabStack.Navigator>
);
return TabNav;
};

export default createTab;
54 changes: 54 additions & 0 deletions packages/apollos-ui-connected/src/TabsConnected/index.js
@@ -0,0 +1,54 @@
import React from 'react';
import { ActivityIndicator } from 'react-native';
import PropTypes from 'prop-types';
import { useQuery, gql } from '@apollo/client';
import Tabs from './Tabs';

const GET_USER_CAMPUS_ID = gql`
query GetUserCampusID {
currentUser {
id
profile {
id
campus {
id
}
}
}
}
`;

const GET_TABS = gql`
query GetTabs($campusId: ID) {
tabs(campusId: $campusId) {
title
icon
feed {
id
}
}
}
`;

const TabsConnected = ({ hasCampus }) => {
const { data: campusData, loading, error } = useQuery(GET_USER_CAMPUS_ID);
const { data } = useQuery(GET_TABS, {
variables: {
campusId: hasCampus ? campusData?.currentUser?.profile?.campus?.id : null,
},
fetchPolicy: 'cache-and-network',
});
if (error) return null;
if (loading) return <ActivityIndicator />;
return <Tabs tabs={data?.tabs ?? []} />;
};

TabsConnected.propTypes = {
hasCampus: PropTypes.bool,
};

TabsConnected.defaultProps = {
hasCampus: false,
};

export default TabsConnected;
1 change: 1 addition & 0 deletions packages/apollos-ui-connected/src/index.js
Expand Up @@ -116,6 +116,7 @@ export ScriptureNodeConnected, {
GET_SCRIPTURE_NODE,
} from './ScriptureNodeConnected';
export { ScriptureFeature, TextFeature, WebviewFeature } from './features';
export { default as TabsConnected } from './TabsConnected';
export ThemeMixinConnected, { GET_NODE_THEME } from './ThemeMixinConnected';
export TagFilterConnected from './TagFilterConnected';
export { default as UserSettingsConnected } from './UserSettingsConnected';
4 changes: 2 additions & 2 deletions templates/mobile/ios/Podfile.lock
Expand Up @@ -297,7 +297,7 @@ PODS:
- React-jsinspector (0.67.2)
- React-logger (0.67.2):
- glog
- react-native-apollos-player (3.3.0):
- react-native-apollos-player (3.5.0):
- React
- react-native-config (0.11.7):
- React
Expand Down Expand Up @@ -721,7 +721,7 @@ SPEC CHECKSUMS:
React-jsiexecutor: 52beb652bbc61201bd70cbe4f0b8edb607e8da4f
React-jsinspector: 595f76eba2176ebd8817a1fffd47b84fbdab9383
React-logger: 23de8ea0f44fa00ee77e96060273225607fd4d78
react-native-apollos-player: b9bd46b7231e01eec1d2fa737a3cfe2250745c26
react-native-apollos-player: d68362bac15f6db6f48d8284bf83e67bebaa2aaf
react-native-config: 55548054279d92e0e4566ea15a8b9b81028ec342
react-native-geolocation: c956aeb136625c23e0dce0467664af2c437888c9
react-native-geolocation-service: c0efb872258ed9240f1003a70fca9e9757e5c785
Expand Down
2 changes: 1 addition & 1 deletion templates/mobile/src/index.js
Expand Up @@ -27,9 +27,9 @@ import {
ContentFeedConnected,
SearchScreenConnected,
UserSettingsConnected,
TabsConnected as Tabs,
} from '@apollosproject/ui-connected';
import Providers from './Providers';
import Tabs from './tabs';

enableScreens(); // improves performance for react-navigation

Expand Down

0 comments on commit 4671c1a

Please sign in to comment.