This commit is contained in:
Philip Cesar Garay
2025-08-12 21:03:49 +08:00
parent 5a521d2f3d
commit 7d8942e125
49 changed files with 1002 additions and 122 deletions
+3
View File
@@ -61,6 +61,9 @@ const App = () => {
HelveticaNeueRegular: require("./src/assets/fonts/HelveticaNeueRegular.ttf"),
HelveticaNeueMedium: require("./src/assets/fonts/HelveticaNeueMedium.ttf"),
HelveticaNeueBold: require("./src/assets/fonts/HelveticaNeueBold.ttf"),
OwnersRegular: require("./src/assets/fonts/OwnersRegular.ttf"),
OwnersMedium: require("./src/assets/fonts/OwnersMedium.ttf"),
OwnersBold: require("./src/assets/fonts/OwnersBold.ttf"),
});
useEffect(() => {
+1 -1
View File
@@ -76,7 +76,7 @@
"react-native-linear-gradient": "^2.8.3",
"react-native-minuit": "^1.3.52",
"react-native-reanimated": "~3.16.1",
"react-native-reanimated-carousel": "^4.0.0-alpha.8",
"react-native-reanimated-carousel": "^4.0.3",
"react-native-responsive-dimensions": "^3.1.1",
"react-native-safe-area-context": "4.12.0",
"react-native-store-review": "^0.3.0",
Binary file not shown.

After

Width:  |  Height:  |  Size: 558 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 783 B

After

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 231 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 290 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 532 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 796 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 336 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 160 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

+18
View File
@@ -4,6 +4,11 @@ import chat from "./UI/tabs/chat.png";
import design from "./UI/tabs/design.png";
import quotes from "./UI/tabs/quotes.png";
import settings from "./UI/tabs/settings.png";
import addTab from "./UI/tabs/add.png";
import albums from "./UI/tabs/albums.png";
import ribbon from "./UI/tabs/ribbon.png";
import mic from "./UI/tabs/mic.png";
import person from "./UI/tabs/person.png";
export const tabs = {
home,
@@ -12,6 +17,11 @@ export const tabs = {
quotes,
chat,
design,
addTab,
albums,
ribbon,
mic,
person,
};
import bell from "./UI/bell.png";
@@ -66,6 +76,9 @@ import disk from "./icons/disk.png";
import stars from "./icons/stars.png";
import musicLandLogo from "./icons/musicLandLogo.png";
import close from "./icons/close.png";
import heart from "./icons/heart.png";
import heartOutline from "./icons/heartOutline.png";
import more from "./icons/more.png";
export const icons = {
bell,
@@ -119,6 +132,9 @@ export const icons = {
stars,
musicLandLogo,
close,
heart,
heartOutline,
more,
};
import triangle from "./art/triangle.png";
@@ -169,6 +185,7 @@ import productionBG from "./UI/productionBG.png";
import productionBG2 from "./UI/productionBG2.png";
import playbackBG from "./UI/playbackBG.png";
import playbackBG2 from "./UI/playbackBG2.png";
import libraryBG from "./UI/libraryBG.png";
export const background = {
writingBG,
@@ -178,6 +195,7 @@ export const background = {
productionBG2,
playbackBG,
playbackBG2,
libraryBG,
};
import nathalie from "./UI/nathalie.png";
@@ -4,17 +4,24 @@ import BorderGradient from "../BorderGradient/BorderGradient";
import { BlurView } from "expo-blur";
import { responsiveHeight } from "react-native-responsive-dimensions";
const ItemContainer = ({ height = responsiveHeight(40), children }) => {
const ItemContainer = ({
height = responsiveHeight(40),
children,
gradientProps,
style,
}) => {
return (
<BorderGradient
gradientProps={{
colors: ["#FFFFFF00", "#FFFFFF"],
start: { x: 0.3, y: 0 },
end: { x: 1, y: 1 },
...gradientProps,
}}
style={{
...styles.borderGradientStyle,
height,
...style,
}}
>
<View style={styles.blurContainer}>
@@ -5,7 +5,12 @@ import { responsiveHeight } from "react-native-responsive-dimensions";
import { BlurView } from "expo-blur";
import { Style } from "../../styles";
const ItemContainer = ({ height = responsiveHeight(40), children }) => {
const ItemContainer = ({
height = responsiveHeight(40),
children,
gradientProps,
style,
}) => {
const [containerLayout, setContainerLayout] = useState(null);
return (
@@ -20,10 +25,12 @@ const ItemContainer = ({ height = responsiveHeight(40), children }) => {
start: { x: 0.3, y: 0 },
end: { x: 1, y: 1 },
locations: [0, 1],
...gradientProps,
}}
style={{
...styles.borderGradientStyle,
height: containerLayout?.height,
...style,
}}
/>
<View
+4 -1
View File
@@ -13,7 +13,10 @@ const MusicLandHeader = ({
}) => {
return (
<View style={{ alignItems: "center", gap: 16 }}>
<Image source={icons.musicLandLogo} />
<Image
source={icons.musicLandLogo}
/>
<View style={{ width: "100%", ...Style.containerRow, gap: 16 }}>
<Pressable
style={{ width: 24, height: 24, ...Style.containerCenter }}
+37
View File
@@ -0,0 +1,37 @@
import { View, Text, TextInput, Image } from "react-native";
import React from "react";
import { BlurView } from "expo-blur";
import { icons } from "../assets";
import Style, { size } from "../styles/Style";
import { Palette } from "../styles";
import { FONT_FAMILY } from "../styles/Fonts";
const SearchBar = ({ placeholder = "Que souhaites-tu écouter?" }) => {
return (
<View style={{ borderRadius: 12, overflow: "hidden" }}>
<BlurView
intensity={10}
style={{
height: 40,
paddingHorizontal: 8,
gap: 10,
...Style.containerRow,
}}
>
<Image source={icons.search} />
<TextInput
placeholder={placeholder}
placeholderTextColor={Palette.gray}
style={{
fontSize: 12,
color: Palette.white,
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
flex: 1,
}}
/>
</BlurView>
</View>
);
};
export default SearchBar;
+9
View File
@@ -493,3 +493,12 @@ export const INSTRUMENTS = [
];
export const RHYTHM = ["Très rapide", "Rapide", "Normal", "Lent", "Très lent"];
export const CHOOSE_DECOR = [
"Plage",
"Café",
"Montagne",
"Rue",
"Jardin",
"Neige",
];
+33 -9
View File
@@ -17,6 +17,7 @@ import TabBar from "./TabBar";
import HomeStack from "./HomeStack";
import ChatStack from "./ChatStack";
import SettingsStack from "./SettingsStack";
import Library from "../screens/Library/Library.js";
const bottomTabStyles = StyleSheet.create({
icon: {
@@ -33,13 +34,13 @@ export const BottomTabScreen = () => {
<Motion.Image
resizeMode={"contain"}
animate={{
tintColor: focused ? Palette.primary : Palette.white,
tintColor: focused ? Palette.white : "#8B8883",
}}
style={[
bottomTabStyles.icon,
{
width: "55%",
height: "55%",
width: 24,
height: 24,
},
]}
source={icon}
@@ -49,30 +50,53 @@ export const BottomTabScreen = () => {
return (
<BottomTab.Navigator tabBar={(props) => <TabBar {...props} />}>
<BottomTab.Screen
name={Routes.HomeStack}
name={Routes.Create}
component={HomeStack}
options={{
tabBarLabel: "Créer",
headerShown: false,
tabBarShowLabel: true,
tabBarIcon: ({ focused }) => renderIcon(tabs.home, focused),
tabBarIcon: ({ focused }) => renderIcon(tabs.addTab, focused),
}}
/>
<BottomTab.Screen
name={Routes.ChatStack}
name={Routes.HitParade}
component={ChatStack}
options={{
tabBarLabel: "Hit Parade",
headerShown: false,
tabBarShowLabel: true,
tabBarIcon: ({ focused }) => renderIcon(tabs.chat, focused),
tabBarIcon: ({ focused }) => renderIcon(tabs.ribbon, focused),
}}
/>
<BottomTab.Screen
name={Routes.SettingsStack}
name={Routes.Playbacks}
component={SettingsStack}
options={{
tabBarLabel: "Playbacks",
headerShown: false,
tabBarShowLabel: true,
tabBarIcon: ({ focused }) => renderIcon(tabs.settings, focused),
tabBarIcon: ({ focused }) => renderIcon(tabs.mic, focused),
}}
/>
<BottomTab.Screen
name={Routes.Library}
component={Library}
options={{
tabBarLabel: "Librairie",
headerShown: false,
tabBarShowLabel: true,
tabBarIcon: ({ focused }) => renderIcon(tabs.albums, focused),
}}
/>
<BottomTab.Screen
name={Routes.Profile}
component={SettingsStack}
options={{
tabBarLabel: "Profil",
headerShown: false,
tabBarShowLabel: true,
tabBarIcon: ({ focused }) => renderIcon(tabs.person, focused),
}}
/>
</BottomTab.Navigator>
+15
View File
@@ -42,6 +42,9 @@ import PlaybackOnboarding from "../screens/Playback/PlaybackOnboarding";
import Playback from "../screens/Playback/Playback";
import RecordPlayback from "../screens/Playback/RecordPlayback";
import RecordedPlayback from "../screens/Playback/RecordedPlayback";
import ChooseDecor from "../screens/Playback/ChooseDecor";
import CreatingDecor from "../screens/Playback/CreatingDecor";
import VideoFinalize from "../screens/Playback/VideoFinalize";
const screenOptions = {
headerShown: false,
@@ -193,6 +196,18 @@ const screens = [
name: Routes.RecordedPlayback,
component: RecordedPlayback,
},
{
name: Routes.ChooseDecor,
component: ChooseDecor,
},
{
name: Routes.CreatingDecor,
component: CreatingDecor,
},
{
name: Routes.VideoFinalize,
component: VideoFinalize,
},
];
export default function Main() {
+9
View File
@@ -53,4 +53,13 @@ export const Routes = {
Playback: "Playback",
RecordPlayback: "RecordPlayback",
RecordedPlayback: "RecordedPlayback",
ChooseDecor: "ChooseDecor",
CreatingDecor: "CreatingDecor",
VideoFinalize: "VideoFinalize",
Create: "Create",
HitParade: "HitParade",
Playbacks: "Playbacks",
Library: "Library",
Profile: "Profile",
};
+45 -12
View File
@@ -1,9 +1,14 @@
import React from "react";
import { View, TouchableOpacity } from "react-native";
import { View, TouchableOpacity, Text } from "react-native";
import * as Haptics from "expo-haptics";
import { gutters, Palette, Style } from "../styles";
import useLayoutType from "../hooks/useLayoutType";
import BorderGradient from "../components/BorderGradient/BorderGradient";
import { colors } from "react-native-swiper-flatlist/src/themes";
import { BlurView } from "expo-blur";
import ItemContainer from "../components/ItemContainer/ItemContainer";
import { FONT_FAMILY } from "../styles/Fonts";
const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => {
const { isDesktop, windowWidth, mediumDesktopBreakpoint, isWeb } =
@@ -14,24 +19,40 @@ const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => {
style={{
position: "absolute",
bottom: gutters * 2,
borderRadius: 500,
flexDirection: "row",
height: 60,
width: "60%",
width: "90%",
alignSelf: "center",
maxWidth: isDesktop ? 200 : 220,
borderColor: Palette.ultraLightWhite,
borderWidth: 3,
paddingHorizontal: 1.2 * gutters,
backgroundColor: Palette.darkPurple,
zIndex: 1,
justifyContent: "center",
}}
>
<ItemContainer
height={64}
gradientProps={{
start: { x: 0, y: 0 },
end: { x: 1, y: 0 },
}}
style={{
height: 65,
}}
>
<View
style={{
...Style.containerSpaceBetween,
...Style.defaultShadows,
paddingHorizontal: 4,
flex: 1,
}}
>
{state?.routes?.map((route, index) => {
const { options } = descriptors[route.key];
const isFocused = state?.index === index;
const label =
options.tabBarLabel !== undefined
? options.tabBarLabel
: options.title !== undefined
? options.title
: route.name;
const _onPressTabBar = () => {
if (!isWeb) {
Haptics.impactAsync(Haptics.ImpactFeedbackStyle.Light);
@@ -63,7 +84,7 @@ const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => {
style={{
alignSelf: "center",
width: `${100 / state?.routes?.length}%`,
height: 40,
height: "100%",
...Style.containerCenter,
}}
accessibilityRole="button"
@@ -74,11 +95,23 @@ const TabBar = ({ state = {}, descriptors = {}, navigation = {} }) => {
onLongPress={onLongPress}
>
{options?.tabBarIcon({ focused: isFocused })}
<Text
style={{
fontSize: 10,
color: isFocused ? Palette.white : "#8B8883",
fontFamily: FONT_FAMILY.HelveticaNeueRegular,
marginTop: 2,
}}
>
{label}
</Text>
</TouchableOpacity>
)
);
})}
</View>
</ItemContainer>
</View>
);
};
+44
View File
@@ -0,0 +1,44 @@
import { View, Image, ScrollView } from "react-native";
import React from "react";
import Page from "../../layouts/Page";
import { background, icons } from "../../assets";
import SearchBar from "../../components/SearchBar";
import MyMusic from "./components/MyMusic";
import BackTracks from "./components/BackTracks";
import MyClips from "./components/MyClips";
import LikedMusic from "./components/LikedMusic";
import LikedPlayback from "./components/LikedPlayback";
import LikedClips from "./components/LikedClips";
import { responsiveHeight } from "react-native-responsive-dimensions";
import MyPlaylist from "./components/MyPlaylist";
const Library = () => {
return (
<Page backgroundImg={background.libraryBG} headerType="NONE">
<View style={{ gap: 17, paddingBottom: 20 }}>
<Image source={icons.musicLandLogo} style={{ alignSelf: "center" }} />
<SearchBar />
</View>
<View style={{ flex: 1 }}>
<ScrollView
contentContainerStyle={{
flexGrow: 1,
gap: 20,
paddingBottom: responsiveHeight(20),
}}
showsVerticalScrollIndicator={false}
>
<MyMusic />
<BackTracks />
<LikedMusic />
<MyClips />
<MyPlaylist />
<LikedPlayback />
<LikedClips />
</ScrollView>
</View>
</Page>
);
};
export default Library;
@@ -0,0 +1,24 @@
import { View, Text, Image } from "react-native";
import React from "react";
import { img } from "../../../assets";
import { Style } from "../../../styles";
import CardContainer from "./CardContainer";
const BackTracks = () => {
return (
<CardContainer label="Mes Playbacks">
<View style={{ ...Style.containerRow, gap: 6 }}>
{Array.from({ length: 3 }).map((_, index) => (
<View style={{ flex: 1 }} key={index}>
<Image
source={img.placeholder3}
style={{ width: "100%", height: 172, borderRadius: 10 }}
/>
</View>
))}
</View>
</CardContainer>
);
};
export default BackTracks;
@@ -0,0 +1,33 @@
import { View, Text, StyleSheet, Pressable } from "react-native";
import React from "react";
import { Palette, Style } from "../../../styles";
import { FONT_FAMILY } from "../../../styles/Fonts";
const CardContainer = ({ children, label = "" }) => {
return (
<View style={{ gap: 12 }}>
<View style={{ ...Style.containerSpaceBetween }}>
<Text style={styles.label}>{label}</Text>
<Pressable>
<Text style={styles.seeAll}>Voir tout</Text>
</Pressable>
</View>
{children}
</View>
);
};
export default CardContainer;
const styles = StyleSheet.create({
label: {
fontSize: 22,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
},
seeAll: {
fontSize: 12,
color: Palette.gray,
fontFamily: FONT_FAMILY.InterRegular,
},
});
@@ -0,0 +1,24 @@
import { View, Text, Image } from "react-native";
import React from "react";
import CardContainer from "./CardContainer";
import { Style } from "../../../styles";
import { img } from "../../../assets";
const LikedClips = () => {
return (
<CardContainer label="Clips likés">
<View style={{ ...Style.containerRow, gap: 6 }}>
{Array.from({ length: 3 }).map((_, index) => (
<View style={{ flex: 1 }} key={index}>
<Image
source={img.placeholder3}
style={{ width: "100%", height: 172, borderRadius: 10 }}
/>
</View>
))}
</View>
</CardContainer>
);
};
export default LikedClips;
@@ -0,0 +1,29 @@
import { View, Text, Image, FlatList } from "react-native";
import React from "react";
import CardContainer from "./CardContainer";
import { Style } from "../../../styles";
import { img } from "../../../assets";
const LikedMusic = () => {
return (
<CardContainer label="Musiques likées">
<FlatList
scrollEnabled={false}
data={Array.from({ length: 6 })}
numColumns={3}
contentContainerStyle={{ gap: 10 }}
columnWrapperStyle={{ gap: 6 }}
renderItem={() => (
<View style={{ flex: 1 }}>
<Image
source={img.placeholder3}
style={{ width: "100%", height: 172, borderRadius: 10 }}
/>
</View>
)}
/>
</CardContainer>
);
};
export default LikedMusic;
@@ -0,0 +1,24 @@
import { View, Text, Image } from "react-native";
import React from "react";
import CardContainer from "./CardContainer";
import { Style } from "../../../styles";
import { img } from "../../../assets";
const LikedPlayback = () => {
return (
<CardContainer label="Playbacks likés">
<View style={{ ...Style.containerRow, gap: 6 }}>
{Array.from({ length: 3 }).map((_, index) => (
<View style={{ flex: 1 }} key={index}>
<Image
source={img.placeholder3}
style={{ width: "100%", height: 172, borderRadius: 10 }}
/>
</View>
))}
</View>
</CardContainer>
);
};
export default LikedPlayback;
@@ -0,0 +1,78 @@
import { View, Text, Image, Pressable, StyleSheet } from "react-native";
import React, { useState } from "react";
import { Palette, Style } from "../../../styles";
import { icons, img } from "../../../assets";
import { size } from "../../../styles/Style";
import { BlurView } from "expo-blur";
import { FONT_FAMILY } from "../../../styles/Fonts";
const MusicCard = () => {
const [selected, setSelected] = useState(false);
return (
<View
style={{
...Style.containerRow,
gap: 6,
}}
>
<Image
source={img.placeholder2}
style={{ ...size({ size: 60 }), borderRadius: 12 }}
/>
<View style={styles.blurContainer}>
<BlurView
intensity={20}
style={{
flex: 1,
...Style.containerSpaceBetween,
paddingHorizontal: 8,
}}
>
<View>
<Text style={styles.title}>Alors on danse</Text>
<Text style={styles.subTitle}>Stromae</Text>
</View>
<View
style={{
...Style.containerRow,
gap: 12,
}}
>
<Pressable onPress={() => setSelected(!selected)}>
<Image
source={selected ? icons.heart : icons.heartOutline}
style={size({ size: 24 })}
resizeMode="contain"
/>
</Pressable>
<Pressable>
<Image source={icons.more} />
</Pressable>
</View>
</BlurView>
</View>
</View>
);
};
export default MusicCard;
const styles = StyleSheet.create({
blurContainer: {
borderRadius: 12,
overflow: "hidden",
flex: 1,
height: "100%",
},
title: {
fontSize: 16,
color: Palette.white,
fontFamily: FONT_FAMILY.OwnersRegular,
},
subTitle: {
fontSize: 12,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
},
});
+24
View File
@@ -0,0 +1,24 @@
import { View, Text, Image } from "react-native";
import React from "react";
import CardContainer from "./CardContainer";
import { Style } from "../../../styles";
import { img } from "../../../assets";
const MyClips = () => {
return (
<CardContainer label="Mes Clips">
<View style={{ ...Style.containerRow, gap: 6 }}>
{Array.from({ length: 3 }).map((_, index) => (
<View style={{ flex: 1 }} key={index}>
<Image
source={img.placeholder3}
style={{ width: "100%", height: 172, borderRadius: 10 }}
/>
</View>
))}
</View>
</CardContainer>
);
};
export default MyClips;
+18
View File
@@ -0,0 +1,18 @@
import { View } from "react-native";
import React from "react";
import CardContainer from "./CardContainer";
import MusicCard from "./MusicCard";
const MyMusic = () => {
return (
<CardContainer label="Mes musiques">
<View style={{ gap: 10 }}>
{Array.from({ length: 3 }).map((_, index) => (
<MusicCard key={index} />
))}
</View>
</CardContainer>
);
};
export default MyMusic;
@@ -0,0 +1,51 @@
import { View, Text, Pressable, Image } from "react-native";
import React from "react";
import CardContainer from "./CardContainer";
import { BlurView } from "expo-blur";
import { icons } from "../../../assets";
import Style, { size } from "../../../styles/Style";
import { Palette } from "../../../styles";
import { FONT_FAMILY } from "../../../styles/Fonts";
const MyPlaylist = () => {
return (
<CardContainer label="Mes Playlists">
<View style={{ gap: 8 }}>
{["Musiques de lover", "Musiques triste"].map((item, index) => (
<View style={{ borderRadius: 12, overflow: "hidden" }} key={index}>
<BlurView
intensity={20}
style={{
...Style.containerSpaceBetween,
height: 59,
paddingHorizontal: 10,
}}
>
<Text
style={{
fontSize: 16,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
{item}
</Text>
<Pressable>
<Image
source={icons.chevronDown}
style={{
...size({ size: 15 }),
transform: [{ rotate: "-90deg" }],
}}
resizeMode="contain"
/>
</Pressable>
</BlurView>
</View>
))}
</View>
</CardContainer>
);
};
export default MyPlaylist;
+2 -1
View File
@@ -29,6 +29,7 @@ import {
import useLayoutType from "../hooks/useLayoutType.js";
import { capitalize } from "../helpers/index.js";
import { navigate } from "../navigation/NavigationService.js";
export default ({ navigation }) => {
console.log("LOGINSCREEN");
@@ -292,7 +293,7 @@ export default ({ navigation }) => {
<Button
{...(mode === "LOGIN"
? { text: "Connexion", onPress: onLogin }
? { text: "Connexion", onPress: () => navigate(Routes.BottomTab) }
: {
text: "Inscription",
onPress: onSignup,
+14 -3
View File
@@ -4,6 +4,8 @@ import Button from "../components/Button";
import { gutters } from "../styles";
import { navigate } from "../navigation/NavigationService";
import { Routes } from "../navigation";
import { LinearGradient } from "../components/LinearGradient/LinearGradient";
import GradientButton from "../components/GradientButton";
export default ({ navigation }) => {
return (
@@ -13,11 +15,20 @@ export default ({ navigation }) => {
justifyContent: "flex-end",
padding: gutters,
paddingBottom: gutters * 2,
backgroundColor: "#0A0D12",
gap: 10,
}}
>
<Button text="WRITING" onPress={() => navigate(Routes.Writing)} />
<Button text="STUDIO" onPress={() => navigate(Routes.Studio)} />
<Button text="PRODUCTION" onPress={() => navigate(Routes.ProductionOnboarding)} />
<GradientButton title="LOGIN" onPress={() => navigate(Routes.Login)} />
<GradientButton
title="WRITING"
onPress={() => navigate(Routes.Writing)}
/>
<GradientButton title="STUDIO" onPress={() => navigate(Routes.Studio)} />
<GradientButton
title="PRODUCTION"
onPress={() => navigate(Routes.ProductionOnboarding)}
/>
</View>
);
};
+75
View File
@@ -0,0 +1,75 @@
import { View, Text } from "react-native";
import React, { useState } from "react";
import Page from "../../layouts/Page";
import { background } from "../../assets";
import MusicLandHeader from "../../components/MusicLandHeader";
import { goBack, navigate } from "../../navigation/NavigationService";
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
import ItemContainer from "../../components/ItemContainer/ItemContainer";
import GradientButton from "../../components/GradientButton";
import { CHOOSE_DECOR } from "../../data/data";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { Routes } from "../../navigation";
const ChooseDecor = () => {
const [selected, setSelected] = useState("");
return (
<Page headerType="NONE" backgroundImg={background.playbackBG2}>
<MusicLandHeader progress={20} onPressBack={goBack} />
<View style={{ flex: 1, marginTop: 12, gap: 34 }}>
<View style={{ gap: 10 }}>
<CreateLyricsHeader
title="Choisis ton décor"
subTitle="Il sera généré derrière toi lors de ton Playback."
/>
<ItemContainer height={402}>
<View style={{ gap: 10, marginTop: 5, paddingHorizontal: 5 }}>
{CHOOSE_DECOR.map((item, index) => {
const selectedItem = selected === item;
return (
<CreateLyricsHeader
key={index}
gradientProps={{
locations: [0, 1],
}}
containerStyle={{
borderRadius: 14,
}}
onPress={() => setSelected(item)}
colors={
selectedItem
? ["#99999900", "#FFFFFF"]
: [Palette.tran, Palette.tran]
}
tint={selectedItem ? "default" : "dark"}
>
<View style={{ paddingVertical: 6 }}>
<Text
style={{
fontSize: 16,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
{item}
</Text>
</View>
</CreateLyricsHeader>
);
})}
</View>
</ItemContainer>
</View>
<GradientButton
title="Suivant"
onPress={() => navigate(Routes.CreatingDecor)}
/>
</View>
</Page>
);
};
export default ChooseDecor;
+129
View File
@@ -0,0 +1,129 @@
import { View, Text, Image } from "react-native";
import React, { useEffect, useState } from "react";
import Page from "../../layouts/Page";
import { ai, background } from "../../assets";
import MusicLandHeader from "../../components/MusicLandHeader";
import { goBack, navigate } from "../../navigation/NavigationService";
import { Palette, Style } from "../../styles";
import { BlurView } from "expo-blur";
import { FONT_FAMILY } from "../../styles/Fonts";
import ProgressBar from "../../components/ProgressBar";
import { Routes } from "../../navigation";
import GradientButton from "../../components/GradientButton";
const CreatingDecor = () => {
const [progress, setProgress] = useState(0);
useEffect(() => {
const interval = setInterval(() => {
setProgress((prevProgress) => {
if (prevProgress >= 100) {
clearInterval(interval);
return 100;
}
return prevProgress + 1;
});
}, 100);
return () => clearInterval(interval);
}, []);
return (
<Page backgroundImg={background.playbackBG2} headerType="NONE">
<MusicLandHeader progress={20} onPressBack={goBack} />
<View
style={{
flex: 1,
paddingTop: 16,
...Style.containerCenter,
}}
>
<View
style={{
width: "100%",
height: "50%",
}}
>
<View
style={{
zIndex: 1,
position: "absolute",
top: -150,
width: "50%",
height: "80%",
alignSelf: "center",
}}
>
<Image
source={ai.john}
style={{ width: "100%", height: "100%", right: -10 }}
resizeMode="contain"
/>
</View>
<View
style={{
flex: 1,
borderRadius: 20,
overflow: "hidden",
backgroundColor: "#0F0C1933",
}}
>
<BlurView
intensity={40}
tint="dark"
style={{ flex: 1, padding: 10, paddingBottom: 20 }}
>
<View style={{ flex: 1, justifyContent: "flex-end", gap: 20 }}>
<View>
<Text
style={{
fontSize: 22,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
textAlign: "center",
}}
>
Ton décor est en cours de{"\n"}création
</Text>
<Text
style={{
fontSize: 14,
color: Palette.gray,
fontFamily: FONT_FAMILY.InterRegular,
textAlign: "center",
}}
>
Veuillez patienter
</Text>
</View>
<View style={{ alignItems: "center", gap: 16 }}>
<ProgressBar gradient progress={progress} />
<Text
style={{
fontSize: 14,
color: Palette.white,
fontFamily: FONT_FAMILY.InterRegular,
}}
>
{progress}%
</Text>
</View>
<GradientButton
title="Découvrir mon Playback"
containerStyle={{
width: "80%",
alignSelf: "center",
}}
onPress={() => navigate(Routes.VideoFinalize)}
/>
</View>
</BlurView>
</View>
</View>
</View>
</Page>
);
};
export default CreatingDecor;
+5 -4
View File
@@ -33,11 +33,12 @@ const RecordedPlayback = () => {
style={{ width: "80%", alignSelf: "center", marginTop: 4, gap: 12 }}
>
<GradientButton
title="Je veux devenir Playbacker"
containerStyle={{}}
onPress={() => navigate(Routes.PlaybackOnboarding)}
title="Je valide"
/>
<BorderGradientButton
title="Je change de décor"
onPress={() => navigate(Routes.ChooseDecor)}
/>
<BorderGradientButton title="Je change de décor" />
<BorderGradientButton title="Recommencer" />
</View>
</View>
+54
View File
@@ -0,0 +1,54 @@
import { View, Text, Image } from "react-native";
import React from "react";
import MusicLandHeader from "../../components/MusicLandHeader";
import Page from "../../layouts/Page";
import { background, icons, img } from "../../assets";
import { goBack, navigate } from "../../navigation/NavigationService";
import Slider from "../../components/Slider";
import GradientButton from "../../components/GradientButton";
import BorderGradientButton from "../../components/BorderGradientButton";
import { gutters } from "../../styles";
import { Routes } from "../../navigation";
const VideoFinalize = () => {
return (
<Page backgroundImg={background.playbackBG2} headerType="NONE">
<MusicLandHeader progress={19} onPressBack={goBack} />
<View
style={{ flex: 1, paddingTop: 12, gap: 14, paddingBottom: gutters * 2 }}
>
<View style={{ flex: 1, gap: 22 }}>
<Image
source={img.placeholder3}
style={{
width: "80%",
flex: 1,
alignSelf: "center",
borderRadius: 16,
}}
/>
<Slider value="0:00" maxValue="2:00" />
</View>
<View
style={{ width: "80%", alignSelf: "center", marginTop: 4, gap: 12 }}
>
<BorderGradientButton
icon={icons.stars}
title="Regénérer"
onPress={goBack}
/>
<GradientButton
title="Valider"
onPress={() =>
navigate(Routes.DownloadSongs, {
action: "playback",
})
}
/>
</View>
</View>
</Page>
);
};
export default VideoFinalize;
+29 -11
View File
@@ -10,31 +10,47 @@ import Style, { size } from "../../styles/Style";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { Routes } from "../../navigation";
import { useRoute } from "@react-navigation/core";
const DownloadPrices = () => {
const params = useRoute().params;
const action = params?.action;
const [selectedIndex, setSelectedIndex] = useState(null);
const PRICES = [
{
title: "Je télécharge ma chanson",
description: "Ce morceau uniquement",
title: action === "playback" ? "1 Playback" : "Je télécharge ma chanson",
description: `Ce ${
action === "playback" ? "Playback" : "morceau"
} uniquement`,
price: "6,99€",
},
{
title: "3 chansons",
description: "Ce morceau et les 2 prochains que tu crées",
title: `3 ${action === "playback" ? "Playbacks" : "chansons"}`,
description: `Ce ${
action === "playback" ? "Playback" : "morceau"
} et les 2 prochains que tu crées`,
price: "12,99€",
},
{
title: "5 chansons",
description: "Ce morceau et les 4 prochains que tu crées",
title: `5 ${action === "playback" ? "Playbacks" : "chansons"}`,
description: `Ce ${
action === "playback" ? "Playback" : "morceau"
} et les 4 prochains que tu crées`,
price: "19,99€",
recommended: true,
},
];
const DownloadPrices = () => {
const [selectedIndex, setSelectedIndex] = useState(null);
return (
<Page backgroundImg={background.productionBG2} headerType="NONE">
<Page
backgroundImg={
action === "playback"
? background.playbackBG2
: background.productionBG2
}
headerType="NONE"
>
<MusicLandHeader onPressBack={goBack} progress={75} />
<View style={{ flex: 1, paddingTop: responsiveHeight(10) }}>
<CreateLyricsHeader
@@ -74,7 +90,9 @@ const DownloadPrices = () => {
tint={!item.recommended ? "dark" : "light"}
onPress={() => {
setSelectedIndex(index);
navigate(Routes.SongDownloaded);
navigate(Routes.SongDownloaded, {
action,
});
}}
>
<View style={{ paddingTop: 5 }}>
+26 -7
View File
@@ -11,10 +11,21 @@ import { size } from "../../styles/Style";
import { BlurView } from "expo-blur";
import { responsiveHeight } from "react-native-responsive-dimensions";
import { Routes } from "../../navigation";
import { useRoute } from "@react-navigation/core";
const DownloadSongs = () => {
const params = useRoute().params;
const action = params?.action;
return (
<Page backgroundImg={background.productionBG2} headerType="NONE">
<Page
backgroundImg={
action === "playback"
? background.playbackBG2
: background.productionBG2
}
headerType="NONE"
>
<MusicLandHeader onPressBack={goBack} progress={50} />
<View style={{ flex: 1, paddingTop: responsiveHeight(15) }}>
<CreateLyricsHeader
@@ -32,29 +43,37 @@ const DownloadSongs = () => {
}}
/>
<View style={{ gap: 12, paddingVertical: 12 }}>
<Text style={styles.title}>Prêt à télécharger ta chanson ?</Text>
<Text style={styles.title}>Prêt à télécharger {action === "playback" ? "ton Playback" : "ta chanson"} ?</Text>
<View style={{ gap: 10 }}>
<Pressable
style={styles.itemContainer}
onPress={() => navigate(Routes.DownloadPrices)}
onPress={() =>
navigate(Routes.DownloadPrices, {
action,
})
}
>
<BlurView style={styles.blurView} intensity={40} tint="dark">
<Text style={styles.label}>Télécharger ma chanson</Text>
<Text style={styles.label}>Télécharger {action === "playback" ? "mon Playback" : "ma chanson"}</Text>
<Text style={styles.description}>Pour moi uniquement</Text>
</BlurView>
</Pressable>
<Pressable
style={styles.itemContainer}
onPress={() => navigate(Routes.StreamSong)}
onPress={() =>
navigate(Routes.StreamSong, {
action,
})
}
>
<BlurView style={styles.blurView} intensity={40} tint="dark">
<Text style={styles.label}>
Diffuser ma chanson sur la plateforme de MusicLand (+
Diffuser {action === "playback" ? "mon Playback" : "ma chanson"} sur la plateforme de MusicLand (+
réseaux sociaux) et participer au concours
</Text>
<Text style={styles.description}>
Top 3: 1er 15% du CA ML - 2ème 10% du CA ML - 3ème 5% du CA
ML (catégorie chanson)
ML (catégorie {action === "playback" ? "Playback" : "chanson"})
</Text>
</BlurView>
</Pressable>
+16 -4
View File
@@ -12,10 +12,21 @@ import { responsiveHeight } from "react-native-responsive-dimensions";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { Routes } from "../../navigation";
import { useRoute } from "@react-navigation/core";
const SongDownloaded = () => {
const params = useRoute().params;
const action = params?.action;
return (
<Page backgroundImg={background.productionBG2} headerType="NONE">
<Page
backgroundImg={
action === "playback"
? background.playbackBG2
: background.productionBG2
}
headerType="NONE"
>
<MusicLandHeader onPressBack={goBack} progress={100} />
<View style={{ flex: 1, paddingTop: responsiveHeight(15) }}>
<CreateLyricsHeader
@@ -41,7 +52,7 @@ const SongDownloaded = () => {
textAlign: "center",
}}
>
Chanson téléchargée !
{action === "playback" ? "Playback" : "Chanson"} téléchargée !
</Text>
<Text
style={{
@@ -50,8 +61,9 @@ const SongDownloaded = () => {
fontFamily: FONT_FAMILY.InterMedium,
}}
>
Ta chanson est désormais téléchargée dans tes fichiers. Nhésite
pas à la partager avec tes proches.
{action === "playback" ? "Ton Playback" : "Ta Chanson"} est
désormais téléchargée dans tes fichiers. Nhésite pas à la
partager avec tes proches.
</Text>
</View>
<View
+16 -5
View File
@@ -12,10 +12,21 @@ import { FONT_FAMILY } from "../../styles/Fonts";
import BorderGradientButton from "../../components/BorderGradientButton";
import GradientButton from "../../components/GradientButton";
import { Routes } from "../../navigation";
import { useRoute } from "@react-navigation/core";
const SongRelease = () => {
const params = useRoute().params;
const action = params?.action;
return (
<Page backgroundImg={background.productionBG2} headerType="NONE">
<Page
backgroundImg={
action === "playback"
? background.playbackBG2
: background.productionBG2
}
headerType="NONE"
>
<MusicLandHeader onPressBack={goBack} progress={100} />
<View style={{ flex: 1, paddingTop: responsiveHeight(15) }}>
<CreateLyricsHeader
@@ -41,7 +52,7 @@ const SongRelease = () => {
textAlign: "center",
}}
>
Chanson publiée!
{action === "playback" ? "Playback" : "Chanson"} publiée !
</Text>
<Text
style={{
@@ -50,9 +61,9 @@ const SongRelease = () => {
fontFamily: FONT_FAMILY.InterMedium,
}}
>
Ta chanson est désormais accessible sur lapplication et les
réseaux sociaux de MusicLand. Nhésite pas à la partager avec tes
proches.
{action === "playback" ? "Ton Playback" : "Ta Chanson"} est
désormais accessible sur lapplication et les réseaux sociaux de
MusicLand. Nhésite pas à la partager avec tes proches.
</Text>
</View>
<View
+35 -3
View File
@@ -10,6 +10,7 @@ import Style, { size } from "../../styles/Style";
import { Palette } from "../../styles";
import { FONT_FAMILY } from "../../styles/Fonts";
import { Routes } from "../../navigation";
import { useRoute } from "@react-navigation/core";
const STREAM_PRICES = [
{
@@ -29,11 +30,40 @@ const STREAM_PRICES = [
},
];
const PLAYBACK_STREAM_PRICES = [
{
title: "Je créer et diffuse mon Playback",
description: "Ce morceau uniquement",
price: "6,99€ / mois",
},
{
title: "3 Playbacks",
description: "Ce morceau et les 2 prochains que tu crées",
price: "12,99€ / mois",
},
{
title: "Illimité",
price: "20€ / mois",
recommended: true,
},
];
const StreamSong = () => {
const params = useRoute().params;
const action = params?.action;
const [selectedIndex, setSelectedIndex] = useState(null);
const DATA = action === "playback" ? PLAYBACK_STREAM_PRICES : STREAM_PRICES;
return (
<Page backgroundImg={background.productionBG2} headerType="NONE">
<Page
backgroundImg={
action === "playback"
? background.playbackBG2
: background.productionBG2
}
headerType="NONE"
>
<MusicLandHeader onPressBack={goBack} progress={75} />
<View style={{ flex: 1, paddingTop: responsiveHeight(5) }}>
<CreateLyricsHeader
@@ -77,7 +107,7 @@ const StreamSong = () => {
</Text>
</View>
<View style={{ gap: 10 }}>
{STREAM_PRICES.map((item, index) => (
{DATA.map((item, index) => (
<CreateLyricsHeader
key={index}
colors={
@@ -88,7 +118,9 @@ const StreamSong = () => {
tint={!item.recommended ? "dark" : "light"}
onPress={() => {
setSelectedIndex(index);
navigate(Routes.SongRelease);
navigate(Routes.SongRelease, {
action,
});
}}
>
<View style={{ paddingTop: 5 }}>
+3
View File
@@ -39,6 +39,9 @@ export const FONT_FAMILY = {
HelveticaNeueRegular: "HelveticaNeueRegular",
HelveticaNeueMedium: "HelveticaNeueMedium",
HelveticaNeueBold: "HelveticaNeueBold",
OwnersRegular: "OwnersRegular",
OwnersMedium: "OwnersMedium",
OwnersBold: "OwnersBold",
};
const Fonts = ({
+4 -4
View File
@@ -7402,10 +7402,10 @@ react-native-modalbox@^2.0.2:
dependencies:
prop-types "^15.5.10"
react-native-reanimated-carousel@^4.0.0-alpha.8:
version "4.0.0-canary.22"
resolved "https://registry.yarnpkg.com/react-native-reanimated-carousel/-/react-native-reanimated-carousel-4.0.0-canary.22.tgz#4fa530548bf330184b252eabd2d95dc02eb31f28"
integrity sha512-GOTSXVuoV08ZUxGPuzQ1Kl1YOOOrKWb18uRlPsa759bFyiqFWpjjLrCUdfgBgF9ZqUHUbb1jj+UffFf2eGDz+A==
react-native-reanimated-carousel@^4.0.3:
version "4.0.3"
resolved "https://registry.yarnpkg.com/react-native-reanimated-carousel/-/react-native-reanimated-carousel-4.0.3.tgz#975f4ff3f5da5bb3790fe60850a46ad8119612bc"
integrity sha512-YZXlvZNghR5shFcI9hTA7h7bEhh97pfUSLZvLBAshpbkuYwJDKmQXejO/199T6hqGq0wCRwR0CWf2P4Vs6A4Fw==
react-native-reanimated@~3.16.1:
version "3.16.3"