mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-16 03:39:15 +02:00
feat: implement reel improvements (clean text, deletion, mobile TTS)
This commit is contained in:
1 parent
cb0ff8a0ea
commit
dbddf3a74e
895 files changed
+26890
-93267
No files matched your search
@@ -14,10 +14,27 @@ type ScheduledPostWithRelations = ScheduledPost & {
|
||||
page?: SocialPage;
|
||||
};
|
||||
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
AlertDialogCancel,
|
||||
AlertDialogContent,
|
||||
AlertDialogDescription,
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/components/ui/alert-dialog";
|
||||
import { Trash2 } from "lucide-react";
|
||||
import { useMutation, useQueryClient } from "@tanstack/react-query";
|
||||
import { apiRequest } from "@/lib/queryClient";
|
||||
|
||||
export default function RecentPublications() {
|
||||
const [previewModalOpen, setPreviewModalOpen] = useState(false);
|
||||
const [previewData, setPreviewData] = useState<{ postText: string; mediaIds: string[]; allMedia: Media[] }>({ postText: '', mediaIds: [], allMedia: [] });
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
const [postToDelete, setPostToDelete] = useState<string | null>(null);
|
||||
const { toast } = useToast();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { data: scheduledPosts = [], isLoading } = useQuery<ScheduledPostWithRelations[]>({
|
||||
queryKey: ['/api/scheduled-posts'],
|
||||
@@ -60,6 +77,42 @@ export default function RecentPublications() {
|
||||
}
|
||||
};
|
||||
|
||||
const deleteReelMutation = useMutation({
|
||||
mutationFn: async (postId: string) => {
|
||||
// Pour les Reels/Posts, l'ID est le même. La route DELETE /api/reels/:id
|
||||
// gère la suppression du Post sous-jacent.
|
||||
const res = await apiRequest("DELETE", `/api/reels/${postId}`);
|
||||
return await res.json();
|
||||
},
|
||||
onSuccess: () => {
|
||||
toast({
|
||||
title: "Succès",
|
||||
description: "Publication supprimée avec succès",
|
||||
});
|
||||
queryClient.invalidateQueries({ queryKey: ['/api/scheduled-posts'] });
|
||||
setDeleteDialogOpen(false);
|
||||
setPostToDelete(null);
|
||||
},
|
||||
onError: (error: Error) => {
|
||||
toast({
|
||||
title: "Erreur",
|
||||
description: error.message || "Impossible de supprimer la publication",
|
||||
variant: "destructive",
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
const handleDeleteClick = (postId: string) => {
|
||||
setPostToDelete(postId);
|
||||
setDeleteDialogOpen(true);
|
||||
};
|
||||
|
||||
const confirmDelete = () => {
|
||||
if (postToDelete) {
|
||||
deleteReelMutation.mutate(postToDelete);
|
||||
}
|
||||
};
|
||||
|
||||
const getPostTypeIcon = (postType: string) => {
|
||||
if (postType === 'feed') {
|
||||
return <ImageIcon className="w-3.5 h-3.5" />;
|
||||
@@ -108,8 +161,8 @@ export default function RecentPublications() {
|
||||
>
|
||||
{/* Platform icon */}
|
||||
<div className={`w-10 h-10 rounded-lg flex items-center justify-center flex-shrink-0 ${scheduledPost.page?.platform === 'facebook'
|
||||
? 'bg-blue-500'
|
||||
: 'bg-gradient-to-br from-purple-500 to-pink-500'
|
||||
? 'bg-blue-500'
|
||||
: 'bg-gradient-to-br from-purple-500 to-pink-500'
|
||||
}`}>
|
||||
{scheduledPost.page?.platform === 'facebook' ? (
|
||||
<Facebook className="w-5 h-5 text-white" />
|
||||
@@ -144,6 +197,16 @@ export default function RecentPublications() {
|
||||
>
|
||||
<Eye className="w-4 h-4 text-muted-foreground hover:text-foreground" />
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => handleDeleteClick(scheduledPost.postId)}
|
||||
className="h-8 w-8 p-0 text-muted-foreground hover:text-destructive transition-colors"
|
||||
data-testid={`button-delete-post-${scheduledPost.id}`}
|
||||
title="Supprimer"
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</Button>
|
||||
{scheduledPost.error ? (
|
||||
<XCircle className="w-4 h-4 text-destructive" />
|
||||
) : (
|
||||
@@ -187,6 +250,30 @@ export default function RecentPublications() {
|
||||
isPublishing={false}
|
||||
readOnly={true}
|
||||
/>
|
||||
|
||||
<AlertDialog open={deleteDialogOpen} onOpenChange={setDeleteDialogOpen}>
|
||||
<AlertDialogContent>
|
||||
<AlertDialogHeader>
|
||||
<AlertDialogTitle>Êtes-vous sûr ?</AlertDialogTitle>
|
||||
<AlertDialogDescription>
|
||||
Cette action est irréversible. Cela supprimera définitivement cette publication de votre historique et des statistiques associées.
|
||||
</AlertDialogDescription>
|
||||
</AlertDialogHeader>
|
||||
<AlertDialogFooter>
|
||||
<AlertDialogCancel disabled={deleteReelMutation.isPending}>Annuler</AlertDialogCancel>
|
||||
<AlertDialogAction
|
||||
onClick={(e) => {
|
||||
e.preventDefault();
|
||||
confirmDelete();
|
||||
}}
|
||||
disabled={deleteReelMutation.isPending}
|
||||
className="bg-destructive text-destructive-foreground hover:bg-destructive/90"
|
||||
>
|
||||
{deleteReelMutation.isPending ? "Suppression..." : "Supprimer"}
|
||||
</AlertDialogAction>
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
@@ -69,6 +69,14 @@ export default function NewReel() {
|
||||
const [drawText, setDrawText] = useState(true);
|
||||
const [stabilize, setStabilize] = useState(true); // default to true
|
||||
|
||||
// Enable TTS by default on mobile
|
||||
useEffect(() => {
|
||||
const isMobile = window.innerWidth < 768;
|
||||
if (isMobile) {
|
||||
setTtsEnabled(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
|
||||
// État audio preview
|
||||
const [isPlaying, setIsPlaying] = useState<string | null>(null);
|
||||
|
||||
Reference in new issue
Block a user