Added first works on the V2 of the partitionview

This commit is contained in:
Clément Le Bihan
2023-10-13 01:21:25 +02:00
parent 57cba61d1b
commit f91ab4c430
8 changed files with 8538 additions and 8 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -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

View File

@@ -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: {

View 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;

View 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[];
}

View File

@@ -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",

View File

@@ -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>

View File

@@ -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"