This repository has been archived on 2025-07-31. You can view files and clone it, but cannot push or open issues or pull requests.
Files
terminally-online/src/navigation.tsx
Nikolaos Karaolidis e794832f38 Add root snackbar
Signed-off-by: Nikolaos Karaolidis <nick@karaolidis.com>
2023-07-29 23:11:00 +03:00

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;