feat(app): allow configurable and accessible audio storage folder (#4702)

TH
3d ago
+444-20

Summary

Fixes #4702

Allows users to configure an accessible storage directory (such as Music/Omi or Documents/Omi) for batch audio recordings instead of being restricted to sandboxed app documents storage (Android/data/com.friend.ios/), which is inaccessible in modern Android (API 30+) Scoped Storage without ADB/root.

Key Changes

  1. Configurable Storage Preference: Added customAudioStorageDir getter/setter on SharedPreferencesUtil in app/lib/backend/preferences.dart.
  2. Precedence Resolution: Added resolveBatchAudioDirectoryPath(...) (pure precedence engine), resolveEffectiveBatchAudioDirectory() (async runtime resolver), and setCustomAudioStorageDirectory() (atomic preference updater with fallback synchronization) in app/lib/utils/batch_recording.dart.
  3. Capture Controller Hardening: Replaced unconditional directory overwrites in CaptureController (setBatchMode, _initiateDeviceAudioStreaming, and _startPhoneMicBatch) to use resolveEffectiveBatchAudioDirectory().
  4. Local Recordings & Playback Integration:
    • Updated LocalRecordingsProvider._dir() to scan the effective batch audio directory.
    • Updated Wal.getFilePath() in wal.dart to inspect customAudioStorageDir and batchAudioDir before falling back to getApplicationDocumentsDirectory(), ensuring uninterrupted playback and waveform generation.
  5. Transcribe Later Settings UI: Added an "Audio Storage Folder" section in the Transcribe Later modal sheet (app/lib/pages/settings/profile.dart) featuring the active folder path, a folder picker (FilePicker.platform.getDirectoryPath), and a reset action.

Verification & Testing

  • Unit Tests (test/unit/batch_audio_directory_resolution_test.dart):
    • Pure precedence resolution (custom > configured > default).
    • Blank/whitespace string handling.
    • Filesystem existence checks and automatic fallback.
    • Setting and resetting custom audio storage directories.
    • LocalRecordingsProvider discovery of files in custom storage.
    • Wal.getFilePath() resolution across custom and fallback locations.
  • Widget Tests (test/widgets/audio_storage_folder_sheet_test.dart):
    • Verified UI rendering of current storage folder.
    • Verified folder change interaction and reset-to-default button behavior.
  • Regression Tests:
    • test/unit/local_recordings_owner_test.dart (5/5 passed).
    • test/unit/local_recordings_auto_upload_test.dart (14/14 passed).
  • Static Analysis & Preflight:
    • flutter analyze on touched/new files: 0 issues found.
    • scripts/pr-preflight: 20/20 checks passed cleanly.

Failure-Class: none
PayPal: rwilcox413@gmail.com