Added first works on the V2 of the partitionview
This commit is contained in:
8314
front/API.ts
8314
front/API.ts
File diff suppressed because it is too large
Load Diff
@@ -16,7 +16,7 @@ COPY . .
|
||||
ARG API_URL
|
||||
ENV EXPO_PUBLIC_API_URL=$API_URL
|
||||
ARG SCORO_URL
|
||||
ENV EXPO_PUBLIC_API_URL=$SCORO_URL
|
||||
ENV EXPO_PUBLIC_SCORO_URL=$SCORO_URL
|
||||
|
||||
RUN yarn tsc && npx expo export:web
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ module.exports = function (api) {
|
||||
allowUndefined: true,
|
||||
},
|
||||
],
|
||||
'@babel/plugin-proposal-export-namespace-from',
|
||||
'react-native-reanimated/plugin',
|
||||
],
|
||||
// plugins: ['@babel/plugin-proposal-export-namespace-from', 'react-native-reanimated/plugin'],
|
||||
// env: {
|
||||
|
||||
137
front/components/Play/PartitionMagic.tsx
Normal file
137
front/components/Play/PartitionMagic.tsx
Normal file
@@ -0,0 +1,137 @@
|
||||
import * as React from 'react';
|
||||
import { ActivityIndicator, View, ImageBackground, Platform } from 'react-native';
|
||||
import API from '../../API';
|
||||
import { useQuery } from '../../Queries';
|
||||
import { SvgCssUri } from 'react-native-svg';
|
||||
import { PianoCC } from '../../views/PlayView';
|
||||
import { Button } from 'native-base';
|
||||
import Animated, { useSharedValue, withTiming, withSpring, Easing } from 'react-native-reanimated';
|
||||
import { CursorInfoItem, SongCursorInfos } from '../../models/SongCursorInfos';
|
||||
|
||||
const myFindLast = <T,>(a: T[], p: (_: T, _2: number) => boolean) => {
|
||||
for (let i = a.length - 1; i >= 0; i--) {
|
||||
if (p(a[i]!, i)) {
|
||||
return a[i];
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
|
||||
// note we are also using timestamp in a context
|
||||
export type ParitionMagicProps = {
|
||||
songID: number;
|
||||
paused: boolean;
|
||||
onEndReached: () => void;
|
||||
onError: (err: string) => void;
|
||||
onReady: () => void;
|
||||
};
|
||||
|
||||
const getSVGURL = (songID: number) => {
|
||||
return 'https://cdn.discordapp.com/attachments/717080637038788731/1161704545785757816/4.svg?ex=653944ab&is=6526cfab&hm=2416ee2cb414cc42fa9de8af58b8db544479d35f13393d76f02e8d9fe27aff45&';
|
||||
};
|
||||
|
||||
const SVGContainer = ({ songID, onReady }: { songID: number; onReady: () => void }) => {
|
||||
if (Platform.OS === 'web') {
|
||||
return <img src={getSVGURL(songID)} onLoad={(e) => onReady()} />;
|
||||
} else {
|
||||
return <SvgCssUri uri={getSVGURL(songID)} />;
|
||||
}
|
||||
};
|
||||
|
||||
const getCursorToPlay = (
|
||||
cursorInfos: CursorInfoItem[],
|
||||
currentCurIdx: number,
|
||||
timestamp: number,
|
||||
onCursorMove: (cursor: CursorInfoItem, idx: number) => void
|
||||
) => {
|
||||
for (let i = cursorInfos.length - 1; i > currentCurIdx; i--) {
|
||||
const cursorInfo = cursorInfos[i]!;
|
||||
if (cursorInfo.timestamp <= timestamp) {
|
||||
onCursorMove(cursorInfo, i);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const PartitionMagic = ({ songID, paused, onEndReached, onError, onReady }: ParitionMagicProps) => {
|
||||
const { data, isLoading, isError } = useQuery(API.getSongCursorInfos(songID));
|
||||
const [currentCurIdx, setCurrentCurIdx] = React.useState(0);
|
||||
const partitionOffset = useSharedValue(0);
|
||||
const cursorPosition = useSharedValue(0);
|
||||
const pianoCC = React.useContext(PianoCC);
|
||||
const partitionWidth = 16573;
|
||||
const partitionHeight = 402;
|
||||
|
||||
getCursorToPlay(data?.cursors ?? [], currentCurIdx, pianoCC.timestamp, (cursor, idx) => {
|
||||
partitionOffset.value = -cursor.x + data!.cursors[0]!.x;
|
||||
|
||||
// cursorPosition.value = cursor.x;
|
||||
setCurrentCurIdx(idx);
|
||||
// duration: 75,
|
||||
// // easing: Easing.inOut(Easing.ease),
|
||||
// });
|
||||
});
|
||||
|
||||
const handlePress = () => {
|
||||
partitionOffset.value = withSpring(partitionOffset.value - 50);
|
||||
};
|
||||
return (
|
||||
<>
|
||||
<View
|
||||
style={{
|
||||
flex: 1,
|
||||
flexDirection: 'row',
|
||||
alignItems: 'flex-start',
|
||||
overflow: 'hidden',
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<Animated.View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
height: '100%',
|
||||
left: partitionOffset,
|
||||
}}
|
||||
>
|
||||
<ImageBackground
|
||||
source={{ uri: getSVGURL(songID) }}
|
||||
onLoad={onReady}
|
||||
style={{
|
||||
aspectRatio: partitionWidth / partitionHeight,
|
||||
height: '100%',
|
||||
position: 'relative',
|
||||
}}
|
||||
>
|
||||
<Animated.View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: `${(data?.cursors[0]?.x ?? 0) / partitionWidth * 100}%`,
|
||||
top: `${(data?.cursors[0]?.y ?? 0) / partitionHeight * 100}%`,
|
||||
backgroundColor: 'rgba(96, 117, 249, 0.33)',
|
||||
width: `${30 / partitionWidth * 100}%`, // 46,
|
||||
height: `${144 / partitionHeight * 100}%`, // 160,
|
||||
}}
|
||||
/>
|
||||
</ImageBackground>
|
||||
{/* <SVGContainer songID={songID} onReady={onReady} /> */}
|
||||
</Animated.View>
|
||||
{/* <View
|
||||
style={{
|
||||
position: 'absolute',
|
||||
left: (data?.cursors[0]?.x ?? 0) - 5,
|
||||
top: data?.cursors[0]?.y ?? 0,
|
||||
backgroundColor: 'rgba(96, 117, 249, 0.33)',
|
||||
borderRadius: 20,
|
||||
borderWidth: 5,
|
||||
borderColor: '#101014',
|
||||
borderStyle: 'solid',
|
||||
paddingVertical: 16,
|
||||
}}
|
||||
> */}
|
||||
{/* </View> */}
|
||||
</View>
|
||||
<Button onPress={handlePress}>Move</Button>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default PartitionMagic;
|
||||
68
front/models/SongCursorInfos.ts
Normal file
68
front/models/SongCursorInfos.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import * as yup from 'yup';
|
||||
import ResponseHandler from './ResponseHandler';
|
||||
|
||||
export const SongCursorInfosValidator = yup.object({
|
||||
pageWidth: yup.number().required(),
|
||||
cursors: yup
|
||||
.array()
|
||||
.of(
|
||||
yup.object({
|
||||
x: yup.number().required(),
|
||||
y: yup.number().required(),
|
||||
width: yup.number().required(),
|
||||
height: yup.number().required(),
|
||||
timestamp: yup.number().required(),
|
||||
timing: yup.number().required(),
|
||||
note: yup
|
||||
.object({
|
||||
note: yup.number().required(),
|
||||
gain: yup.number().required(),
|
||||
duration: yup.number().required(),
|
||||
})
|
||||
.required(),
|
||||
})
|
||||
)
|
||||
.required(),
|
||||
});
|
||||
|
||||
export const SongCursorInfosHandler: ResponseHandler<
|
||||
yup.InferType<typeof SongCursorInfosValidator>,
|
||||
SongCursorInfos
|
||||
> = {
|
||||
validator: SongCursorInfosValidator,
|
||||
transformer: (songCursorInfos: yup.InferType<typeof SongCursorInfosValidator>) => ({
|
||||
pageWidth: songCursorInfos.pageWidth,
|
||||
cursors: songCursorInfos.cursors.map((cursor) => ({
|
||||
x: cursor.x,
|
||||
y: cursor.y,
|
||||
width: cursor.width,
|
||||
height: cursor.height,
|
||||
timestamp: cursor.timestamp,
|
||||
timing: cursor.timing,
|
||||
note: {
|
||||
note: cursor.note.note,
|
||||
gain: cursor.note.gain,
|
||||
duration: cursor.note.duration,
|
||||
},
|
||||
})),
|
||||
}),
|
||||
};
|
||||
|
||||
export interface CursorInfoItem {
|
||||
x: number;
|
||||
y: number;
|
||||
width: number;
|
||||
height: number;
|
||||
timestamp: number;
|
||||
timing: number;
|
||||
note: {
|
||||
note: number;
|
||||
gain: number;
|
||||
duration: number;
|
||||
};
|
||||
}
|
||||
|
||||
export interface SongCursorInfos {
|
||||
pageWidth: number;
|
||||
cursors: CursorInfoItem[];
|
||||
}
|
||||
@@ -34,7 +34,7 @@
|
||||
"expo-status-bar": "~1.6.0",
|
||||
"i18next": "^23.5.1",
|
||||
"iconsax-react-native": "^0.0.8",
|
||||
"moti": "^0.26.0",
|
||||
"moti": "^0.27.0",
|
||||
"native-base": "^3.4.28",
|
||||
"normalize-css-color": "^1.0.2",
|
||||
"opensheetmusicdisplay": "^1.8.4",
|
||||
@@ -66,6 +66,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@babel/plugin-transform-export-namespace-from": "^7.22.11",
|
||||
"@types/lodash": "^4.14.199",
|
||||
"@types/react": "~18.2.14",
|
||||
"@typescript-eslint/eslint-plugin": "^6.7.3",
|
||||
|
||||
@@ -33,6 +33,7 @@ import * as Linking from 'expo-linking';
|
||||
import url from 'url';
|
||||
import { PianoCanvasContext, PianoCanvasMsg, NoteTiming } from '../models/PianoGame';
|
||||
import { Metronome } from '../components/Metronome';
|
||||
import PartitionMagic from '../components/Play/PartitionMagic';
|
||||
|
||||
type PlayViewProps = {
|
||||
songId: number;
|
||||
@@ -347,14 +348,21 @@ const PlayView = ({ songId, type, route }: RouteProps<PlayViewProps>) => {
|
||||
messages: pianoMsgs,
|
||||
}}
|
||||
>
|
||||
<PartitionCoord
|
||||
<PartitionMagic
|
||||
songID={song.data.id}
|
||||
paused={paused}
|
||||
onReady={() => setPartitionRendered(true)}
|
||||
onEndReached={() => {}}
|
||||
onError={() => {}}
|
||||
/>
|
||||
{/* <PartitionCoord
|
||||
file={musixml.data}
|
||||
bpmRef={bpm}
|
||||
onEndReached={onEnd}
|
||||
onPause={onPause}
|
||||
onResume={onResume}
|
||||
onPartitionReady={() => setPartitionRendered(true)}
|
||||
/>
|
||||
/> */}
|
||||
</PianoCC.Provider>
|
||||
{!partitionRendered && <LoadingComponent />}
|
||||
</View>
|
||||
|
||||
@@ -9213,10 +9213,10 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
|
||||
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
|
||||
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
|
||||
|
||||
moti@^0.26.0:
|
||||
version "0.26.0"
|
||||
resolved "https://registry.yarnpkg.com/moti/-/moti-0.26.0.tgz#863e70e61c9d597f4fd701e588f41963335b927f"
|
||||
integrity sha512-430HDIwhPQi/DkMvocyAZGkAX3ibmbyF3Fj23GuhbTB+RUXYTOnbsvygr89ABJjllYuxx4Xjd2Z4Qab0Su5mcg==
|
||||
moti@^0.27.0:
|
||||
version "0.27.0"
|
||||
resolved "https://registry.yarnpkg.com/moti/-/moti-0.27.0.tgz#1590589e566044fcb2ffa775a7b333b319151248"
|
||||
integrity sha512-sVEFFVvo4XKGn3POUUTRONIuQCH1iA0THnjZdb4SSxn/x365ptoqZg1DflTq3egTox3WJT+7u27HErrzGmU/7g==
|
||||
dependencies:
|
||||
framer-motion "^6.5.1"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user