Add the desktop scaffold
This commit is contained in:
@@ -1,69 +0,0 @@
|
||||
import { Flex, useBreakpointValue } from 'native-base';
|
||||
import useColorScheme from '../../hooks/colorScheme';
|
||||
import { useQuery } from '../../Queries';
|
||||
import API from '../../API';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { Cup, Discover, Music, SearchNormal1, Setting2, User } from 'iconsax-react-native';
|
||||
import { LoadingView } from '../Loading';
|
||||
import ScaffoldDesktopCC from './ScaffoldDesktopCC';
|
||||
import ScaffoldMobileCC from './ScaffoldMobileCC';
|
||||
import { useAssets } from 'expo-asset';
|
||||
|
||||
const menu = [
|
||||
{ type: 'main', title: 'menuDiscovery', icon: Discover, link: 'Home' },
|
||||
{ type: 'main', title: 'menuProfile', icon: User, link: 'User' },
|
||||
{ type: 'main', title: 'menuMusic', icon: Music, link: 'Music' },
|
||||
{ type: 'main', title: 'menuSearch', icon: SearchNormal1, link: 'Search' },
|
||||
{ type: 'main', title: 'menuLeaderBoard', icon: Cup, link: 'Leaderboard' },
|
||||
{ type: 'sub', title: 'menuSettings', icon: Setting2, link: 'Settings' },
|
||||
] as const;
|
||||
|
||||
type ScaffoldCCProps = {
|
||||
children?: React.ReactNode;
|
||||
routeName: string;
|
||||
withPadding?: boolean;
|
||||
enableScroll?: boolean;
|
||||
};
|
||||
|
||||
const ScaffoldCC = ({
|
||||
children,
|
||||
routeName,
|
||||
}: ScaffoldCCProps) => {
|
||||
const userQuery = useQuery(API.getUserInfo);
|
||||
const screenSize = useBreakpointValue({ base: 'small', md: 'big' });
|
||||
|
||||
if (!userQuery.data || userQuery.isLoading) {
|
||||
return <LoadingView />;
|
||||
}
|
||||
const colorScheme = useColorScheme();
|
||||
const [logo] = useAssets(
|
||||
colorScheme == 'light'
|
||||
? require('../../assets/icon_light.png')
|
||||
: require('../../assets/icon_dark.png')
|
||||
);
|
||||
|
||||
return (
|
||||
<Flex style={{ flex: 1, backgroundColor: '#cdd4fd' }}>
|
||||
{screenSize === 'small' ? (
|
||||
<ScaffoldMobileCC
|
||||
routeName={routeName}
|
||||
menu={menu}
|
||||
>
|
||||
{children}
|
||||
</ScaffoldMobileCC>
|
||||
) : (
|
||||
<ScaffoldDesktopCC
|
||||
user={userQuery.data}
|
||||
logo={logo?.at(0)?.uri ?? ''}
|
||||
routeName={routeName}
|
||||
menu={menu}
|
||||
widthPadding={true}
|
||||
>
|
||||
{children}
|
||||
</ScaffoldDesktopCC>
|
||||
)}
|
||||
</Flex>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScaffoldCC;
|
||||
@@ -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 (
|
||||
<View key={'key-menu-link-' + label}>
|
||||
<ButtonBase
|
||||
style={!isSmallScreen ? { width: '100%' } : {}}
|
||||
type="menu"
|
||||
icon={icon}
|
||||
title={!isSmallScreen ? translate(label as any) : undefined}
|
||||
isDisabled={isFocused}
|
||||
iconVariant={isFocused ? 'Bold' : 'Outline'}
|
||||
onPress={() => {
|
||||
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,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<Spacer height="xs" />
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
const ScaffoldDesktopCC = ({
|
||||
state,
|
||||
descriptors,
|
||||
navigation,
|
||||
children,
|
||||
}: Omit<BottomTabBarProps, 'insets'> & { children: ReactElement }) => {
|
||||
const user = useQuery(API.getUserInfo);
|
||||
const [isSmallScreen] = useMediaQuery({ maxWidth: 1100 });
|
||||
const { colors } = useTheme();
|
||||
|
||||
if (!userQuery.data || userQuery.isLoading) {
|
||||
return <LoadingView />;
|
||||
}
|
||||
const colorScheme = useColorScheme();
|
||||
const [logo] = useAssets(
|
||||
colorScheme == 'light'
|
||||
? require('../../assets/icon_light.png')
|
||||
: require('../../assets/icon_dark.png')
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={{ height: '100%', flexDirection: 'row', overflow: 'hidden' }}>
|
||||
@@ -111,7 +154,7 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
|
||||
style={{ justifyContent: isSmallScreen ? 'center' : 'flex-start' }}
|
||||
>
|
||||
<Image
|
||||
source={{ uri: props.logo }}
|
||||
source={{ uri: logo?.at(0)?.uri ?? '' }}
|
||||
style={{
|
||||
aspectRatio: 1,
|
||||
width: 32,
|
||||
@@ -126,39 +169,21 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
|
||||
</Row>
|
||||
<Spacer height="lg" />
|
||||
<View>
|
||||
{props.menu.map(
|
||||
(value) =>
|
||||
value.type === 'main' && (
|
||||
<View key={'key-menu-link-' + value.title}>
|
||||
<ButtonBase
|
||||
style={!isSmallScreen ? { width: '100%' } : {}}
|
||||
type="menu"
|
||||
icon={value.icon}
|
||||
title={
|
||||
!isSmallScreen
|
||||
? translate(
|
||||
value.title as
|
||||
| 'menuDiscovery'
|
||||
| 'menuProfile'
|
||||
| 'menuMusic'
|
||||
| 'menuSearch'
|
||||
| 'menuLeaderBoard'
|
||||
| 'menuSettings'
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
isDisabled={props.routeName === value.link}
|
||||
iconVariant={
|
||||
props.routeName === value.link ? 'Bold' : 'Outline'
|
||||
}
|
||||
onPress={async () =>
|
||||
navigation.navigate(value.link as never)
|
||||
}
|
||||
/>
|
||||
<Spacer height="xs" />
|
||||
</View>
|
||||
)
|
||||
)}
|
||||
{state.routes.map((route, index) => {
|
||||
const { options } = descriptors[route.key]!;
|
||||
|
||||
if ((options as any).subMenu) return null;
|
||||
return (
|
||||
<NavigationButton
|
||||
isSmallScreen={!!isSmallScreen}
|
||||
label={options.title !== undefined ? options.title : route.name}
|
||||
icon={options.tabBarIcon as Icon}
|
||||
isFocused={state.index === index}
|
||||
navigation={navigation}
|
||||
route={route}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</View>
|
||||
</View>
|
||||
{!isSmallScreen && (
|
||||
@@ -182,59 +207,45 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
|
||||
<View style={!isSmallScreen ? { width: '100%' } : {}}>
|
||||
<Divider my="2" _light={{ bg: colors.black[500] }} _dark={{ bg: '#FFF' }} />
|
||||
<Spacer height="xs" />
|
||||
{props.menu.map(
|
||||
(value) =>
|
||||
value.type === 'sub' && (
|
||||
<ButtonBase
|
||||
key={'key-menu-link-' + value.title}
|
||||
style={!isSmallScreen ? { width: '100%' } : {}}
|
||||
type="menu"
|
||||
icon={value.icon}
|
||||
title={
|
||||
!isSmallScreen
|
||||
? translate(
|
||||
value.title as
|
||||
| 'menuDiscovery'
|
||||
| 'menuProfile'
|
||||
| 'menuMusic'
|
||||
| 'menuSearch'
|
||||
| 'menuLeaderBoard'
|
||||
| 'menuSettings'
|
||||
)
|
||||
: undefined
|
||||
}
|
||||
isDisabled={props.routeName === value.link}
|
||||
iconVariant={
|
||||
props.routeName === value.link ? 'Bold' : 'Outline'
|
||||
}
|
||||
onPress={async () => navigation.navigate(value.link as never)}
|
||||
/>
|
||||
)
|
||||
)}
|
||||
{state.routes.map((route, index) => {
|
||||
const { options } = descriptors[route.key]!;
|
||||
|
||||
if (!(options as any).subMenu) return null;
|
||||
return (
|
||||
<NavigationButton
|
||||
isSmallScreen={!!isSmallScreen}
|
||||
label={options.title !== undefined ? options.title : route.name}
|
||||
icon={options.tabBarIcon as Icon}
|
||||
isFocused={state.index === index}
|
||||
navigation={navigation}
|
||||
route={route}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
<Spacer height="xs" />
|
||||
<LogoutButtonCC
|
||||
collapse={isSmallScreen}
|
||||
isGuest={props.user.isGuest}
|
||||
isGuest={user.data?.isGuest}
|
||||
style={!isSmallScreen ? { width: '100%' } : {}}
|
||||
buttonType={'menu'}
|
||||
/>
|
||||
</View>
|
||||
</View>
|
||||
<ScrollView style={{ flex: 1, maxHeight: '100%' }} contentContainerStyle={{ flex: 1 }}>
|
||||
<GlassmorphismCC
|
||||
<View
|
||||
style={{
|
||||
backgroundColor: colors.coolGray[500],
|
||||
flex: 1,
|
||||
margin: 8,
|
||||
marginBottom: 0,
|
||||
marginLeft: 0,
|
||||
padding: props.widthPadding ? 20 : 0,
|
||||
padding: 20,
|
||||
borderRadius: 12,
|
||||
minHeight: 'auto',
|
||||
}}
|
||||
>
|
||||
{props.children}
|
||||
</GlassmorphismCC>
|
||||
{children}
|
||||
</View>
|
||||
<Spacer height="xs" />
|
||||
</ScrollView>
|
||||
</View>
|
||||
|
||||
@@ -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 (
|
||||
<ButtonBase
|
||||
key={'key-menu-link-' + label}
|
||||
type="menu"
|
||||
icon={Discover}
|
||||
icon={icon}
|
||||
title={
|
||||
isFocused && !isSmallScreen ? translate(label as any) : undefined
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user