clear last tickets

This commit is contained in:
Thomas Demirdjian
2025-11-25 14:58:06 +01:00
parent 72852ad92b
commit ee9cc5dccd
31 changed files with 1009 additions and 531 deletions
+150 -15
View File
@@ -35,25 +35,48 @@ import { Image as ExpoImage } from "expo-image";
import SubscriptionConfirmModal from "../../components/SubscriptionConfirmModal";
import { isWeb } from "../../hooks/useLayoutType";
const triggerWebDownload = (url, title) => {
const triggerWebDownload = async (url, title) => {
if (Platform.OS !== "web") return;
if (!url) return;
if (typeof document === "undefined") return;
const baseName = (title || "Playback").toString().trim() || "Playback";
const sanitized = baseName.replace(/[\\/:*?"<>|]/g, "-");
const filename = `${sanitized}.mp4`;
const extension = guessExtension(url) || "mp4";
const filename = `${sanitized}.${extension}`;
try {
const response = await fetch(url);
if (!response.ok || response.type === "opaque") {
throw new Error(`download_failed_${response.status || "opaque"}`);
}
const blob = await response.blob();
const blobUrl = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.href = blobUrl;
anchor.download = filename;
anchor.rel = "noopener noreferrer";
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
URL.revokeObjectURL(blobUrl);
} catch (error) {
console.log("[PlaybackDownload] web download fallback", {
message: error?.message,
});
try {
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = filename;
anchor.rel = "noopener noreferrer";
anchor.target = "_blank";
document.body.appendChild(anchor);
anchor.click();
document.body.removeChild(anchor);
return;
} catch (fallbackError) {
console.log("[PlaybackDownload] anchor fallback failed", {
message: fallbackError?.message,
});
}
try {
window.open(url, "_blank", "noopener,noreferrer");
} catch {}
@@ -94,7 +117,7 @@ const uploadSourceRecording = async ({ uri, uid, projectId }) => {
const { resultURI: videoUrl } = await uploadFileToFirebase({
uri,
path: sourcePath,
shouldCompress: false,
shouldCompress: true,
fileType: "VIDEO",
blob: cachedBlob || undefined,
});
@@ -116,6 +139,10 @@ const PlaybackDownload = ({ route }) => {
const [isAfterPlaybackVideoVisible, setIsAfterPlaybackVideoVisible] =
useState(false);
const [showConfirmModal, setShowConfirmModal] = useState(false);
const [pendingPlaybackUrl, setPendingPlaybackUrl] = useState(
project?.playbackUrl || null,
);
const [isPublishing, setIsPublishing] = useState(false);
const hasShownAfterPlaybackRef = useRef(false);
const { data: video } = useDataFromRef({
@@ -136,6 +163,12 @@ const PlaybackDownload = ({ route }) => {
setIsAfterPlaybackVideoVisible(true);
}, [action, afterPlaybackUrl]);
useEffect(() => {
if (project?.playbackUrl) {
setPendingPlaybackUrl(project.playbackUrl);
}
}, [project?.playbackUrl]);
useEffect(() => {
return () => {
releaseBlobUrl(uri || null);
@@ -143,7 +176,12 @@ const PlaybackDownload = ({ route }) => {
}, [uri]);
const handleDownloadUri = async () => {
if (isPublishing) return;
if (action === "playback" && project?.id) {
if (pendingPlaybackUrl) {
await triggerWebDownload(pendingPlaybackUrl, project?.title);
return;
}
// Publication du playback
console.log("[PlaybackDownload] handleDownloadUri playback", {
projectId: project.id,
@@ -194,18 +232,12 @@ const PlaybackDownload = ({ route }) => {
const resultURI = result?.url || null;
if (resultURI) {
await projectsRef.doc(project.id).set(
{
playbackUrl: resultURI,
updatedAt: serverTimestamp(),
},
{ merge: true },
);
setPendingPlaybackUrl(resultURI);
setTooltip({
type: "success",
text: "Vidéo uploadée",
text: "Playback prêt à télécharger",
});
triggerWebDownload(resultURI, project?.title);
await triggerWebDownload(resultURI, project?.title);
if (tempSourcePath) {
try {
await firebase.storage().ref(tempSourcePath).delete();
@@ -249,6 +281,109 @@ const PlaybackDownload = ({ route }) => {
// Handle song download
}
};
const handlePublish = async () => {
if (isPublishing) return;
if (!project?.id) {
if (action === "playback") {
setTooltip({
type: "success",
text: "Playback publié !",
});
navigate(Routes.Home);
} else {
navigate(Routes.SongRelease, { action });
}
return;
}
let tempSourcePath = null;
let playbackUrlToSave = pendingPlaybackUrl || project?.playbackUrl || null;
const audioUrl = project?.songUrl || null;
if (!audioUrl && !playbackUrlToSave) {
setTooltip({
type: "error",
text: "Aucune piste audio disponible pour ce projet",
});
return;
}
try {
setIsPublishing(true);
setIsLoading(true);
if (!playbackUrlToSave) {
const { sourcePath, videoUrl } = await uploadSourceRecording({
uri,
uid: currentUID,
projectId: project.id,
});
tempSourcePath = sourcePath;
const callable = firebase
.functions()
.httpsCallable("upload-mergeVideoAndAudio");
const payload = {
projectId: project?.id,
videoUrl,
audioUrl,
storagePath: `users/${currentUID}/projects/${project.id}/playback.mp4`,
};
console.log("[PlaybackDownload] publish: calling merge", payload);
const { data: result } = await callable(payload);
playbackUrlToSave = result?.url || null;
if (!playbackUrlToSave) {
throw new Error("merge_failed");
}
setPendingPlaybackUrl(playbackUrlToSave);
}
await projectsRef.doc(project.id).set(
{
playbackUrl: playbackUrlToSave,
updatedAt: serverTimestamp(),
},
{ merge: true },
);
if (action === "playback") {
setTooltip({
type: "success",
text: "Playback publié !",
});
navigate(Routes.Home);
} else {
navigate(Routes.SongRelease, { action });
}
} catch (error) {
console.log("[PlaybackDownload] publish error", {
message: error?.message,
code: error?.code,
name: error?.name,
details: error?.details,
});
setTooltip({
type: "error",
text: String(error?.message || "Publication impossible"),
});
} finally {
if (tempSourcePath) {
try {
await firebase.storage().ref(tempSourcePath).delete();
} catch (cleanupError) {
console.log("[PlaybackDownload] unable to delete temp source", {
message: cleanupError?.message,
code: cleanupError?.code,
});
}
}
setIsPublishing(false);
setIsLoading(false);
}
};
const continueLabel = hasActiveSubscription
? "Publier"
: "Publier sans générer de revenus";
@@ -298,7 +433,7 @@ const PlaybackDownload = ({ route }) => {
title={continueLabel}
onPress={() => {
if (hasActiveSubscription) {
navigate(Routes.SongRelease, { action });
handlePublish();
} else {
setShowConfirmModal(true);
}
@@ -312,7 +447,7 @@ const PlaybackDownload = ({ route }) => {
isVisible={showConfirmModal}
setIsVisible={setShowConfirmModal}
onJoinClub={() => navigate(Routes.Payments)}
onContinue={() => navigate(Routes.SongRelease, { action })}
onContinue={handlePublish}
/>
</>
);