feat: restart on web
This commit is contained in:
@@ -0,0 +1,61 @@
|
|||||||
|
import * as React from "react";
|
||||||
|
import { View } from "react-native";
|
||||||
|
import Svg, { ClipPath, Defs, G, Path, Rect } from "react-native-svg";
|
||||||
|
|
||||||
|
const RestartSpinnerIcon = ({
|
||||||
|
size = 30,
|
||||||
|
color = "#F94697",
|
||||||
|
background = "transparent",
|
||||||
|
style,
|
||||||
|
}) => {
|
||||||
|
return (
|
||||||
|
<View
|
||||||
|
style={[
|
||||||
|
{
|
||||||
|
width: size + 8,
|
||||||
|
height: size + 8,
|
||||||
|
borderRadius: size,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
|
backgroundColor: background,
|
||||||
|
},
|
||||||
|
style,
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
||||||
|
<G clipPath="url(#restartSpinnerClip)">
|
||||||
|
<Path
|
||||||
|
d="
|
||||||
|
M19.7285 10.9286
|
||||||
|
C20.4412 13.5975 19.7507 16.5633 17.6569 18.6571
|
||||||
|
C14.5327 21.7813 9.46734 21.7813 6.34315 18.6571
|
||||||
|
C3.21895 15.5329 3.21895 10.4676 6.34315 7.34338
|
||||||
|
C9.46734 4.21918 14.5327 4.21918 17.6569 7.34338
|
||||||
|
L18.364 8.05048
|
||||||
|
"
|
||||||
|
stroke={color}
|
||||||
|
strokeWidth={2}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<Path
|
||||||
|
d="M14.1214 8.05026H18.364V3.80762"
|
||||||
|
stroke={color}
|
||||||
|
strokeWidth={2}
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</G>
|
||||||
|
|
||||||
|
<Defs>
|
||||||
|
<ClipPath id="restartSpinnerClip">
|
||||||
|
<Rect width="24" height="24" fill="white" />
|
||||||
|
</ClipPath>
|
||||||
|
</Defs>
|
||||||
|
</Svg>
|
||||||
|
</View>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default RestartSpinnerIcon;
|
||||||
@@ -10,12 +10,13 @@ import React, {
|
|||||||
} from "react";
|
} from "react";
|
||||||
import { Text, TouchableOpacity, View } from "react-native";
|
import { Text, TouchableOpacity, View } from "react-native";
|
||||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
import Svg, { Circle, Path, G, Defs, Rect, ClipPath } from "react-native-svg";
|
import Svg, { Circle } from "react-native-svg";
|
||||||
import alert from "../../components/Alert";
|
import alert from "../../components/Alert";
|
||||||
import GradientButton from "../../components/GradientButton";
|
import GradientButton from "../../components/GradientButton";
|
||||||
import KaraokeLyrics from "../../components/KaraokeLyrics";
|
import KaraokeLyrics from "../../components/KaraokeLyrics";
|
||||||
import MusicLandHeader from "../../components/MusicLandHeader";
|
import MusicLandHeader from "../../components/MusicLandHeader";
|
||||||
import { increment, projectsRef } from "../../config/firebase";
|
import { increment, projectsRef } from "../../config/firebase";
|
||||||
|
import RestartSpinnerIcon from "../../assets/UI/RestartSpinnerIcon";
|
||||||
import usePlayer from "../../hooks/usePlayer";
|
import usePlayer from "../../hooks/usePlayer";
|
||||||
import useSharedAudioPlayer from "../../hooks/useSharedAudioPlayer";
|
import useSharedAudioPlayer from "../../hooks/useSharedAudioPlayer";
|
||||||
import { Routes } from "../../navigation";
|
import { Routes } from "../../navigation";
|
||||||
@@ -887,60 +888,6 @@ const ProgressRing = ({ size = 50, strokeWidth = 12, progress = 0 }) => {
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const RestartSpinnerIcon = ({
|
|
||||||
size = 30,
|
|
||||||
color = "#F94697", // couleur unie
|
|
||||||
background = "transparent",
|
|
||||||
}) => {
|
|
||||||
return (
|
|
||||||
<View
|
|
||||||
style={{
|
|
||||||
width: size + 8,
|
|
||||||
height: size + 8,
|
|
||||||
borderRadius: size,
|
|
||||||
alignItems: "center",
|
|
||||||
justifyContent: "center",
|
|
||||||
backgroundColor: background,
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Svg width={size} height={size} viewBox="0 0 24 24" fill="none">
|
|
||||||
<G clipPath="url(#clip0)">
|
|
||||||
{/* Cercle re-dessiné sans opacité */}
|
|
||||||
<Path
|
|
||||||
d="
|
|
||||||
M19.7285 10.9286
|
|
||||||
C20.4412 13.5975 19.7507 16.5633 17.6569 18.6571
|
|
||||||
C14.5327 21.7813 9.46734 21.7813 6.34315 18.6571
|
|
||||||
C3.21895 15.5329 3.21895 10.4676 6.34315 7.34338
|
|
||||||
C9.46734 4.21918 14.5327 4.21918 17.6569 7.34338
|
|
||||||
L18.364 8.05048
|
|
||||||
"
|
|
||||||
stroke={color}
|
|
||||||
strokeWidth={2}
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
|
|
||||||
{/* Flèche */}
|
|
||||||
<Path
|
|
||||||
d="M14.1214 8.05026H18.364V3.80762"
|
|
||||||
stroke={color}
|
|
||||||
strokeWidth={2}
|
|
||||||
strokeLinecap="round"
|
|
||||||
strokeLinejoin="round"
|
|
||||||
/>
|
|
||||||
</G>
|
|
||||||
|
|
||||||
<Defs>
|
|
||||||
<ClipPath id="clip0">
|
|
||||||
<Rect width="24" height="24" fill="white" />
|
|
||||||
</ClipPath>
|
|
||||||
</Defs>
|
|
||||||
</Svg>
|
|
||||||
</View>
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
export default RecordPlayback;
|
export default RecordPlayback;
|
||||||
|
|
||||||
// Render previous/current/next line to reduce jumpiness
|
// Render previous/current/next line to reduce jumpiness
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import React, {
|
|||||||
useRef,
|
useRef,
|
||||||
useState,
|
useState,
|
||||||
} from "react";
|
} from "react";
|
||||||
import { Text, View } from "react-native";
|
import { Text, TouchableOpacity, View } from "react-native";
|
||||||
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
import { useSafeAreaInsets } from "react-native-safe-area-context";
|
||||||
import Svg, { Circle } from "react-native-svg";
|
import Svg, { Circle } from "react-native-svg";
|
||||||
import alert from "../../components/Alert";
|
import alert from "../../components/Alert";
|
||||||
@@ -26,6 +26,7 @@ import { FONT_FAMILY } from "../../styles/Fonts";
|
|||||||
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
|
import CreateLyricsHeader from "../Writing/components/CreateLyricsHeader";
|
||||||
import { background } from "../../assets";
|
import { background } from "../../assets";
|
||||||
import playbackBG2 from "../../assets/UI/playbackBG2.png";
|
import playbackBG2 from "../../assets/UI/playbackBG2.png";
|
||||||
|
import RestartSpinnerIcon from "../../assets/UI/RestartSpinnerIcon";
|
||||||
|
|
||||||
const TIME_BEFORE_INCREMENT_MS = 20000;
|
const TIME_BEFORE_INCREMENT_MS = 20000;
|
||||||
const LOG_PREFIX = "[RecordPlayback.web]";
|
const LOG_PREFIX = "[RecordPlayback.web]";
|
||||||
@@ -736,6 +737,23 @@ const RecordPlayback = ({ route }) => {
|
|||||||
});
|
});
|
||||||
}, 1000);
|
}, 1000);
|
||||||
}, [songUrl, canRecord, resetSession, startPlayback]);
|
}, [songUrl, canRecord, resetSession, startPlayback]);
|
||||||
|
|
||||||
|
const handleRestartRecording = useCallback(async () => {
|
||||||
|
console.log(LOG_PREFIX, "restartButton:pressed", {
|
||||||
|
isPreparing,
|
||||||
|
isRecording,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
await startCountdownThenRecord();
|
||||||
|
} catch (e) {
|
||||||
|
console.log(
|
||||||
|
LOG_PREFIX,
|
||||||
|
"restartButton:error",
|
||||||
|
String(e?.message || e || ""),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [isPreparing, isRecording, startCountdownThenRecord]);
|
||||||
|
|
||||||
const progressRatio = dur > 0 ? Math.min(1, pos / dur) : 0;
|
const progressRatio = dur > 0 ? Math.min(1, pos / dur) : 0;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -873,7 +891,7 @@ const RecordPlayback = ({ route }) => {
|
|||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
{/* Progress circulaire */}
|
{/* Progress circulaire + restart */}
|
||||||
{permissionsGranted && (isRecording || isPreparing) && (
|
{permissionsGranted && (isRecording || isPreparing) && (
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
@@ -887,27 +905,38 @@ const RecordPlayback = ({ route }) => {
|
|||||||
>
|
>
|
||||||
<View
|
<View
|
||||||
style={{
|
style={{
|
||||||
width: 100,
|
width: 120,
|
||||||
height: 100,
|
height: 120,
|
||||||
borderRadius: 105,
|
borderRadius: 120,
|
||||||
alignItems: "center",
|
alignItems: "center",
|
||||||
justifyContent: "center",
|
justifyContent: "center",
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ProgressRing
|
<ProgressRing
|
||||||
size={100}
|
size={120}
|
||||||
strokeWidth={8}
|
strokeWidth={8}
|
||||||
progress={progressRatio}
|
progress={progressRatio}
|
||||||
/>
|
/>
|
||||||
<View
|
<TouchableOpacity
|
||||||
|
activeOpacity={0.9}
|
||||||
|
onPress={handleRestartRecording}
|
||||||
style={{
|
style={{
|
||||||
position: "absolute",
|
position: "absolute",
|
||||||
width: 50,
|
width: 70,
|
||||||
height: 50,
|
height: 70,
|
||||||
borderRadius: 55,
|
borderRadius: 80,
|
||||||
|
alignItems: "center",
|
||||||
|
justifyContent: "center",
|
||||||
backgroundColor: Palette.white,
|
backgroundColor: Palette.white,
|
||||||
|
shadowColor: "#000000",
|
||||||
|
shadowOpacity: 0.12,
|
||||||
|
shadowRadius: 10,
|
||||||
|
shadowOffset: { width: 0, height: 4 },
|
||||||
|
elevation: 4,
|
||||||
}}
|
}}
|
||||||
/>
|
>
|
||||||
|
<RestartSpinnerIcon />
|
||||||
|
</TouchableOpacity>
|
||||||
</View>
|
</View>
|
||||||
</View>
|
</View>
|
||||||
)}
|
)}
|
||||||
@@ -981,7 +1010,7 @@ const ProgressRing = ({ size = 50, strokeWidth = 12, progress = 0 }) => {
|
|||||||
style={{
|
style={{
|
||||||
transform: [{ rotate: "-90deg" }],
|
transform: [{ rotate: "-90deg" }],
|
||||||
backgroundColor: "#ffffff3d",
|
backgroundColor: "#ffffff3d",
|
||||||
borderRadius: 55,
|
borderRadius: size / 2,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Circle
|
<Circle
|
||||||
|
|||||||
@@ -291,9 +291,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
updateData.musicUrls = firebase.firestore.FieldValue.delete();
|
updateData.musicUrls = firebase.firestore.FieldValue.delete();
|
||||||
updateData.musicStatus = firebase.firestore.FieldValue.delete();
|
updateData.musicStatus = firebase.firestore.FieldValue.delete();
|
||||||
}
|
}
|
||||||
await projectsRef
|
await projectsRef.doc(selectedProjectId).set(updateData, { merge: true });
|
||||||
.doc(selectedProjectId)
|
|
||||||
.set(updateData, { merge: true });
|
|
||||||
const projectForStage = {
|
const projectForStage = {
|
||||||
...selectedProject,
|
...selectedProject,
|
||||||
title: titleTrimmed,
|
title: titleTrimmed,
|
||||||
@@ -507,9 +505,7 @@ const Lyrics = ({ navigation }) => {
|
|||||||
<View style={styles.sensitiveCheckboxWrapper}>
|
<View style={styles.sensitiveCheckboxWrapper}>
|
||||||
<AppCheckbox
|
<AppCheckbox
|
||||||
selected={isSensitiveContentAcknowledged}
|
selected={isSensitiveContentAcknowledged}
|
||||||
onPress={() =>
|
onPress={() => setIsSensitiveContentAcknowledged((prev) => !prev)}
|
||||||
setIsSensitiveContentAcknowledged((prev) => !prev)
|
|
||||||
}
|
|
||||||
label={RESPONSIBILITY_CHECKBOX_LABEL}
|
label={RESPONSIBILITY_CHECKBOX_LABEL}
|
||||||
/>
|
/>
|
||||||
</View>
|
</View>
|
||||||
|
|||||||
Reference in New Issue
Block a user