Skip to content

feat: custom download directory, Unicode/Chinese path sanitization, audio transcoding with ID3 tags, and auto-downloading - #202

Open
checkcctvwo-star wants to merge 1 commit into
amugofjava:masterfrom
checkcctvwo-star:feature/enhanced-storage-transcode-autodownload
Open

feat: custom download directory, Unicode/Chinese path sanitization, audio transcoding with ID3 tags, and auto-downloading#202
checkcctvwo-star wants to merge 1 commit into
amugofjava:masterfrom
checkcctvwo-star:feature/enhanced-storage-transcode-autodownload

Conversation

@checkcctvwo-star

@checkcctvwo-star checkcctvwo-star commented Aug 27, 2026

Copy link
Copy Markdown

Hi Ben (@amugofjava),

Thank you for building and maintaining Anytime Podcast Player! It is an exceptional, clean, and distraction-free podcast client.

In accordance with CONTRIBUTING.md, this PR has been prepared with:

  • Single Squashed Commit: All changes are consolidated into a single clean commit on top of master.
  • Code Formatting: Fully formatted using dart format --line-length 120 (dartfmt -l 120).
  • Translations: Followed TRANSLATION.md workflow using intl_translation:extract_to_arb and intl_translation:generate_from_arb with full English and Chinese ARB resources and descriptive metadata.
  • Accessibility: UI additions include Semantics labels, tooltips, and touch targets tested for screen readers (Android TalkBack & iOS VoiceOver).
  • Code Quality & Tests: flutter analyze reports 0 errors, and all 96 of 96 unit tests pass.
  • Non-Breaking & Backward-Compatible: Zero breaking changes to existing databases, models, or user settings.

Summary of Enhancements

1. Custom Download Root Directory & Android 11+ Permission Handling

  • User Pain Point: Previously, audio files could only be stored in app-internal or SD card default locations, making them inaccessible to external file explorers or other media players on Android 11+ without root.
  • Solution: Added a "Custom download folder" setting under Data options allowing users to pick any destination folder (e.g. /storage/emulated/0/Podcasts). Handled the MANAGE_EXTERNAL_STORAGE permission flow on Android 11+ (API 30+) gracefully.

2. Unicode & Multi-Byte (Chinese/Japanese) Character Support in File Paths

  • User Pain Point: safePath() and safeFile() stripped non-ASCII characters, causing podcast titles containing Chinese or other Unicode characters to collapse into empty folder names or extension-less files.
  • Solution: Updated character sanitization in lib/core/utils.dart to preserve valid Unicode letters while stripping filesystem-reserved characters (\/:*?"<>|). Standardized downloaded episode file names to [YYYY-MM-DD]_[Title].mp3 grouped under dedicated podcast folders.

3. Audio Transcoding State (DownloadState.converting) & Progress Indicator

  • User Pain Point: When auto-converting non-MP3 files (like M4A/AAC), the download UI would stay at 100% throughout the entire FFmpeg encoding phase, causing users to believe the download was frozen or unresponsive.
  • Solution: Added a dedicated DownloadState.converting enum state (mapping to index 7 for 100% backward compatibility). Linked FFmpeg conversion progress callbacks to feed 0% ~ 100% into the UI, updating circular progress and transport control icons.

4. Embedded ID3v2.3 Metadata in Transcoded MP3s

  • User Pain Point: Transcoded MP3s did not embed standard ID3 title tags, causing car Bluetooth players and external music apps to display internal CDN hashes (e.g. 080081082) instead of actual episode names.
  • Solution: Added ID3v2.3 tag writing (-metadata title=..., -metadata artist=..., -metadata album=..., -metadata date=...) during transcoding.

5. Cold-Start Process Crash Recovery

  • User Pain Point: If the app was terminated by Android OS while downloading or transcoding in the background, episodes could remain stranded in an incomplete state.
  • Solution: Added recoverUnfinishedTranscodes() during download service startup to inspect and automatically resume unfinished conversion queues.

6. Selective Auto-Download for Subscribed Podcasts

  • User Pain Point: Users had to manually tap download on every newly released episode.
  • Solution: Added an "Auto-download new episodes" option in Settings, complete with a multi-select dialog allowing users to choose exactly which subscribed podcasts to auto-download. Includes network protection (Wi-Fi only safeguard) and a cap of at most 2 newest episodes per refresh to protect storage and data plans.

7. Dual-Tab Downloads Screen & Active Downloads Queue with Interactive Controls

  • User Pain Point: The Downloads view only showed completed downloads. There was no visibility into currently downloading, pending, converting, or failed items, nor could users interactively pause, resume, cancel, or retry them.
  • Solution: Refactored Downloads into a dual-tab layout (Downloaded and Downloading (N) with a dynamic task count badge). The Active Downloads Queue presents real-time progress for downloading, FFmpeg transcoding, and failure states, accompanied by inline controls to Pause, Resume, Retry, and Cancel.

8. Multi-Select Batch Operations in Downloaded Library

  • User Pain Point: Managing large collections of downloaded episodes was tedious, requiring single deletions one by one.
  • Solution: Added a multi-select batch mode activated via long-press in the Downloaded list. Users can select multiple items (or "Select All") to perform Batch Delete (with confirmation dialog and automatic player safety pause if currently playing), Batch Add to Queue, or Batch Toggle Played/Unplayed.

9. Language Switching & Simplified Chinese Localization

  • User Pain Point: Switching to Chinese previously caused a grey screen because MaterialLocalizations did not recognize zh_Hans.
  • Solution: Refined locale resolution to Locale('zh', 'Hans') and generated complete Simplified Chinese string definitions per TRANSLATION.md.

Verification & Automated Testing

  • Ran full test suite: 96 of 96 tests passed.
  • Validated flutter analyze: 0 errors.
  • Adhered to all standards in CONTRIBUTING.md and TRANSLATION.md.

Please let us know if you have any feedback or would like any part of this PR adjusted or split into separate PRs. Thank you!

…d, downloads queue controls, and batch multi-select

- Custom download folder support with Android 11+ MANAGE_EXTERNAL_STORAGE handling
- Unicode/Chinese path sanitization and structured episode filename formatting
- Background audio transcoding to MP3 with FFmpeg and ID3v2.3 tag embedding
- Cold-start crash recovery for unfinished transcode operations
- Selective automatic downloading for new episodes of subscribed podcasts
- Dual-tab downloads screen (Downloaded / Downloading) with live active task badge
- Active downloads queue with real-time progress and controls (pause, resume, retry, cancel)
- Multi-select batch mode in Downloaded view with batch delete, add to queue, and toggle played
- Simplified Chinese localization with full ARB translation bindings per TRANSLATION.md
- Full accessibility support (Semantics / TalkBack / VoiceOver) across new UI elements
- Code formatted with dartfmt 120 chars per CONTRIBUTING.md
- 96 unit tests passing (100% test coverage for all new features)
@checkcctvwo-star
checkcctvwo-star force-pushed the feature/enhanced-storage-transcode-autodownload branch from f08f4ea to 0714ef1 Compare August 27, 2026 13:25
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.

1 participant