clear lot of tickets

This commit is contained in:
Thomas Demirdjian
2025-11-07 17:33:06 +01:00
parent 4365f1e46d
commit d7d9211fbe
30 changed files with 970 additions and 355 deletions
+91 -4
View File
@@ -11,6 +11,7 @@ import React, {
import {
Pressable,
Image as RNImage,
Platform,
ScrollView,
StyleSheet,
Text,
@@ -52,6 +53,7 @@ import {
createMusicSharePayload,
openShareSheet,
} from "../../utils/shareSheet";
import { goBack } from "../../navigation/NavigationService";
// 20 secondes
const timeBeforeIncrement = 20000;
@@ -71,6 +73,29 @@ const MusicDetails = ({ route }) => {
const timerRef = React.useRef(null);
const hasAutoPlayedRef = React.useRef(false);
const { isLooping, setLooping } = usePlayer() || {};
const isWeb = Platform.OS === "web";
const handleBackPress = useCallback(() => {
goBack();
}, []);
const renderWebBackButton = useCallback(() => {
if (!isWeb) return null;
return (
<View style={styles.webBackContainer}>
<Pressable
accessibilityRole="button"
onPress={handleBackPress}
style={styles.webBackButton}
>
<RNImage
source={icons.chevronDown}
style={styles.webBackIcon}
resizeMode="contain"
/>
<Text style={styles.webBackText}>Retour</Text>
</Pressable>
</View>
);
}, [handleBackPress, isWeb]);
const { data: project } = useDataFromRef({
ref: projectId ? projectsRef.doc(projectId) : null,
@@ -297,6 +322,38 @@ const MusicDetails = ({ route }) => {
}
}, [project?.musicTimestamps, project?.songIndex]);
const estimatedDurationMs = useMemo(() => {
const toMs = (value) => {
const num = Number(value);
if (!Number.isFinite(num) || num <= 0) return 0;
return num > 1000 ? Math.round(num) : Math.round(num * 1000);
};
const idx = Number(project?.songIndex);
const normalizedIdx = Number.isFinite(idx) && idx >= 0 ? idx : 0;
const tsEntry = project?.musicTimestamps?.[normalizedIdx];
if (tsEntry && typeof tsEntry === "object") {
const fromMetadata =
toMs(tsEntry.durationMs) ||
toMs(tsEntry.duration) ||
toMs(tsEntry.durationS) ||
toMs(tsEntry.durationSeconds) ||
toMs(tsEntry.audioDuration) ||
toMs(tsEntry.audioLength);
if (fromMetadata > 0) return fromMetadata;
}
let maxEndS = 0;
for (let i = 0; i < alignedWords.length; i++) {
const word = alignedWords[i];
const end = Number(word?.endS ?? word?.startS ?? 0);
if (Number.isFinite(end) && end > maxEndS) {
maxEndS = end;
}
}
return maxEndS > 0 ? Math.round(maxEndS * 1000) : 0;
}, [alignedWords, project?.musicTimestamps, project?.songIndex]);
const sliderDurationMs = durationMs > 0 ? durationMs : estimatedDurationMs;
// Reset counters when the track changes
useEffect(() => {
listenedMsRef.current = 0;
@@ -411,7 +468,7 @@ const MusicDetails = ({ route }) => {
const handleSliderSeek = useCallback(
async (ratio) => {
const dur = durationMs || 0;
const dur = sliderDurationMs || 0;
if (!trackDescriptor || dur <= 0) return;
const targetMs = Math.max(0, Math.floor(dur * ratio));
lastSeekTargetMs.current = targetMs;
@@ -431,7 +488,7 @@ const MusicDetails = ({ route }) => {
console.log("MusicDetails seek error", e?.message);
}
},
[trackDescriptor, durationMs, isCurrentTrack, ensureLoaded, seekTrackTo]
[trackDescriptor, sliderDurationMs, isCurrentTrack, ensureLoaded, seekTrackTo]
);
const handleToggleLoop = useCallback(async () => {
@@ -905,6 +962,8 @@ const MusicDetails = ({ route }) => {
return (
<Page
headerType="NAVIGATION"
hideBackButton={isWeb}
topStickyContent={renderWebBackButton}
title={action === "userProfile" ? "Mon profil" : "Détail musique"}
backgroundImg={
action === "userProfile" ? background.profileBG : background.libraryBG2
@@ -1078,8 +1137,10 @@ const MusicDetails = ({ route }) => {
</View>
<Slider
value={fmt(positionMs)}
maxValue={fmt(durationMs)}
progress={durationMs ? (positionMs || 0) / durationMs : 0}
maxValue={fmt(sliderDurationMs)}
progress={
sliderDurationMs ? (positionMs || 0) / sliderDurationMs : 0
}
seekEnabled={!!songUrl}
onSeekStart={handleSliderSeekStart}
onSeek={handleSliderSeek}
@@ -1191,6 +1252,32 @@ const MusicDetails = ({ route }) => {
export default MusicDetails;
const styles = StyleSheet.create({
webBackContainer: {
alignSelf: "flex-start",
marginBottom: 12,
},
webBackButton: {
flexDirection: "row",
alignItems: "center",
gap: 8,
alignSelf: "flex-start",
paddingHorizontal: 14,
paddingVertical: 7,
borderRadius: 999,
borderWidth: 1,
borderColor: Palette.ultraLightWhite,
backgroundColor: Palette.ultraLightWhite,
},
webBackIcon: {
width: 16,
height: 16,
transform: [{ rotate: "90deg" }],
},
webBackText: {
fontSize: 14,
color: Palette.white,
fontFamily: FONT_FAMILY.InterSemiBold,
},
img: {
width: 200,
height: 200,