use folder not list of files to prevent exceed input data passing limit

Signed-off-by: alperozturk <alper_ozturk@proton.me>
This commit is contained in:
alperozturk 2024-12-19 10:42:30 +01:00
parent b2b87a831e
commit 3ee4153baa
No known key found for this signature in database
GPG key ID: 4E577DC593B59BDF
5 changed files with 31 additions and 56 deletions

View file

@ -172,6 +172,6 @@ interface BackgroundJobManager {
fun startPeriodicallyOfflineOperation() fun startPeriodicallyOfflineOperation()
fun scheduleInternal2WaySync(intervalMinutes: Long) fun scheduleInternal2WaySync(intervalMinutes: Long)
fun cancelAllFilesDownloadJobs() fun cancelAllFilesDownloadJobs()
fun syncFolder(files: List<OCFile>, folderId: Long) fun syncFolder(folder: OCFile)
fun cancelSyncFolder(folderId: Long) fun cancelSyncFolder(folderId: Long)
} }

View file

@ -716,9 +716,8 @@ internal class BackgroundJobManagerImpl(
workManager.enqueueUniquePeriodicWork(JOB_INTERNAL_TWO_WAY_SYNC, ExistingPeriodicWorkPolicy.UPDATE, request) workManager.enqueueUniquePeriodicWork(JOB_INTERNAL_TWO_WAY_SYNC, ExistingPeriodicWorkPolicy.UPDATE, request)
} }
override fun syncFolder(files: List<OCFile>, folderId: Long) { override fun syncFolder(folder: OCFile) {
val tag = getSyncFolderTag(folderId) val tag = getSyncFolderTag(folder.fileId)
val filePaths = files.map { it.decryptedRemotePath }
val constraints = Constraints.Builder() val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED) .setRequiredNetworkType(NetworkType.CONNECTED)
@ -726,7 +725,7 @@ internal class BackgroundJobManagerImpl(
.build() .build()
val data = Data.Builder() val data = Data.Builder()
.putStringArray(SyncWorker.FILE_PATHS, filePaths.toTypedArray()) .putLong(SyncWorker.FOLDER_ID, folder.fileId)
.build() .build()
val request = oneTimeRequestBuilder(SyncWorker::class, JOB_SYNC_FOLDER) val request = oneTimeRequestBuilder(SyncWorker::class, JOB_SYNC_FOLDER)

View file

@ -141,13 +141,7 @@ class FileDownloadHelper {
) )
} }
fun syncFolder(files: List<OCFile>) { fun syncFolder(folder: OCFile) {
if (files.isEmpty()) { backgroundJobManager.syncFolder(folder)
return
}
val firstFile = files.first()
val topParentFileId = fileStorageManager.getTopParentId(firstFile)
backgroundJobManager.syncFolder(files, topParentFileId)
} }
} }

View file

