Skip to content

Add multiple accounts and fix podcasts#21

Merged
Promises merged 1 commit into
Promises:mainfrom
kvmgithub:fix/upstream-19-20-main-worktree
Jun 1, 2026
Merged

Add multiple accounts and fix podcasts#21
Promises merged 1 commit into
Promises:mainfrom
kvmgithub:fix/upstream-19-20-main-worktree

Conversation

@kvmgithub
Copy link
Copy Markdown
Contributor

Context

This PR fixes the Audible flows around account login, multi-account handling,
podcast library handling, podcast episode syncing, and podcast episode
downloads.

The user-facing problem was that Audible podcast parents and episodes were
imported enough to appear in the library, but the Android app still treated
parts of the flow like normal audiobooks. That caused account-screen crashes,
podcast parents with bogus duration/status display, paged podcast episode lists
that could not be opened cleanly, and downloaded podcast episodes being placed
under Unknown Author instead of the podcast title.

The download path also needed to be stable for external audiobook players:
podcast episodes should sort in release-date order and should be grouped by the
podcast title, not by an absent author.

Fixes #19
Fixes #20

What changed

Audible account and login hardening

The Android account screens now tolerate partially populated account data from
the Rust storage layer.

Changes include:

  • defensive access to account display fields;
  • safer handling of identity/locale data;
  • account refresh/save behavior that preserves the stored identity shape;
  • login/account screens that no longer crash when optional account fields are
    absent after Audible login.

This fixes the crash path where the UI attempted to read name from an
undefined account value.

Multi-account handling

Audible sync and download flows now preserve account ownership more carefully.

Changes include:

  • library sync stores and reads account ownership for imported titles;
  • account filters are carried into library and podcast episode queries;
  • podcast episode sync chooses the selected/owning Audible account instead of
    falling back blindly to the primary account;
  • downloads resolve the account from the selected library item before falling
    back to the primary account;
  • refreshed tokens are saved back to the same account record used for the
    request.

This matters for users with multiple Audible accounts because podcast episodes,
library rows, and download tasks should use the same account context that owns
the content.

Podcast parent library behavior

Podcast parents now behave as library containers instead of downloadable
audiobooks.

Changes include:

  • podcast parents open an episode screen from the library;
  • parent podcasts no longer show 0h 0m;
  • parent podcasts no longer expose invalid downloaded-state actions;
  • duplicate podcast labeling in the library row was removed;
  • podcast rows use an episodes-only status instead of a normal audiobook
    download state.

This keeps the main library focused on the podcast as a container while moving
episode-specific duration and download behavior to the episode screen.

Podcast episode paging

The podcast episode screen now syncs and lists episodes in pages.

Changes include:

  • episode pages are fetched in batches of 100;
  • scrolling loads the next page;
  • pull refresh reloads from the first page;
  • episodes are ordered newest first in the app;
  • episode rows can be downloaded individually.

The implementation stores episode metadata in the same library tables while
keeping origin_asin linked to the podcast parent.

Podcast episode download support

Podcast episode downloads now use the plain podcast audio path instead of the
audiobook DRM-only path.

Changes include:

  • podcast license/content responses are parsed for plain MP3 delivery;
  • Android download workers accept podcast MP3 tasks;
  • podcast episode metadata is carried through the task pipeline;
  • completed podcast downloads update the stored final file path;
  • episode status refreshes in the podcast episode screen after state changes.

This keeps audiobook downloads unchanged while allowing podcast episodes to use
their own content-delivery behavior.

Podcast naming pattern

Podcast episode naming is now separate from audiobook naming.

Settings now includes Podcast Naming Pattern with two options:

  • Episode Folder: Podcast/2026-05-31 - Episode/2026-05-31 - Episode.mp3
  • Flat Episode Files: Podcast/2026-05-31 - Episode.mp3

The default is Episode Folder.

The Rust file-path builder detects podcast episodes from both new
PodcastEpisode rows and older synced rows that were stored as SinglePartBook
but have a podcast parent. It then uses:

  • the parent podcast title as the top-level folder;
  • the episode release date as a filename prefix;
  • sanitized folder and file names;
  • .mp3 output for podcast episodes.

This fixes the Unknown Author folder issue and makes downloaded episodes sort
by release date in external players.

Download state cleanup

Marking podcast episodes as not downloaded now updates app state consistently.

Changes include:

  • SAF/content URI deletion has a stronger DocumentFile and tree-walk fallback;
  • manual file deletion followed by clear-status still clears the app download
    state;
  • successful file deletion no longer reports a false deletion error;
  • podcast episode rows refresh after clear/delete actions.

This keeps the database state, episode screen, and on-disk files aligned.

User-visible behavior

After this change:

  1. Audible account login no longer crashes the account screen.
  2. Account-specific library, podcast, and download flows use the owning account
    where available.
  3. Podcast parents appear in the library as podcast containers.
  4. Tapping a podcast opens its episode list.
  5. Episode lists page in batches of 100 and load more while scrolling.
  6. Podcast parents do not show duration; episodes do.
  7. Podcast episodes can be downloaded.
  8. Downloaded podcast episodes are stored under the podcast title.
  9. Podcast episode file/folder names begin with release date for external
    sorting.
  10. Marking a podcast episode as not downloaded clears status reliably.

Review focus

The main review areas are:

  • account ownership through sync, podcast episode loading, and download enqueue;
  • podcast parent and episode detection in the Rust library import code;
  • the podcast episode paging path from React Native to Rust;
  • podcast MP3 license/content parsing;
  • Android worker handling for podcast downloads;
  • file naming for old and new podcast episode rows;
  • SAF deletion fallback behavior;
  • the new podcast naming setting in SettingsScreen.

Validation

Validation run for this branch:

  • npm run typecheck
  • cargo check --manifest-path native/rust-core/Cargo.toml --lib
  • git diff --check
  • Android app launched cleanly with no crash logs
  • Manual Android validation: podcast episode download works
  • Manual Android validation: podcast episode delete/clear status works

Fix Audible account login, podcast episode paging/downloads, and SAF cleanup.

Podcast downloads use parent podcast title plus release date so external players sort episodes.

Refs Promises#19

Refs Promises#20
@Promises
Copy link
Copy Markdown
Owner

Promises commented Jun 1, 2026

Thank you!, could i sign you up as a tester for google play? I need 12 to publish, currently at 7.

@kvmgithub
Copy link
Copy Markdown
Contributor Author

I'd already applied if I'd use play store. 🥹

@Promises Promises merged commit d1644f4 into Promises:main Jun 1, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Handle multiple Audible accounts and regions Option to include/exclude podcasts - periodical download error

2 participants