Conversation
This change adds a new 'FOLDERS' tab to the Library screen, allowing users to browse their music by folders. The new tab functions as a file manager for music, with support for subfolder navigation, filtering by allowed directories, and correct playback queueing. It also includes permission handling for storage access.
This change adds a new 'FOLDERS' tab to the Library screen, allowing users to browse their music by folders. The new tab functions as a file manager for music, with support for subfolder navigation, filtering by allowed directories, and correct playback queueing. It also includes permission handling for storage access.
This commit introduces a new "Folders" tab to the library screen, providing users with a file-manager-like experience to browse their music collection by directory structure. Key features and changes include: - A new `LibraryFoldersTab` composable that displays a hierarchical view of folders and the songs within them. - A robust `getMusicFolders` implementation in `MusicRepositoryImpl` that correctly scans and structures the folder hierarchy from the device's media store. - Correct handling of the `MANAGE_EXTERNAL_STORAGE` permission, ensuring the tab only loads data after the user has granted access. - A filter option in the `LibraryActionRow` to show either all music folders or only those within the user-defined "allowed directories". - A one-time data migration in `UserPreferencesRepository` to seamlessly add the "Folders" tab for existing users without disrupting their custom tab order. - Improved state management in `LibraryScreen` by hoisting state and using stateless composables for better performance and maintainability.
This commit addresses a critical bug where the 'Folders' tab would incorrectly display 'No folders found' even when music files were present. The primary fix involves using the correct `song.path` property instead of `song.contentUriString` to determine a song's parent directory. This ensures that the folder hierarchy is built correctly. Additionally, extensive logging has been added to the `getMusicFolders` function to trace the folder scanning process, from the initial song list to the final filtered output. This will aid in debugging any further issues. The recursive folder building has also been made safer with protection against circular dependencies.
… `song.path`. The `path` attribute does not exist on the `Song` model, and this change was causing a crash. This commit also adds comprehensive diagnostic logging to the `getMusicFolders` function in `MusicRepositoryImpl.kt`. This will help debug the original 'No folders found' issue by tracing the flow of data, including URI parsing, folder path extraction, and the final construction of the folder hierarchy. URI parsing is now also wrapped in a try-catch block to prevent crashes from malformed URIs.
This commit addresses two UI/UX issues in the Folders tab: 1. **Folder Hierarchy:** The folder scanning logic has been updated to find the common storage root for all music files (e.g., /storage/emulated/0) and display its children (e.g., 'Music', 'Download') as the top-level folders. This prevents the display of irrelevant parent directories like '0' and 'external', providing a more intuitive user experience. 2. **Song Count:** The `MusicFolder` data class now includes a `totalSongCount` property that recursively calculates the total number of songs within a folder and all of its subfolders. The UI has been updated to display this accurate total, rather than just the count of songs in the immediate directory.
This commit completely reworks the folder scanning logic in `MusicRepositoryImpl.kt` to address the recurring 'No folders found' bug and incorrect hierarchy display. The previous 'common root' detection was flawed and has been removed. The new, simpler approach is as follows: 1. The logic now assumes the top-level view should start from the standard external storage directory (`Environment.getExternalStorageDirectory()`). It builds the folder tree and attempts to display the children of this root. 2. A robust fallback mechanism has been added. If the standard root contains no music folders (e.g., on devices with non-standard storage paths), the logic will find the absolute top-level folders in the hierarchy that contain music and display them instead. 3. The final list is always filtered to ensure that only folders containing audio files (either directly or in subdirectories) are displayed, providing a clean and relevant file explorer experience.
This commit provides a definitive fix for the 'Folders' tab functionality by addressing the root cause of previous failures: the lack of a direct file path. The following changes have been made: 1. **Model Update:** The `Song` data class now includes a `path` property to store the absolute file path. 2. **Data Mapping:** The `SongEntity.toSong()` mapping function has been corrected to populate the new `song.path` property from the database entity's `filePath`. 3. **Reworked Folder Logic:** The `getMusicFolders` function in `MusicRepositoryImpl` has been rewritten. It now exclusively uses the reliable `song.path` to build a correct folder hierarchy, starting from the main external storage root and including a fallback for non-standard storage layouts. This ensures the folder structure is displayed exactly as it appears on the user's file system, resolving all previously reported issues of 'No folders found' or incorrect hierarchy displays.
This commit introduces two UI/UX improvements to the 'Folders' tab based on user feedback: 1. **Breadcrumb Navigation:** A new `Breadcrumbs` composable has been added to the top of the tab. It displays the current folder path as a clickable series of directory names (e.g., "Internal Storage > Music > Artist"), allowing for quick and intuitive navigation back to any parent directory. This replaces the previous, simple back button. 2. **Top-Aligned List:** The content of the `LibraryFoldersTab` is now wrapped in a `Column` to ensure that the list of folders and songs is always anchored to the top of the view. This prevents the list from being vertically centered when it contains only a few items, creating a more standard and polished look.
This commit applies final UI/UX improvements to the Folders tab based on user feedback, enhancing its visual appeal and integrating it with the app's expressive design language. Changes include: 1. **Animated Navigation:** The main content area of the tab is now wrapped in an `AnimatedContent` composable. This adds a smooth horizontal slide-in/slide-out transition when the user navigates into a subfolder or back to a parent, creating a more fluid user experience. 2. **Expressive Breadcrumbs:** The `Breadcrumbs` component has been restyled to better match the Material 3 expressive theme. The back button is now a `FilledTonalIconButton`, and the typography, colors, and spacing of the path segments have been refined for a cleaner, more modern look.
This commit provides the final UI polish for the Folders tab by integrating the breadcrumb navigation directly into the `LibraryActionRow`. Key changes: - The `LibraryActionRow` now accepts folder navigation parameters and uses an `AnimatedContent` composable to smoothly transition between the standard action buttons and the breadcrumb view. - When the 'Folders' tab is selected, the action buttons slide out and are replaced by the horizontally-scrollable breadcrumbs and a back button. - The `LibraryFoldersTab` has been cleaned up, removing the now-redundant, separate breadcrumb component. - The main content of the `LibraryFoldersTab` is also wrapped in `AnimatedContent` to provide a slide-in/slide-out animation when navigating between directories. This creates a more elegant, space-efficient, and dynamic UI that aligns with the app's expressive design language.
This commit applies the final UI adjustments to the Folders tab based on user feedback. Changes include: 1. **Animation Refinements:** The `AnimatedContent` transition in `LibraryActionRow` has been updated. The breadcrumb view now uses a combination of `slideInVertically` and `fadeIn`. The transition for the standard action buttons has been reverted to a vertical slide to match the user's preference. 2. **Layout Correction:** The main content of `LibraryFoldersTab` is now correctly wrapped in a `Column` within the `AnimatedContent`. This ensures the list of folders and songs is always aligned to the top of its container, preventing it from being centered vertically when the list is short.
This commit refactors the codebase by cleaning up redundant and disorganized imports across `MusicRepositoryImpl.kt` and `LibraryScreen.kt`. Additionally, the `loadFoldersFromRepository` method in `PlayerViewModel.kt` has been changed from `private` to `public` to allow it to be called from other components, improving its accessibility.
This commit improves the animations and cleans up the code in the `LibraryActionRow` component. The key changes include: - Removing a significant number of unused imports, tidying up the file. - Setting `clip = false` for the `expandHorizontally` and `shrinkHorizontally` animations. This prevents the "clipping" effect during the transition, resulting in a smoother visual expansion and contraction of the action buttons. - Adding an `animateContentSize()` modifier to the `Text` component within the sort button to ensure its size changes are also animated smoothly.
This commit updates the `LibraryActionRow` component to use icons from the Material Design "Rounded" theme for better visual consistency. The following icons have been changed: - `Icons.AutoMirrored.Filled.ArrowBack` is replaced with `Icons.Rounded.ArrowBack`. - `Icons.Default.ChevronRight` is replaced with `Icons.Rounded.ChevronRight`. This minor refactor aligns the iconography within the file browser's breadcrumb navigation.
This commit introduces several UI/UX improvements to the Library screen, focusing on the action row and folder navigation.
### Key Changes:
1. **Redesigned Sort Menu**: The sort option dropdown menu has been completely redesigned for better visual appeal and clarity.
- It now uses `AbsoluteSmoothCornerShape` for a modern, rounded appearance.
- The currently selected option is highlighted with a `CheckCircle` icon and a distinct background, improving usability.
2. **Enhanced Breadcrumbs Navigation**: The folder path breadcrumbs have been significantly improved.
- A fade effect is now applied to the start and end of the `LazyRow` to indicate that the path is scrollable.
- The breadcrumbs now automatically scroll to show the latest folder when navigating deeper into the file system.
- The overall styling, including fonts and icons, has been refined for better readability.
3. **Cleaned Up Library List**: Removed the static "Folders" and "Songs" headers from the main list in `LibraryScreen.kt`. This creates a cleaner, more continuous scrolling experience for the user.
This commit resolves an issue where the breadcrumb navigation row in the library view would not scroll to the very end when navigating deep into folders. The `LaunchedEffect` in `LibraryActionRow.kt` that triggers the scroll was targeting the last index of the path segments. The fix corrects this by changing the scroll target from `pathSegments.lastIndex` to `pathSegments.lastIndex + 1`, ensuring the view always animates to the end of the breadcrumb trail.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
ℹ️ 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
| "FOLDERS" -> { | ||
| val context = LocalContext.current | ||
| var hasPermission by remember { mutableStateOf(Environment.isExternalStorageManager()) } |
There was a problem hiding this comment.
Guard Environment.isExternalStorageManager for pre‑R devices
Opening the Folders tab always evaluates Environment.isExternalStorageManager() to seed the permission state. This API only exists on Android 11+, but the app’s minSdk is 29, so selecting the tab on Android 10 will invoke a missing method and crash with NoSuchMethodError. Wrap both the initial value and the launcher callback in a Build.VERSION.SDK_INT >= Build.VERSION_CODES.R check (or provide a fallback) so the library screen remains usable on devices below R.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
yes, share a fix for this
No description provided.