summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Sima <ben@bsima.me>2025-11-09 14:42:22 -0500
committerBen Sima <ben@bsima.me>2025-11-09 14:42:22 -0500
commitf788270a82a5c8b7f7c0a5417b65e55f064c8cb6 (patch)
tree1e536b47015378a86a127876781c9640eb6a1b7d
parentc76c83987fae48c995e605d947aea72d513ee7cd (diff)
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
-rw-r--r--.tasks/tasks.jsonl2
-rw-r--r--Biz/PodcastItLater/Web.py63
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",
)