diff --git a/front/Navigation.tsx b/front/Navigation.tsx index 90bb9ae..db136c6 100644 --- a/front/Navigation.tsx +++ b/front/Navigation.tsx @@ -36,13 +36,16 @@ import MusicView from './views/MusicView'; import Leaderboardiew from './views/LeaderboardView'; import { LinearGradient } from 'expo-linear-gradient'; import ScaffoldMobileCC from './components/UI/ScaffoldMobileCC'; +import ScaffoldDesktopCC from './components/UI/ScaffoldDesktopCC'; +import { createCustomNavigator } from './utils/navigator'; +import { Cup, Discover, Music, SearchNormal1, Setting2, User } from 'iconsax-react-native'; const Stack = createNativeStackNavigator(); -const Tab = createBottomTabNavigator(); +const Tab = createCustomNavigator(); const Tabs = () => { return ( - + {Object.entries(tabRoutes).map(([name, route], routeIndex) => ( ''; const tabRoutes = { Home: { component: DiscoveryView, - options: { headerShown: false }, + options: { headerShown: false, tabBarIcon: Discover }, link: '/', }, - Settings: { - component: SettingsTab, - options: { headerShown: false }, - link: '/settings/:screen?', - stringify: { - screen: removeMe, - }, + User: { + component: ProfileView, + options: { headerShown: false, tabBarIcon: User }, + link: '/user', }, - User: { component: ProfileView, options: { headerShown: false }, link: '/user' }, Music: { component: MusicView, - options: { headerShown: false }, + options: { headerShown: false, tabBarIcon: Music }, link: '/music', }, Search: { component: SearchView, - options: { headerShown: false }, + options: { headerShown: false, tabBarIcon: SearchNormal1 }, link: '/search/:query?', }, Leaderboard: { component: Leaderboardiew, - options: { title: translate('leaderboardTitle'), headerShown: false }, + options: { title: translate('leaderboardTitle'), headerShown: false, tabBarIcon: Cup }, link: '/leaderboard', }, + Settings: { + component: SettingsTab, + options: { headerShown: false, tabBarIcon: Setting2, subMenu: true }, + link: '/settings/:screen?', + stringify: { + screen: removeMe, + }, + }, }; const protectedRoutes = { @@ -178,7 +185,7 @@ const RouteToScreen = (Component: Route['component']) => return ( { - const userQuery = useQuery(API.getUserInfo); - const screenSize = useBreakpointValue({ base: 'small', md: 'big' }); - - if (!userQuery.data || userQuery.isLoading) { - return ; - } - const colorScheme = useColorScheme(); - const [logo] = useAssets( - colorScheme == 'light' - ? require('../../assets/icon_light.png') - : require('../../assets/icon_dark.png') - ); - - return ( - - {screenSize === 'small' ? ( - - {children} - - ) : ( - - {children} - - )} - - ); -}; - -export default ScaffoldCC; diff --git a/front/components/UI/ScaffoldDesktopCC.tsx b/front/components/UI/ScaffoldDesktopCC.tsx index 0ec7dbb..c2b62af 100644 --- a/front/components/UI/ScaffoldDesktopCC.tsx +++ b/front/components/UI/ScaffoldDesktopCC.tsx @@ -1,6 +1,7 @@ /* eslint-disable no-mixed-spaces-and-tabs */ -import { View, Image, Pressable } from 'react-native'; +import { View, Image, Pressable, useColorScheme } from 'react-native'; import { Divider, Text, ScrollView, Row, useMediaQuery, useTheme } from 'native-base'; +import { useAssets } from 'expo-asset'; import { useQuery } from '../../Queries'; import API from '../../API'; import ButtonBase from './ButtonBase'; @@ -12,20 +13,9 @@ import Spacer from './Spacer'; import User from '../../models/User'; import LogoutButtonCC from './LogoutButtonCC'; import GlassmorphismCC from './Glassmorphism'; - -type ScaffoldDesktopCCProps = { - widthPadding: boolean; - children?: React.ReactNode; - user: User; - logo: string; - routeName: string; - menu: readonly { - type: 'main' | 'sub'; - title: TranslationKey; - icon: Icon; - link: string; - }[]; -}; +import { BottomTabBarProps } from '@react-navigation/bottom-tabs'; +import { ReactElement } from 'react'; +import { NavigationState, ParamListBase } from '@react-navigation/native'; // TODO a tester avec un historique de plus de 3 musics différente mdr !! const SongHistory = (props: { quantity: number }) => { @@ -81,15 +71,68 @@ const SongHistory = (props: { quantity: number }) => { ); }; -const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => { - const navigation = useNavigation(); - const userQuery = useQuery(API.getUserInfo); +const NavigationButton = ({ + isSmallScreen, + label, + icon, + isFocused, + navigation, + route, +}: { + isSmallScreen: boolean; + label: string; + icon?: Icon; + isFocused: boolean; + navigation: BottomTabBarProps['navigation']; + route: NavigationState['routes'][0]; +}) => { + return ( + + { + const event = navigation.emit({ + type: 'tabPress', + target: route.key, + canPreventDefault: true, + }); + + if (!isFocused && !event.defaultPrevented) { + navigation.navigate(route.name, route.params); + } + }} + onLongPress={() => { + navigation.emit({ + type: 'tabLongPress', + target: route.key, + }); + }} + /> + + + ); +}; + +const ScaffoldDesktopCC = ({ + state, + descriptors, + navigation, + children, +}: Omit & { children: ReactElement }) => { + const user = useQuery(API.getUserInfo); const [isSmallScreen] = useMediaQuery({ maxWidth: 1100 }); const { colors } = useTheme(); - - if (!userQuery.data || userQuery.isLoading) { - return ; - } + const colorScheme = useColorScheme(); + const [logo] = useAssets( + colorScheme == 'light' + ? require('../../assets/icon_light.png') + : require('../../assets/icon_dark.png') + ); return ( @@ -111,7 +154,7 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => { style={{ justifyContent: isSmallScreen ? 'center' : 'flex-start' }} > { - {props.menu.map( - (value) => - value.type === 'main' && ( - - - navigation.navigate(value.link as never) - } - /> - - - ) - )} + {state.routes.map((route, index) => { + const { options } = descriptors[route.key]!; + + if ((options as any).subMenu) return null; + return ( + + ); + })} {!isSmallScreen && ( @@ -182,59 +207,45 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => { - {props.menu.map( - (value) => - value.type === 'sub' && ( - navigation.navigate(value.link as never)} - /> - ) - )} + {state.routes.map((route, index) => { + const { options } = descriptors[route.key]!; + + if (!(options as any).subMenu) return null; + return ( + + ); + })} - - {props.children} - + {children} + diff --git a/front/components/UI/ScaffoldMobileCC.tsx b/front/components/UI/ScaffoldMobileCC.tsx index d286b61..766482d 100644 --- a/front/components/UI/ScaffoldMobileCC.tsx +++ b/front/components/UI/ScaffoldMobileCC.tsx @@ -1,7 +1,7 @@ import { View } from 'react-native'; import { Flex, useMediaQuery, useTheme } from 'native-base'; import ButtonBase from './ButtonBase'; -import { Discover } from 'iconsax-react-native'; +import { Discover, Icon } from 'iconsax-react-native'; import { translate } from '../../i18n/i18n'; import { BottomTabBarProps } from '@react-navigation/bottom-tabs'; import { ComponentProps } from 'react'; @@ -25,13 +25,14 @@ const ScaffoldMobileCC = ({ state, descriptors, navigation }: BottomTabBarProps) {state.routes.map((route, index) => { const { options } = descriptors[route.key]!; const label = options.title !== undefined ? options.title : route.name; + const icon = options.tabBarIcon as Icon; const isFocused = state.index === index; return ( - + {screenSize === 'small' ? ( + + ) : ( + + {descriptors[state.routes[state.index]!.key]!.render()} + + )} ); }