177 lines
5.2 KiB
TypeScript
177 lines
5.2 KiB
TypeScript
import React, { useCallback, useEffect } from 'react';
|
|
import {
|
|
NavigationContainer as NavigationContainerBase,
|
|
ParamListBase,
|
|
createNavigationContainerRef,
|
|
} from '@react-navigation/native';
|
|
import FontAwesome5 from 'react-native-vector-icons/FontAwesome5';
|
|
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
|
|
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
import { Snackbar, useTheme } from 'react-native-paper';
|
|
import { useDispatch, useSelector } from 'react-redux';
|
|
import {
|
|
Memes,
|
|
Tags,
|
|
Settings,
|
|
EditMeme,
|
|
EditTag,
|
|
AddMeme,
|
|
AddTag,
|
|
MemeView,
|
|
} from './screens';
|
|
import { darkNavigationTheme, lightNavigationTheme } from './theme';
|
|
import {
|
|
FloatingActionButton,
|
|
HideableBottomNavigationBar,
|
|
} from './components';
|
|
import {
|
|
ROUTE,
|
|
RootStackParamList,
|
|
SharedItem,
|
|
sharedItemToAddMemeFile,
|
|
} from './types';
|
|
import { RootState } from './state';
|
|
import ShareMenu from 'react-native-share-menu';
|
|
import { setSnackbarMessage } from './state/navigation';
|
|
import { StyleSheet } from 'react-native';
|
|
import { useKeyboard } from '@react-native-community/hooks';
|
|
|
|
const tabNavigatorStyles = StyleSheet.create({
|
|
snackbar: {
|
|
marginBottom: 90,
|
|
},
|
|
snackbarKeyboard: {
|
|
marginBottom: 10,
|
|
},
|
|
});
|
|
|
|
const TabNavigator = () => {
|
|
const navVisible = useSelector(
|
|
(state: RootState) => state.navigation.navVisible,
|
|
);
|
|
const snackbarMessage = useSelector(
|
|
(state: RootState) => state.navigation.snackbarMessage,
|
|
);
|
|
const dispatch = useDispatch();
|
|
const keyboardOpen = useKeyboard().keyboardShown;
|
|
|
|
const [route, setRoute] = React.useState(ROUTE.MEMES);
|
|
const TabNavigatorBase = createBottomTabNavigator();
|
|
|
|
return (
|
|
<>
|
|
<TabNavigatorBase.Navigator
|
|
screenOptions={{
|
|
headerShown: false,
|
|
lazy: false,
|
|
}}
|
|
tabBar={({ navigation, state, descriptors, insets }) => (
|
|
<HideableBottomNavigationBar
|
|
navigation={navigation}
|
|
state={state}
|
|
descriptors={descriptors}
|
|
insets={insets}
|
|
visible={!!navVisible}
|
|
routeCallback={newRoute => setRoute(newRoute)}
|
|
/>
|
|
)}>
|
|
<TabNavigatorBase.Screen
|
|
name={ROUTE.MEMES}
|
|
component={Memes}
|
|
options={{
|
|
tabBarIcon: ({ color, size }) => (
|
|
<FontAwesome5 name="images" color={color} size={size} />
|
|
),
|
|
}}
|
|
/>
|
|
<TabNavigatorBase.Screen
|
|
name={ROUTE.TAGS}
|
|
component={Tags}
|
|
options={{
|
|
tabBarIcon: ({ color, size }) => (
|
|
<FontAwesome5 name="tags" color={color} size={size} />
|
|
),
|
|
}}
|
|
/>
|
|
<TabNavigatorBase.Screen
|
|
name={ROUTE.SETTINGS}
|
|
component={Settings}
|
|
options={{
|
|
tabBarIcon: ({ color, size }) => (
|
|
<FontAwesome5 name="cog" color={color} size={size} />
|
|
),
|
|
}}
|
|
/>
|
|
</TabNavigatorBase.Navigator>
|
|
<FloatingActionButton visible={navVisible && route !== ROUTE.SETTINGS} />
|
|
<Snackbar
|
|
visible={!!snackbarMessage}
|
|
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
onDismiss={() => dispatch(setSnackbarMessage(undefined))}
|
|
style={
|
|
keyboardOpen
|
|
? tabNavigatorStyles.snackbarKeyboard
|
|
: tabNavigatorStyles.snackbar
|
|
}
|
|
action={{
|
|
label: 'Dismiss',
|
|
// eslint-disable-next-line unicorn/no-useless-undefined
|
|
onPress: () => dispatch(setSnackbarMessage(undefined)),
|
|
}}>
|
|
{snackbarMessage}
|
|
</Snackbar>
|
|
</>
|
|
);
|
|
};
|
|
|
|
const NavigationContainer = () => {
|
|
const theme = useTheme();
|
|
|
|
const navigationRef = createNavigationContainerRef<ParamListBase>();
|
|
|
|
const handleShare = useCallback(
|
|
(item: SharedItem | undefined) => {
|
|
if (!item) return;
|
|
const files = sharedItemToAddMemeFile(item);
|
|
navigationRef.current?.navigate(ROUTE.ADD_MEME, { files });
|
|
},
|
|
[navigationRef],
|
|
);
|
|
|
|
useEffect(() => {
|
|
ShareMenu.getInitialShare(handleShare);
|
|
const listener = ShareMenu.addNewShareListener(handleShare);
|
|
return () => listener.remove();
|
|
}, [handleShare]);
|
|
|
|
const StackNavigatorBase = createNativeStackNavigator<RootStackParamList>();
|
|
|
|
return (
|
|
<NavigationContainerBase
|
|
ref={navigationRef}
|
|
theme={theme.dark ? darkNavigationTheme : lightNavigationTheme}>
|
|
<StackNavigatorBase.Navigator
|
|
screenOptions={{
|
|
headerShown: false,
|
|
animation: 'slide_from_bottom',
|
|
}}>
|
|
<StackNavigatorBase.Screen name={ROUTE.MAIN} component={TabNavigator} />
|
|
<StackNavigatorBase.Screen
|
|
name={ROUTE.MEME_VIEW}
|
|
component={MemeView}
|
|
options={{ presentation: 'modal', animation: 'default' }}
|
|
/>
|
|
<StackNavigatorBase.Screen name={ROUTE.ADD_MEME} component={AddMeme} />
|
|
<StackNavigatorBase.Screen
|
|
name={ROUTE.EDIT_MEME}
|
|
component={EditMeme}
|
|
/>
|
|
<StackNavigatorBase.Screen name={ROUTE.ADD_TAG} component={AddTag} />
|
|
<StackNavigatorBase.Screen name={ROUTE.EDIT_TAG} component={EditTag} />
|
|
</StackNavigatorBase.Navigator>
|
|
</NavigationContainerBase>
|
|
);
|
|
};
|
|
|
|
export default NavigationContainer;
|