feat: hero player, LU/NOUVEAU badges, metadata resync, sticky mini-bar

- Refresh podcast title/author/imageUrl/description on RSS sync (fixes
  legacy 'Unknown Podcast' records)
- Always-visible Resync button on Library cards
- LU badge on completed episodes, NOUVEAU badge on <7-day-old episodes
- AudioPlayer gains mode='inline' that embeds in the Dashboard hero card
- Floating player suppressed on /dashboard to avoid dual audio
- Sticky mini-bar appears via IntersectionObserver when inline player
  scrolls out of view (shares the same <audio> element)
- Fix: 'Reprendre' button called undefined setSelectedEpisode; now calls
  playEpisode
- Add progress field to Episode TS interface

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
MichaelandClaude Sonnet 4.6 committed 2026-04-17 11:33:47 +02:00
1 parent a3225cb4c4
commit 6786226a6c
7 files changed
+330 -47

No files matched your search

+18 -1
View File
@@ -241,7 +241,24 @@ export const rssParserService = {
// Update podcast metadata
podcast.lastFetched = new Date();
podcast.episodeCount = await Episode.countDocuments({ podcastId });
// Refresh podcast metadata from fresh RSS data (fixes "Unknown Podcast" legacy records)
if (feedData.title && feedData.title !== 'Unknown Podcast') {
podcast.title = feedData.title;
}
if (feedData.author && (!podcast.author || podcast.author.trim() === '' || force)) {
podcast.author = feedData.author;
}
if (feedData.imageUrl && (!podcast.imageUrl || force)) {
podcast.imageUrl = feedData.imageUrl;
}
if (feedData.description && (!podcast.description || force)) {
podcast.description = feedData.description;
}
if (feedData.language && (!podcast.language || force)) {
podcast.language = feedData.language;
}
if (episodes.length > 0) {
podcast.lastEpisodeTitle = episodes[0].title;
podcast.lastEpisodeDate = episodes[0].pubDate;