From 2934d760eba8a6da650c7ed7f9d5e02cfbd806cb Mon Sep 17 00:00:00 2001 From: Arthi-chaud Date: Sat, 7 Jan 2023 08:19:36 +0000 Subject: [PATCH] Front: Play Page: Use Scorometer --- front/API.ts | 2 +- front/Navigation.tsx | 2 +- front/views/PlayView.tsx | 176 +++++++++++++++++++++------------- front/views/SongLobbyView.tsx | 2 +- 4 files changed, 110 insertions(+), 72 deletions(-) diff --git a/front/API.ts b/front/API.ts index ccb7b7c..f948eda 100644 --- a/front/API.ts +++ b/front/API.ts @@ -232,4 +232,4 @@ export default class API { userId: 1 }]; } -} \ No newline at end of file +} diff --git a/front/Navigation.tsx b/front/Navigation.tsx index f2faee1..c82ce1b 100644 --- a/front/Navigation.tsx +++ b/front/Navigation.tsx @@ -18,7 +18,7 @@ import { RootState, useSelector } from './state/Store'; const Stack = createNativeStackNavigator(); export const protectedRoutes = <> - + PlayView({ songId: 1 })} options={{ title: translate('play') }} /> diff --git a/front/views/PlayView.tsx b/front/views/PlayView.tsx index 655716d..28cc5a6 100644 --- a/front/views/PlayView.tsx +++ b/front/views/PlayView.tsx @@ -1,30 +1,68 @@ -import React, { Component } from 'react'; +import React, { useEffect, useRef, useState } from 'react'; import { SafeAreaView, Text } from 'react-native'; import * as ScreenOrientation from 'expo-screen-orientation'; -import { Box, Center, Column, IconButton, Progress, Row, Toast, View } from 'native-base'; +import { Box, Center, Column, IconButton, Progress, Row, View, useToast } from 'native-base'; import { Ionicons } from "@expo/vector-icons"; import { useNavigation } from '@react-navigation/native'; import { useQuery } from 'react-query'; import API from '../API'; import LoadingComponent from '../components/Loading'; +type PlayViewProps = { + songId: number +} -class PlayView extends Component { - constructor(props: any) { - super(props); +const PlayView = ({ songId }: PlayViewProps) => { + const navigation = useNavigation(); + const song = useQuery(['song'], () => API.getSong(songId)); + const toast = useToast(); + const webSocket = useRef(); + const timer = useRef(); + // If paused is undefined, it means the song as not started yet + const [paused, setPause] = useState(); - this.onMIDISuccess = this.onMIDISuccess.bind(this); + const onPause = () => { + setPause(true); + webSocket.current?.send(JSON.stringify({ + type: "pause", + paused: true, + time: Date.now() + })); + } + const onResume = () => { + setPause(false); + webSocket.current?.send(JSON.stringify({ + type: "pause", + paused: false, + time: Date.now() + })); + } + const onEnd = () => { + webSocket.current?.close(); } - private onMIDISuccess(access) { + const onMIDISuccess = (access) => { const inputs = access.inputs; + webSocket.current?.send(JSON.stringify({ + type: "start", + paused: false, + time: Date.now() + })); - if (inputs.size > 1) { - Toast.show({ description: `MIDI ready!`, placement: 'top' }); - } else { + if (inputs.size < 1) { return; } + toast.show({ description: `MIDI ready!`, placement: 'top' }); let inputIndex = 0; + webSocket.current = new WebSocket(process.env.SCORO_URL!); + webSocket.current.send(JSON.stringify({ + type: "start", + name: "clair-de-lune" /*song.data.id*/, + })); + webSocket.current.onmessage = (message) => { + toast.show({ description: message.data }); + } + setPause(false); inputs.forEach((input) => { if (inputIndex != 0) { return; @@ -32,73 +70,73 @@ class PlayView extends Component { input.onmidimessage = (message) => { const keyIsPressed = message.data[2] == 100; const keyCode = message.data[1]; - const eventTime = Date.now(); - const intensity = null; - Toast.show({ description: [keyIsPressed, keyCode, eventTime].toString() }); + webSocket.current?.send(JSON.stringify({ + type: keyIsPressed ? "note_on" : "note_off", + node: keyCode, + intensity: null, + time: Date.now() + })) } inputIndex++; }); } - - private onMIDIFailure(msg) { - Toast.show({ description: `Failed to get MIDI access` }); + const onMIDIFailure = () => { + toast.show({ description: `Failed to get MIDI access` }); } - - - override componentDidMount(): void { + useEffect(() => { ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE).catch(() => {}); - navigator.requestMIDIAccess().then(this.onMIDISuccess, this.onMIDIFailure); - } + navigator.requestMIDIAccess().then(onMIDISuccess, onMIDIFailure); - override componentWillUnmount(): void { - ScreenOrientation.unlockAsync().catch(() => {}); - } - override render() { - const score = 20; - - if (!this.props.songQuery.data) { - return
- -
+ return () => { + ScreenOrientation.unlockAsync().catch(() => {}); + onEnd(); } - return ( - - - {this.state.tick} - - - - - Score: {score}% - - -
- Rolling in the Deep -
- - - - 0:30 - this.props.navigation.navigate('Score')}/> - -
-
-
- ); + }, []) + const score = 20; + + if (!song.data) { + return
+ +
} + return ( + + + + + + + Score: {score}% + + +
+ Rolling in the Deep +
+ + + { + if (paused == true) { + onResume(); + } else if (paused === false) { + onPause(); + } + }}/> + 0:30 + navigation.navigate('Score')}/> + +
+
+
+ ); } -export default function (props: any) { - const navigation = useNavigation(); - const song = useQuery(['song'], () => API.getSong(props.songId)); - return ; -}; \ No newline at end of file +export default PlayView \ No newline at end of file diff --git a/front/views/SongLobbyView.tsx b/front/views/SongLobbyView.tsx index 7498a99..7e37926 100644 --- a/front/views/SongLobbyView.tsx +++ b/front/views/SongLobbyView.tsx @@ -45,7 +45,7 @@ const SongLobbyView = () => { format={(level) => `${level} - ${ chaptersQuery.data!.reduce((a, b) => a + b.difficulty, 0) / chaptersQuery.data!.length }`} /> -