Myatom
This commit is contained in:
@@ -16,7 +16,7 @@ import { SplendidGrandPiano } from 'smplr';
|
||||
|
||||
export type ParitionMagicProps = {
|
||||
playType: 'practice' | 'normal' | null;
|
||||
timestamp: number;
|
||||
timestamp: React.MutableRefObject<number>;
|
||||
songID: number;
|
||||
shouldPlay: boolean;
|
||||
onEndReached: () => void;
|
||||
@@ -48,6 +48,8 @@ const getCursorToPlay = (
|
||||
|
||||
const transitionDuration = 50;
|
||||
|
||||
export let updateCursor: (() => void) | undefined = undefined;
|
||||
|
||||
const PartitionMagic = ({
|
||||
playType,
|
||||
timestamp,
|
||||
@@ -78,7 +80,36 @@ const PartitionMagic = ({
|
||||
const cursorTop = (data?.cursors[cursorDisplayIdx]?.y ?? 0) - cursorPaddingVertical;
|
||||
const cursorLeft = (data?.cursors[0]?.x ?? 0) - cursorPaddingHorizontal;
|
||||
|
||||
console.log(melodySound.current?._loaded);
|
||||
updateCursor = () => {
|
||||
if (!shouldPlay) return;
|
||||
if (!data || data?.cursors.length === 0) return;
|
||||
getCursorToPlay(
|
||||
data!.cursors,
|
||||
currentCurIdx.current,
|
||||
timestamp.current + transitionDuration,
|
||||
(cursor, idx) => {
|
||||
currentCurIdx.current = idx;
|
||||
partitionOffset.value = withTiming(
|
||||
-(cursor.x - data!.cursors[0]!.x) / partitionDims[0],
|
||||
{
|
||||
duration: transitionDuration,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
}
|
||||
);
|
||||
if (idx === data!.cursors.length - 1) {
|
||||
setEndPartitionReached(true);
|
||||
}
|
||||
if (playType === 'practice') return;
|
||||
if (!isPianoLoaded) return;
|
||||
cursor.notes.forEach((note) => {
|
||||
piano.current?.start({
|
||||
note: note.note,
|
||||
duration: note.duration,
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
if (!endPartitionReached && currentCurIdx.current + 1 === data?.cursors.length) {
|
||||
// weird contraption but the mobile don't want classic functions to be called
|
||||
@@ -166,58 +197,7 @@ const PartitionMagic = ({
|
||||
}
|
||||
}, [endPartitionReached]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!melodySound.current || !melodySound.current._loaded) return;
|
||||
if (!data || data?.cursors.length === 0) return;
|
||||
|
||||
melodySound.current.setOnPlaybackStatusUpdate((status) => {
|
||||
//@ts-expect-error positionMillis is not in the type
|
||||
const timestamp = status?.positionMillis ?? 0;
|
||||
getCursorToPlay(
|
||||
data!.cursors,
|
||||
currentCurIdx.current,
|
||||
timestamp + transitionDuration,
|
||||
(cursor, idx) => {
|
||||
currentCurIdx.current = idx;
|
||||
partitionOffset.value = withTiming(
|
||||
-(cursor.x - data!.cursors[0]!.x) / partitionDims[0],
|
||||
{
|
||||
duration: transitionDuration,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
});
|
||||
}, [data?.cursors, melodySound.current?._loaded]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (!shouldPlay) return;
|
||||
if (!isPianoLoaded || melodySound.current) return;
|
||||
if (!data || data?.cursors.length === 0) return;
|
||||
getCursorToPlay(
|
||||
data!.cursors,
|
||||
currentCurIdx.current,
|
||||
timestamp + transitionDuration,
|
||||
(cursor, idx) => {
|
||||
currentCurIdx.current = idx;
|
||||
partitionOffset.value = withTiming(
|
||||
-(cursor.x - data!.cursors[0]!.x) / partitionDims[0],
|
||||
{
|
||||
duration: transitionDuration,
|
||||
easing: Easing.inOut(Easing.ease),
|
||||
}
|
||||
);
|
||||
if (playType === 'practice') return;
|
||||
cursor.notes.forEach((note) => {
|
||||
piano.current?.start({
|
||||
note: note.note,
|
||||
duration: note.duration,
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
}, [timestamp, data?.cursors, isPianoLoaded]);
|
||||
React.useEffect(updateCursor, [data?.cursors, isPianoLoaded, timestamp.current]);
|
||||
|
||||
const animatedStyle = useAnimatedStyle(() => ({
|
||||
left: `${partitionOffset.value * 100}%`,
|
||||
|
||||
35
front/components/Play/PlayTimestampShow.tsx
Normal file
35
front/components/Play/PlayTimestampShow.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { Text, useTheme } from 'native-base';
|
||||
import { MutableRefObject, useEffect, useState } from 'react';
|
||||
|
||||
export let updateTime: (() => void) | undefined = undefined;
|
||||
|
||||
type PlayTimestampShowProps = {
|
||||
paused: boolean;
|
||||
time: MutableRefObject<number>;
|
||||
};
|
||||
|
||||
export const PlayTimestampShow = ({ paused, time }: PlayTimestampShowProps) => {
|
||||
const { colors } = useTheme();
|
||||
const textColor = colors.text;
|
||||
const [timeD, setTimeD] = useState<number>(time.current);
|
||||
|
||||
updateTime = () => {
|
||||
setTimeD(time.current);
|
||||
};
|
||||
|
||||
useEffect(updateTime, [time]);
|
||||
return (
|
||||
<Text color={textColor[900]}>
|
||||
{timeD < 0
|
||||
? paused
|
||||
? '0:00'
|
||||
: Math.floor((timeD % 60000) / 1000)
|
||||
.toFixed(0)
|
||||
.toString()
|
||||
: `${Math.floor(timeD / 60000)}:${Math.floor((timeD % 60000) / 1000)
|
||||
.toFixed(0)
|
||||
.toString()
|
||||
.padStart(2, '0')}`}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
@@ -6,11 +6,12 @@ import { MetronomeControls } from '../Metronome';
|
||||
import StarProgress from '../StarProgress';
|
||||
import Song from '../../models/Song';
|
||||
import { useTheme } from 'native-base';
|
||||
import { PlayTimestampShow } from './PlayTimestampShow';
|
||||
|
||||
type PlayViewControlBarProps = {
|
||||
playType: 'practice' | 'normal' | null;
|
||||
song: Song;
|
||||
time: number;
|
||||
time: React.MutableRefObject<number>;
|
||||
paused: boolean;
|
||||
score: number;
|
||||
disabled: boolean;
|
||||
@@ -132,18 +133,7 @@ const PlayViewControlBar = ({
|
||||
}}
|
||||
onPress={onEnd}
|
||||
/>
|
||||
<Text color={textColor[900]}>
|
||||
{time < 0
|
||||
? paused
|
||||
? '0:00'
|
||||
: Math.floor((time % 60000) / 1000)
|
||||
.toFixed(0)
|
||||
.toString()
|
||||
: `${Math.floor(time / 60000)}:${Math.floor((time % 60000) / 1000)
|
||||
.toFixed(0)
|
||||
.toString()
|
||||
.padStart(2, '0')}`}
|
||||
</Text>
|
||||
<PlayTimestampShow paused={paused} time={time} />
|
||||
<StarProgress
|
||||
value={score}
|
||||
max={100}
|
||||
|
||||
@@ -15,7 +15,7 @@ import { useStopwatch } from 'react-use-precision-timer';
|
||||
import { MIDIAccess, MIDIMessageEvent, requestMIDIAccess } from '@motiz88/react-native-midi';
|
||||
import * as Linking from 'expo-linking';
|
||||
import url from 'url';
|
||||
import PartitionMagic from '../components/Play/PartitionMagic';
|
||||
import PartitionMagic, { updateCursor } from '../components/Play/PartitionMagic';
|
||||
import useColorScheme from '../hooks/colorScheme';
|
||||
import { LinearGradient } from 'expo-linear-gradient';
|
||||
import { useTheme, useBreakpointValue } from 'native-base';
|
||||
@@ -25,6 +25,7 @@ import { Clock, Cup } from 'iconsax-react-native';
|
||||
import PlayViewControlBar from '../components/Play/PlayViewControlBar';
|
||||
import ScoreModal from '../components/ScoreModal';
|
||||
import { PlayScore, ScoreMessage } from '../components/Play/PlayScore';
|
||||
import { updateTime as updateTimeControlBar } from '../components/Play/PlayTimestampShow';
|
||||
|
||||
type PlayViewProps = {
|
||||
songId: number;
|
||||
@@ -68,7 +69,8 @@ const PlayView = ({ songId }: PlayViewProps) => {
|
||||
const webSocket = useRef<WebSocket>();
|
||||
const [paused, setPause] = useState<boolean>(true);
|
||||
const stopwatch = useStopwatch();
|
||||
const [time, setTime] = useState(0);
|
||||
// const [time, setTime] = useState(0);
|
||||
const time = useRef(0);
|
||||
const [endResult, setEndResult] = useState<unknown>();
|
||||
const [shouldPlay, setShouldPlay] = useState(false);
|
||||
const songHistory = useQuery(API.getSongHistory(songId));
|
||||
@@ -195,7 +197,10 @@ const PlayView = ({ songId }: PlayViewProps) => {
|
||||
setScore(Math.floor((Math.max(points, 0) * 100) / maxPoints));
|
||||
|
||||
if (data.type == 'step') {
|
||||
setTime(data.timestamp);
|
||||
// setTime(data.timestamp);
|
||||
time.current = data.timestamp;
|
||||
updateCursor?.();
|
||||
updateTimeControlBar?.();
|
||||
return;
|
||||
}
|
||||
let formattedMessage = '';
|
||||
@@ -261,7 +266,9 @@ const PlayView = ({ songId }: PlayViewProps) => {
|
||||
if (playType == 'practice') return;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
setTime(() => getElapsedTime());
|
||||
time.current = getElapsedTime();
|
||||
updateCursor?.();
|
||||
updateTimeControlBar?.();
|
||||
}, 200);
|
||||
return () => clearInterval(interval);
|
||||
}, [playType]);
|
||||
|
||||
Reference in New Issue
Block a user