diff --git a/App.js b/App.js index 8eca2ee..05a9b7c 100644 --- a/App.js +++ b/App.js @@ -58,6 +58,9 @@ const App = () => { InterSemiBold: Inter_600SemiBold, InterBold: Inter_700Bold, InterRegularItalic: Inter_400Regular_Italic, + HelveticaNeueRegular: require("./src/assets/fonts/HelveticaNeueRegular.ttf"), + HelveticaNeueMedium: require("./src/assets/fonts/HelveticaNeueMedium.ttf"), + HelveticaNeueBold: require("./src/assets/fonts/HelveticaNeueBold.ttf"), }); useEffect(() => { diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index a0f18ba..ec77dac 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,6 +1,7 @@ + diff --git a/app.json b/app.json index 50218e8..79b02b1 100644 --- a/app.json +++ b/app.json @@ -97,7 +97,15 @@ "iCloudContainerEnvironment": "Production" } ], - "expo-font" + "expo-font", + [ + "expo-camera", + { + "cameraPermission": "Allow $(PRODUCT_NAME) to access your camera", + "microphonePermission": "Allow $(PRODUCT_NAME) to access your microphone", + "recordAudioAndroid": true + } + ] ], "extra": { "eas": { diff --git a/ios/minuitstarter/SplashScreen.storyboard b/ios/minuitstarter/SplashScreen.storyboard index 2e79a66..bd8b5e1 100644 --- a/ios/minuitstarter/SplashScreen.storyboard +++ b/ios/minuitstarter/SplashScreen.storyboard @@ -29,6 +29,7 @@ + @@ -44,5 +45,8 @@ + + + \ No newline at end of file diff --git a/package.json b/package.json index 425dd09..e04a687 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "expo-av": "~15.0.1", "expo-blur": "~14.0.1", "expo-build-properties": "~0.13.1", + "expo-camera": "~16.0.18", "expo-constants": "~17.0.3", "expo-dev-client": "~5.0.5", "expo-document-picker": "~13.0.1", diff --git a/src/assets/UI/placeholder3.png b/src/assets/UI/placeholder3.png new file mode 100644 index 0000000..fcda94f Binary files /dev/null and b/src/assets/UI/placeholder3.png differ diff --git a/src/assets/fonts/HelveticaNeueBold.ttf b/src/assets/fonts/HelveticaNeueBold.ttf new file mode 100644 index 0000000..f44af64 Binary files /dev/null and b/src/assets/fonts/HelveticaNeueBold.ttf differ diff --git a/src/assets/fonts/HelveticaNeueMedium.ttf b/src/assets/fonts/HelveticaNeueMedium.ttf new file mode 100644 index 0000000..1a2a9df Binary files /dev/null and b/src/assets/fonts/HelveticaNeueMedium.ttf differ diff --git a/src/assets/fonts/HelveticaNeueRegular.ttf b/src/assets/fonts/HelveticaNeueRegular.ttf new file mode 100644 index 0000000..4961505 Binary files /dev/null and b/src/assets/fonts/HelveticaNeueRegular.ttf differ diff --git a/src/assets/index.js b/src/assets/index.js index b493749..292d3b4 100644 --- a/src/assets/index.js +++ b/src/assets/index.js @@ -194,8 +194,10 @@ export const ai = { import placeholder from "./UI/placeholder.jpg"; import placeholder2 from "./UI/placeholder2.jpg"; +import placeholder3 from "./UI/placeholder3.png"; export const img = { placeholder, placeholder2, + placeholder3, }; diff --git a/src/navigation/MainStack.js b/src/navigation/MainStack.js index 4cb5f2a..7f0184a 100644 --- a/src/navigation/MainStack.js +++ b/src/navigation/MainStack.js @@ -32,6 +32,16 @@ import AddPhotoCover from "../screens/Studio/AddPhotoCover"; import FinishCompose from "../screens/Studio/FinishCompose"; import Production from "../screens/Production/Production"; import ProductionOnboarding from "../screens/Production/ProductionOnboarding"; +import DownloadSongs from "../screens/Production/DownloadSongs"; +import DownloadPrices from "../screens/Production/DownloadPrices"; +import SongDownloaded from "../screens/Production/SongDownloaded"; +import StreamSong from "../screens/Production/StreamSong"; +import SongRelease from "../screens/Production/SongRelease"; +import PlaybackExample from "../screens/Production/PlaybackExample"; +import PlaybackOnboarding from "../screens/Playback/PlaybackOnboarding"; +import Playback from "../screens/Playback/Playback"; +import RecordPlayback from "../screens/Playback/RecordPlayback"; +import RecordedPlayback from "../screens/Playback/RecordedPlayback"; const screenOptions = { headerShown: false, @@ -143,6 +153,46 @@ const screens = [ name: Routes.Production, component: Production, }, + { + name: Routes.DownloadSongs, + component: DownloadSongs, + }, + { + name: Routes.DownloadPrices, + component: DownloadPrices, + }, + { + name: Routes.SongDownloaded, + component: SongDownloaded, + }, + { + name: Routes.StreamSong, + component: StreamSong, + }, + { + name: Routes.SongRelease, + component: SongRelease, + }, + { + name: Routes.PlaybackExample, + component: PlaybackExample, + }, + { + name: Routes.PlaybackOnboarding, + component: PlaybackOnboarding, + }, + { + name: Routes.Playback, + component: Playback, + }, + { + name: Routes.RecordPlayback, + component: RecordPlayback, + }, + { + name: Routes.RecordedPlayback, + component: RecordedPlayback, + }, ]; export default function Main() { diff --git a/src/navigation/Routes.js b/src/navigation/Routes.js index 3f4d50f..d36f951 100644 --- a/src/navigation/Routes.js +++ b/src/navigation/Routes.js @@ -42,4 +42,15 @@ export const Routes = { ProductionOnboarding: "ProductionOnboarding", Production: "Production", + DownloadSongs: "DownloadSongs", + DownloadPrices: "DownloadPrices", + SongDownloaded: "SongDownloaded", + StreamSong: "StreamSong", + SongRelease: "SongRelease", + PlaybackExample: "PlaybackExample", + + PlaybackOnboarding: "PlaybackOnboarding", + Playback: "Playback", + RecordPlayback: "RecordPlayback", + RecordedPlayback: "RecordedPlayback", }; diff --git a/src/screens/Playback/Playback.js b/src/screens/Playback/Playback.js new file mode 100644 index 0000000..b9db567 --- /dev/null +++ b/src/screens/Playback/Playback.js @@ -0,0 +1,46 @@ +import { View, Text, StyleSheet, Image } from "react-native"; +import React from "react"; +import { ai, background } from "../../assets"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import { gutters } from "../../styles"; +import Page from "../../layouts/Page"; +import BorderGradientButton from "../../components/BorderGradientButton"; +import GradientButton from "../../components/GradientButton"; +import { Routes } from "../../navigation"; + +const Playback = () => { + return ( + + + + + + + + navigate(Routes.RecordPlayback)} + /> + + + + ); +}; + +export default Playback; + +const styles = StyleSheet.create({ + img: { + width: "100%", + height: "70%", + position: "absolute", + bottom: -40, + }, +}); diff --git a/src/screens/Playback/PlaybackOnboarding.js b/src/screens/Playback/PlaybackOnboarding.js new file mode 100644 index 0000000..494ef04 --- /dev/null +++ b/src/screens/Playback/PlaybackOnboarding.js @@ -0,0 +1,29 @@ +import { View, Text } from "react-native"; +import React from "react"; +import Page from "../../layouts/Page"; +import { background } from "../../assets"; +import { gutters } from "../../styles"; +import GradientButton from "../../components/GradientButton"; +import { navigate } from "../../navigation/NavigationService"; +import { Routes } from "../../navigation"; + +const PlaybackOnboarding = () => { + return ( + + + navigate(Routes.Playback)} + /> + + + ); +}; + +export default PlaybackOnboarding; diff --git a/src/screens/Playback/RecordPlayback.js b/src/screens/Playback/RecordPlayback.js new file mode 100644 index 0000000..56941a1 --- /dev/null +++ b/src/screens/Playback/RecordPlayback.js @@ -0,0 +1,56 @@ +import { Text, View } from "react-native"; +import React from "react"; +import { CameraView } from "expo-camera"; +import { gutters, Palette } from "../../styles"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import { useSafeAreaInsets } from "react-native-safe-area-context"; +import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; +import { FONT_FAMILY } from "../../styles/Fonts"; +import GradientButton from "../../components/GradientButton"; +import { Routes } from "../../navigation"; + +const RecordPlayback = () => { + const { top } = useSafeAreaInsets(); + + return ( + + + + + + + + L'enregistrement de ta vidéo commencera lorsque tu lanceras ta + musique, et s'arrêtera à la fin du morceau. + + + + navigate(Routes.RecordedPlayback)} + /> + + + + ); +}; + +export default RecordPlayback; diff --git a/src/screens/Playback/RecordedPlayback.js b/src/screens/Playback/RecordedPlayback.js new file mode 100644 index 0000000..e7db13f --- /dev/null +++ b/src/screens/Playback/RecordedPlayback.js @@ -0,0 +1,48 @@ +import { View, Text, Image } from "react-native"; +import React from "react"; +import Page from "../../layouts/Page"; +import { background, img } from "../../assets"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import { gutters } from "../../styles"; +import Slider from "../../components/Slider"; +import GradientButton from "../../components/GradientButton"; +import { Routes } from "../../navigation"; +import BorderGradientButton from "../../components/BorderGradientButton"; + +const RecordedPlayback = () => { + return ( + + + + + + + + + navigate(Routes.PlaybackOnboarding)} + /> + + + + + + ); +}; + +export default RecordedPlayback; diff --git a/src/screens/Production/DownloadPrices.js b/src/screens/Production/DownloadPrices.js new file mode 100644 index 0000000..4292cd2 --- /dev/null +++ b/src/screens/Production/DownloadPrices.js @@ -0,0 +1,146 @@ +import { View, Text, Image } from "react-native"; +import React, { useState } from "react"; +import Page from "../../layouts/Page"; +import { background, img } from "../../assets"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import { responsiveHeight } from "react-native-responsive-dimensions"; +import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; +import Style, { size } from "../../styles/Style"; +import { Palette } from "../../styles"; +import { FONT_FAMILY } from "../../styles/Fonts"; +import { Routes } from "../../navigation"; + +const PRICES = [ + { + title: "Je télécharge ma chanson", + description: "Ce morceau uniquement", + price: "6,99€", + }, + { + title: "3 chansons", + description: "Ce 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", + price: "19,99€", + recommended: true, + }, +]; + +const DownloadPrices = () => { + const [selectedIndex, setSelectedIndex] = useState(null); + + return ( + + + + + + + + Tarifs + + + {PRICES.map((item, index) => ( + { + setSelectedIndex(index); + navigate(Routes.SongDownloaded); + }} + > + + + {item.title} + + + {item.description} + + + + + {item.price} + + + {item.recommended && ( + + + Recommandé + + + )} + + ))} + + + + + + ); +}; + +export default DownloadPrices; diff --git a/src/screens/Production/DownloadSongs.js b/src/screens/Production/DownloadSongs.js index bf80563..911b7d5 100644 --- a/src/screens/Production/DownloadSongs.js +++ b/src/screens/Production/DownloadSongs.js @@ -1,12 +1,106 @@ -import { View, Text } from "react-native"; +import { View, Text, StyleSheet, Image, Pressable } from "react-native"; import React from "react"; +import Page from "../../layouts/Page"; +import { background, img } from "../../assets"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import { Palette } from "../../styles"; +import { FONT_FAMILY } from "../../styles/Fonts"; +import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; +import { size } from "../../styles/Style"; +import { BlurView } from "expo-blur"; +import { responsiveHeight } from "react-native-responsive-dimensions"; +import { Routes } from "../../navigation"; const DownloadSongs = () => { return ( - - DownloadSongs - + + + + + + + Prêt à télécharger ta chanson ? + + navigate(Routes.DownloadPrices)} + > + + Télécharger ma chanson + Pour moi uniquement + + + navigate(Routes.StreamSong)} + > + + + Diffuser ma chanson sur la plateforme de MusicLand (+ + réseaux sociaux) et participer au concours + + + Top 3: 1er 15% du CA ML - 2ème 10% du CA ML - 3ème 5% du CA + ML (catégorie chanson) + + + + + + + + ); }; export default DownloadSongs; + +const styles = StyleSheet.create({ + title: { + fontSize: 22, + color: Palette.white, + fontFamily: FONT_FAMILY.InterSemiBold, + }, + label: { + fontSize: 16, + color: Palette.white, + fontFamily: FONT_FAMILY.HelveticaNeueBold, + }, + description: { + fontSize: 12, + color: Palette.white, + fontFamily: FONT_FAMILY.InterRegular, + }, + blurView: { + paddingHorizontal: 10, + paddingBottom: 8, + paddingTop: 10, + }, + itemContainer: { + borderRadius: 12, + overflow: "hidden", + backgroundColor: "#FFFFFF03", + shadowColor: "#0000001A", + shadowOffset: { + width: 0, + height: 2, + }, + shadowOpacity: 0.25, + shadowRadius: 3.84, + + elevation: 5, + }, +}); diff --git a/src/screens/Production/PlaybackExample.js b/src/screens/Production/PlaybackExample.js new file mode 100644 index 0000000..129ccc6 --- /dev/null +++ b/src/screens/Production/PlaybackExample.js @@ -0,0 +1,47 @@ +import { View, Text, Image } from "react-native"; +import React from "react"; +import Page from "../../layouts/Page"; +import { background, img } from "../../assets"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; +import Slider from "../../components/Slider"; +import { gutters } from "../../styles"; +import GradientButton from "../../components/GradientButton"; +import { Routes } from "../../navigation"; + +const PlaybackExample = () => { + return ( + + + + + + + + + navigate(Routes.PlaybackOnboarding)} + /> + + + ); +}; + +export default PlaybackExample; diff --git a/src/screens/Production/Production.js b/src/screens/Production/Production.js index a6be7d1..acb9328 100644 --- a/src/screens/Production/Production.js +++ b/src/screens/Production/Production.js @@ -1,17 +1,19 @@ -import { View } from "react-native"; +import { Image, StyleSheet, View } from "react-native"; import React from "react"; import Page from "../../layouts/Page"; -import { background } from "../../assets"; +import { ai, background } from "../../assets"; import { gutters } from "../../styles"; import GradientButton from "../../components/GradientButton"; import MusicLandHeader from "../../components/MusicLandHeader"; -import { goBack } from "../../navigation/NavigationService"; +import { goBack, navigate } from "../../navigation/NavigationService"; import BorderGradientButton from "../../components/BorderGradientButton"; +import { Routes } from "../../navigation"; const Production = () => { return ( - + + { gap: 37, }} > - + navigate(Routes.DownloadSongs)} + /> - + navigate(Routes.PlaybackExample)} + /> @@ -35,3 +43,13 @@ const Production = () => { }; export default Production; + +const styles = StyleSheet.create({ + img: { + width: "100%", + height: "70%", + position: "absolute", + bottom: -40, + right: -30, + }, +}); diff --git a/src/screens/Production/SongDownloaded.js b/src/screens/Production/SongDownloaded.js new file mode 100644 index 0000000..0e3c5b3 --- /dev/null +++ b/src/screens/Production/SongDownloaded.js @@ -0,0 +1,81 @@ +import { View, Text, Image } from "react-native"; +import React from "react"; +import Page from "../../layouts/Page"; +import { background, img } from "../../assets"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; +import { size } from "../../styles/Style"; +import BorderGradientButton from "../../components/BorderGradientButton"; +import GradientButton from "../../components/GradientButton"; +import { responsiveHeight } from "react-native-responsive-dimensions"; +import { Palette } from "../../styles"; +import { FONT_FAMILY } from "../../styles/Fonts"; +import { Routes } from "../../navigation"; + +const SongDownloaded = () => { + return ( + + + + + + + + Chanson téléchargée ! + + + Ta chanson est désormais téléchargée dans tes fichiers. N’hésite + pas à la partager avec tes proches. + + + + navigate(Routes.Production)} + /> + navigate(Routes.Production)} + /> + + + + + ); +}; + +export default SongDownloaded; diff --git a/src/screens/Production/SongRelease.js b/src/screens/Production/SongRelease.js new file mode 100644 index 0000000..aa18a76 --- /dev/null +++ b/src/screens/Production/SongRelease.js @@ -0,0 +1,82 @@ +import { View, Text, Image } from "react-native"; +import React from "react"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import Page from "../../layouts/Page"; +import { background, img } from "../../assets"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import { responsiveHeight } from "react-native-responsive-dimensions"; +import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; +import { size } from "../../styles/Style"; +import { Palette } from "../../styles"; +import { FONT_FAMILY } from "../../styles/Fonts"; +import BorderGradientButton from "../../components/BorderGradientButton"; +import GradientButton from "../../components/GradientButton"; +import { Routes } from "../../navigation"; + +const SongRelease = () => { + return ( + + + + + + + + Chanson publiée! + + + Ta chanson est désormais accessible sur l’application et les + réseaux sociaux de MusicLand. N’hésite pas à la partager avec tes + proches. + + + + navigate(Routes.Production)} + /> + navigate(Routes.Production)} + /> + + + + + ); +}; + +export default SongRelease; diff --git a/src/screens/Production/StreamSong.js b/src/screens/Production/StreamSong.js new file mode 100644 index 0000000..31ce98b --- /dev/null +++ b/src/screens/Production/StreamSong.js @@ -0,0 +1,162 @@ +import { View, Text, Image } from "react-native"; +import React, { useState } from "react"; +import Page from "../../layouts/Page"; +import MusicLandHeader from "../../components/MusicLandHeader"; +import { background, img } from "../../assets"; +import { goBack, navigate } from "../../navigation/NavigationService"; +import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader"; +import { responsiveHeight } from "react-native-responsive-dimensions"; +import Style, { size } from "../../styles/Style"; +import { Palette } from "../../styles"; +import { FONT_FAMILY } from "../../styles/Fonts"; +import { Routes } from "../../navigation"; + +const STREAM_PRICES = [ + { + title: "Je diffuse ma chanson", + description: "Ce morceau uniquement", + price: "1,99€ / mois", + }, + { + title: "Je diffuse 3 chansons", + description: "Ce morceau et les 2 prochains que tu crées", + price: "3,99€ / mois", + }, + { + title: "Illimité", + price: "14,99€ / mois", + recommended: true, + }, +]; + +const StreamSong = () => { + const [selectedIndex, setSelectedIndex] = useState(null); + + return ( + + + + + + + + + Diffuser ta chanson{"\n"} + Tarifs + + + Si tu désires diffuser ta chanson ou tes chansons sur la + plateforme de MusicLand et participer au concours et être dans + le top 3 voici le tarif. + + + + {STREAM_PRICES.map((item, index) => ( + { + setSelectedIndex(index); + navigate(Routes.SongRelease); + }} + > + + + {item.title} + + {item.description && ( + + {item.description} + + )} + + + + {item.price} + + + {item.recommended && ( + + + Recommandé + + + )} + + ))} + + + + + + ); +}; + +export default StreamSong; diff --git a/src/screens/Studio/ComposeSong.js b/src/screens/Studio/ComposeSong.js index 62bf5be..a1e3684 100644 --- a/src/screens/Studio/ComposeSong.js +++ b/src/screens/Studio/ComposeSong.js @@ -112,14 +112,4 @@ const ComposeSong = () => { ); }; -export default ComposeSong; - -const styles = StyleSheet.create({ - img: { - width: "100%", - height: "70%", - position: "absolute", - bottom: -40, - right: -30, - }, -}); +export default ComposeSong; \ No newline at end of file diff --git a/src/screens/Writing/components/CreateLyricsHeader.js b/src/screens/Writing/components/CreateLyricsHeader.js index ffffaae..221e31a 100644 --- a/src/screens/Writing/components/CreateLyricsHeader.js +++ b/src/screens/Writing/components/CreateLyricsHeader.js @@ -28,7 +28,7 @@ const CreateLyricsHeader = ({ locations: [0.2, 1], start: { x: 0, y: 0 }, end: { x: 1, y: 0 }, - ...{ gradientProps }, + ...gradientProps, }} style={{ height: isWeb ? onLayout?.height + 2 : onLayout?.height, diff --git a/src/styles/Fonts.js b/src/styles/Fonts.js index 104cedb..9b26f4a 100644 --- a/src/styles/Fonts.js +++ b/src/styles/Fonts.js @@ -36,6 +36,9 @@ export const FONT_FAMILY = { InterSemiBold: "InterSemiBold", InterBold: "InterBold", InterRegularItalic: "InterRegularItalic", + HelveticaNeueRegular: "HelveticaNeueRegular", + HelveticaNeueMedium: "HelveticaNeueMedium", + HelveticaNeueBold: "HelveticaNeueBold", }; const Fonts = ({ diff --git a/yarn.lock b/yarn.lock index 8fa8359..56717d7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4180,6 +4180,13 @@ expo-build-properties@~0.13.1: ajv "^8.11.0" semver "^7.6.0" +expo-camera@~16.0.18: + version "16.0.18" + resolved "https://registry.yarnpkg.com/expo-camera/-/expo-camera-16.0.18.tgz#5b54dc1a929c12732c585b137b04cef2b01dee3b" + integrity sha512-NP5u2yyc+wZc9GdUXH+jcEytyXZwBnHxItMwXoZQQxi4wgltwvs4XfSWjBtRZe1LngnhpBfPyPJV0aShjWlLDg== + dependencies: + invariant "^2.2.4" + expo-constants@~17.0.0, expo-constants@~17.0.3: version "17.0.3" resolved "https://registry.yarnpkg.com/expo-constants/-/expo-constants-17.0.3.tgz#a05b38e0417d59759ece1642b4d483889e04dbda"