diff --git a/frontend/src/components/AudioPlayer.tsx b/frontend/src/components/AudioPlayer.tsx index 99a372c..4c358ec 100644 --- a/frontend/src/components/AudioPlayer.tsx +++ b/frontend/src/components/AudioPlayer.tsx @@ -33,6 +33,7 @@ export default function AudioPlayer({ episode, onClose, userId }: AudioPlayerPro const [playbackSpeed, setPlaybackSpeed] = useState(() => parseFloat(localStorage.getItem('podcastic-speed') || '1')); const [isMuted, setIsMuted] = useState(false); const [isExpanded, setIsExpanded] = useState(false); + const [isResuming, setIsResuming] = useState(false); const [error, setError] = useState(null); const podcast = typeof episode?.podcastId === 'object' ? episode.podcastId : null; @@ -67,11 +68,17 @@ export default function AudioPlayer({ episode, onClose, userId }: AudioPlayerPro // Load previous progress useEffect(() => { if (!episode || !userId) return; + setIsResuming(true); episodeService.getProgress(episode._id).then((r) => { if (r.progress?.position && audioRef.current) { + console.log(`[AudioPlayer] Resuming at ${r.progress.position}s`); audioRef.current.currentTime = r.progress.position; + setCurrentTime(r.progress.position); } - }).catch(() => {}); + setIsResuming(false); + }).catch(() => { + setIsResuming(false); + }); }, [episode, userId]); const handlePlayPause = () => { @@ -167,7 +174,11 @@ export default function AudioPlayer({ episode, onClose, userId }: AudioPlayerPro

{episode.title}

-

{podcast?.title || ''}

+ {isResuming ? ( +

Reprise de lecture...

+ ) : ( +

{podcast?.title || ''}

+ )}
diff --git a/frontend/src/components/EpisodeCard.tsx b/frontend/src/components/EpisodeCard.tsx index 282e632..fd3577a 100644 --- a/frontend/src/components/EpisodeCard.tsx +++ b/frontend/src/components/EpisodeCard.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { Episode } from '../services/episodeService'; -import { Play, Calendar } from 'lucide-react'; +import { Play, Calendar, Activity } from 'lucide-react'; +import { useAudio } from '../context/AudioContext'; interface EpisodeCardProps { episode: Episode; @@ -9,6 +10,8 @@ interface EpisodeCardProps { } export default function EpisodeCard({ episode, onPlay, onDetails }: EpisodeCardProps) { + const { currentEpisode, isPlaying } = useAudio(); + const isCurrent = currentEpisode?._id === episode._id; const podcast = typeof episode.podcastId === 'object' ? episode.podcastId : null; const pubDate = new Date(episode.pubDate).toLocaleDateString('fr-FR', { month: 'short', @@ -57,9 +60,17 @@ export default function EpisodeCard({ episode, onPlay, onDetails }: EpisodeCardP - {/* Duration Badge */} -
- {durationMinutes} MIN + {/* Duration/Status Badge */} +
+ {isCurrent && ( +
+ + {isPlaying ? "EN COURS" : "EN PAUSE"} +
+ )} +
+ {durationMinutes} MIN +
diff --git a/frontend/src/pages/AddPodcast.tsx b/frontend/src/pages/AddPodcast.tsx index 75c3471..9c42ac3 100644 --- a/frontend/src/pages/AddPodcast.tsx +++ b/frontend/src/pages/AddPodcast.tsx @@ -286,18 +286,18 @@ export default function AddPodcast() { ))} - ) : searchType === 'episodes' && episodeResults?.episodes && episodeResults.episodes.length > 0 ? ( -
- {episodeResults.episodes.map((episode) => ( - - ))} + ) : searchType === 'episodes' && episodeResults?.episodes ? ( +
+ {episodeResults.episodes.map((episode) => ( + + ))}
- ) : searchQuery.length >= 2 ? ( + ) : searchQuery.length >= 2 && !isSearching && !isSearchingEpisodes ? (

Aucun résultat sur iTunes FR

diff --git a/frontend/src/styles/globals.css b/frontend/src/styles/globals.css index 4d75e9d..41ea75b 100644 --- a/frontend/src/styles/globals.css +++ b/frontend/src/styles/globals.css @@ -40,17 +40,32 @@ /* ── Explicit Dark Theme (for nesting/inversion) ── */ .dark-theme { - --bg-primary: #080d1a; - --bg-secondary: rgba(255, 255, 255, 0.025); + --bg-primary: #000000; /* Solid Black */ + --bg-secondary: #0a0a0a; --text-primary: #ffffff; --text-secondary: #94a3b8; --accent-primary: #6366f1; --accent-secondary: #06b6d4; - --accent-glow: rgba(99, 102, 241, 0.35); - --border-color: rgba(255, 255, 255, 0.07); - --input-bg: rgba(255, 255, 255, 0.03); - --shadow-premium: 0 25px 60px rgba(0, 0, 0, 0.6), 0 0 1px rgba(255, 255, 255, 0.1); - --shadow-hover: 0 35px 80px rgba(0, 0, 0, 0.8), 0 0 1px rgba(255, 255, 255, 0.2); + --accent-glow: rgba(99, 102, 241, 0.4); + --border-color: rgba(255, 255, 255, 0.15); + --input-bg: rgba(255, 255, 255, 0.05); + --shadow-premium: 0 30px 100px rgba(0, 0, 0, 0.9), 0 0 1px rgba(255, 255, 255, 0.2); + --glass-blur: none; /* No transparency for the player */ + } + + /* Explicit light override for dark mode player inversion */ + .light-theme { + --bg-primary: #ffffff; /* Solid White */ + --bg-secondary: #f8fafc; + --text-primary: #0f172a; + --text-secondary: #64748b; + --accent-primary: #6366f1; + --accent-secondary: #06b6d4; + --accent-glow: rgba(99, 102, 241, 0.15); + --border-color: #e2e8f0; + --input-bg: #f1f5f9; + --shadow-premium: 0 20px 60px rgba(0, 0, 0, 0.1), 0 0 1px rgba(0, 0, 0, 0.05); + --glass-blur: none; } }