mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
feat: clean up mobile remotion page — remove preview player and download button
Remove unused Player, ImageComposition, useMemo imports and all associated computed values (combinedUrls, previewWordTimings, ENDING_FRAMES, totalFrames, previewLogoUrl, previewStoreName, cloudinaryConfig query). Remove Aperçu card with broken Player preview, download button, and conditional generate button wrapper. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
36fe05c04b
commit
ff5e02e30d
1 file changed
+6
-78
@@ -1,6 +1,4 @@
|
|||||||
import { useState, useMemo, useRef } from "react";
|
import { useState, useRef } from "react";
|
||||||
import { Player } from "@remotion/player";
|
|
||||||
import { ImageComposition } from "@/remotion/ImageComposition";
|
|
||||||
import { useToast } from "@/hooks/use-toast";
|
import { useToast } from "@/hooks/use-toast";
|
||||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||||
import { Button } from "@/components/ui/button";
|
import { Button } from "@/components/ui/button";
|
||||||
@@ -31,18 +29,6 @@ function stripForTTS(text: string) {
|
|||||||
return text.replace(/#\w+/g, '').replace(/[\uD800-\uDFFF]/g, '').replace(/[\u2600-\u27BF]/g, '').replace(/\s+/g, ' ').trim();
|
return text.replace(/#\w+/g, '').replace(/[\uD800-\uDFFF]/g, '').replace(/[\u2600-\u27BF]/g, '').replace(/\s+/g, ' ').trim();
|
||||||
}
|
}
|
||||||
|
|
||||||
function estimateWordTimings(text: string, fps = 30, wps = 2.5) {
|
|
||||||
const words = text.split(/\s+/).filter(Boolean);
|
|
||||||
const framesPerWord = fps / wps;
|
|
||||||
let frame = 0;
|
|
||||||
return words.map(word => {
|
|
||||||
const isSpoken = !/^#/.test(word) && !(/[\uD800-\uDFFF\u2600-\u27BF]/.test(word));
|
|
||||||
const dur = isSpoken ? framesPerWord : framesPerWord * 0.4;
|
|
||||||
const start = frame;
|
|
||||||
frame += Math.round(dur);
|
|
||||||
return { word, startFrame: start, endFrame: frame };
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
export default function MobileRemotionVideoPage() {
|
export default function MobileRemotionVideoPage() {
|
||||||
const [images, setImages] = useState<File[]>([]);
|
const [images, setImages] = useState<File[]>([]);
|
||||||
@@ -67,13 +53,8 @@ export default function MobileRemotionVideoPage() {
|
|||||||
|
|
||||||
const { data: allMedia = [] } = useQuery<Media[]>({ queryKey: ['/api/media'] });
|
const { data: allMedia = [] } = useQuery<Media[]>({ queryKey: ['/api/media'] });
|
||||||
const { data: audioTracks = [], isLoading: tracksLoading } = useQuery<AudioTrack[]>({ queryKey: ['/api/audio-tracks'] });
|
const { data: audioTracks = [], isLoading: tracksLoading } = useQuery<AudioTrack[]>({ queryKey: ['/api/audio-tracks'] });
|
||||||
const { data: cloudinaryConfig } = useQuery<{ cloudName?: string; logoPublicId?: string } | null>({ queryKey: ['/api/cloudinary/config'] });
|
|
||||||
const { data: socialPages = [] } = useQuery<SocialPage[]>({ queryKey: ['/api/pages'] });
|
const { data: socialPages = [] } = useQuery<SocialPage[]>({ queryKey: ['/api/pages'] });
|
||||||
|
|
||||||
const previewLogoUrl = cloudinaryConfig?.cloudName && cloudinaryConfig?.logoPublicId
|
|
||||||
? `https://res.cloudinary.com/${cloudinaryConfig.cloudName}/image/upload/${cloudinaryConfig.logoPublicId}`
|
|
||||||
: undefined;
|
|
||||||
const previewStoreName = socialPages[0]?.pageName as string | undefined;
|
|
||||||
const facebookPages = socialPages.filter(p => p.platform === 'facebook');
|
const facebookPages = socialPages.filter(p => p.platform === 'facebook');
|
||||||
const imageMediaList = allMedia.filter(m => m.type === 'image').slice(0, 20);
|
const imageMediaList = allMedia.filter(m => m.type === 'image').slice(0, 20);
|
||||||
|
|
||||||
@@ -95,22 +76,7 @@ export default function MobileRemotionVideoPage() {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const combinedUrls = useMemo(() => {
|
|
||||||
const urls: string[] = [];
|
|
||||||
images.forEach(f => urls.push(URL.createObjectURL(f)));
|
|
||||||
selectedLibraryImages.forEach(m => urls.push(m.originalUrl));
|
|
||||||
return urls;
|
|
||||||
}, [images, selectedLibraryImages]);
|
|
||||||
|
|
||||||
const totalSelected = images.length + selectedLibraryImages.length;
|
const totalSelected = images.length + selectedLibraryImages.length;
|
||||||
const previewWordTimings = useMemo(() => overlayText ? estimateWordTimings(overlayText) : undefined, [overlayText]);
|
|
||||||
const ENDING_FRAMES = (previewLogoUrl || previewStoreName) ? 90 : 0;
|
|
||||||
const totalFrames = useMemo(() => {
|
|
||||||
const ttsEnd = previewWordTimings?.length ? previewWordTimings[previewWordTimings.length - 1].endFrame : 0;
|
|
||||||
const naturalContent = Math.max(ttsEnd / 30, combinedUrls.length * 3);
|
|
||||||
const contentSeconds = Math.min(Math.max(naturalContent, 22), 27);
|
|
||||||
return Math.round(contentSeconds * 30) + ENDING_FRAMES;
|
|
||||||
}, [previewWordTimings, combinedUrls, ENDING_FRAMES]);
|
|
||||||
|
|
||||||
const handleTtsPreview = async () => {
|
const handleTtsPreview = async () => {
|
||||||
const ttsText = stripForTTS(overlayText);
|
const ttsText = stripForTTS(overlayText);
|
||||||
@@ -325,55 +291,17 @@ export default function MobileRemotionVideoPage() {
|
|||||||
</CardContent>
|
</CardContent>
|
||||||
</Card>
|
</Card>
|
||||||
|
|
||||||
{/* Aperçu */}
|
|
||||||
<Card>
|
|
||||||
<CardHeader className="pb-2">
|
|
||||||
<CardTitle className="text-base">Aperçu</CardTitle>
|
|
||||||
</CardHeader>
|
|
||||||
<CardContent className="flex justify-center bg-zinc-950 rounded-lg p-2">
|
|
||||||
{combinedUrls.length > 0 ? (
|
|
||||||
<Player
|
|
||||||
component={ImageComposition}
|
|
||||||
inputProps={{
|
|
||||||
images: combinedUrls,
|
|
||||||
overlayText: overlayText || undefined,
|
|
||||||
wordTimings: previewWordTimings,
|
|
||||||
logoUrl: previewLogoUrl,
|
|
||||||
storeName: previewStoreName,
|
|
||||||
endingFrames: ENDING_FRAMES,
|
|
||||||
}}
|
|
||||||
durationInFrames={totalFrames}
|
|
||||||
compositionWidth={1080}
|
|
||||||
compositionHeight={1920}
|
|
||||||
fps={30}
|
|
||||||
controls
|
|
||||||
acknowledgeRemotionLicense
|
|
||||||
style={{ width: "auto", height: "380px", maxWidth: "100%", borderRadius: "6px" }}
|
|
||||||
/>
|
|
||||||
) : (
|
|
||||||
<div className="h-[380px] w-full flex items-center justify-center text-xs text-muted-foreground text-center px-4">
|
|
||||||
Sélectionnez des images pour prévisualiser.
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
</CardContent>
|
|
||||||
</Card>
|
|
||||||
|
|
||||||
{/* Générer */}
|
{/* Générer */}
|
||||||
{totalSelected > 0 && (
|
<Button onClick={handleGenerate} disabled={isRendering || totalSelected < 3} className="w-full h-12" size="lg">
|
||||||
<Button onClick={handleGenerate} disabled={isRendering || totalSelected < 3} className="w-full h-12" size="lg">
|
{isRendering
|
||||||
{isRendering
|
? <><Loader2 className="mr-2 h-4 w-4 animate-spin" /> Génération (1-2 min)…</>
|
||||||
? <><Loader2 className="mr-2 h-4 w-4 animate-spin" /> Génération (1-2 min)…</>
|
: <><Video className="mr-2 h-4 w-4" /> Générer la vidéo MP4</>}
|
||||||
: <><Video className="mr-2 h-4 w-4" /> Générer la vidéo MP4</>}
|
</Button>
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{videoUrl && (
|
{videoUrl && (
|
||||||
<div className="space-y-3">
|
<div className="space-y-3">
|
||||||
<p className="font-semibold text-sm text-green-600">Vidéo prête :</p>
|
<p className="font-semibold text-sm text-green-600">Vidéo prête :</p>
|
||||||
<video src={videoUrl} controls className="w-full rounded-md shadow bg-black" />
|
<video src={videoUrl} controls className="w-full rounded-md shadow bg-black" />
|
||||||
<Button variant="outline" className="w-full" asChild>
|
|
||||||
<a href={videoUrl} download="remotion-video.mp4">Télécharger</a>
|
|
||||||
</Button>
|
|
||||||
|
|
||||||
<Card className="border-primary/40">
|
<Card className="border-primary/40">
|
||||||
<CardHeader className="pb-2">
|
<CardHeader className="pb-2">
|
||||||
|
|||||||
Reference in new issue
Block a user