[FIX] Reviwed comments on the RP

This commit is contained in:
mathysPaul
2023-11-17 00:23:28 +01:00
parent cc65a3bd09
commit 36316b0333
21 changed files with 125 additions and 1657 deletions

View File

@@ -66,9 +66,7 @@ export class ValidationError extends Error {
export default class API {
public static readonly baseUrl =
process.env.NODE_ENV != 'development' && Platform.OS === 'web'
? '/api'
: 'https://nightly.chroma.octohub.app/api';
Platform.OS === 'web' ? '/api' : process.env.EXPO_PUBLIC_API_URL!;
public static async fetch(
params: FetchParams,
handle: Pick<Required<HandleParams>, 'raw'>

View File

@@ -31,7 +31,7 @@ export const RawElement = ({ element }: RawElementProps) => {
const isSmallScreen = screenSize === 'small';
const { width: screenWidth } = useWindowDimensions();
const { colors } = useTheme();
const IconElement = icon as IconSax;
const IconElement = icon;
return (
<Column

View File

@@ -95,7 +95,7 @@ const ButtonBase: React.FC<ButtonProps> = ({
});
const typeToStyleAnimator = { filled: styleButton, outlined: styleButton, menu: styleMenu };
const MyIcon: Icon = icon as Icon;
const MyIcon = icon;
return (
<InteractiveBase
@@ -104,8 +104,13 @@ const ButtonBase: React.FC<ButtonProps> = ({
onPress={async () => {
if (onPress && !isDisabled) {
setLoading(true);
await onPress();
setLoading(false);
try {
await onPress();
} catch (error) {
console.error(error);
} finally {
setLoading(false);
}
}
}}
isDisabled={isDisabled}
@@ -124,7 +129,7 @@ const ButtonBase: React.FC<ButtonProps> = ({
type === 'menu' ? { justifyContent: 'flex-start' } : {},
]}
>
{icon && (
{MyIcon && (
<MyIcon
size={'18'}
color={

View File

@@ -1,171 +0,0 @@
import React, { useState } from 'react';
import { StyleSheet, ActivityIndicator, View, Image, StyleProp, ViewStyle } from 'react-native';
import InteractiveBase from './InteractiveBase';
import { Text, useTheme } from 'native-base';
import { Icon } from 'iconsax-react-native';
import useColorScheme from '../../hooks/colorScheme';
export type ButtonType = 'filled' | 'outlined' | 'menu';
interface ButtonProps {
title?: string;
style?: StyleProp<ViewStyle>;
onPress?: () => Promise<void>;
isDisabled?: boolean;
icon?: Icon;
iconVariant?: 'Bold' | 'Outline';
iconImage?: string;
type?: ButtonType;
}
const ButtonBase: React.FC<ButtonProps> = ({
title,
style,
onPress,
isDisabled,
icon,
iconImage,
type = 'filled',
iconVariant = 'Outline',
}) => {
const { colors } = useTheme();
const [loading, setLoading] = useState(false);
const colorScheme = useColorScheme();
const styleButton = StyleSheet.create({
Default: {
scale: 1,
shadowOpacity: 0.3,
shadowRadius: 4.65,
elevation: 8,
backgroundColor: colors.primary[400],
},
onHover: {
scale: 1.02,
shadowOpacity: 0.37,
shadowRadius: 7.49,
elevation: 12,
backgroundColor: colors.primary[500],
},
onPressed: {
scale: 0.98,
shadowOpacity: 0.23,
shadowRadius: 2.62,
elevation: 4,
backgroundColor: colors.primary[600],
},
Disabled: {
scale: 1,
shadowOpacity: 0.3,
shadowRadius: 4.65,
elevation: 8,
backgroundColor: colors.primary[400],
},
});
const styleMenu = StyleSheet.create({
Default: {
scale: 1,
shadowOpacity: 0,
shadowRadius: 0,
elevation: 0,
backgroundColor: 'transparent',
},
onHover: {
scale: 1.01,
shadowOpacity: 0.37,
shadowRadius: 7.49,
elevation: 12,
backgroundColor: colors.coolGray[400],
},
onPressed: {
scale: 0.99,
shadowOpacity: 0.23,
shadowRadius: 2.62,
elevation: 4,
backgroundColor: colors.coolGray[600],
},
Disabled: {
scale: 1,
shadowOpacity: 0.3,
shadowRadius: 4.65,
elevation: 8,
backgroundColor: colors.coolGray[500],
},
});
const typeToStyleAnimator = { filled: styleButton, outlined: styleButton, menu: styleMenu };
const MyIcon: Icon = icon as Icon;
return (
<InteractiveBase
style={[styles.container, style]}
styleAnimate={typeToStyleAnimator[type]}
onPress={async () => {
if (onPress && !isDisabled) {
setLoading(true);
await onPress();
setLoading(false);
}
}}
isDisabled={isDisabled}
isOutlined={type === 'outlined'}
>
{loading ? (
<ActivityIndicator
style={styles.content}
size="small"
color={type === 'outlined' ? '#6075F9' : '#FFFFFF'}
/>
) : (
<View
style={[
styles.content,
type === 'menu' ? { justifyContent: 'flex-start' } : {},
]}
>
{icon && (
<MyIcon
size={'18'}
color={
type === 'outlined'
? '#6075F9'
: colorScheme === 'light'
? colors.black[500]
: '#FFFFFF'
}
variant={iconVariant}
/>
)}
{iconImage && <Image source={{ uri: iconImage }} style={styles.icon} />}
{title && (
<Text style={styles.text} selectable={false}>
{title}
</Text>
)}
</View>
)}
</InteractiveBase>
);
};
const styles = StyleSheet.create({
container: {
borderRadius: 8,
},
content: {
padding: 10,
justifyContent: 'center',
flexDirection: 'row',
alignItems: 'center',
},
icon: {
width: 18,
height: 18,
},
text: {
marginHorizontal: 8,
},
});
export default ButtonBase;

View File

@@ -11,13 +11,12 @@ type GlassmorphismCCProps = {
const GlassmorphismCC = ({ children, style }: GlassmorphismCCProps) => {
const colorScheme = useColorScheme();
console.log(colorScheme);
return (
<BlurView
style={[{ borderRadius: 12 }, style]}
intensity={60}
tint={colorScheme === 'light' ? 'light' : 'dark'}
tint={colorScheme}
>
{children}
</BlurView>

View File

@@ -39,7 +39,7 @@ export interface MusicItemType {
onLike: () => void;
/** Callback function triggered when the song is played. */
onPlay?: () => void;
onPlay: () => void;
}
// Custom hook to handle the number formatting based on the current user's language.

View File

@@ -4,6 +4,7 @@ import { ActivityIndicator, StyleSheet } from 'react-native';
import MusicItem, { MusicItemType } from './MusicItem';
import ButtonBase from './ButtonBase';
import { ArrowDown2, Chart2, ArrowRotateLeft, Cup, Icon } from 'iconsax-react-native';
import { translate } from '../../i18n/i18n';
// Props type definition for MusicItemTitle.
interface MusicItemTitleProps {
@@ -108,7 +109,6 @@ function MusicListComponent({
// 'currentPage': current page in pagination.
// 'loading': indicates if more items are being loaded.
// 'hasMoreMusics': flag for more items availability.
console.log('initialMusics', initialMusics.length);
const [musicListState, setMusicListState] = useState({
allMusics: initialMusics,
displayedMusics: initialMusics.slice(0, musicsPerPage),
@@ -119,7 +119,6 @@ function MusicListComponent({
const { colors } = useTheme();
const screenSize = useBreakpointValue({ base: 'small', md: 'md', xl: 'xl' });
const isBigScreen = screenSize === 'xl';
console.log('coucou', initialMusics.length);
// Loads additional music items.
// Uses useCallback to avoid unnecessary redefinitions on re-renders.
@@ -174,12 +173,12 @@ function MusicListComponent({
paddingRight: 60,
}}
>
Song
{ translate('musicListTitleSong') }
</Text>
{[
{ text: 'level', icon: Chart2 },
{ text: 'lastScore', icon: ArrowRotateLeft },
{ text: 'BastScore', icon: Cup },
{ text: translate('musicListTitleLevel'), icon: Chart2 },
{ text: translate('musicListTitleLastScore'), icon: ArrowRotateLeft },
{ text: translate('musicListTitleBestScore'), icon: Cup },
].map((value) => (
<MusicItemTitle
key={value.text + 'key'}

View File

@@ -1,258 +0,0 @@
import { View, Image } from 'react-native';
import { Divider, Text, ScrollView, Flex, Row, Popover, Heading, Button } from 'native-base';
import useColorScheme from '../../hooks/colorScheme';
import { useQuery, useQueries } from '../../Queries';
import API from '../../API';
import Song from '../../models/Song';
import { LinearGradient } from 'expo-linear-gradient';
import ButtonBase from './ButtonBase';
import {
Cup,
Discover,
Icon,
LogoutCurve,
Music,
SearchNormal1,
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';
const menu: {
title: string;
icon: Icon;
link: string;
}[] = [
{ title: 'Discovery', icon: Discover, link: 'HomeNew' },
{ title: 'Profile', icon: User, link: 'User' },
{ title: 'Music', icon: Music, link: 'Home' },
{ title: 'Search', icon: SearchNormal1, link: 'Search' },
{ title: 'LeaderBoard', icon: Cup, link: 'Score' },
];
type ScaffoldCCProps = {
children?: React.ReactNode;
routeName: string;
};
const ScaffoldCC = (props: ScaffoldCCProps) => {
const navigation = useNavigation();
const userQuery = useQuery(API.getUserInfo);
const dispatch = useDispatch();
if (!userQuery.data || userQuery.isLoading) {
return <LoadingView />;
}
const user = userQuery.data;
const layout = useWindowDimensions();
const colorScheme = useColorScheme();
const logo =
colorScheme == 'light'
? require('../../assets/icon_light.png')
: require('../../assets/icon_dark.png');
const playHistoryQuery = useQuery(API.getUserPlayHistory);
const songHistory = useQueries(
playHistoryQuery.data?.map(({ songID }) => API.getSong(songID)) ?? []
);
return (
<Flex style={{ flex: 1 }}>
<View style={{ height: '100%', flexDirection: 'row', overflow: 'hidden' }}>
<View
style={{
display: 'flex',
width: '300px',
height: '100vh',
maxHeight: '100vh',
padding: '32px',
flexDirection: 'column',
justifyContent: 'space-between',
alignItems: 'flex-start',
flexShrink: 0,
}}
>
<View style={{ width: '100%' }}>
<Row>
<Image
source={{ uri: logo }}
style={{
aspectRatio: 1,
width: 32,
height: 32,
}}
/>
{layout.width > 650 && (
<Text fontSize={'xl'} selectable={false}>
Chromacase
</Text>
)}
</Row>
<Spacer height="xl" />
<View style={{ width: '100%' }}>
{menu.map((value) => (
<View key={'key-menu-link-' + value.title}>
<ButtonBase
style={{ width: '100%' }}
type="menu"
icon={value.icon}
title={value.title}
isDisabled={props.routeName === value.link}
iconVariant={
props.routeName === value.link ? 'Bold' : 'Outline'
}
onPress={async () =>
navigation.navigate(value.link as never)
}
/>
<Spacer />
</View>
))}
</View>
</View>
<View style={{ width: '100%' }}>
<Divider />
<Spacer />
<Text
bold
style={{
paddingHorizontal: '16px',
paddingVertical: '10px',
fontSize: 20,
}}
>
Recently played
</Text>
{songHistory.length === 0 && (
<Text
style={{
paddingHorizontal: '16px',
paddingVertical: '10px',
}}
>
No songs played yet
</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: '16px',
paddingVertical: '10px',
}}
>
<Text numberOfLines={1}>{histoItem.name}</Text>
</View>
))}
</View>
<Spacer />
<View style={{ width: '100%' }}>
<Divider />
<Spacer />
<ButtonBase
style={{ width: '100%' }}
title="Settings"
icon={Setting2}
type="menu"
isDisabled={props.routeName === 'Settings'}
iconVariant={props.routeName === 'Settings' ? 'Bold' : 'Outline'}
onPress={async () => navigation.navigate('Settings', {})}
/>
<Spacer />
{!user.isGuest && (
<ButtonBase
style={{ width: '100%' }}
icon={LogoutCurve}
title={translate('signOutBtn')}
type="menu"
onPress={async () => {
dispatch(unsetAccessToken());
}}
/>
)}
{user.isGuest && (
<Popover
trigger={(triggerProps) => (
<ButtonBase {...triggerProps}>
{translate('signOutBtn')}
</ButtonBase>
)}
>
<Popover.Content>
<Popover.Arrow />
<Popover.Body>
<Heading size="md" mb={2}>
{translate('Attention')}
</Heading>
<Text>
{translate(
'YouAreCurrentlyConnectedWithAGuestAccountWarning'
)}
</Text>
<Button.Group variant="ghost" space={2}>
<Button
onPress={() => dispatch(unsetAccessToken())}
colorScheme="red"
>
{translate('signOutBtn')}
</Button>
<Button
onPress={() => {
navigation.navigate('Login');
}}
colorScheme="green"
>
{translate('signUpBtn')}
</Button>
</Button.Group>
</Popover.Body>
</Popover.Content>
</Popover>
)}
</View>
</View>
<ScrollView
style={{ flex: 1, maxHeight: '100vh' }}
contentContainerStyle={{ flex: 1 }}
>
<View
style={{
backgroundColor: 'rgba(16,16,20,0.5)',
flex: 1,
margin: 8,
padding: 20,
borderRadius: 12,
minHeight: 'fit-content',
}}
>
{props.children}
</View>
</ScrollView>
</View>
<LinearGradient
colors={['#101014', '#6075F9']}
style={{
width: '100%',
height: '100%',
position: 'absolute',
zIndex: -2,
}}
/>
</Flex>
);
};
export default ScaffoldCC;

View File

@@ -74,7 +74,7 @@ const ScaffoldAuth: FunctionComponent<ScaffoldAuthProps> = ({
/>
{layout.width > 650 && (
<Text fontSize={'xl'} selectable={false}>
Chromacase
ChromaCase
</Text>
)}
</Row>

View File

@@ -8,19 +8,14 @@ import { LoadingView } from '../Loading';
import ScaffoldDesktopCC from './ScaffoldDesktopCC';
import ScaffoldMobileCC from './ScaffoldMobileCC';
const menu: {
type: 'main' | 'sub';
title: string;
icon: Icon;
link: string;
}[] = [
const menu = [
{ type: 'main', title: 'menuDiscovery', icon: Discover, link: 'HomeNew' },
{ 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: 'Score' },
{ type: 'sub', title: 'menuSettings', icon: Setting2, link: 'Settings' },
];
] as const;
type ScaffoldCCProps = {
children?: React.ReactNode;

View File

@@ -1,5 +1,5 @@
/* eslint-disable no-mixed-spaces-and-tabs */
import { View, Image } from 'react-native';
import { View, Image, TouchableOpacity } from 'react-native';
import { Divider, Text, ScrollView, Row, useMediaQuery, useTheme } from 'native-base';
import { useQuery, useQueries } from '../../Queries';
import API from '../../API';
@@ -7,7 +7,7 @@ import Song from '../../models/Song';
import ButtonBase from './ButtonBase';
import { Icon } from 'iconsax-react-native';
import { LoadingView } from '../Loading';
import { translate } from '../../i18n/i18n';
import { TranslationKey, translate } from '../../i18n/i18n';
import { useNavigation } from '../../Navigation';
import Spacer from './Spacer';
import User from '../../models/User';
@@ -20,48 +20,58 @@ type ScaffoldDesktopCCProps = {
user: User;
logo: string;
routeName: string;
menu: {
menu: readonly{
type: 'main' | 'sub';
title: string;
title: TranslationKey;
icon: Icon;
link: string;
}[];
};
// TODO a tester avec un historique de plus de 3 musics différente mdr !!
const SongHistory = (props: { quantity: number }) => {
const playHistoryQuery = useQuery(API.getUserPlayHistory);
const songHistory = useQueries(
playHistoryQuery.data?.map(({ songID }) => API.getSong(songID)) ?? []
);
const navigation = useNavigation();
if (!playHistoryQuery.data || playHistoryQuery.isLoading) {
const musics =
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)
.map((song: Song) => (
<View
key={'short-history-tab' + song.id}
style={{
paddingHorizontal: 16,
paddingVertical: 10,
flex: 1,
}}
>
<TouchableOpacity
onPress={() => navigation.navigate('Song', { songId: song.id })}
>
<Text numberOfLines={1}>{song.name}</Text>
</TouchableOpacity>
</View>
))
if (!playHistoryQuery.data || playHistoryQuery.isLoading || !songHistory) {
return <LoadingView />;
}
return (
<View>
{songHistory.length === 0 ? (
{musics.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>
))
musics
)}
</View>
);
@@ -148,7 +158,7 @@ const ScaffoldDesktopCC = (props: ScaffoldDesktopCCProps) => {
</View>
</View>
{!isSmallScreen && (
<View>
<View style={{width: '100%'}}>
<Divider my="2" _light={{ bg: colors.black[500] }} _dark={{ bg: '#FFF' }} />
<Spacer height="xs" />
<Text

View File

@@ -14,7 +14,7 @@ type ScaffoldMobileCCProps = {
logo: string;
routeName: string;
widthPadding: boolean;
menu: {
menu: readonly {
type: 'main' | 'sub';
title: string;
icon: Icon;
@@ -27,8 +27,6 @@ const ScaffoldMobileCC = (props: ScaffoldMobileCCProps) => {
const [isSmallScreen] = useMediaQuery({ maxWidth: 400 });
const { colors } = useTheme();
console.log(isSmallScreen);
return (
<View style={{ height: '100%', flexDirection: 'column', overflow: 'hidden' }}>
<ScrollView

View File

@@ -10,6 +10,7 @@ interface SigninFormProps {
onSubmit: (username: string, password: string) => Promise<string>;
}
// TODO not use !!
const LoginForm = ({ onSubmit }: SigninFormProps) => {
const [formData, setFormData] = React.useState({
username: {
@@ -47,7 +48,7 @@ const LoginForm = ({ onSubmit }: SigninFormProps) => {
<Input
isRequired
type="text"
placeholder="Username"
placeholder={translate('formPlaceholderUsername')}
autoComplete="username"
value={formData.username.value}
onChangeText={(t) => {
@@ -68,6 +69,7 @@ const LoginForm = ({ onSubmit }: SigninFormProps) => {
</FormControl.Label>
<Input
isRequired
placeholder={translate('formPlaceholderPassword')}
type="password"
autoComplete="password"
value={formData.password.value}

View File

@@ -58,7 +58,7 @@ const SignUpForm = ({ onSubmit }: SignupFormProps) => {
isRequired
icon={User}
error={formData.username.error}
placeholder="Username"
placeholder={translate('formPlaceholderUsername')}
autoComplete="username-new"
value={formData.username.value}
onChangeText={(t) => {
@@ -75,7 +75,7 @@ const SignUpForm = ({ onSubmit }: SignupFormProps) => {
isRequired
icon={Sms}
error={formData.email.error}
placeholder="Email"
placeholder={translate('formPlaceholderEmail')}
autoComplete="email"
value={formData.email.value}
onChangeText={(t) => {
@@ -93,7 +93,7 @@ const SignUpForm = ({ onSubmit }: SignupFormProps) => {
isSecret
icon={Lock1}
error={formData.password.error}
placeholder="Password"
placeholder={translate('formPlaceholderPassword')}
autoComplete="password-new"
value={formData.password.value}
onChangeText={(t) => {
@@ -111,7 +111,7 @@ const SignUpForm = ({ onSubmit }: SignupFormProps) => {
isSecret
error={formData.repeatPassword.error}
icon={Lock1}
placeholder="Repeat password"
placeholder={translate('formPlaceholderRepeatPassword')}
autoComplete="password-new"
value={formData.repeatPassword.value}
onChangeText={(t) => {

View File

@@ -38,6 +38,17 @@ export const en = {
levelProgress: 'good notes',
score: 'Score',
// Form
formPlaceholderUsername: 'Username',
formPlaceholderEmail: "Email",
formPlaceholderPassword: 'Password',
formPlaceholderRepeatPassword: 'Repeat password',
// MusicListTitle
musicListTitleSong : "Song",
musicListTitleLevel: 'Level',
musicListTitleLastScore: 'Last Score',
musicListTitleBestScore: 'Best Score',
// Menu
menuDiscovery: 'Discovery',
menuProfile: 'Profile',
@@ -58,7 +69,7 @@ export const en = {
//signin
signinPageTitle: 'Welcome !',
signinPageParagraph: 'Continue with Google or enter your details.',
signinLinkLabel: "You don't have an account? ",
signinLinkLabel: "You don't have an account?",
signinLinkText: 'Sign up for free.',
//music
@@ -305,8 +316,8 @@ export const fr: typeof en = {
songPageBtn: 'Aller sur la page de la chanson',
level: 'Niveau',
chapters: 'Chapitres',
bestScore: 'Meilleur Score',
lastScore: 'Dernier Score',
bestScore: 'Meilleur',
lastScore: 'Dernier',
bestStreak: 'Meilleure série',
precision: 'Précision',
@@ -330,6 +341,16 @@ export const fr: typeof en = {
longestCombo: 'Combo le plus long : ',
favoriteGenre: 'Genre favori : ',
// Form
formPlaceholderUsername : "Nom d'utilisateur",
formPlaceholderEmail : "Email",
formPlaceholderPassword : 'Mot de passe',
formPlaceholderRepeatPassword : 'Répéter le mot de passe',
// MusicListTitle
musicListTitleSong : "Musique",
musicListTitleLevel : "Niveau",
musicListTitleLastScore : "Dernier",
musicListTitleBestScore : "Meilleur",
// Menu
menuDiscovery: 'Découverte',
menuProfile: 'Profil',
@@ -350,7 +371,7 @@ export const fr: typeof en = {
//signin
signinPageTitle: 'Bienvenue !',
signinPageParagraph: 'Continuez avec Google ou entrez vos coordonnées.',
signinLinkLabel: "Vous n'avez pas de compte ? ",
signinLinkLabel: "Vous n'avez pas de compte ?",
signinLinkText: 'Inscrivez-vous gratuitement',
//music
@@ -635,6 +656,17 @@ export const sp: typeof en = {
longestCombo: 'combo más largo : ',
favoriteGenre: 'genero favorito : ',
// Form
formPlaceholderUsername: 'NombreUsuario',
formPlaceholderEmail: "Email",
formPlaceholderPassword: 'Contraseña',
formPlaceholderRepeatPassword: 'Repetir contraseña',
// MusicListTitle
musicListTitleSong : "Canción",
musicListTitleLevel: 'Nivel',
musicListTitleLastScore: 'Última',
musicListTitleBestScore: 'Mejor',
// Menu
menuDiscovery: 'Descubrimiento',
menuProfile: 'Perfil',
@@ -655,7 +687,7 @@ export const sp: typeof en = {
//signin
signinPageTitle: 'Bienvenido !',
signinPageParagraph: 'Continúa con Google o introduce tus datos.',
signinLinkLabel: '¿No tienes una cuenta? ',
signinLinkLabel: '¿No tienes una cuenta?',
signinLinkText: 'Regístrate gratis.',
//music

View File

@@ -39,4 +39,6 @@ export const translate = (key: keyof typeof en, language?: AvailableLanguages) =
});
};
export type TranslationKey = keyof typeof en;
export { Translate };

View File

@@ -24,7 +24,7 @@
"@react-navigation/native": "^6.1.8",
"@react-navigation/native-stack": "^6.9.14",
"@reduxjs/toolkit": "^1.9.6",
"expo": "^49.0.16",
"expo": "~49.0.13",
"expo-blur": "~12.4.1",
"expo-image-picker": "~14.3.2",
"expo-linear-gradient": "~12.3.0",

File diff suppressed because it is too large Load Diff

View File

@@ -69,7 +69,7 @@ const SigninView = () => {
key={'signin-form-1'}
error={formData.username.error}
icon={User}
placeholder="Username"
placeholder={translate('formPlaceholderUsername')}
autoComplete="username"
value={formData.username.value}
onChangeText={(t) => {
@@ -87,7 +87,7 @@ const SigninView = () => {
key={'signin-form-2'}
error={formData.password.error}
icon={Lock1}
placeholder="Password"
placeholder={translate('formPlaceholderPassword')}
autoComplete="password"
value={formData.password.value}
onChangeText={(t) => {
@@ -136,7 +136,7 @@ const SigninView = () => {
/>
}
link={{
label: translate('signinLinkLabel'),
label: translate('signinLinkLabel') + ' ',
text: translate('signinLinkText'),
onPress: () => navigation.navigate('Signup'),
}}

View File

@@ -83,7 +83,7 @@ const SignupView = () => {
key={'signup-form-1'}
error={formData.username.error}
icon={User}
placeholder="Username"
placeholder={translate('formPlaceholderUsername')}
autoComplete="username"
value={formData.username.value}
onChangeText={(t) => {
@@ -101,7 +101,7 @@ const SignupView = () => {
key={'signup-form-2'}
error={formData.email.error}
icon={Sms}
placeholder="Email"
placeholder={translate('formPlaceholderEmail')}
autoComplete="email"
value={formData.email.value}
onChangeText={(t) => {
@@ -121,7 +121,7 @@ const SignupView = () => {
isSecret
error={formData.password.error}
icon={Lock1}
placeholder="Password"
placeholder={translate('formPlaceholderPassword')}
autoComplete="password-new"
value={formData.password.value}
onChangeText={(t) => {
@@ -140,7 +140,7 @@ const SignupView = () => {
isSecret
error={formData.repeatPassword.error}
icon={Lock1}
placeholder="Repeat password"
placeholder={translate('formPlaceholderRepeatPassword')}
autoComplete="password-new"
value={formData.repeatPassword.value}
onChangeText={(t) => {

View File

@@ -27,6 +27,7 @@ import PremiumSettings from './SettingsPremium';
import { RouteProps } from '../../Navigation';
import ScaffoldCC from '../../components/UI/ScaffoldCC';
import { translate } from '../../i18n/i18n';
import { useLanguage } from '../../state/LanguageSlice';
export const PianoSettings = () => {
return (
@@ -69,7 +70,7 @@ const SettingsTab = (props: RouteProps<{}>) => {
const layout = useWindowDimensions();
const [index, setIndex] = React.useState(0);
const { colors } = useTheme();
const [routes] = React.useState<Route[]>([
const routes = ([
{ key: 'profile', title: 'settingsTabProfile' },
{ key: 'premium', title: 'settingsTabPremium' },
{ key: 'preferences', title: 'settingsTabPreferences' },