Conversation
- Make FileDataStorageManager.getFolderContent() public to allow MetadataWorker access - Add recursive parameter to BackgroundJobManager.downloadFolder() with default false - Add job dependency in BackgroundJobManagerImpl to ensure MetadataWorker runs before FolderDownloadWorker - Add recursive parameter to FileDownloadHelper.downloadFolder() - Pass recursive parameter in SynchronizeFolderOperation
- Add FORCE_REFRESH flag to bypass eTag caching and always fetch fresh content - Implement BFS-based recursive folder processing to fetch metadata for ALL nested subfolders - Before: Only processed one level of subfolders (e.g., Artists but not ABBA inside it) - After: Recursively processes all nested folders at every depth level - Also fetches files at each folder level to ensure FolderDownloadWorker has access to all files
- Add warning log when no files found for recursive download - Add detailed debug logging in getAllFilesRecursive() to track folder processing - Log content count at each folder level to help diagnose issues
- Add DOWNLOAD_FOLDER_RECURSIVE action in FileAction - Add action ID in ids.xml - Add UI strings for recursive download confirmation dialogs - Add showDownloadFolderRecursiveConfirmation() in FileActivity - Add downloadFolderRecursive() method in FileOperationsHelper - Add overloaded syncFile() method with recursive parameter
- FileDetailFragment: Add handler for action_sync_file_recursive to show recursive download dialog - OCFileListFragment: Add handler for recursive download action in file list - PreviewTextFileFragment: Add confirmation dialog for folder sync
|
Going to paste a message from the linked issue here:
|
| storageManager.getFolderContent(folder, false) | ||
| .filter { !it.isFolder && !it.isDown } | ||
| private fun getFiles(folder: OCFile, storageManager: FileDataStorageManager, recursive: Boolean): List<OCFile> { | ||
| if (recursive) { |
There was a problem hiding this comment.
Could you please use FiledatastorageManager.getAllFilesRecursivelyInsideFolder() together with the OCFile.isDown check instead of introducing a new function?
Using isDown should not negatively impact this process; in fact, it helps reduce unnecessary operations.
Also, let’s remove the comments where possible. Ideally, the code should be self-explanatory and clear enough that extensive comments aren’t needed.
| val files = getFiles(folder, storageManager, recursiveDownload) | ||
|
|
||
| // Add warning log when no files found for recursive download | ||
| if (files.isEmpty()) { |
There was a problem hiding this comment.
Why do we need warning log here? It is just extra info if file list is empty.
Please change with info log and remove the emoji along with comment since Log already prints.
| /** | ||
| * Recursively get all files in the folder and its subfolders | ||
| */ | ||
| private fun getAllFilesRecursive(folder: OCFile, storageManager: FileDataStorageManager): List<OCFile> { |
There was a problem hiding this comment.
Please remove this and use FiledatastorageManager.getAllFilesRecursivelyInsideFolder()
| } | ||
|
|
||
| override fun downloadFolder(folder: OCFile, accountName: String) { | ||
| override fun downloadFolder(folder: OCFile, accountName: String, recursive: Boolean) { |
There was a problem hiding this comment.
Thank you for the PR and your time.
I’d suggest keeping the scope of this PR strictly limited. The changes proposed outside of FolderDownloadWorker are quite significant and would require thorough testing.
For now, let’s focus only on FolderDownloadWorker with a minimal adjustment, for example, adding the new boolean parameter. From the UI side, we can introduce a separate action for this behavior, and have the worker that uses either the full nested structure or only the first-level depth based on that parameter.
Keeping the scope small will help us review more effectively and move forward with confidence. Once this is merged and validated, we can discuss and plan the next steps separately.
Thanks for understanding and we can test, review other findings in separate PR.
Summary
This PR fixes #269 , the inability to recursively sync folders (an issue that is 10 years old). Previously, when users tried to sync a folder with subfolders recursively, only the immediate children were synced. I spent three days of time I should have been focusing on my programming assignments on this, so please let me know if there is anything wrong with my code instead of just throwing it out. I am happy to collaborate, but I needed this feature so that I can properly sync and listen to my music.
Root Cause
The issue had three contributing factors:
Race Condition: MetadataWorker and FolderDownloadWorker were running without proper dependency, causing FolderDownloadWorker to query the database before metadata was populated.
eTag Caching: MetadataWorker was skipping folder content refresh when eTag hadn't changed, leaving the database empty.
Single-Level Processing: MetadataWorker only fetched one level of subfolders, not recursively traversing into nested folders like
Artists/ABBA, for example.Changes
🏁 Checklist