Play works on web websocket not reimplemented
This commit is contained in:
@@ -9,6 +9,7 @@ import { SvgContainer } from './SvgContainer';
|
||||
import LoadingComponent from '../Loading';
|
||||
import { SplendidGrandPiano } from 'smplr';
|
||||
import { atom, useAtom } from 'jotai';
|
||||
import { useStopwatch } from 'react-use-precision-timer';
|
||||
|
||||
export const timestampAtom = atom(0);
|
||||
export const shouldPlayAtom = atom(false);
|
||||
@@ -37,20 +38,21 @@ const getCursorToPlay = (
|
||||
}
|
||||
};
|
||||
|
||||
const transitionDuration = 50;
|
||||
const transitionDuration = 200;
|
||||
|
||||
const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
||||
const { data, isLoading, isError } = useQuery(API.getSongCursorInfos(songID));
|
||||
const currentCurIdx = React.useRef(-1);
|
||||
const stopwatch = useStopwatch();
|
||||
const [endPartitionReached, setEndPartitionReached] = React.useState(false);
|
||||
const [isPartitionSvgLoaded, setIsPartitionSvgLoaded] = React.useState(false);
|
||||
const partitionOffset = useSharedValue(0);
|
||||
const melodySound = React.useRef<Audio.Sound | null>(null);
|
||||
const piano = React.useRef<SplendidGrandPiano | null>(null);
|
||||
const [isPianoLoaded, setIsPianoLoaded] = React.useState(false);
|
||||
const timestamp = useAtom(timestampAtom)[0];
|
||||
const [timestamp, setTimestamp] = useAtom(timestampAtom);
|
||||
const shouldPlay = useAtom(shouldPlayAtom)[0];
|
||||
const [, setPartitionState] = useAtom(partitionStateAtom);
|
||||
const [partitionState, setPartitionState] = useAtom(partitionStateAtom);
|
||||
const cursorPaddingVertical = 10;
|
||||
const cursorPaddingHorizontal = 3;
|
||||
|
||||
@@ -62,13 +64,28 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
||||
const cursorTop = (data?.cursors[cursorDisplayIdx]?.y ?? 0) - cursorPaddingVertical;
|
||||
const cursorLeft = (data?.cursors[0]?.x ?? 0) - cursorPaddingHorizontal;
|
||||
|
||||
console.log('state', partitionState);
|
||||
|
||||
if (!endPartitionReached && currentCurIdx.current + 1 === data?.cursors.length) {
|
||||
// weird contraption but the mobile don't want classic functions to be called
|
||||
// with the withTiming function :(
|
||||
melodySound.current?.pauseAsync();
|
||||
piano.current?.stop();
|
||||
setPartitionState('ended');
|
||||
}
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isError) {
|
||||
setPartitionState('error');
|
||||
}
|
||||
}, [isError]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isPartitionSvgLoaded && !isLoading && (melodySound.current?._loaded || isPianoLoaded)) {
|
||||
setPartitionState('ready');
|
||||
}
|
||||
}, [isPartitionSvgLoaded, isLoading, melodySound.current?._loaded, isPianoLoaded]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (Platform.OS === 'web' && !piano.current) {
|
||||
const audio = new AudioContext();
|
||||
@@ -106,28 +123,23 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
||||
}, [data]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isError) {
|
||||
setPartitionState('error');
|
||||
}
|
||||
}, [isError]);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (isPartitionSvgLoaded && !isLoading && (melodySound.current?._loaded || isPianoLoaded)) {
|
||||
setPartitionState('ready');
|
||||
}
|
||||
}, [isPartitionSvgLoaded, isLoading, melodySound.current?._loaded, isPianoLoaded]);
|
||||
const interval = setInterval(() => {
|
||||
setTimestamp(stopwatch.getElapsedRunningTime());
|
||||
}, 200);
|
||||
return () => {
|
||||
clearInterval(interval);
|
||||
};
|
||||
}, []);
|
||||
|
||||
React.useEffect(() => {
|
||||
if (Platform.OS === 'web') {
|
||||
if (!piano.current || !isPianoLoaded) {
|
||||
return;
|
||||
}
|
||||
if (!piano.current || !isPianoLoaded) return;
|
||||
shouldPlay ? stopwatch.start() : stopwatch.pause();
|
||||
setPartitionState(shouldPlay ? 'playing' : 'paused');
|
||||
return;
|
||||
}
|
||||
if (!melodySound.current || !melodySound.current._loaded) {
|
||||
return;
|
||||
}
|
||||
if (!melodySound.current || !melodySound.current._loaded) return;
|
||||
shouldPlay ? stopwatch.start() : stopwatch.pause();
|
||||
if (shouldPlay) {
|
||||
melodySound.current
|
||||
.playAsync()
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
import PopupCC from '../UI/PopupCC';
|
||||
import { shouldEndAtom } from './PlayViewControlBar';
|
||||
import { partitionStateAtom } from './PartitionMagic';
|
||||
import ScoreModal from '../ScoreModal';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
export const PlayEndModal = () => {
|
||||
const [shouldEnd] = useAtom(shouldEndAtom);
|
||||
const [partitionState] = useAtom(partitionStateAtom);
|
||||
|
||||
const isEnd = shouldEnd || partitionState === 'ended';
|
||||
return (
|
||||
<PopupCC isVisible={isEnd}>
|
||||
<ScoreModal
|
||||
songId={0}
|
||||
overallScore={0}
|
||||
precision={0}
|
||||
score={{
|
||||
max_score: 0,
|
||||
missed: 0,
|
||||
wrong: 0,
|
||||
good: 0,
|
||||
great: 0,
|
||||
perfect: 0,
|
||||
current_streak: 0,
|
||||
max_streak: 0,
|
||||
}}
|
||||
/>
|
||||
</PopupCC>
|
||||
);
|
||||
};
|
||||
@@ -25,7 +25,7 @@ const PlayViewControlBar = ({ song }: PlayViewControlBarProps) => {
|
||||
const bpm = React.useRef<number>(60);
|
||||
const { colors } = useTheme();
|
||||
const textColor = colors.text;
|
||||
const paused = partitionState === 'paused';
|
||||
const isPlaying = partitionState === 'playing';
|
||||
const disabled = partitionState === 'loading' || partitionState === 'error';
|
||||
return (
|
||||
<Row
|
||||
@@ -108,9 +108,9 @@ const PlayViewControlBar = ({ song }: PlayViewControlBarProps) => {
|
||||
_icon={{
|
||||
as: Ionicons,
|
||||
color: colors.coolGray[900],
|
||||
name: paused ? 'play' : 'pause',
|
||||
name: isPlaying ? 'pause' : 'play',
|
||||
}}
|
||||
onPress={() => setShouldPlay(paused)}
|
||||
onPress={() => setShouldPlay(!isPlaying)}
|
||||
/>
|
||||
<IconButton
|
||||
size="sm"
|
||||
@@ -144,7 +144,7 @@ const PlayViewControlBar = ({ song }: PlayViewControlBarProps) => {
|
||||
minWidth: 120,
|
||||
}}
|
||||
>
|
||||
<MetronomeControls paused={paused} bpm={bpm.current} />
|
||||
<MetronomeControls paused={isPlaying} bpm={bpm.current} />
|
||||
</View>
|
||||
</Row>
|
||||
);
|
||||
|
||||
+31
-29
@@ -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 { PlayEndModal } from '../components/Play/PlayEndModal';
|
||||
|
||||
type PlayViewProps = {
|
||||
songId: number;
|
||||
@@ -63,22 +64,22 @@ const PlayView = ({ songId }: PlayViewProps) => {
|
||||
const isPhone = screenSize === 'small';
|
||||
const song = useQuery(API.getSong(songId, ['artist']), { staleTime: Infinity });
|
||||
const toast = useToast();
|
||||
const [lastScoreMessage, setLastScoreMessage] = useState<ScoreMessage>();
|
||||
// const [lastScoreMessage, setLastScoreMessage] = useState<ScoreMessage>();
|
||||
const webSocket = useRef<WebSocket>();
|
||||
const [paused, setPause] = useState<boolean>(true);
|
||||
const stopwatch = useStopwatch();
|
||||
const [time, setTime] = useState(0);
|
||||
// const [paused, setPause] = useState<boolean>(true);
|
||||
// const stopwatch = useStopwatch();
|
||||
// const [time, setTime] = useState(0);
|
||||
const [endResult, setEndResult] = useState<unknown>();
|
||||
const [shouldPlay, setShouldPlay] = useState(false);
|
||||
// const [shouldPlay, setShouldPlay] = useState(false);
|
||||
const songHistory = useQuery(API.getSongHistory(songId));
|
||||
const [score, setScore] = useState(0); // Between 0 and 100
|
||||
const getElapsedTime = () => stopwatch.getElapsedRunningTime();
|
||||
const [readyToPlay, setReadyToPlay] = useState(false);
|
||||
// const [score, setScore] = useState(0); // Between 0 and 100
|
||||
// const getElapsedTime = () => stopwatch.getElapsedRunningTime();
|
||||
// const [readyToPlay, setReadyToPlay] = useState(false);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [midiKeyboardFound, setMidiKeyboardFound] = useState<boolean>();
|
||||
// first number is the note, the other is the time when pressed on release the key is removed
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [streak, setStreak] = useState(0);
|
||||
// const [streak, setStreak] = useState(0);
|
||||
const colorScheme = useColorScheme();
|
||||
const { colors } = useTheme();
|
||||
const statColor = colors.lightText;
|
||||
@@ -131,7 +132,7 @@ const PlayView = ({ songId }: PlayViewProps) => {
|
||||
console.log('MIDI inputs', inputs);
|
||||
let endMsgReceived = false; // Used to know if to go to error screen when websocket closes
|
||||
|
||||
if (inputs.size <= 0) {
|
||||
if (inputs.size <= 10) {
|
||||
toast.show({ description: 'No MIDI Keyboard found' });
|
||||
return;
|
||||
}
|
||||
@@ -238,14 +239,14 @@ const PlayView = ({ songId }: PlayViewProps) => {
|
||||
|
||||
useEffect(() => {
|
||||
ScreenOrientation.lockAsync(ScreenOrientation.OrientationLock.LANDSCAPE).catch(() => {});
|
||||
const interval = setInterval(() => {
|
||||
setTime(() => getElapsedTime()); // Countdown
|
||||
}, 200);
|
||||
// const interval = setInterval(() => {
|
||||
// setTime(() => getElapsedTime()); // Countdown
|
||||
// }, 200);
|
||||
|
||||
return () => {
|
||||
ScreenOrientation.unlockAsync().catch(() => {});
|
||||
stopwatch.stop();
|
||||
clearInterval(interval);
|
||||
// stopwatch.stop();
|
||||
// clearInterval(interval);
|
||||
};
|
||||
}, []);
|
||||
|
||||
@@ -290,12 +291,13 @@ const PlayView = ({ songId }: PlayViewProps) => {
|
||||
zIndex: 100,
|
||||
}}
|
||||
>
|
||||
<PopupCC isVisible={endResult != undefined}>
|
||||
<PlayEndModal />
|
||||
{/* <PopupCC isVisible={endResult != undefined}>
|
||||
{
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(() => (endResult ? <ScoreModal {...(endResult as any)} /> : <></>))()
|
||||
endResult ? <ScoreModal {...(endResult as any)} /> : <></>
|
||||
}
|
||||
</PopupCC>
|
||||
</PopupCC> */}
|
||||
<PopupCC
|
||||
title={translate('selectPlayMode')}
|
||||
description={translate('selectPlayModeExplaination')}
|
||||
@@ -404,18 +406,18 @@ const PlayView = ({ songId }: PlayViewProps) => {
|
||||
/>
|
||||
</View>
|
||||
<PlayViewControlBar
|
||||
score={score}
|
||||
time={time}
|
||||
paused={paused}
|
||||
disabled={playType == null || !readyToPlay}
|
||||
// score={score}
|
||||
// time={time}
|
||||
// paused={paused}
|
||||
// disabled={playType == null || !readyToPlay}
|
||||
song={song.data}
|
||||
onEnd={onEnd}
|
||||
onPause={() => {
|
||||
setShouldPlay(false);
|
||||
}}
|
||||
onResume={() => {
|
||||
setShouldPlay(true);
|
||||
}}
|
||||
// onEnd={onEnd}
|
||||
// onPause={() => {
|
||||
// setShouldPlay(false);
|
||||
// }}
|
||||
// onResume={() => {
|
||||
// setShouldPlay(true);
|
||||
// }}
|
||||
/>
|
||||
</SafeAreaView>
|
||||
{colorScheme === 'dark' && (
|
||||
|
||||
Reference in New Issue
Block a user