diff --git a/src/pages/Upload.tsx b/src/pages/Upload.tsx index 641a229..8ed2717 100644 --- a/src/pages/Upload.tsx +++ b/src/pages/Upload.tsx @@ -1,6 +1,6 @@ -import { useState, useRef, useCallback } from 'react' +import { useState, useRef, useCallback, useEffect } from 'react' import { useNavigate } from 'react-router-dom' -import { Upload as UploadIcon, Music, X, Image, Mic, Link2, Loader2, Sparkles } from 'lucide-react' +import { Upload as UploadIcon, Music, X, Image, Mic, Link2, Loader2, Sparkles, Circle, Square } from 'lucide-react' import { supabase } from '@/lib/supabase' import { useAuthStore } from '@/stores/auth' import { Button } from '@/components/ui/Button' @@ -111,11 +111,73 @@ export function Upload() { const [dragActive, setDragActive] = useState(false) const audioInputRef = useRef(null) + // Recording mode + const [isRecording, setIsRecording] = useState(false) + const [recordingTime, setRecordingTime] = useState(0) + const mediaRecorderRef = useRef(null) + const chunksRef = useRef([]) + const timerRef = useRef | null>(null) + // External mode const [externalUrl, setExternalUrl] = useState('') const [fetching, setFetching] = useState(false) const [platform, setPlatform] = useState('') + // Cleanup recording on unmount + useEffect(() => { + return () => { + if (timerRef.current) clearInterval(timerRef.current) + if (mediaRecorderRef.current?.state === 'recording') { + mediaRecorderRef.current.stop() + mediaRecorderRef.current.stream.getTracks().forEach(t => t.stop()) + } + } + }, []) + + async function startRecording() { + try { + const stream = await navigator.mediaDevices.getUserMedia({ audio: true }) + const mediaRecorder = new MediaRecorder(stream, { mimeType: 'audio/webm;codecs=opus' }) + mediaRecorderRef.current = mediaRecorder + chunksRef.current = [] + + mediaRecorder.ondataavailable = (e) => { + if (e.data.size > 0) chunksRef.current.push(e.data) + } + + mediaRecorder.onstop = () => { + stream.getTracks().forEach(t => t.stop()) + if (timerRef.current) { clearInterval(timerRef.current); timerRef.current = null } + + const blob = new Blob(chunksRef.current, { type: 'audio/webm' }) + const file = new File([blob], `enregistrement-${Date.now()}.webm`, { type: 'audio/webm' }) + setAudioFile(file) + setDuration(recordingTime) + if (!title) setTitle('Mon enregistrement') + setIsRecording(false) + } + + mediaRecorder.start(1000) + setIsRecording(true) + setRecordingTime(0) + timerRef.current = setInterval(() => setRecordingTime(t => t + 1), 1000) + } catch { + setError('Impossible d\'acceder au microphone. Verifiez les permissions de votre navigateur.') + } + } + + function stopRecording() { + if (mediaRecorderRef.current?.state === 'recording') { + mediaRecorderRef.current.stop() + } + } + + function formatRecordTime(s: number) { + const m = Math.floor(s / 60) + const sec = s % 60 + return `${m.toString().padStart(2, '0')}:${sec.toString().padStart(2, '0')}` + } + const handleAudioSelect = useCallback((file: File) => { if (!file.type.startsWith('audio/')) { setError('Veuillez selectionner un fichier audio.') @@ -321,30 +383,77 @@ export function Upload() {
{mode === 'original' ? ( - /* ---- ORIGINAL: Audio file picker ---- */ - !audioFile ? ( -
audioInputRef.current?.click()} - onDragOver={(e) => { e.preventDefault(); setDragActive(true) }} - onDragLeave={() => setDragActive(false)} - onDrop={(e) => { - e.preventDefault() - setDragActive(false) - const file = e.dataTransfer.files[0] - if (file) handleAudioSelect(file) - }} - > - -

Glissez votre fichier audio ici

-

ou cliquez pour selectionner (MP3, WAV, M4A)

- e.target.files?.[0] && handleAudioSelect(e.target.files[0])} - /> + /* ---- ORIGINAL: Audio file picker + Recorder ---- */ + isRecording ? ( + /* Recording in progress */ +
+
+
+
+ +
+
+

{formatRecordTime(recordingTime)}

+

Enregistrement en cours...

+ +
+ ) : !audioFile ? ( +
+ {/* Drag & drop zone */} +
audioInputRef.current?.click()} + onDragOver={(e) => { e.preventDefault(); setDragActive(true) }} + onDragLeave={() => setDragActive(false)} + onDrop={(e) => { + e.preventDefault() + setDragActive(false) + const file = e.dataTransfer.files[0] + if (file) handleAudioSelect(file) + }} + > + +

Glissez votre fichier audio ici

+

ou cliquez pour selectionner (MP3, WAV, M4A)

+ e.target.files?.[0] && handleAudioSelect(e.target.files[0])} + /> +
+ +
+
+ ou +
+
+ + {/* Record button */} +
) : (