Repository navigation
feat: behavioral-audit UI and interaction fixes (front-end, 2/2) - #215
Conversation
- add a fullscreen button to video playback (no native controls) - fix the chapter-list active-row highlight to track currentTime (the reactive statement had no dependencies) and follow a clicked chapter - clear stale chapters on episode switch and ignore out-of-order fetches - give the progress bar an accessible name + human-readable aria-valuetext, and the chapter list aria-controls + descriptive seek labels - restore by composite key and end-of-episode cleanup by composite key, so a same-titled episode from another podcast isn't resumed/removed by mistake
…tion - add a keyboard/mobile reachable overflow (kebab) affordance that opens the episode context menu via showAtPosition (was right-click only) - only render the playlist context-menu separator when there are playlists - settle the dropped download promise from the context menu - show the playlist/queue name on grid tiles (and stop the name from clipping/overlapping the count by letting the card grow) - validate playlist names: reject empty names and refuse to overwrite an existing playlist (data loss); key the list so per-row delete state can't drift; reset the icon dropdown after add - remove the unreachable repeat-toggle dead code - enlarge the reorder-modal action buttons to a comfortable touch target
- make Refresh actually refresh all feeds in the Latest Episodes view - avoid duplicate loading indicators for a selected feed - treat a whitespace-only search as empty and live-update an open playlist - surface feed-load and search failures (invalid feed URL, iTunes errors) to the user instead of failing silently
The queue identifies episodes by title everywhere (queue.add dedupes and queue.remove filters by title), so the context-menu membership check, the reorder index lookup, and the end-of-episode queue cleanup must match by title too. A composite-key check offered "Add to Queue" for a same-titled episode from another podcast, which queue.add then no-opped. Addresses the Codex review on #214.
Add isSameStoredEpisode, which matches a stored playlist/favorite entry by composite key and, for LEGACY entries saved without podcastName, by title alone (without matching a different podcast's same title). Use it for the favorites and playlist context-menu checks and the end-of-episode playlist cleanup, so a legacy entry is no longer treated as absent (duplicated on add, skipped on cleanup). Addresses the Codex review on #214.
A custom playlist named like a built-in (Queue/Favorites/Local Files/Played) is ambiguous because those tiles come from separate stores, so an open custom playlist could silently switch to the built-in list on refresh. Reject those names on create. Addresses the follow-up Codex review on #214.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4dcabc18d5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| live = get(playlists)[name]; | ||
| if (!live) { | ||
| // A custom playlist deleted while open: fall back to Latest Episodes. | ||
| showLatestEpisodes(); |
There was a problem hiding this comment.
Don't force the player back to Latest Episodes
When an episode is started from a custom playlist, handleClickEpisode leaves selectedPlaylist populated while switching to ViewState.Player; if that playlist is then deleted from settings during playback, this new branch runs from the playlists subscription and showLatestEpisodes() flips viewState back to EpisodeList. That unexpectedly knocks the user out of the player even though the playlist list is not open, so guard this fallback to the visible episode-list view or clear selectedPlaylist when entering the player.
Useful? React with 👍 / 👎.
# [2.17.0](2.16.0...2.17.0) (2026-06-22) ### Bug Fixes * behavioral-audit logic and robustness fixes (back-end, 1/2) ([#213](#213)) ([4e2845d](4e2845d)) * **download:** default per-episode download path and migrate empty default ([#183](#183)) ([#186](#186)) ([46a6486](46a6486)) * **download:** prevent Android crash and create missing folders on download ([#178](#178)) ([ecd09d5](ecd09d5)), closes [#113](#113) [#86](#86) [#113](#113) [#86](#86) * **lifecycle:** defer mobile podcast view startup ([#208](#208)) ([8bf9ce4](8bf9ce4)) * **notes:** cap note path length and harden folder creation ([#22](#22), [#87](#87)) ([#192](#192)) ([858e280](858e280)), closes [#87-class](#87) * **playback:** persist listened time during playback ([#33](#33)) ([#190](#190)) ([e3433c2](e3433c2)), closes [#191](#191) [#108](#108) [#163](#163) [#183](#183) * **playback:** play local files and downloads on iOS via resource path ([#100](#100)) ([#184](#184)) ([12c503a](12c503a)) * **player:** clear progress on episode switch to stop end-of-playback glitch ([#94](#94)) ([#194](#194)) ([59dccb3](59dccb3)) * **player:** reveal PodNotes view on Play with PodNotes so local files play ([#84](#84)) ([#198](#198)) ([5953625](5953625)) * **settings:** show labelled Add/Remove buttons in podcast search ([#109](#109)) ([#195](#195)) ([33399f5](33399f5)) * show downloaded episodes in the Local Files playlist ([#176](#176)) ([#177](#177)) ([184188c](184188c)) * **timestamps:** capture into the cursor's table cell without breaking the row ([#165](#165)) ([#203](#203)) ([964e342](964e342)) * **transcription:** always transcribe the currently playing episode ([#182](#182)) ([62b488a](62b488a)), closes [#107](#107) * **uri:** preserve '+' in episode titles and paths for timestamp links ([#181](#181)) ([8ad7aa5](8ad7aa5)), closes [#164](#164) * **view:** reliably reveal PodNotes view via command + ribbon icon ([#55](#55)) ([#199](#199)) ([fa1d708](fa1d708)) ### Features * add podcast segment links ([#205](#205)) ([d97e59e](d97e59e)) * **api:** expose generated episode transcripts ([e264465](e264465)), closes [#105](#105) * behavioral-audit UI and interaction fixes (front-end, 2/2) ([#215](#215)) ([894d93d](894d93d)) * **commands:** add playback rate and media timestamp controls ([#206](#206)) ([a8bb44a](a8bb44a)) * **devx:** isolated per-worktree Obsidian E2E vault wrapper ([#188](#188)) ([a8b7a4a](a8b7a4a)) * **episodes:** add a setting to control the Latest Episodes list length ([#114](#114)) ([#200](#200)) ([7b3e3c6](7b3e3c6)) * **notes:** add {{episodelink}} template tag to resume an episode from its note ([#35](#35)) ([#193](#193)) ([8c1ddd6](8c1ddd6)) * **notes:** add podcast feed-level notes ([#163](#163)) ([#187](#187)) ([db0de47](db0de47)), closes [#161](#161) [#160](#160) * **notes:** ship a Bases-friendly default episode note template ([#160](#160)) ([#201](#201)) ([209431d](209431d)), closes [#163](#163) [#183](#183) * **player:** scale episode title font size to its length ([#81](#81)) ([#202](#202)) ([659b6b8](659b6b8)) * **player:** support video episode playback ([#209](#209)) ([f92a91f](f92a91f)) * **queue:** add setting to disable queue auto-population and auto-advance ([#108](#108)) ([#185](#185)) ([cf3d73c](cf3d73c)) * **queue:** allow reordering the playback queue ([#80](#80)) ([#179](#179)) ([d994d61](d994d61)), closes [#173](#173) * **settings:** import/export settings & templates ([#180](#180)) ([a27d23d](a27d23d)), closes [#162](#162) [#162](#162) * **templates:** add {{currentDate}}, {{episodeNumber}}, {{duration}} template variables ([#189](#189)) ([ec573eb](ec573eb)), closes [#75](#75) [#34](#34) [#88](#88) [163/#186](#186) * **templates:** add episode chapters tag ([#207](#207)) ([9c98863](9c98863)) * **transcripts:** opt-in speaker diarization for transcripts ([#168](#168)) ([#204](#204)) ([a96e12f](a96e12f))
|
🎉 This PR is included in version 2.17.0 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
Part 2 of 2 of the behavioral-audit fixes: the UI / interaction half (player, chapters, context menu, playlists, podcast view). This supersedes #214, which GitHub auto-closed when its stacked base branch was deleted on the #213 merge; the branch is unchanged in content and has been rebased onto
master(which now contains #213).#214 reached CI green + Codex sign-off (👍) with all review threads resolved before it was closed; this PR is that same reviewed branch, rebased.
What's added / fixed
Player, chapters, accessible seek
aria-valuetext; chapter listaria-controls+ descriptive seek labels.Context menu, playlists, validation
showAtPosition(was right-click only).Podcast view
Verification
lint,format:check,typecheck,build,check:a11y: clean.