end of home

This commit is contained in:
Thomas Demirdjian
2025-10-01 10:49:03 +02:00
parent 4097143559
commit 167e62fcfc
18 changed files with 928 additions and 558 deletions
-3
View File
@@ -55,9 +55,6 @@ const BorderGradientButton = ({
borderRadius: 14,
gap: 11,
}}
// experimentalBlurMethod={
// Platform.OS !== "ios" ? "dimezisBlurView" : "none"
// }
>
{icon && <Image source={icon} style={size({ size: 16 })} />}
<Text
@@ -0,0 +1,148 @@
import React, { useCallback, useEffect, useMemo, useRef } from "react";
import { FlatList, StyleSheet, View, useWindowDimensions } from "react-native";
import PersonaCard from "../cards/PersonaCard/PersonaCard";
import { ai } from "../../assets";
import { getCreationStageStates } from "../../utils/projectStages";
const STAGE_CARD_CONTENT = [
{
key: "songwriter",
title: "Nathalie",
description: "Lets write lyrics together !",
image: ai.nathalie,
},
{
key: "beatmaker",
title: "Theo",
description: "Come back, when you'll have lyrics!",
image: ai.theo,
},
{
key: "designer",
title: "Bena",
description: "Come back when you want to generate cover!",
image: ai.bena,
},
{
key: "director",
title: "John",
description: "Come back when your audio is ready!",
image: ai.john,
},
];
const FeatureCarousel = ({
style,
selectedProject,
activeIndex,
onActiveIndexChange,
}) => {
const stageStates = useMemo(
() => getCreationStageStates(selectedProject),
[selectedProject],
);
const carouselItems = useMemo(
() =>
STAGE_CARD_CONTENT.map((item, index) => ({
...item,
isLocked: stageStates[index]?.isLocked ?? true,
})),
[stageStates],
);
const { height: windowHeight } = useWindowDimensions();
const itemHeight = Math.max(windowHeight, 1);
const listRef = useRef(null);
const keyExtractor = useCallback((item) => item.key, []);
const renderItem = useCallback(
({ item }) => <PersonaCard item={item} isLock={item.isLocked} />,
[],
);
const getItemLayout = useCallback(
(_data, index) => ({
length: itemHeight,
offset: itemHeight * index,
index,
}),
[itemHeight],
);
const viewabilityConfig = useRef({ viewAreaCoveragePercentThreshold: 60 });
const handleViewableItemsChanged = useCallback(
({ viewableItems }) => {
if (!onActiveIndexChange) {
return;
}
const firstVisible = viewableItems?.[0];
if (firstVisible?.index != null) {
onActiveIndexChange(firstVisible.index);
}
},
[onActiveIndexChange],
);
useEffect(() => {
if (
listRef.current == null ||
typeof activeIndex !== "number" ||
activeIndex < 0 ||
activeIndex >= carouselItems.length
) {
return;
}
try {
listRef.current.scrollToIndex({ index: activeIndex, animated: true });
} catch (_error) {
// Ignore scroll errors when list is not ready yet.
}
}, [activeIndex, carouselItems.length]);
return (
<View style={[styles.container, style]}>
<FlatList
ref={listRef}
data={carouselItems}
keyExtractor={keyExtractor}
renderItem={renderItem}
onViewableItemsChanged={handleViewableItemsChanged}
viewabilityConfig={viewabilityConfig.current}
getItemLayout={getItemLayout}
showsVerticalScrollIndicator={false}
pagingEnabled
initialNumToRender={1}
maxToRenderPerBatch={2}
windowSize={3}
scrollEventThrottle={16}
snapToAlignment="start"
snapToInterval={itemHeight}
decelerationRate="fast"
style={styles.list}
contentContainerStyle={styles.listContent}
/>
</View>
);
};
export default FeatureCarousel;
const styles = StyleSheet.create({
container: {
flex: 1,
width: "100%",
},
list: {
flex: 1,
},
listContent: {
flexGrow: 1,
},
cardRight: {
flexDirection: "row-reverse",
alignItems: "center",
},
});
@@ -124,12 +124,20 @@ const ProjectDropDown = ({
<BlurView
intensity={BUTTON_BLUR_INTENSITY}
tint="dark"
style={[
styles.dropdownOverlayBlur,
{
width: dropdownWidth || "100%",
},
]}
style={{
position: "absolute",
top: 0,
left: 0,
borderRadius: 16,
paddingHorizontal: 8,
paddingVertical: 8,
gap: 9,
maxHeight: 400,
zIndex: 4,
elevation: 4,
width: dropdownWidth || "100%",
overflow: "hidden",
}}
>
<ProjectRow
isTitle={true}
@@ -279,6 +287,7 @@ const styles = StyleSheet.create({
borderRadius: 15,
padding: 8,
position: "relative",
overflow: "hidden",
},
dropdownBlurDisabled: {
opacity: 0.6,
@@ -291,18 +300,6 @@ const styles = StyleSheet.create({
position: "relative",
zIndex: 3,
},
dropdownOverlayBlur: {
position: "absolute",
top: 0,
left: 0,
borderRadius: 16,
paddingHorizontal: 8,
paddingVertical: 8,
gap: 9,
maxHeight: 400,
zIndex: 4,
elevation: 4,
},
dropdownOverlayContent: {
maxHeight: 260,
width: "100%",
@@ -346,6 +343,7 @@ const styles = StyleSheet.create({
paddingHorizontal: 18,
paddingVertical: 12,
borderRadius: 10,
overflow: "hidden",
},
projectImage: {
width: 60,
+31
View File
@@ -0,0 +1,31 @@
import React from "react";
import { BlurView } from "expo-blur";
import { Pressable } from "react-native";
import { Entypo } from "@expo/vector-icons";
export default function ShareBtn({ style, onPress = null }) {
return (
<Pressable
onPress={onPress}
disabled={!onPress}
style={{
...style,
}}
>
<BlurView
intensity={20}
tint="dark"
style={{
padding: 12,
borderRadius: 15,
overflow: "hidden",
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
}}
>
<Entypo name="share-alternative" size={18} color="white" />
</BlurView>
</Pressable>
);
}
+41
View File
@@ -0,0 +1,41 @@
import React from "react";
import { BlurView } from "expo-blur";
import { Pressable, Text } from "react-native";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { Entypo } from "@expo/vector-icons";
export default function ShareBtn({ style, onPress = null }) {
return (
<Pressable
onPress={onPress}
disabled={!onPress}
style={{
...style,
}}
>
<BlurView
style={{
paddingHorizontal: 10,
paddingVertical: 5,
borderRadius: 15,
flexDirection: "row",
alignItems: "center",
justifyContent: "center",
}}
>
<Text
style={{
fontSize: 14,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
marginRight: 5,
}}
>
{"Partager lexpérience"}
</Text>
<Entypo name="share-alternative" size={16} color="white" />
</BlurView>
</Pressable>
);
}
@@ -0,0 +1,99 @@
import React from "react";
import { Text, useWindowDimensions, View } from "react-native";
import { Image } from "expo-image";
import { BlurView } from "expo-blur";
import { gutters, Palette } from "../../../styles";
import { FONT_FAMILY } from "../../../styles/Fonts";
import FontAwesome from "@expo/vector-icons/FontAwesome";
import palette from "../../../styles/Palette";
export default function PersonaCard({ item, isLock = false }) {
const { height: windowHeight } = useWindowDimensions();
return (
<View
style={{
justifyContent: "center",
alignItems: "center",
height: windowHeight,
marginTop: -20,
}}
>
<View
style={{
borderRadius: 10,
alignItems: "center",
justifyContent: "center",
width: "100%",
}}
>
<Image
source={item.image}
style={{ height: 190, width: "100%" }}
contentFit="contain"
/>
<BlurView
intensity={30}
tint="dark"
style={{
borderRadius: 20,
paddingVertical: 20,
paddingHorizontal: gutters,
overflow: "hidden",
width: "100%",
}}
>
<Text
style={{
fontSize: 18,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
marginBottom: 15,
}}
>
{item.title}
</Text>
<Text
style={{
fontSize: 12,
lineHeight: 20,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
{item.description}
</Text>
{isLock && (
<View
pointerEvents="none"
style={{
position: "absolute",
left: 0,
right: 0,
top: 0,
bottom: 0,
borderRadius: 20,
justifyContent: "center",
alignItems: "center",
backgroundColor: "rgba(0,0,0,0.2)",
}}
>
<View
style={{
width: 36,
height: 36,
borderRadius: 18,
backgroundColor: "rgba(0,0,0,0.4)",
alignItems: "center",
justifyContent: "center",
}}
>
<FontAwesome name="lock" size={24} color={palette.primary} />
</View>
</View>
)}
</BlurView>
</View>
</View>
);
}
@@ -0,0 +1,111 @@
import React from "react";
import { Text, useWindowDimensions, View } from "react-native";
import { Image } from "expo-image";
import { BlurView } from "expo-blur";
import { Palette } from "../../../styles";
import { FONT_FAMILY } from "../../../styles/Fonts";
import FontAwesome from "@expo/vector-icons/FontAwesome";
import palette from "../../../styles/Palette";
export default function PersonaCard({ item, index, isLock = true }) {
const isImageOnLeft = index % 2 === 0;
const { height: windowHeight } = useWindowDimensions();
return (
<View
style={{
width: "100%",
justifyContent: "center",
alignItems: "center",
height: windowHeight,
marginTop: 50,
}}
>
<View
style={{
padding: 10,
borderRadius: 10,
backgroundColor: isLock
? "rgba(0, 0, 0, 0.2)"
: "rgba(0, 0, 0, 0.05)",
alignItems: "center",
justifyContent: "center",
width: "90%",
height: "30%",
flexDirection: isImageOnLeft ? "row" : "row-reverse",
}}
>
<Image
source={item.image}
style={{ height: 250, width: 400 }}
contentFit="contain"
/>
<BlurView
intensity={30}
tint="dark"
style={{
flex: 1,
borderRadius: 20,
paddingHorizontal: 18,
paddingVertical: 16,
}}
>
<View
style={{
minHeight: 100,
}}
>
<Text
style={{
fontSize: 20,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
marginBottom: 8,
}}
>
{item.title}
</Text>
<Text
style={{
fontSize: 14,
lineHeight: 20,
color: "rgba(255, 255, 255, 0.7)",
fontFamily: FONT_FAMILY.InterRegular,
}}
>
{item.description}
</Text>
{isLock && (
<View
pointerEvents="none"
style={{
position: "absolute",
left: 0,
right: 0,
top: 0,
bottom: 0,
borderRadius: 20,
justifyContent: "center",
alignItems: "center",
}}
>
<View
style={{
width: 36,
height: 36,
borderRadius: 18,
backgroundColor: "rgba(0,0,0,0.4)",
alignItems: "center",
justifyContent: "center",
}}
>
<FontAwesome name="lock" size={24} color={palette.primary} />
</View>
</View>
)}
</View>
</BlurView>
</View>
</View>
);
}