[IMP] Color theme & MusicList optional property

This commit is contained in:
mathysPaul
2023-11-13 14:30:10 +01:00
parent ee98e6e352
commit 19d64c1bc5
13 changed files with 110 additions and 223 deletions
-137
View File
@@ -1,137 +0,0 @@
import { FlatList, HStack, View, useBreakpointValue, useTheme, Text, Row } from 'native-base';
import MusicItem, { MusicItemType } from './MusicItem';
import React, { useState } from 'react';
import { ActivityIndicator } from 'react-native';
import { ArrowDown2, ArrowRotateLeft, Chart2, Cup, Icon } from 'iconsax-react-native';
import { StyleSheet } from 'react-native';
import ButtonBase from './ButtonBase';
import useColorScheme from '../../hooks/colorScheme';
interface MusicItemTitleProps {
text: string;
icon: Icon;
isBigScreen: boolean;
}
const MusicItemTitle = (props: MusicItemTitleProps) => {
const colorScheme = useColorScheme();
return (
<Row
style={{
display: 'flex',
flex: 1,
maxWidth: props.isBigScreen ? 150 : 50,
height: '100%',
alignItems: 'center',
justifyContent: props.isBigScreen ? 'flex-end' : 'center',
}}
>
{props.isBigScreen && (
<Text fontSize="lg" style={{ paddingRight: 8 }}>
{props.text}
</Text>
)}
<props.icon
size={18}
color={colorScheme === 'light' ? 'rgba(0,0,0,0.7)' : 'rgba(255,255,255,0.7)'}
/>
</Row>
);
};
type MusicListProps = {
initialMusics: MusicItemType[];
loadMoreMusics: (page: number) => Promise<MusicItemType[]>; // fonction pour charger plus de musiques
};
const MusicList: React.FC<MusicListProps> = ({ initialMusics }) => {
const [musicData, setMusicData] = useState<MusicItemType[]>(initialMusics);
const [loading, setLoading] = useState(false);
const { colors } = useTheme();
const screenSize = useBreakpointValue({ base: 'small', md: 'md', xl: 'xl' });
const isSmallScreen = screenSize === 'small';
const isBigScreen = screenSize === 'xl';
const loadMoreMusicItems = () => {
if (!loading) {
setLoading(true);
setTimeout(() => {
const moreItems: MusicItemType[] = [];
setMusicData((currentItems) => [...currentItems, ...moreItems]);
setLoading(false);
}, 2000); // Simule un appel réseau avec un délai de 2 secondes.
}
};
return (
<View>
<View style={styles.container}>
<HStack
space={isSmallScreen ? 1 : 2}
style={{
backgroundColor: colors.coolGray[500],
paddingHorizontal: isSmallScreen ? 8 : 16,
paddingVertical: 12,
}}
>
<Text
fontSize="lg"
style={{
flex: 4,
width: '100%',
justifyContent: 'center',
paddingRight: 60,
}}
>
Song
</Text>
{[
{ text: 'level', icon: Chart2 },
{ text: 'lastScore', icon: ArrowRotateLeft },
{ text: 'BastScore', icon: Cup },
].map((value) => (
<MusicItemTitle
key={value.text + 'key'}
text={value.text}
icon={value.icon}
isBigScreen={isBigScreen}
/>
))}
</HStack>
<FlatList
data={musicData}
renderItem={({ item }) => <MusicItem style={{ marginBottom: 2 }} {...item} />}
keyExtractor={(item) => item.artist + item.song}
/>
</View>
<View style={styles.footerContainer}>
{loading ? (
<ActivityIndicator color={colors.primary[300]} />
) : (
<ButtonBase
style={{ borderRadius: 999 }}
onPress={loadMoreMusicItems}
icon={ArrowDown2}
/>
)}
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
gap: 2,
borderRadius: 10,
overflow: 'hidden',
},
footerContainer: {
height: 60,
justifyContent: 'center',
alignItems: 'center',
},
});
export default MusicList;
+12 -9
View File
@@ -4,7 +4,6 @@ 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 useColorScheme from '../../hooks/colorScheme';
// Props type definition for MusicItemTitle.
interface MusicItemTitleProps {
@@ -19,7 +18,7 @@ interface MusicItemTitleProps {
}
function MusicItemTitleComponent(props: MusicItemTitleProps) {
const colorScheme = useColorScheme();
const { colors } = useTheme();
return (
<Row
@@ -41,7 +40,7 @@ function MusicItemTitleComponent(props: MusicItemTitleProps) {
{/* Icon with color based on the current color scheme. */}
<props.icon
size={18}
color={colorScheme === 'light' ? 'rgba(0,0,0,0.7)' : 'rgba(255,255,255,0.7)'}
color={colors.text[700]}
/>
</Row>
);
@@ -64,12 +63,12 @@ type MusicListProps = {
* Function to load more music items asynchronously. Called with current page number
* and the list of all music items. Should return a Promise with additional music items.
*/
loadMoreMusics: (page: number, musics: MusicItemType[]) => Promise<MusicItemType[]>;
loadMoreMusics?: (page: number, musics: MusicItemType[]) => Promise<MusicItemType[]>;
/**
* Number of music items to display per page. Determines initial and additional items displayed.
*/
musicsPerPage: number;
musicsPerPage?: number;
};
/**
@@ -101,23 +100,25 @@ type MusicListProps = {
* making it suitable for use cases where the list of items is expected to grow over time.
* - The layout and styling are optimized for performance and responsiveness.
*/
function MusicListComponent({ initialMusics, loadMoreMusics, musicsPerPage }: MusicListProps) {
function MusicListComponent({ initialMusics, loadMoreMusics, musicsPerPage = loadMoreMusics ? 50 : initialMusics.length }: MusicListProps) {
// State initialization for MusicList.
// 'allMusics': all music items.
// 'displayedMusics': items displayed per page.
// '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),
currentPage: 1,
loading: false,
hasMoreMusics: true,
hasMoreMusics: initialMusics.length > musicsPerPage || !!loadMoreMusics,
});
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.
@@ -132,11 +133,13 @@ function MusicListComponent({ initialMusics, loadMoreMusics, musicsPerPage }: Mu
const nextEndIndex = (musicListState.currentPage + 1) * musicsPerPage;
let updatedAllMusics = musicListState.allMusics;
if (updatedAllMusics.length <= nextEndIndex) {
if (loadMoreMusics && updatedAllMusics.length <= nextEndIndex) {
const newMusics = await loadMoreMusics(musicListState.currentPage, updatedAllMusics);
updatedAllMusics = [...updatedAllMusics, ...newMusics];
hasMoreMusics = newMusics.length > 0;
}
} else {
hasMoreMusics = updatedAllMusics.length > nextEndIndex;
}
setMusicListState((prevState) => ({
...prevState,
+2 -5
View File
@@ -1,7 +1,6 @@
import React, { FunctionComponent, ReactNode } from 'react';
import { View, StyleSheet } from 'react-native';
import { Text, useTheme } from 'native-base';
import useColorScheme from '../../hooks/colorScheme';
const styles = StyleSheet.create({
line: {
@@ -24,15 +23,13 @@ interface SeparatorBaseProps {
}
const SeparatorBase: FunctionComponent<SeparatorBaseProps> = ({ children }) => {
const colorScheme = useColorScheme();
const { colors } = useTheme();
const color = colorScheme === 'light' ? colors.black[500] : '#FFFFFF';
return (
<View style={styles.container}>
<View style={[styles.line, { backgroundColor: color }]} />
<View style={[styles.line, { backgroundColor: colors.text[700] }]} />
<Text style={styles.text}>{children}</Text>
<View style={[styles.line, { backgroundColor: color }]} />
<View style={[styles.line, { backgroundColor: colors.text[700] }]} />
</View>
);
};
+1 -5
View File
@@ -3,7 +3,6 @@ import React, { useState } from 'react';
import { View, TouchableOpacity, StyleSheet, StyleProp, ViewStyle } from 'react-native';
import InteractiveBase from './InteractiveBase';
import { Input, useTheme } from 'native-base';
import useColorScheme from '../../hooks/colorScheme';
export interface TextFieldBaseProps {
style?: StyleProp<ViewStyle>;
@@ -69,7 +68,6 @@ const TextFieldBase: React.FC<TextFieldBaseProps> = ({
const [isFocused, setFocused] = useState(false);
const MyIcon: Icon = icon as Icon;
const { colors } = useTheme();
const colorScheme = useColorScheme();
const styleAnimate = StyleSheet.create({
Default: {
@@ -124,9 +122,7 @@ const TextFieldBase: React.FC<TextFieldBaseProps> = ({
style={[styles.input, icon ? {} : { paddingLeft: 12 }]}
autoComplete={autoComplete}
placeholder={placeholder + (isRequired ? '*' : '')}
placeholderTextColor={
colorScheme === 'light' ? 'rgba(0,0,0,0.7)' : 'rgba(255,255,255,0.7)'
}
placeholderTextColor={colors.text[700]}
secureTextEntry={isSecret ? !isPasswordVisible : false}
onFocus={() => setFocused(true)}
onBlur={() => setFocused(false)}