[ADD] SettingsView: translation, Menu: collapsed mode && translation
This commit is contained in:
@@ -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')}
|
||||
|
||||
@@ -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 = {
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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' }}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user