Added a loading dispaly for the play button and removed onProgressUpdate from expo av and reusing the timestamp to advance the cursor despite perf issues
This commit is contained in:
@@ -34,6 +34,7 @@ const getCursorToPlay = (
|
|||||||
const cursorInfo = cursorInfos[i]!;
|
const cursorInfo = cursorInfos[i]!;
|
||||||
if (cursorInfo.timestamp <= timestamp) {
|
if (cursorInfo.timestamp <= timestamp) {
|
||||||
onCursorMove(cursorInfo, i);
|
onCursorMove(cursorInfo, i);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -63,7 +64,7 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
|||||||
const piano = React.useRef<SplendidGrandPiano | null>(null);
|
const piano = React.useRef<SplendidGrandPiano | null>(null);
|
||||||
const [isPianoLoaded, setIsPianoLoaded] = React.useState(false);
|
const [isPianoLoaded, setIsPianoLoaded] = React.useState(false);
|
||||||
const [timestamp, setTimestamp] = useAtom(timestampAtom);
|
const [timestamp, setTimestamp] = useAtom(timestampAtom);
|
||||||
const shouldPlay = useAtom(shouldPlayAtom)[0];
|
const [shouldPlay, setShouldPlay] = useAtom(shouldPlayAtom);
|
||||||
const [partitionState, setPartitionState] = useAtom(partitionStateAtom);
|
const [partitionState, setPartitionState] = useAtom(partitionStateAtom);
|
||||||
const cursorPaddingVertical = 10;
|
const cursorPaddingVertical = 10;
|
||||||
const cursorPaddingHorizontal = 3;
|
const cursorPaddingHorizontal = 3;
|
||||||
@@ -76,7 +77,7 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
|||||||
const cursorTop = (data?.cursors[cursorDisplayIdx]?.y ?? 0) - cursorPaddingVertical;
|
const cursorTop = (data?.cursors[cursorDisplayIdx]?.y ?? 0) - cursorPaddingVertical;
|
||||||
const cursorLeft = (data?.cursors[0]?.x ?? 0) - cursorPaddingHorizontal;
|
const cursorLeft = (data?.cursors[0]?.x ?? 0) - cursorPaddingHorizontal;
|
||||||
|
|
||||||
console.log('state', partitionState);
|
console.log('state', partitionState, timestamp);
|
||||||
|
|
||||||
if (!endPartitionReached && currentCurIdx.current + 1 === data?.cursors.length) {
|
if (!endPartitionReached && currentCurIdx.current + 1 === data?.cursors.length) {
|
||||||
// weird contraption but the mobile don't want classic functions to be called
|
// weird contraption but the mobile don't want classic functions to be called
|
||||||
@@ -101,6 +102,8 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
|||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
setPartitionState('loading');
|
setPartitionState('loading');
|
||||||
|
setTimestamp(0);
|
||||||
|
setShouldPlay(false);
|
||||||
};
|
};
|
||||||
}, [isPartitionSvgLoaded, isLoading, melodySound.current?._loaded, isPianoLoaded]);
|
}, [isPartitionSvgLoaded, isLoading, melodySound.current?._loaded, isPianoLoaded]);
|
||||||
|
|
||||||
@@ -112,14 +115,9 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
|||||||
setIsPianoLoaded(true);
|
setIsPianoLoaded(true);
|
||||||
});
|
});
|
||||||
} else if (!melodySound.current) {
|
} else if (!melodySound.current) {
|
||||||
Audio.Sound.createAsync(
|
Audio.Sound.createAsync({
|
||||||
{
|
uri: API.getPartitionMelodyUrl(songID),
|
||||||
uri: API.getPartitionMelodyUrl(songID),
|
}).then((track) => {
|
||||||
},
|
|
||||||
{
|
|
||||||
progressUpdateIntervalMillis: 200,
|
|
||||||
}
|
|
||||||
).then((track) => {
|
|
||||||
melodySound.current = track.sound;
|
melodySound.current = track.sound;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -141,9 +139,13 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
|||||||
}, [data]);
|
}, [data]);
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
const interval = setInterval(() => {
|
const interval = setInterval(
|
||||||
setTimestamp(stopwatch.getElapsedRunningTime());
|
() => {
|
||||||
}, 200);
|
// if (partitionState !== 'playing') return;
|
||||||
|
setTimestamp(stopwatch.getElapsedRunningTime());
|
||||||
|
},
|
||||||
|
Platform.OS === 'web' ? 200 : 500
|
||||||
|
);
|
||||||
return () => {
|
return () => {
|
||||||
clearInterval(interval);
|
clearInterval(interval);
|
||||||
};
|
};
|
||||||
@@ -152,13 +154,13 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
|||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
if (Platform.OS === 'web') {
|
if (Platform.OS === 'web') {
|
||||||
if (!piano.current || !isPianoLoaded) return;
|
if (!piano.current || !isPianoLoaded) return;
|
||||||
startResumePauseWatch(stopwatch, shouldPlay);
|
|
||||||
setPartitionState(shouldPlay ? 'playing' : 'paused');
|
setPartitionState(shouldPlay ? 'playing' : 'paused');
|
||||||
|
startResumePauseWatch(stopwatch, shouldPlay);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!melodySound.current || !melodySound.current._loaded) return;
|
if (!melodySound.current || !melodySound.current._loaded) return;
|
||||||
startResumePauseWatch(stopwatch, shouldPlay);
|
|
||||||
setPartitionState(shouldPlay ? 'playing' : 'paused');
|
setPartitionState(shouldPlay ? 'playing' : 'paused');
|
||||||
|
startResumePauseWatch(stopwatch, shouldPlay);
|
||||||
if (shouldPlay) {
|
if (shouldPlay) {
|
||||||
melodySound.current.playAsync().catch(console.error);
|
melodySound.current.playAsync().catch(console.error);
|
||||||
} else {
|
} else {
|
||||||
@@ -166,34 +168,9 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
|||||||
}
|
}
|
||||||
}, [shouldPlay]);
|
}, [shouldPlay]);
|
||||||
|
|
||||||
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(() => {
|
React.useEffect(() => {
|
||||||
if (!shouldPlay) return;
|
if (!shouldPlay) return;
|
||||||
if (!piano.current || !isPianoLoaded) return;
|
if (!melodySound.current || !melodySound.current._loaded) return;
|
||||||
if (!data || data?.cursors.length === 0) return;
|
if (!data || data?.cursors.length === 0) return;
|
||||||
getCursorToPlay(
|
getCursorToPlay(
|
||||||
data!.cursors,
|
data!.cursors,
|
||||||
@@ -208,6 +185,7 @@ const PartitionMagic = ({ songID }: ParitionMagicProps) => {
|
|||||||
easing: Easing.inOut(Easing.ease),
|
easing: Easing.inOut(Easing.ease),
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
if (!piano.current || !isPianoLoaded) return;
|
||||||
cursor.notes.forEach((note) => {
|
cursor.notes.forEach((note) => {
|
||||||
piano.current?.start({
|
piano.current?.start({
|
||||||
note: note.note,
|
note: note.note,
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import { View } from 'react-native';
|
import { View } from 'react-native';
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { Row, Image, Text, useBreakpointValue, IconButton } from 'native-base';
|
import { Row, Image, Text, useBreakpointValue, IconButton, Button } from 'native-base';
|
||||||
import { Ionicons } from '@expo/vector-icons';
|
import { Ionicons } from '@expo/vector-icons';
|
||||||
import { MetronomeControls } from '../Metronome';
|
import { MetronomeControls } from '../Metronome';
|
||||||
import StarProgress from '../StarProgress';
|
import StarProgress from '../StarProgress';
|
||||||
@@ -26,7 +26,7 @@ const PlayViewControlBar = ({ song }: PlayViewControlBarProps) => {
|
|||||||
const { colors } = useTheme();
|
const { colors } = useTheme();
|
||||||
const textColor = colors.text;
|
const textColor = colors.text;
|
||||||
const isPlaying = partitionState === 'playing';
|
const isPlaying = partitionState === 'playing';
|
||||||
const disabled = partitionState === 'loading' || partitionState === 'error';
|
const isPartitionLoading = partitionState === 'loading';
|
||||||
|
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
return () => {
|
return () => {
|
||||||
@@ -109,17 +109,20 @@ const PlayViewControlBar = ({ song }: PlayViewControlBarProps) => {
|
|||||||
gap: isPhone ? 10 : 25,
|
gap: isPhone ? 10 : 25,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<IconButton
|
{isPartitionLoading ? (
|
||||||
size="sm"
|
<Button isLoading size="sm" variant="solid" color={colors.coolGray[900]} />
|
||||||
variant="solid"
|
) : (
|
||||||
disabled={disabled}
|
<IconButton
|
||||||
_icon={{
|
size="sm"
|
||||||
as: Ionicons,
|
variant="solid"
|
||||||
color: colors.coolGray[900],
|
_icon={{
|
||||||
name: isPlaying ? 'pause' : 'play',
|
as: Ionicons,
|
||||||
}}
|
color: colors.coolGray[900],
|
||||||
onPress={() => setShouldPlay(!isPlaying)}
|
name: isPlaying ? 'pause' : 'play',
|
||||||
/>
|
}}
|
||||||
|
onPress={() => setShouldPlay(!isPlaying)}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
<IconButton
|
<IconButton
|
||||||
size="sm"
|
size="sm"
|
||||||
colorScheme="coolGray"
|
colorScheme="coolGray"
|
||||||
|
|||||||
Reference in New Issue
Block a user