@ -22,7 +22,6 @@ import com.owncloud.android.operations.DownloadFileOperation
import com.owncloud.android.ui.helpers.FileOperationsHelper import com.owncloud.android.ui.helpers.FileOperationsHelper
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.Collections
class SyncWorker( class SyncWorker(
private val user: User, private val user: User,
@ -33,19 +32,19 @@ class SyncWorker(
companion object { companion object {
private const val TAG = "SyncWorker" private const val TAG = "SyncWorker"
const val FILE_PATHS = "FILE_PATHS" const val FOLDER_ID = "FOLDER_ID"
const val SYNC_WORKER_COMPLETION_BROADCAST = "SYNC_WORKER_COMPLETION_BROADCAST" const val SYNC_WORKER_COMPLETION_BROADCAST = "SYNC_WORKER_COMPLETION_BROADCAST"
const val FILE_DOWNLOAD_COMPLETION_BROADCAST = "FILE_DOWNLOAD_COMPLETION_BROADCAST" const val FILE_DOWNLOAD_COMPLETION_BROADCAST = "FILE_DOWNLOAD_COMPLETION_BROADCAST"
const val FILE_PATH = "FILE_PATH" const val FILE_PATH = "FILE_PATH"
private var downloadingFilePaths = mutableListOf<String>() private var files = mutableListOf<OCFile>()
/** /**
* It is used to add the sync icon next to the file in the folder. * It is used to add the sync icon next to the file in the folder.
*/ */
fun isDownloading(path: String): Boolean { fun isDownloading(path: String): Boolean {
return downloadingFilePaths.contains(path) return files.any { it.decryptedRemotePath == path }
} }
} }
@ -61,35 +60,36 @@ class SyncWorker(
return withContext(Dispatchers.IO) { return withContext(Dispatchers.IO) {
try { try {
val filePaths = inputData.getStringArray(FILE_PATHS) val folderID = inputData.getLong(FOLDER_ID, -1)
if (filePaths.isNullOrEmpty()) { if (folderID == -1L) {
return@withContext Result.success() return@withContext Result.failure()
} }
val storageManager = FileDataStorageManager(user, context.contentResolver) val storageManager = FileDataStorageManager(user, context.contentResolver)
val folder = storageManager.getFileById(folderID) ?: return@withContext Result.failure()
val topParentPath = prepareDownloadingFilePathsAndGetTopParentPath(storageManager, filePaths) files = ArrayList(getFiles(folder, storageManager)).apply {
// Add the topParentPath to mark the sync icon on the selected folder.
add(folder)
}
val client = getClient() val client = getClient()
var result = true var result = true
filePaths.forEachIndexed { index, path -> files.forEachIndexed { index, file ->
if (isStopped) { if (isStopped) {
notificationManager.dismiss() notificationManager.dismiss()
return@withContext Result.failure() return@withContext Result.failure()
} }
val file = storageManager.getFileByDecryptedRemotePath(path) ?: return@forEachIndexed
if (!checkDiskSize(file)) { if (!checkDiskSize(file)) {
return@withContext Result.failure() return@withContext Result.failure()
} }
withContext(Dispatchers.Main) { withContext(Dispatchers.Main) {
notificationManager.showProgressNotification(file.fileName, index, filePaths.size) notificationManager.showProgressNotification(file.fileName, index, files.size)
} }
val syncFileResult = syncFile(file, path, client) val syncFileResult = syncFile(file, client)
if (!syncFileResult) { if (!syncFileResult) {
result = false result = false
} }
@ -100,7 +100,7 @@ class SyncWorker(
} }
if (result) { if (result) {
downloadingFilePaths.remove(topParentPath) files.remove(folder)
sendSyncWorkerCompletionBroadcast() sendSyncWorkerCompletionBroadcast()
Log_OC.d(TAG, "SyncWorker completed") Log_OC.d(TAG, "SyncWorker completed")
Result.success() Result.success()
@ -115,27 +115,16 @@ class SyncWorker(
} }
} }
private fun getFiles(folder: OCFile, storageManager: FileDataStorageManager): List<OCFile> =
storageManager.getFolderContent(folder, false)
.filter { !it.isFolder && !it.isDown }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private fun getClient(): OwnCloudClient { private fun getClient(): OwnCloudClient {
val account = user.toOwnCloudAccount() val account = user.toOwnCloudAccount()
return OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(account, context) return OwnCloudClientManagerFactory.getDefaultSingleton().getClientFor(account, context)
} }
/**
* Add the topParentPath to mark the sync icon on the selected folder.
*/
private fun prepareDownloadingFilePathsAndGetTopParentPath(
storageManager: FileDataStorageManager,
filePaths: Array<String>
): String {
val topParentPath = getTopParentPath(storageManager, filePaths.first())
downloadingFilePaths = Collections.synchronizedList(ArrayList(filePaths.toList())).apply {
add(topParentPath)
}
return topParentPath
}
private suspend fun checkDiskSize(file: OCFile): Boolean { private suspend fun checkDiskSize(file: OCFile): Boolean {
val fileSizeInByte = file.fileLength val fileSizeInByte = file.fileLength
val availableDiskSpace = FileOperationsHelper.getAvailableSpaceOnDevice() val availableDiskSpace = FileOperationsHelper.getAvailableSpaceOnDevice()
@ -149,31 +138,25 @@ class SyncWorker(
} }
@Suppress("DEPRECATION") @Suppress("DEPRECATION")
private fun syncFile(file: OCFile, path: String, client: OwnCloudClient): Boolean { private fun syncFile(file: OCFile, client: OwnCloudClient): Boolean {
val operation = DownloadFileOperation(user, file, context).execute(client) val operation = DownloadFileOperation(user, file, context).execute(client)
Log_OC.d(TAG, "Syncing file: " + file.decryptedRemotePath) Log_OC.d(TAG, "Syncing file: " + file.decryptedRemotePath)
return if (operation.isSuccess) { return if (operation.isSuccess) {
sendFileDownloadCompletionBroadcast(path) sendFileDownloadCompletionBroadcast(file)
downloadingFilePaths.remove(path) files.remove(file)
true true
} else { } else {
false false
} }
} }
private fun getTopParentPath(storageManager: FileDataStorageManager, firstFilePath: String): String {
val firstFile = storageManager.getFileByDecryptedRemotePath(firstFilePath)
val topParentFile = storageManager.getTopParent(firstFile)
return topParentFile.decryptedRemotePath
}
/** /**
* It is used to remove the sync icon next to the file in the folder. * It is used to remove the sync icon next to the file in the folder.
*/ */
private fun sendFileDownloadCompletionBroadcast(path: String) { private fun sendFileDownloadCompletionBroadcast(file: OCFile) {
val intent = Intent(FILE_DOWNLOAD_COMPLETION_BROADCAST).apply { val intent = Intent(FILE_DOWNLOAD_COMPLETION_BROADCAST).apply {
putExtra(FILE_PATH, path) putExtra(FILE_PATH, file.decryptedRemotePath)
} }
LocalBroadcastManager.getInstance(context).sendBroadcast(intent) LocalBroadcastManager.getInstance(context).sendBroadcast(intent)

View file

@ -416,7 +416,6 @@ public class SynchronizeFolderOperation extends SyncOperation {
} }
} }
private void prepareOpsFromLocalKnowledge() throws OperationCancelledException { private void prepareOpsFromLocalKnowledge() throws OperationCancelledException {
List<OCFile> children = getStorageManager().getFolderContent(mLocalFolder, false); List<OCFile> children = getStorageManager().getFolderContent(mLocalFolder, false);
for (OCFile child : children) { for (OCFile child : children) {
@ -500,7 +499,7 @@ public class SynchronizeFolderOperation extends SyncOperation {
Log_OC.d(TAG, "Exception caught at startDirectDownloads" + e); Log_OC.d(TAG, "Exception caught at startDirectDownloads" + e);
} }
} else { } else {
fileDownloadHelper.syncFolder(mFilesForDirectDownload); fileDownloadHelper.syncFolder(mLocalFolder);
} }
} }