Skip to content

feat: Add in-app filesystem folder picker dialog with SAF fallback - #23

Merged
Mahmud0808 merged 1 commit into
Mahmud0808:masterfrom
Ruslik31:master
Sep 5, 2026
Merged

feat: Add in-app filesystem folder picker dialog with SAF fallback#23
Mahmud0808 merged 1 commit into
Mahmud0808:masterfrom
Ruslik31:master

Conversation

@Ruslik31

@Ruslik31 Ruslik31 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR introduces a built-in, theme-consistent in-app folder chooser dialog (FileSystemFolderPickerDialog) for selecting backup and download directories on Android, as an enhancement to the system Storage Access Framework (SAF) picker.

What's Changed

  • In-App Folder Chooser (FileSystemFolderPickerDialog):
    • Added a Material 3 Expressive styled dialog matching TeleDriveTheme (both light & dark modes).
    • Quick-jump shortcut chips for common directories (Internal Storage, Download, Documents, DCIM, Pictures).
    • Interactive directory listing with breadcrumb path display and 1-level-up navigation.
    • Ability to create new subfolders directly within the dialog.
    • Included a "Use System SAF Picker" fallback button so users can seamlessly switch to Android's native system picker if preferred.
  • Platform Provider Wiring (AndroidPlatformProviders.kt):
    • Connected LocalFolderPicker to present the in-app folder picker dialog wrapped in TeleDriveTheme.
  • Localization:
    • Added English and Russian string resources for all dialog actions and shortcuts.

Why

On certain Android versions and custom ROMs, the default SAF (OpenDocumentTree) can be unintuitive or restricted. Providing a direct in-app folder browser that matches TeleDrive's UI theme gives users a smoother, more responsive experience while preserving standard SAF compatibility.

Testing

  • Verified folder navigation and subfolder creation on Android API 36 emulator.
  • Tested light and dark theme styling integration.
  • Passed all unit tests (:android:testDebugUnitTest).

Copilot AI lite review requested due to automatic review settings September 4, 2026 16:46

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Mahmud0808

Copy link
Copy Markdown
Owner

Nice work, the SAF fallback and the suspend-lambda design are exactly right. A few things before merge:

  1. The dialog is wrapped in a bare TeleDriveTheme, which defaults to the system theme and dynamic color. Users who force light/dark or disable dynamic color in settings get a mismatched dialog. The theme preference needs to reach this call.
  2. /storage/emulated/0 is hardcoded (default path and all quick chips). Secondary users and work profiles live on a different user id path. Please pass Environment.getExternalStorageDirectory() from the Android side and derive the chips from it.
  3. When the folder can't be read (no all-files access), listFiles() returns null and the dialog shows "no subfolders" as if it were empty, while still allowing selection. Please distinguish unreadable from empty and point users at the permission or the SAF button.
  4. createSubfolder's return value is ignored, so a failed creation closes the naming dialog silently.
  5. Small style things to match the codebase: LocalFolderItem in its own file, keep the new strings alphabetical within their section, and loadPath plus the LaunchedEffect both list the same path, one mechanism is enough.

@Ruslik31

Ruslik31 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the detailed review! I've addressed all 5 points in a single updated commit:

  1. Theme preference forwarding: Injected SettingsRepository in AndroidPlatformProviders.kt to observe prefs.theme and prefs.dynamicColor. Passed darkTheme (evaluating LIGHT, DARK, SYSTEM) and dynamicColor into TeleDriveTheme.
  2. Environment storage path: Passed Environment.getExternalStorageDirectory().absolutePath dynamically into FileSystemFolderPickerDialog as
    ootPath. Derived all quick folder chips (Download, Documents, DCIM, Pictures) dynamically relative to
    ootPath.
  3. Unreadable vs Empty distinction: Introduced FolderListResult (Success / Unreadable). Unreadable folders display a lock icon, error text, and hint ("Grant All files access in Settings or use the system SAF picker below."), while disabling the selection confirm button (enabled = resultState is FolderListResult.Success).
  4. createSubfolder return handling: If folder creation fails ( alse), the naming dialog remains open and displays an error message ("Failed to create folder").
  5. Codebase style polish:
    • Extracted LocalFolderItem & FolderListResult into LocalFolderItem.kt.
    • Kept string resources alphabetized under .
    • Removed duplicate folder fetching by using LaunchedEffect(currentPath) as the single source of truth.

@Mahmud0808
Mahmud0808 merged commit 14f55c0 into Mahmud0808:master Sep 5, 2026
2 checks passed
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.

3 participants