From f788270a82a5c8b7f7c0a5417b65e55f064c8cb6 Mon Sep 17 00:00:00 2001 From: Ben Sima Date: Sun, 9 Nov 2025 14:42:22 -0500 Subject: fix(PodcastItLater): Remove audio player, move RSS to episodes section - Remove audio player from Recent Episodes (use podcast app instead) - Move RSS feed link from user info card to Recent Episodes section - Fix audio playback interruption on refresh - Simplify user info card to just show email and logout button This fixes the UX issue where dashboard refresh would interrupt playing audio. Completes task t-17Z0069 --- .tasks/tasks.jsonl | 2 +- Biz/PodcastItLater/Web.py | 63 +++++++++++++++++++++++++++-------------------- 2 files changed, 37 insertions(+), 28 deletions(-) diff --git a/.tasks/tasks.jsonl b/.tasks/tasks.jsonl index b9fa72d..189033a 100644 --- a/.tasks/tasks.jsonl +++ b/.tasks/tasks.jsonl @@ -31,4 +31,4 @@ {"taskCreatedAt":"2025-11-09T16:48:47.737218185Z","taskDependencies":[],"taskId":"t-144gds4","taskNamespace":"Biz/PodcastItLater.hs","taskParent":"t-143KQl2","taskStatus":"Open","taskTitle":"Migrate from SQLite to PostgreSQL","taskType":"WorkTask","taskUpdatedAt":"2025-11-09T16:48:47.737218185Z"} {"taskCreatedAt":"2025-11-09T16:48:47.887102357Z","taskDependencies":[],"taskId":"t-144gQry","taskNamespace":"Biz/PodcastItLater.hs","taskParent":"t-143KQl2","taskStatus":"Open","taskTitle":"Create basic admin dashboard","taskType":"WorkTask","taskUpdatedAt":"2025-11-09T16:48:47.887102357Z"} {"taskCreatedAt":"2025-11-09T16:48:48.072927212Z","taskDependencies":[],"taskId":"t-144hCMJ","taskNamespace":"Biz/PodcastItLater.hs","taskParent":"t-143KQl2","taskStatus":"Open","taskTitle":"Complete comprehensive test suite","taskType":"WorkTask","taskUpdatedAt":"2025-11-09T16:48:48.072927212Z"} -{"taskCreatedAt":"2025-11-09T17:48:34.522286485Z","taskDependencies":[],"taskId":"t-17Z0069","taskNamespace":"Biz/PodcastItLater.hs","taskParent":"t-143KQl2","taskStatus":"Open","taskTitle":"Fix Recent Episodes refresh to prepend instead of reload (interrupts audio playback)","taskType":"WorkTask","taskUpdatedAt":"2025-11-09T17:48:34.522286485Z"} +{"taskCreatedAt":"2025-11-09T17:48:34.522286485Z","taskDependencies":[],"taskId":"t-17Z0069","taskNamespace":"Biz/PodcastItLater.hs","taskParent":"t-143KQl2","taskStatus":"Done","taskTitle":"Fix Recent Episodes refresh to prepend instead of reload (interrupts audio playback)","taskType":"WorkTask","taskUpdatedAt":"2025-11-09T19:42:22.105902786Z"} diff --git a/Biz/PodcastItLater/Web.py b/Biz/PodcastItLater/Web.py index bd4b973..65c002a 100644 --- a/Biz/PodcastItLater/Web.py +++ b/Biz/PodcastItLater/Web.py @@ -499,14 +499,17 @@ class EpisodeListAttrs(Attrs): """Attributes for EpisodeList component.""" episodes: list[dict[str, typing.Any]] + rss_url: str | None class EpisodeList(Component[AnyChildren, EpisodeListAttrs]): - """List recent episodes with audio player.""" + """List recent episodes (no audio player - use podcast app).""" @override def render(self) -> html.div: episodes = self.attrs["episodes"] + rss_url = self.attrs.get("rss_url") + if not episodes: return html.div( html.h4( @@ -535,15 +538,6 @@ class EpisodeList(Component[AnyChildren, EpisodeListAttrs]): ) if episode.get("author") else html.div(), - html.audio( - html.source( - src=episode["audio_url"], - type="audio/mpeg", - ), - "Your browser does not support the audio element.", - controls=True, - classes=["w-100", "mb-3"], - ), html.div( html.small( html.i(classes=["bi", "bi-clock", "me-1"]), @@ -585,6 +579,23 @@ class EpisodeList(Component[AnyChildren, EpisodeListAttrs]): "Recent Episodes", classes=["mb-3"], ), + # RSS feed link + html.div( + html.div( + html.i(classes=["bi", "bi-rss-fill", "me-2"]), + html.strong("Subscribe in your podcast app:"), + classes=["mb-2"], + ), + html.div( + html.code( + rss_url or "", + classes=["text-break", "user-select-all"], + ), + classes=["mb-3", "p-2", "bg-light", "rounded"], + ), + ) + if rss_url + else html.div(), *episode_items, ) @@ -667,20 +678,9 @@ class HomePage(Component[AnyChildren, HomePageAttrs]): html.div( html.div( html.div( - html.h6( - "Logged in as:", - classes=["card-title", "mb-2"], - ), - html.p(user["email"], classes=["mb-3"]), - html.h6( - "Your RSS Feed:", - classes=["card-title", "mb-2"], - ), - html.div( - html.code( - f"{BASE_URL}/feed/{user['token']}.xml", - classes=["text-break"], - ), + html.p( + html.strong("Logged in as: "), + user["email"], classes=["mb-3"], ), html.div( @@ -732,7 +732,12 @@ class HomePage(Component[AnyChildren, HomePageAttrs]): SubmitForm(), html.div( QueueStatus(items=queue_items), - EpisodeList(episodes=episodes), + EpisodeList( + episodes=episodes, + rss_url=f"{BASE_URL}/feed/{user['token']}.xml" + if user + else None, + ), id="dashboard-content", hx_get="/dashboard-updates", hx_trigger="every 3s, queue-updated from:body", @@ -1097,16 +1102,20 @@ def dashboard_updates(request: Request) -> html.div: if not user_id: return html.div( QueueStatus(items=[]), - EpisodeList(episodes=[]), + EpisodeList(episodes=[], rss_url=None), ) + # Get user info for RSS URL + user = Core.Database.get_user_by_id(user_id) + rss_url = f"{BASE_URL}/feed/{user['token']}.xml" if user else None + # Get user-specific queue items and episodes queue_items = Core.Database.get_user_queue_status(user_id) episodes = Core.Database.get_user_recent_episodes(user_id, 10) return html.div( QueueStatus(items=queue_items), - EpisodeList(episodes=episodes), + EpisodeList(episodes=episodes, rss_url=rss_url), id="dashboard-content", ) -- cgit v1.2.3