[ADD] SettingsView: translation, Menu: collapsed mode && translation

This commit is contained in:
mathysPaul
2023-10-28 00:47:27 +02:00
parent b87ec1dd44
commit e499bb2f9f
6 changed files with 146 additions and 92 deletions

View File

@@ -24,12 +24,13 @@ const handleSubmit = async (username: string, password: string, email: string) =
};
type LogoutButtonCCProps = {
collapse?: boolean;
isGuest?: boolean;
style: any;
buttonType: ButtonType
};
const LogoutButtonCC = ({isGuest = false, buttonType = 'menu', style}: LogoutButtonCCProps) => {
const LogoutButtonCC = ({collapse = false, isGuest = false, buttonType = 'menu', style}: LogoutButtonCCProps) => {
const dispatch = useDispatch();
const [isVisible, setIsVisible] = useState(false);
@@ -38,7 +39,7 @@ const LogoutButtonCC = ({isGuest = false, buttonType = 'menu', style}: LogoutBut
<ButtonBase
style={style}
icon={LogoutCurve}
title={translate('signOutBtn')}
title={collapse ? translate('signOutBtn') : undefined}
type={buttonType}
onPress={async () => {isGuest ? setIsVisible(true) : dispatch(unsetAccessToken());}}
/>
@@ -50,7 +51,7 @@ const LogoutButtonCC = ({isGuest = false, buttonType = 'menu', style}: LogoutBut
>
<SignUpForm onSubmit={handleSubmit} />
<ButtonBase
style={{width: '100%'}}
style={!collapse ? { width: '100%' } : {}}
type="outlined"
icon={LogoutCurve}
title={translate('signOutBtn')}

View File

@@ -1,11 +1,8 @@
import { View, Image } from 'react-native';
import { Divider, Text, ScrollView, Flex, Row, Popover, Heading, Button, useBreakpointValue } from 'native-base';
import { Flex, useBreakpointValue } from 'native-base';
import useColorScheme from '../../hooks/colorScheme';
import { useQuery, useQueries } from '../../Queries';
import { useQuery } from '../../Queries';
import API from '../../API';
import Song from '../../models/Song';
import { LinearGradient } from 'expo-linear-gradient';
import ButtonBase from './ButtonBase';
import {
Cup,
Discover,
@@ -15,12 +12,7 @@ import {
Setting2,
User,
} from 'iconsax-react-native';
import { useDispatch } from 'react-redux';
import { LoadingView } from '../Loading';
import { translate } from '../../i18n/i18n';
import { unsetAccessToken } from '../../state/UserSlice';
import { useNavigation } from '../../Navigation';
import Spacer from './Spacer';
import ScaffoldDesktopCC from './ScaffoldDesktopCC';
import ScaffoldMobileCC from './ScaffoldMobileCC';
@@ -30,12 +22,12 @@ const menu: {
icon: Icon;
link: string;
}[] = [
{ type: "main", title: 'Discovery', icon: Discover, link: 'HomeNew' },
{ type: "main", title: 'Profile', icon: User, link: 'User' },
{ type: "main", title: 'Music', icon: Music, link: 'Home' },
{ type: "main", title: 'Search', icon: SearchNormal1, link: 'Search' },
{ type: "main", title: 'LeaderBoard', icon: Cup, link: 'Score' },
{ type: "sub", title: 'Settings', icon: Setting2, link: 'Settings' },
{ type: "main", title: 'menuDiscovery', icon: Discover, link: 'HomeNew' },
{ type: "main", title: 'menuProfile', icon: User, link: 'User' },
{ type: "main", title: 'menuMusic', icon: Music, link: 'Home' },
{ type: "main", title: 'menuSearch', icon: SearchNormal1, link: 'Search' },
{ type: "main", title: 'menuLeaderBoard', icon: Cup, link: 'Score' },
{ type: "sub", title: 'menuSettings', icon: Setting2, link: 'Settings' },
];
type ScaffoldCCProps = {

View File

@@ -30,61 +30,95 @@ type ScaffoldDesktopCCProps = {
}[]
};
const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
const navigation = useNavigation();
const userQuery = useQuery(API.getUserInfo);
const [isSmallScreen] = useMediaQuery({ maxWidth: 400 });
const layout = useWindowDimensions();
const colorScheme = useColorScheme();
if (!userQuery.data || userQuery.isLoading) {
return <LoadingView />;
}
const SongHistory = (props: {quantity: number}) => {
const playHistoryQuery = useQuery(API.getUserPlayHistory);
const songHistory = useQueries(
playHistoryQuery.data?.map(({ songID }) => API.getSong(songID)) ?? []
);
if (!playHistoryQuery.data || playHistoryQuery.isLoading) {
return <LoadingView />;
}
return (
<View>
{songHistory.length === 0 ?
<Text style={{ paddingHorizontal: 16 }}>{translate('menuNoSongsPlayedYet')}</Text>
: songHistory
.map((h) => h.data)
.filter((data): data is Song => data !== undefined)
.filter(
(song, i, array) =>
array.map((s) => s.id).findIndex((id) => id == song.id) == i
)
.slice(0, props.quantity + 1)
.map((histoItem, index) => (
<View
key={'tab-navigation-other-' + index}
style={{
paddingHorizontal: 16,
paddingVertical: 10,
}}
>
<Text numberOfLines={1}>{histoItem.name}</Text>
</View>
)
)
}
</View>
);
}
const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
const navigation = useNavigation();
const userQuery = useQuery(API.getUserInfo);
const [isSmallScreen] = useMediaQuery({ maxWidth: 1100 });
const { colors } = useTheme();
if (!userQuery.data || userQuery.isLoading) {
return <LoadingView />;
}
return (
<View style={{ height: '100%', flexDirection: 'row', overflow: 'hidden' }}>
<View
style={{
display: 'flex',
width: 300,
width: !isSmallScreen ? 300 : undefined,
padding: 20,
flexDirection: 'column',
justifyContent: 'space-between',
alignItems: 'flex-start',
alignItems: isSmallScreen ? 'center' : 'flex-start',
flexShrink: 0,
}}
>
<View style={{ width: '100%' }}>
<Row space={2} flex={1}>
<View style={!isSmallScreen ? { width: '100%' } : {}}>
<Row space={2} flex={1} style={{ justifyContent: 'center' }}>
<Image
source={{ uri: props.logo }}
style={{
aspectRatio: 1,
width: 32,
height: 32,
alignItems: isSmallScreen ? 'center' : 'flex-start',
}}
/>
{layout.width > 650 &&
{!isSmallScreen &&
<Text fontSize={'xl'} selectable={false}>
Chromacase
</Text>
}
</Row>
<Spacer height="lg" />
<View style={{ width: '100%' }}>
<View>
{props.menu.map((value) => (
value.type === "main" &&
<View key={'key-menu-link-' + value.title}>
<ButtonBase
style={{ width: '100%' }}
style={!isSmallScreen ? { width: '100%' } : {}}
type="menu"
icon={value.icon}
title={value.title}
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'
@@ -98,61 +132,35 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
))}
</View>
</View>
<View style={{ width: '100%' }}>
<Divider my="2" _light={{bg: colors.black[500]}} _dark={{bg:'#FFF'}}/>
<Spacer height='xs'/>
<Text
bold
style={{
paddingHorizontal: 16,
paddingVertical: 10,
fontSize: 20,
}}
>
Recently played
</Text>
{songHistory.length === 0 && (
{!isSmallScreen &&
<View>
<Divider my="2" _light={{bg: colors.black[500]}} _dark={{bg:'#FFF'}}/>
<Spacer height='xs'/>
<Text
bold
style={{
paddingHorizontal: 16,
paddingVertical: 10,
paddingBottom: 10,
fontSize: 20,
}}
>
No songs played yet
{translate('menuRecentlyPlayed')}
</Text>
)}
{songHistory
.map((h) => h.data)
.filter((data): data is Song => data !== undefined)
.filter(
(song, i, array) =>
array.map((s) => s.id).findIndex((id) => id == song.id) == i
)
.slice(0, 4)
.map((histoItem, index) => (
<View
key={'tab-navigation-other-' + index}
style={{
paddingHorizontal: 16,
paddingVertical: 10,
}}
>
<Text numberOfLines={1}>{histoItem.name}</Text>
</View>
))}
</View>
<SongHistory quantity={3}/>
</View>
}
<Spacer height='xs'/>
<View style={{ width: '100%' }}>
<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={{ width: '100%' }}
style={!isSmallScreen ? { width: '100%' } : {}}
type="menu"
icon={value.icon}
title={!isSmallScreen ? value.title : undefined}
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'
@@ -163,7 +171,7 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
/>
))}
<Spacer height='xs'/>
<LogoutButtonCC isGuest={props.user.isGuest} style={{with: '100%'}} buttonType={'menu'}/>
<LogoutButtonCC collapse={!isSmallScreen} isGuest={props.user.isGuest} style={!isSmallScreen ? { width: '100%' } : {}} buttonType={'menu'}/>
</View>
</View>
<ScrollView
@@ -176,6 +184,7 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
flex: 1,
margin: 8,
marginBottom: 0,
marginLeft: 0,
padding: props.widthPadding ? 20 : 0,
borderRadius: 12,
minHeight: 'fit-content',

View File

@@ -1,11 +1,11 @@
import { View, useWindowDimensions } from 'react-native';
import { ScrollView, Flex, useBreakpointValue, useMediaQuery, useTheme } from 'native-base';
import { LinearGradient } from 'expo-linear-gradient';
import { View } from 'react-native';
import { ScrollView, Flex, useMediaQuery, useTheme } from 'native-base';
import ButtonBase from './ButtonBase';
import { Icon } from 'iconsax-react-native';
import { useNavigation } from '../../Navigation';
import Spacer from './Spacer';
import User from '../../models/User';
import { translate } from '../../i18n/i18n';
type ScaffoldMobileCCProps = {
children?: React.ReactNode;
@@ -61,7 +61,7 @@ const ScaffoldMobileCC = (props: ScaffoldMobileCCProps) => {
key={'key-menu-link-' + value.title}
type="menu"
icon={value.icon}
title={props.routeName === value.link && !isSmallScreen ? value.title : undefined}
title={props.routeName === value.link && !isSmallScreen ? translate(value.title as 'menuDiscovery' | 'menuProfile' | 'menuMusic' | 'menuSearch' | 'menuLeaderBoard' | 'menuSettings') : undefined}
isDisabled={props.routeName === value.link}
iconVariant={
props.routeName === value.link ? 'Bold' : 'Outline'

View File

@@ -38,6 +38,17 @@ export const en = {
levelProgress: 'good notes',
score: 'Score',
// Menu
menuDiscovery: 'Discovery',
menuProfile: 'Profile',
menuMusic: 'Music',
menuSearch: 'Search',
menuLeaderBoard: 'LeaderBoard',
menuSettings: 'Settings',
menuRecentlyPlayed: 'Recently played',
menuNoSongsPlayedYet: 'No songs played yet',
//signup
signupPageTitle: "Create an account",
signupPageParagraph: "Learn to play the piano in an enjoyable and free way.",
@@ -151,6 +162,12 @@ export const en = {
emailUpdated: 'Email updated',
//Settings
settingsTabProfile: 'Profile',
settingsTabPremium: 'Premium',
settingsTabPreferences: 'Preferences',
settingsTabNotifications: 'Notifications',
settingsTabPrivacy: 'Privacy',
settingsTabPiano: 'Piano',
// Profile Tab
settingsProfileTabGoogleSectionTitle: 'Google account',
settingsProfileTabGoogleSectionDescription: 'Link your Google account to ChromaCase',
@@ -297,13 +314,24 @@ export const fr: typeof en = {
longestCombo: 'Combo le plus long : ',
favoriteGenre: 'Genre favori : ',
// Menu
menuDiscovery: 'Découverte',
menuProfile: 'Profil',
menuMusic: 'Musique',
menuSearch: 'Recherche',
menuLeaderBoard: 'Classement',
menuSettings: 'Paramètres',
menuRecentlyPlayed : 'Récemment jouée',
menuNoSongsPlayedYet : 'Aucune chanson jouée pour l\'instant',
//signup
signupPageTitle: "Créer un compte",
signupPageParagraph: "Apprendre le piano gratuitement et de manière ludique",
signupLinkLabel: "Vous avez déjà un compte ? ",
signupLinkText: "S'identifier",
//signup
//signin
signinPageTitle: "Bienvenue !",
signinPageParagraph: "Continuez avec Google ou entrez vos coordonnées.",
signinLinkLabel: "Vous n'avez pas de compte ? ",
@@ -406,6 +434,12 @@ export const fr: typeof en = {
emailUpdated: 'Email mis à jour',
//Settings
settingsTabProfile: 'Profil',
settingsTabPremium: 'Premium',
settingsTabPreferences: 'Preferences',
settingsTabNotifications: 'Notifications',
settingsTabPrivacy: "Confidentialité",
settingsTabPiano: "Piano",
// Profile Tab
settingsProfileTabGoogleSectionTitle: 'Compte Google',
settingsProfileTabGoogleSectionDescription: 'Liez votre compte Google à ChromaCase',
@@ -565,6 +599,17 @@ export const sp: typeof en = {
longestCombo: 'combo más largo : ',
favoriteGenre: 'genero favorito : ',
// Menu
menuDiscovery: 'Descubrimiento',
menuProfile: 'Perfil',
menuMusic: 'Música',
menuSearch: 'Búsqueda',
menuLeaderBoard: 'Clasificación',
menuSettings: 'Configuración',
menuRecentlyPlayed: 'Reproducidas recientemente',
menuNoSongsPlayedYet: 'No hay canciones reproducidas todavía',
//signup
signupPageTitle: "Crear una cuenta",
signupPageParagraph: "Aprende a tocar el piano de forma amena y gratuita.",
@@ -664,6 +709,12 @@ export const sp: typeof en = {
emailUpdated: 'Email actualizado',
//Settings
settingsTabProfile: 'Perfil',
settingsTabPremium: 'Premium',
settingsTabPreferences: 'Preferencias',
settingsTabNotifications: 'Notificaciones',
settingsTabPrivacy: 'Privacidad',
settingsTabPiano: 'Piano',
// Profile Tab
settingsProfileTabGoogleSectionTitle: 'Cuenta de Google',
settingsProfileTabGoogleSectionDescription: 'Vincula tu cuenta de Google con ChromaCase',

View File

@@ -28,6 +28,7 @@ import { RouteProps } from '../../Navigation';
import ScaffoldCC from '../../components/UI/ScaffoldCC';
import { ColorSchemeProvider } from '../../Theme';
import useColorScheme from '../../hooks/colorScheme';
import { translate } from '../../i18n/i18n';
export const PianoSettings = () => {
return (
@@ -71,12 +72,12 @@ const SetttingsNavigator = (props: RouteProps<{}>) => {
const colorScheme = useColorScheme();
const { colors } = useTheme();
const [routes] = React.useState<Route[]>([
{ key: 'profile', title: 'Profile' },
{ key: 'premium', title: 'Premium' },
{ key: 'preferences', title: 'Preferences' },
{ key: 'notifications', title: 'Notifications' },
{ key: 'privacy', title: 'Privacy' },
{ key: 'piano', title: 'Piano' },
{ key: 'profile', title: 'settingsTabProfile' },
{ key: 'premium', title: 'settingsTabPremium' },
{ key: 'preferences', title: 'settingsTabPreferences' },
{ key: 'notifications', title: 'settingsTabNotifications' },
{ key: 'privacy', title: 'settingsTabPrivacy' },
{ key: 'piano', title: 'settingsTabPiano' },
]);
const renderTabBar = (
props: SceneRendererProps & { navigationState: NavigationState<Route> }
@@ -103,11 +104,11 @@ const SetttingsNavigator = (props: RouteProps<{}>) => {
);
}}
renderLabel={({ route, color }) =>
layout.width > 1100 ? (
layout.width > 1100 && (
<Text style={{ color: color, paddingLeft: 10, overflow: 'hidden' }}>
{route.title}
{translate(route.title as 'settingsTabProfile' | 'settingsTabPremium' | 'settingsTabPreferences' | 'settingsTabNotifications' | 'settingsTabPrivacy' | 'settingsTabPiano')}
</Text>
) : null
)
}
tabStyle={{ flexDirection: 'row' }}
/>