clear lot of tickets
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user