diff --git a/owncloudApp/src/main/java/com/owncloud/android/datamodel/OCUpload.java b/owncloudApp/src/main/java/com/owncloud/android/datamodel/OCUpload.java index 6523dd6690b..3d7424ee60b 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/datamodel/OCUpload.java +++ b/owncloudApp/src/main/java/com/owncloud/android/datamodel/OCUpload.java @@ -38,6 +38,7 @@ import java.io.File; +@Deprecated /** * Stores all information in order to start upload operations. PersistentUploadObject can * be stored persistently by {@link UploadsStorageManager}. diff --git a/owncloudApp/src/main/java/com/owncloud/android/datamodel/UploadsStorageManager.java b/owncloudApp/src/main/java/com/owncloud/android/datamodel/UploadsStorageManager.java index 101d9f93e94..bb8634a2088 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/datamodel/UploadsStorageManager.java +++ b/owncloudApp/src/main/java/com/owncloud/android/datamodel/UploadsStorageManager.java @@ -94,42 +94,6 @@ public UploadsStorageManager(ContentResolver contentResolver) { mContentResolver = contentResolver; } - /** - * Stores an upload object in DB. - * - * @param ocUpload Upload object to store - * @return upload id, -1 if the insert process fails. - */ - public long storeUpload(OCUpload ocUpload) { - Timber.v("Inserting " + ocUpload.getLocalPath() + " with status=" + ocUpload.getUploadStatus()); - - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.UPLOADS_LOCAL_PATH, ocUpload.getLocalPath()); - cv.put(ProviderTableMeta.UPLOADS_REMOTE_PATH, ocUpload.getRemotePath()); - cv.put(ProviderTableMeta.UPLOADS_ACCOUNT_NAME, ocUpload.getAccountName()); - cv.put(ProviderTableMeta.UPLOADS_FILE_SIZE, ocUpload.getFileSize()); - cv.put(ProviderTableMeta.UPLOADS_STATUS, ocUpload.getUploadStatus().value); - cv.put(ProviderTableMeta.UPLOADS_LOCAL_BEHAVIOUR, ocUpload.getLocalAction()); - cv.put(ProviderTableMeta.UPLOADS_FORCE_OVERWRITE, ocUpload.isForceOverwrite() ? 1 : 0); - cv.put(ProviderTableMeta.UPLOADS_IS_CREATE_REMOTE_FOLDER, ocUpload.createsRemoteFolder() ? 1 : 0); - cv.put(ProviderTableMeta.UPLOADS_LAST_RESULT, ocUpload.getLastResult().getValue()); - cv.put(ProviderTableMeta.UPLOADS_CREATED_BY, ocUpload.getCreatedBy()); - cv.put(ProviderTableMeta.UPLOADS_TRANSFER_ID, ocUpload.getTransferId()); - - Uri result = getDB().insert(ProviderTableMeta.CONTENT_URI_UPLOADS, cv); - - Timber.d("storeUpload returns with: " + result + " for file: " + ocUpload.getLocalPath()); - if (result == null) { - Timber.e("Failed to insert item " + ocUpload.getLocalPath() + " into upload db."); - return -1; - } else { - long new_id = Long.parseLong(result.getPathSegments().get(1)); - ocUpload.setUploadId(new_id); - notifyObserversNow(); - return new_id; - } - } - /** * Update an upload object in DB. * @@ -164,63 +128,6 @@ public int updateUpload(OCUpload ocUpload) { return result; } - private int updateUploadInternal(Cursor c, UploadStatus status, UploadResult result, String remotePath, - String localPath) { - int r = 0; - while (c.moveToNext()) { - // read upload object and update - OCUpload upload = createOCUploadFromCursor(c); - - String path = getStringFromColumnOrThrow(c, ProviderTableMeta.UPLOADS_LOCAL_PATH); - Timber.v("Updating " + path + " with status:" + status + " and result:" + (result == null ? "null" : - result.toString()) + " (old:" + upload.toFormattedString() + ")"); - - upload.setUploadStatus(status); - upload.setLastResult(result); - upload.setRemotePath(remotePath); - if (localPath != null) { - upload.setLocalPath(localPath); - } - upload.setUploadEndTimestamp(Calendar.getInstance().getTimeInMillis()); - - // store update upload object to db - r = updateUpload(upload); - } - - return r; - } - - /** - * Update upload status of file uniquely referenced by id. - * - * @param id upload id. - * @param status new status. - * @param result new result of upload operation - * @param remotePath path of the file to upload in the ownCloud storage - * @param localPath path of the file to upload in the device storage - * @return 1 if file status was updated, else 0. - */ - public int updateUploadStatus(long id, UploadStatus status, UploadResult result, String remotePath, - String localPath) { - int returnValue = 0; - Cursor c = getDB().query( - ProviderTableMeta.CONTENT_URI_UPLOADS, - null, - ProviderTableMeta._ID + "=?", - new String[]{String.valueOf(id)}, - null - ); - - if (c.getCount() != 1) { - Timber.e(c.getCount() + " items for id=" + id - + " available in UploadDb. Expected 1. Failed to update upload db."); - } else { - returnValue = updateUploadInternal(c, status, result, remotePath, localPath); - } - c.close(); - return returnValue; - } - /** * Should be called when some value of this DB was changed. All observers * are informed. @@ -231,64 +138,6 @@ public void notifyObserversNow() { notifyObservers(); } - /** - * Remove an upload from the uploads list, known its target account and remote path. - * - * @param upload Upload instance to remove from persisted storage. - * @return true when the upload was stored and could be removed. - */ - public int removeUpload(OCUpload upload) { - int result = getDB().delete( - ProviderTableMeta.CONTENT_URI_UPLOADS, - ProviderTableMeta._ID + "=?", - new String[]{Long.toString(upload.getUploadId())} - ); - Timber.d("delete returns " + result + " for upload " + upload); - if (result > 0) { - notifyObserversNow(); - } - return result; - } - - /** - * Remove an upload from the uploads list, known its target account and remote path. - * - * @param accountName Name of the OC account target of the upload to remove. - * @param remotePath Absolute path in the OC account target of the upload to remove. - * @return true when one or more upload entries were removed - */ - public int removeUpload(String accountName, String remotePath) { - int result = getDB().delete( - ProviderTableMeta.CONTENT_URI_UPLOADS, - ProviderTableMeta.UPLOADS_ACCOUNT_NAME + "=? AND " + ProviderTableMeta.UPLOADS_REMOTE_PATH + "=?", - new String[]{accountName, remotePath} - ); - Timber.d("delete returns " + result + " for file " + remotePath + " in " + accountName); - if (result > 0) { - notifyObserversNow(); - } - return result; - } - - /** - * Remove all the uploads of a given account from the uploads list. - * - * @param accountName Name of the OC account target of the uploads to remove. - * @return true when one or more upload entries were removed - */ - public int removeUploads(String accountName) { - int result = getDB().delete( - ProviderTableMeta.CONTENT_URI_UPLOADS, - ProviderTableMeta.UPLOADS_ACCOUNT_NAME + "=?", - new String[]{accountName} - ); - Timber.d("delete returns " + result + " for uploads in " + accountName); - if (result > 0) { - notifyObserversNow(); - } - return result; - } - public OCUpload[] getAllStoredUploads() { return getUploads(null, null, null); } @@ -368,19 +217,6 @@ public OCUpload[] getCurrentAndPendingUploads() { ); } - /** - * Get all failed uploads. - */ - public OCUpload[] getFailedUploads() { - return getUploads( - ProviderTableMeta.UPLOADS_STATUS + "== ?", - new String[]{ - String.valueOf(UploadStatus.UPLOAD_FAILED.value) - }, - null - ); - } - /** * Get all uploads which where successfully completed. */ @@ -442,37 +278,4 @@ public long clearSuccessfulUploads() { } return result; } - - /** - * Changes the status of any in progress upload from UploadStatus.UPLOAD_IN_PROGRESS - * to UploadStatus.UPLOAD_FAILED - * - * @return Number of uploads which status was changed. - */ - public int failInProgressUploads(UploadResult uploadResult) { - Timber.v("Updating state of any killed upload"); - - ContentValues cv = new ContentValues(); - cv.put(ProviderTableMeta.UPLOADS_STATUS, UploadStatus.UPLOAD_FAILED.getValue()); - cv.put( - ProviderTableMeta.UPLOADS_LAST_RESULT, - uploadResult != null ? uploadResult.getValue() : UploadResult.UNKNOWN.getValue() - ); - cv.put(ProviderTableMeta.UPLOADS_UPLOAD_END_TIMESTAMP, Calendar.getInstance().getTimeInMillis()); - - int result = getDB().update( - ProviderTableMeta.CONTENT_URI_UPLOADS, - cv, - ProviderTableMeta.UPLOADS_STATUS + "=?", - new String[]{String.valueOf(UploadStatus.UPLOAD_IN_PROGRESS.getValue())} - ); - - if (result == 0) { - Timber.v("No upload was killed"); - } else { - Timber.w("%s uploads where abruptly interrupted", result); - notifyObserversNow(); - } - return result; - } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/LocalDataSourceModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/LocalDataSourceModule.kt index 09dead943eb..ec36ab4b526 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/LocalDataSourceModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/LocalDataSourceModule.kt @@ -3,7 +3,9 @@ * * @author David González Verdugo * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -26,18 +28,20 @@ import com.owncloud.android.MainApp.Companion.dataFolder import com.owncloud.android.data.OwncloudDatabase import com.owncloud.android.data.authentication.datasources.LocalAuthenticationDataSource import com.owncloud.android.data.authentication.datasources.implementation.OCLocalAuthenticationDataSource -import com.owncloud.android.data.folderbackup.datasources.FolderBackupLocalDataSource -import com.owncloud.android.data.folderbackup.datasources.implementation.FolderBackupLocalDataSourceImpl import com.owncloud.android.data.capabilities.datasources.LocalCapabilitiesDataSource import com.owncloud.android.data.capabilities.datasources.implementation.OCLocalCapabilitiesDataSource import com.owncloud.android.data.files.datasources.LocalFileDataSource import com.owncloud.android.data.files.datasources.implementation.OCLocalFileDataSource +import com.owncloud.android.data.folderbackup.datasources.FolderBackupLocalDataSource +import com.owncloud.android.data.folderbackup.datasources.implementation.FolderBackupLocalDataSourceImpl import com.owncloud.android.data.preferences.datasources.SharedPreferencesProvider import com.owncloud.android.data.preferences.datasources.implementation.SharedPreferencesProviderImpl import com.owncloud.android.data.sharing.shares.datasources.LocalShareDataSource import com.owncloud.android.data.sharing.shares.datasources.implementation.OCLocalShareDataSource import com.owncloud.android.data.storage.LocalStorageProvider import com.owncloud.android.data.storage.ScopedStorageProvider +import com.owncloud.android.data.transfers.datasources.LocalTransferDataSource +import com.owncloud.android.data.transfers.datasources.implementation.OCLocalTransferDataSource import com.owncloud.android.data.user.datasources.LocalUserDataSource import com.owncloud.android.data.user.datasources.implementation.OCLocalUserDataSource import org.koin.android.ext.koin.androidContext @@ -51,6 +55,7 @@ val localDataSourceModule = module { single { OwncloudDatabase.getDatabase(androidContext()).shareDao() } single { OwncloudDatabase.getDatabase(androidContext()).userDao() } single { OwncloudDatabase.getDatabase(androidContext()).folderBackUpDao() } + single { OwncloudDatabase.getDatabase(androidContext()).transferDao() } single { SharedPreferencesProviderImpl(get()) } single { ScopedStorageProvider(dataFolder, androidContext()) } @@ -61,4 +66,5 @@ val localDataSourceModule = module { factory { OCLocalShareDataSource(get()) } factory { OCLocalUserDataSource(get()) } factory { FolderBackupLocalDataSourceImpl(get()) } + factory { OCLocalTransferDataSource(get()) } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/RepositoryModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/RepositoryModule.kt index d53dab98960..17cd746feb1 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/RepositoryModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/RepositoryModule.kt @@ -2,7 +2,10 @@ * ownCloud Android client application * * @author David González Verdugo - * Copyright (C) 2020 ownCloud GmbH. + * @author Abel García de Prada + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -27,6 +30,7 @@ import com.owncloud.android.data.oauth.OAuthRepositoryImpl import com.owncloud.android.data.server.repository.OCServerInfoRepository import com.owncloud.android.data.sharing.sharees.repository.OCShareeRepository import com.owncloud.android.data.sharing.shares.repository.OCShareRepository +import com.owncloud.android.data.transfers.repository.OCTransferRepository import com.owncloud.android.data.user.repository.OCUserRepository import com.owncloud.android.domain.authentication.AuthenticationRepository import com.owncloud.android.domain.authentication.oauth.OAuthRepository @@ -36,6 +40,7 @@ import com.owncloud.android.domain.files.FileRepository import com.owncloud.android.domain.server.ServerInfoRepository import com.owncloud.android.domain.sharing.sharees.ShareeRepository import com.owncloud.android.domain.sharing.shares.ShareRepository +import com.owncloud.android.domain.transfers.TransferRepository import com.owncloud.android.domain.user.UserRepository import org.koin.dsl.module @@ -49,4 +54,5 @@ val repositoryModule = module { factory { OCUserRepository(get(), get()) } factory { OAuthRepositoryImpl(get()) } factory { FolderBackupRepositoryImpl(get()) } + factory { OCTransferRepository(get()) } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt index 7f76b386319..e95bc62bda3 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/UseCaseModule.kt @@ -2,7 +2,10 @@ * ownCloud Android client application * * @author David González Verdugo - * Copyright (C) 2020 ownCloud GmbH. + * @author Abel García de Prada + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -73,6 +76,7 @@ import com.owncloud.android.usecases.transfers.downloads.DownloadFileUseCase import com.owncloud.android.usecases.transfers.downloads.GetLiveDataForDownloadingFileUseCase import com.owncloud.android.usecases.transfers.downloads.GetLiveDataForFinishedDownloadsFromAccountUseCase import com.owncloud.android.usecases.transfers.uploads.CancelUploadForFileUseCase +import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromSystemUseCase import com.owncloud.android.usecases.transfers.uploads.UploadFileInConflictUseCase import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSAFUseCase import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase @@ -131,10 +135,11 @@ val useCaseModule = module { factory { DownloadFileUseCase(get()) } factory { GetLiveDataForDownloadingFileUseCase(get()) } factory { GetLiveDataForFinishedDownloadsFromAccountUseCase(get()) } - factory { UploadFilesFromSAFUseCase(get()) } - factory { UploadFilesFromSystemUseCase(get()) } - factory { UploadFileInConflictUseCase(get()) } - factory { CancelUploadForFileUseCase(get()) } + factory { UploadFilesFromSAFUseCase(get(), get()) } + factory { UploadFilesFromSystemUseCase(get(), get()) } + factory { UploadFileInConflictUseCase(get(), get()) } + factory { CancelUploadForFileUseCase(get(), get()) } + factory { RetryUploadFromSystemUseCase(get(), get()) } // User factory { GetStoredQuotaUseCase(get()) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt index b597d497aa5..328dc7aca50 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/dependecyinjection/ViewModelModule.kt @@ -46,6 +46,7 @@ import com.owncloud.android.presentation.viewmodels.settings.SettingsSecurityVie import com.owncloud.android.presentation.viewmodels.settings.SettingsVideoUploadsViewModel import com.owncloud.android.presentation.viewmodels.settings.SettingsViewModel import com.owncloud.android.presentation.viewmodels.sharing.OCShareViewModel +import com.owncloud.android.presentation.viewmodels.transfers.TransfersViewModel import com.owncloud.android.ui.dialog.RemoveAccountDialogViewModel import com.owncloud.android.ui.preview.PreviewImageViewModel import org.koin.androidx.viewmodel.dsl.viewModel @@ -87,4 +88,5 @@ val viewModelModule = module { viewModel { FileDetailsViewModel(get(), get(), get(), get(), get()) } viewModel { FileOperationsViewModel(get(), get(), get(), get(), get(), get(), get(), get()) } viewModel { MainFileListViewModel(get(), get(), get(), get(), get(), get(), get(), get(), get(), get()) } + viewModel { TransfersViewModel(get(), get(), get()) } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/operations/SynchronizeFileOperation.java b/owncloudApp/src/main/java/com/owncloud/android/operations/SynchronizeFileOperation.java index 0c6f6a5627d..da006f6a0cc 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/operations/SynchronizeFileOperation.java +++ b/owncloudApp/src/main/java/com/owncloud/android/operations/SynchronizeFileOperation.java @@ -28,6 +28,9 @@ import android.content.Context; import androidx.work.WorkManager; +import com.owncloud.android.data.OwncloudDatabase; +import com.owncloud.android.data.transfers.datasources.implementation.OCLocalTransferDataSource; +import com.owncloud.android.data.transfers.repository.OCTransferRepository; import com.owncloud.android.domain.files.model.OCFile; import com.owncloud.android.lib.common.OwnCloudClient; import com.owncloud.android.lib.common.operations.RemoteOperationResult; @@ -229,7 +232,9 @@ protected RemoteOperationResult run(OwnCloudClient client) { */ private void requestForUpload(OCFile file) { WorkManager workManager = WorkManager.getInstance(mContext); - UploadFileInConflictUseCase uploadFileInConflictUseCase = new UploadFileInConflictUseCase(workManager); + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(mContext).transferDao())); + UploadFileInConflictUseCase uploadFileInConflictUseCase = new UploadFileInConflictUseCase(workManager, transferRepository); UploadFileInConflictUseCase.Params params = new UploadFileInConflictUseCase.Params( file.getOwner(), file.getStoragePath(), diff --git a/owncloudApp/src/main/java/com/owncloud/android/presentation/viewmodels/transfers/TransfersViewModel.kt b/owncloudApp/src/main/java/com/owncloud/android/presentation/viewmodels/transfers/TransfersViewModel.kt new file mode 100644 index 00000000000..b6366e611c0 --- /dev/null +++ b/owncloudApp/src/main/java/com/owncloud/android/presentation/viewmodels/transfers/TransfersViewModel.kt @@ -0,0 +1,67 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.presentation.viewmodels.transfers + +import android.net.Uri +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.owncloud.android.providers.CoroutinesDispatcherProvider +import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSAFUseCase +import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase +import kotlinx.coroutines.launch + +class TransfersViewModel( + private val uploadFilesFromSAFUseCase: UploadFilesFromSAFUseCase, + private val uploadFilesFromSystemUseCase: UploadFilesFromSystemUseCase, + private val coroutinesDispatcherProvider: CoroutinesDispatcherProvider, +) : ViewModel() { + fun uploadFilesFromSAF( + accountName: String, + listOfContentUris: List, + uploadFolderPath: String + ) { + viewModelScope.launch(coroutinesDispatcherProvider.io) { + uploadFilesFromSAFUseCase.execute( + UploadFilesFromSAFUseCase.Params( + accountName = accountName, + listOfContentUris = listOfContentUris, + uploadFolderPath = uploadFolderPath + ) + ) + } + } + + fun uploadFilesFromSystem( + accountName: String, + listOfLocalPaths: List, + uploadFolderPath: String + ) { + viewModelScope.launch(coroutinesDispatcherProvider.io) { + uploadFilesFromSystemUseCase.execute( + UploadFilesFromSystemUseCase.Params( + accountName = accountName, + listOfLocalPaths = listOfLocalPaths, + uploadFolderPath = uploadFolderPath + ) + ) + } + } +} diff --git a/owncloudApp/src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.kt b/owncloudApp/src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.kt index 7206e3ed75e..c9f8675c692 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/providers/DocumentsStorageProvider.kt @@ -35,7 +35,6 @@ import android.os.ParcelFileDescriptor import android.preference.PreferenceManager import android.provider.DocumentsContract import android.provider.DocumentsProvider -import androidx.work.WorkManager import com.owncloud.android.MainApp import com.owncloud.android.R import com.owncloud.android.authentication.AccountUtils @@ -131,8 +130,7 @@ class DocumentsStorageProvider : DocumentsProvider() { // If only needs to upload that file if (uploadOnly) { ocFile.length = fileToOpen.length() - val workManager = WorkManager.getInstance(MainApp.appContext) - val uploadFilesUseCase = UploadFilesFromSystemUseCase(workManager) + val uploadFilesUseCase: UploadFilesFromSystemUseCase by inject() val uploadFilesUseCaseParams = UploadFilesFromSystemUseCase.Params( accountName = ocFile.owner, listOfLocalPaths = listOf(fileToOpen.path), diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.java b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.java index 89594065df4..2a17bdc14bf 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.java +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/ConflictsResolveActivity.java @@ -24,6 +24,9 @@ import android.os.Bundle; import androidx.work.WorkManager; +import com.owncloud.android.data.OwncloudDatabase; +import com.owncloud.android.data.transfers.datasources.implementation.OCLocalTransferDataSource; +import com.owncloud.android.data.transfers.repository.OCTransferRepository; import com.owncloud.android.domain.files.model.OCFile; import com.owncloud.android.ui.dialog.ConflictsResolveDialog; import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision; @@ -79,7 +82,9 @@ public void conflictDecisionMade(Decision decision) { WorkManager workManager = WorkManager.getInstance(getApplicationContext()); if (forceOverwrite) { - UploadFileInConflictUseCase uploadFileInConflictUseCase = new UploadFileInConflictUseCase(workManager); + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(this).transferDao())); + UploadFileInConflictUseCase uploadFileInConflictUseCase = new UploadFileInConflictUseCase(workManager, transferRepository); UploadFileInConflictUseCase.Params params = new UploadFileInConflictUseCase.Params( getFile().getOwner(), getFile().getStoragePath(), @@ -87,7 +92,9 @@ public void conflictDecisionMade(Decision decision) { ); uploadFileInConflictUseCase.execute(params); } else { - UploadFilesFromSystemUseCase uploadFilesFromSystemUseCase = new UploadFilesFromSystemUseCase(workManager); + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(this).transferDao())); + UploadFilesFromSystemUseCase uploadFilesFromSystemUseCase = new UploadFilesFromSystemUseCase(workManager, transferRepository); ArrayList listOfPaths = new ArrayList<>(); listOfPaths.add(getFile().getStoragePath()); UploadFilesFromSystemUseCase.Params params = new UploadFilesFromSystemUseCase.Params( diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt index a7a6d8e815e..510362e20a9 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.kt @@ -7,8 +7,10 @@ * @author Christian Schabesberger * @author Shashvat Kedia * @author Abel García de Prada + * @author Juan Carlos Garrote Gascón + * * Copyright (C) 2011 Bartek Przybylski - * Copyright (C) 2020 ownCloud GmbH. + * Copyright (C) 2022 ownCloud GmbH. * * * This program is free software: you can redistribute it and/or modify @@ -74,6 +76,7 @@ import com.owncloud.android.presentation.ui.files.filelist.MainFileListFragment import com.owncloud.android.presentation.ui.files.operations.FileOperation import com.owncloud.android.presentation.ui.files.operations.FileOperationsViewModel import com.owncloud.android.presentation.ui.security.bayPassUnlockOnce +import com.owncloud.android.presentation.viewmodels.transfers.TransfersViewModel import com.owncloud.android.syncadapter.FileSyncAdapter import com.owncloud.android.ui.fragment.FileDetailFragment import com.owncloud.android.ui.fragment.FileFragment @@ -89,7 +92,6 @@ import com.owncloud.android.usecases.synchronization.SynchronizeFileUseCase import com.owncloud.android.usecases.transfers.DOWNLOAD_FINISH_MESSAGE import com.owncloud.android.usecases.transfers.downloads.DownloadFileUseCase import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSAFUseCase -import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase import com.owncloud.android.utils.Extras import com.owncloud.android.utils.PreferenceUtils import kotlinx.coroutines.CoroutineScope @@ -153,6 +155,7 @@ class FileDisplayActivity : FileActivity(), private var localBroadcastManager: LocalBroadcastManager? = null private val fileOperationsViewModel: FileOperationsViewModel by viewModel() + private val transfersViewModel: TransfersViewModel by viewModel() var filesUploadHelper: FilesUploadHelper? = null internal set @@ -537,11 +540,10 @@ class FileDisplayActivity : FileActivity(), remotePaths[j] = remotePathBase + File(filePaths[j]).name } - val uploadFilesFromSystemUseCase: UploadFilesFromSystemUseCase by inject() - uploadFilesFromSystemUseCase.execute( - UploadFilesFromSystemUseCase.Params( - accountName = account.name, listOfLocalPaths = filePaths.toList(), uploadFolderPath = remotePathBase!! - ) + transfersViewModel.uploadFilesFromSystem( + accountName = account.name, + listOfLocalPaths = filePaths.toList(), + uploadFolderPath = remotePathBase!! ) } else { @@ -566,12 +568,11 @@ class FileDisplayActivity : FileActivity(), val currentDir = currentDir val remotePath = currentDir?.remotePath ?: OCFile.ROOT_PATH - val uploadFileUseCaseParams = UploadFilesFromSAFUseCase.Params( + transfersViewModel.uploadFilesFromSAF( accountName = account.name, listOfContentUris = streamsToUpload, uploadFolderPath = remotePath, ) - uploadFileUseCase.execute(uploadFileUseCaseParams) } /** diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.java b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.java index 1a7c795c110..726d4f11be6 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.java +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/ManageAccountsActivity.java @@ -42,6 +42,9 @@ import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; +import com.owncloud.android.data.OwncloudDatabase; +import com.owncloud.android.data.transfers.datasources.implementation.OCLocalTransferDataSource; +import com.owncloud.android.data.transfers.repository.OCTransferRepository; import com.owncloud.android.datamodel.FileDataStorageManager; import com.owncloud.android.presentation.ui.authentication.AuthenticatorConstants; import com.owncloud.android.presentation.ui.authentication.LoginActivity; @@ -51,7 +54,7 @@ import com.owncloud.android.ui.dialog.RemoveAccountDialogFragment; import com.owncloud.android.ui.dialog.RemoveAccountDialogViewModel; import com.owncloud.android.ui.helpers.FileOperationsHelper; -import com.owncloud.android.usecases.transfers.uploads.CancelUploadFromAccountUseCase; +import com.owncloud.android.usecases.transfers.uploads.CancelUploadsFromAccountUseCase; import com.owncloud.android.usecases.transfers.downloads.CancelDownloadsForAccountUseCase; import com.owncloud.android.utils.PreferenceUtils; import kotlin.Lazy; @@ -294,10 +297,12 @@ public void run(AccountManagerFuture future) { if (future != null && future.isDone()) { Account account = new Account(mAccountBeingRemoved, MainApp.Companion.getAccountType()); if (!AccountUtils.exists(account.name, MainApp.Companion.getAppContext())) { + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(this).transferDao())); // Cancel transfers of the removed account - CancelUploadFromAccountUseCase cancelUploadFromAccountUseCase = - new CancelUploadFromAccountUseCase(WorkManager.getInstance(getBaseContext())); - cancelUploadFromAccountUseCase.execute(new CancelUploadFromAccountUseCase.Params(account.name)); + CancelUploadsFromAccountUseCase cancelUploadsFromAccountUseCase = + new CancelUploadsFromAccountUseCase(WorkManager.getInstance(getBaseContext()), transferRepository); + cancelUploadsFromAccountUseCase.execute(new CancelUploadsFromAccountUseCase.Params(account.name)); CancelDownloadsForAccountUseCase cancelDownloadsForAccountUseCase = new CancelDownloadsForAccountUseCase(WorkManager.getInstance(getBaseContext())); diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java index 81a0ee8178c..3969893cd8c 100755 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java @@ -30,8 +30,12 @@ import android.view.View; import androidx.fragment.app.FragmentTransaction; +import androidx.work.WorkManager; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; +import com.owncloud.android.data.OwncloudDatabase; +import com.owncloud.android.data.transfers.datasources.implementation.OCLocalTransferDataSource; +import com.owncloud.android.data.transfers.repository.OCTransferRepository; import com.owncloud.android.datamodel.OCUpload; import com.owncloud.android.datamodel.UploadsStorageManager; import com.owncloud.android.lib.common.operations.RemoteOperation; @@ -39,6 +43,9 @@ import com.owncloud.android.operations.CheckCurrentCredentialsOperation; import com.owncloud.android.ui.fragment.UploadListFragment; import com.owncloud.android.usecases.transfers.uploads.RetryFailedUploadsForAccountUseCase; +import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromContentUriUseCase; +import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromSystemUseCase; +import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase; import com.owncloud.android.utils.MimetypeIconUtil; import timber.log.Timber; @@ -141,8 +148,13 @@ protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (account == null) { return; } - - RetryFailedUploadsForAccountUseCase retryFailedUploadsForAccountUseCase = new RetryFailedUploadsForAccountUseCase(this); + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(this).transferDao())); + RetryUploadFromContentUriUseCase retryUploadFromContentUriUseCase = new RetryUploadFromContentUriUseCase(this, transferRepository); + WorkManager workManager = WorkManager.getInstance(this); + UploadFilesFromSystemUseCase uploadFilesFromSystemUseCase = new UploadFilesFromSystemUseCase(workManager, transferRepository); + RetryUploadFromSystemUseCase retryUploadFromSystemUseCase = new RetryUploadFromSystemUseCase(uploadFilesFromSystemUseCase, transferRepository); + RetryFailedUploadsForAccountUseCase retryFailedUploadsForAccountUseCase = new RetryFailedUploadsForAccountUseCase(this, retryUploadFromContentUriUseCase, retryUploadFromSystemUseCase, transferRepository); retryFailedUploadsForAccountUseCase.execute(new RetryFailedUploadsForAccountUseCase.Params(account.name)); } } @@ -164,7 +176,13 @@ public void onRemoteOperationFinish(RemoteOperation operation, RemoteOperationRe } else { // already updated -> just retry! - RetryFailedUploadsForAccountUseCase retryFailedUploadsForAccountUseCase = new RetryFailedUploadsForAccountUseCase(this); + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(this).transferDao())); + RetryUploadFromContentUriUseCase retryUploadFromContentUriUseCase = new RetryUploadFromContentUriUseCase(this, transferRepository); + WorkManager workManager = WorkManager.getInstance(this); + UploadFilesFromSystemUseCase uploadFilesFromSystemUseCase = new UploadFilesFromSystemUseCase(workManager, transferRepository); + RetryUploadFromSystemUseCase retryUploadFromSystemUseCase = new RetryUploadFromSystemUseCase(uploadFilesFromSystemUseCase, transferRepository); + RetryFailedUploadsForAccountUseCase retryFailedUploadsForAccountUseCase = new RetryFailedUploadsForAccountUseCase(this, retryUploadFromContentUriUseCase, retryUploadFromSystemUseCase, transferRepository); retryFailedUploadsForAccountUseCase.execute(new RetryFailedUploadsForAccountUseCase.Params(account.name)); } diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/adapter/ExpandableUploadListAdapter.java b/owncloudApp/src/main/java/com/owncloud/android/ui/adapter/ExpandableUploadListAdapter.java index 54f50aadb25..cc0878f7449 100755 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/adapter/ExpandableUploadListAdapter.java +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/adapter/ExpandableUploadListAdapter.java @@ -44,6 +44,9 @@ import com.google.android.material.snackbar.Snackbar; import com.owncloud.android.R; import com.owncloud.android.authentication.AccountUtils; +import com.owncloud.android.data.OwncloudDatabase; +import com.owncloud.android.data.transfers.datasources.implementation.OCLocalTransferDataSource; +import com.owncloud.android.data.transfers.repository.OCTransferRepository; import com.owncloud.android.datamodel.OCUpload; import com.owncloud.android.datamodel.ThumbnailsCacheManager; import com.owncloud.android.datamodel.UploadsStorageManager; @@ -58,6 +61,7 @@ import com.owncloud.android.usecases.transfers.uploads.CancelUploadWithIdUseCase; import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromContentUriUseCase; import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromSystemUseCase; +import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase; import com.owncloud.android.utils.DisplayUtils; import com.owncloud.android.utils.MimetypeIconUtil; import com.owncloud.android.utils.PreferenceUtils; @@ -308,8 +312,9 @@ private View getView(OCUpload[] uploadsItems, int position, View convertView, Vi rightButton.setImageResource(R.drawable.ic_action_cancel_grey); rightButton.setVisibility(View.VISIBLE); rightButton.setOnClickListener(v -> { - CancelUploadWithIdUseCase cancelUploadWithIdUseCase = new CancelUploadWithIdUseCase(WorkManager.getInstance(parent.getContext())); - cancelUploadWithIdUseCase.execute(new CancelUploadWithIdUseCase.Params(upload)); + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(v.getContext()).transferDao())); + CancelUploadWithIdUseCase cancelUploadWithIdUseCase = new CancelUploadWithIdUseCase(WorkManager.getInstance(parent.getContext()), transferRepository); + cancelUploadWithIdUseCase.execute(new CancelUploadWithIdUseCase.Params(upload.getUploadId())); refreshView(); }); @@ -318,7 +323,8 @@ private View getView(OCUpload[] uploadsItems, int position, View convertView, Vi rightButton.setImageResource(R.drawable.ic_action_delete_grey); rightButton.setVisibility(View.VISIBLE); rightButton.setOnClickListener(v -> { - mUploadsStorageManager.removeUpload(upload); + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(v.getContext()).transferDao())); + transferRepository.removeTransferById(upload.getUploadId()); refreshView(); }); @@ -340,13 +346,18 @@ private View getView(OCUpload[] uploadsItems, int position, View convertView, Vi public void onClick(View v) { File file = new File(upload.getLocalPath()); if (file.exists()) { - RetryUploadFromSystemUseCase retryUploadFromContentUriUseCase = new RetryUploadFromSystemUseCase(v.getContext()); + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(v.getContext()).transferDao())); + WorkManager workManager = WorkManager.getInstance(v.getContext()); + UploadFilesFromSystemUseCase uploadFilesFromSystemUseCase = new UploadFilesFromSystemUseCase(workManager, transferRepository); + RetryUploadFromSystemUseCase retryUploadFromSystemUseCase = new RetryUploadFromSystemUseCase(uploadFilesFromSystemUseCase, transferRepository); RetryUploadFromSystemUseCase.Params useCaseParams = new RetryUploadFromSystemUseCase.Params(upload.getUploadId()); - retryUploadFromContentUriUseCase.execute(useCaseParams); + retryUploadFromSystemUseCase.execute(useCaseParams); refreshView(); } else if (DocumentFile.isDocumentUri(v.getContext(), Uri.parse(upload.getLocalPath()))) { + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(v.getContext()).transferDao())); RetryUploadFromContentUriUseCase retryUploadFromContentUriUseCase = - new RetryUploadFromContentUriUseCase(v.getContext()); + new RetryUploadFromContentUriUseCase(v.getContext(), transferRepository); RetryUploadFromContentUriUseCase.Params useCaseParams = new RetryUploadFromContentUriUseCase.Params( upload.getUploadId() ); diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.java b/owncloudApp/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.java index 3faf585e5e7..12004270846 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.java +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/asynctasks/CopyAndUploadContentUrisTask.java @@ -30,6 +30,10 @@ import androidx.work.WorkManager; import com.owncloud.android.R; +import com.owncloud.android.data.OwncloudDatabase; +import com.owncloud.android.data.transfers.datasources.implementation.OCLocalTransferDataSource; +import com.owncloud.android.data.transfers.db.TransferDao; +import com.owncloud.android.data.transfers.repository.OCTransferRepository; import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase; import com.owncloud.android.utils.FileStorageUtils; @@ -159,7 +163,9 @@ protected ResultCode doInBackground(Object[] params) { filesToUpload.add(fullTempPath); WorkManager workManager = WorkManager.getInstance(mAppContext); - UploadFilesFromSystemUseCase uploadFilesFromSystemUseCase = new UploadFilesFromSystemUseCase(workManager); + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(mAppContext).transferDao())); + UploadFilesFromSystemUseCase uploadFilesFromSystemUseCase = new UploadFilesFromSystemUseCase(workManager, transferRepository); UploadFilesFromSystemUseCase.Params useCaseParams = new UploadFilesFromSystemUseCase.Params( account.name, filesToUpload, diff --git a/owncloudApp/src/main/java/com/owncloud/android/ui/fragment/UploadListFragment.java b/owncloudApp/src/main/java/com/owncloud/android/ui/fragment/UploadListFragment.java index 6bbe6574bee..48b4ed47d5f 100755 --- a/owncloudApp/src/main/java/com/owncloud/android/ui/fragment/UploadListFragment.java +++ b/owncloudApp/src/main/java/com/owncloud/android/ui/fragment/UploadListFragment.java @@ -26,12 +26,19 @@ import android.widget.ExpandableListView; import android.widget.ListView; +import androidx.work.WorkManager; import com.owncloud.android.R; +import com.owncloud.android.data.OwncloudDatabase; +import com.owncloud.android.data.transfers.datasources.implementation.OCLocalTransferDataSource; +import com.owncloud.android.data.transfers.repository.OCTransferRepository; import com.owncloud.android.datamodel.OCUpload; import com.owncloud.android.datamodel.UploadsStorageManager; import com.owncloud.android.ui.activity.FileActivity; import com.owncloud.android.ui.adapter.ExpandableUploadListAdapter; import com.owncloud.android.usecases.transfers.uploads.RetryFailedUploadsUseCase; +import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromContentUriUseCase; +import com.owncloud.android.usecases.transfers.uploads.RetryUploadFromSystemUseCase; +import com.owncloud.android.usecases.transfers.uploads.UploadFilesFromSystemUseCase; import kotlin.Unit; import timber.log.Timber; @@ -117,7 +124,13 @@ public void onClick(OptionsInUploadList option) { switch (option) { case RETRY_FAILED: - RetryFailedUploadsUseCase retryFailedUploadsUseCase = new RetryFailedUploadsUseCase(requireContext()); + // Workaround... should be removed as soon as possible + OCTransferRepository transferRepository = new OCTransferRepository(new OCLocalTransferDataSource(OwncloudDatabase.Companion.getDatabase(requireContext()).transferDao())); + RetryUploadFromContentUriUseCase retryUploadFromContentUriUseCase = new RetryUploadFromContentUriUseCase(requireContext(), transferRepository); + WorkManager workManager = WorkManager.getInstance(requireContext()); + UploadFilesFromSystemUseCase uploadFilesFromSystemUseCase = new UploadFilesFromSystemUseCase(workManager, transferRepository); + RetryUploadFromSystemUseCase retryUploadFromSystemUseCase = new RetryUploadFromSystemUseCase(uploadFilesFromSystemUseCase, transferRepository); + RetryFailedUploadsUseCase retryFailedUploadsUseCase = new RetryFailedUploadsUseCase(requireContext(), retryUploadFromContentUriUseCase, retryUploadFromSystemUseCase, transferRepository); retryFailedUploadsUseCase.execute(Unit.INSTANCE); break; case CLEAR_FAILED: diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadForFileUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadForFileUseCase.kt index 0cb8781815a..c6753ec3383 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadForFileUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadForFileUseCase.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,13 +18,13 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import androidx.work.WorkManager -import com.owncloud.android.MainApp -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase import com.owncloud.android.domain.files.model.OCFile +import com.owncloud.android.domain.transfers.TransferRepository import com.owncloud.android.extensions.getWorkInfoByTags import com.owncloud.android.workers.UploadFileFromContentUriWorker.Companion.TRANSFER_TAG_MANUAL_UPLOAD import timber.log.Timber @@ -32,16 +34,16 @@ import timber.log.Timber * policy and work that is already executing may continue to run. */ class CancelUploadForFileUseCase( - private val workManager: WorkManager + private val workManager: WorkManager, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Params) { val file = params.file - val uploadsStorageManager = UploadsStorageManager(MainApp.appContext.contentResolver) // Check if there are pending uploads for this file. // FirstOrNull because it should not be 2 uploads with same owner and remote path at the same time - val uploadForFile = uploadsStorageManager.currentAndPendingUploads.firstOrNull { + val uploadForFile = transferRepository.getCurrentAndPendingTransfers().firstOrNull { file.owner == it.accountName && file.remotePath == it.remotePath } @@ -51,7 +53,7 @@ class CancelUploadForFileUseCase( } val workersToCancel = - workManager.getWorkInfoByTags(listOf(TRANSFER_TAG_MANUAL_UPLOAD, uploadForFile.uploadId.toString(), file.owner)) + workManager.getWorkInfoByTags(listOf(TRANSFER_TAG_MANUAL_UPLOAD, uploadForFile.id.toString(), file.owner)) workersToCancel.forEach { // TODO: We need to check if the work is cancelled before finishing. diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadWithIdUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadWithIdUseCase.kt index 1b2f1a3a530..ee883235780 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadWithIdUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadWithIdUseCase.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,29 +18,28 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import androidx.work.WorkManager -import com.owncloud.android.MainApp -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase +import com.owncloud.android.domain.transfers.TransferRepository import timber.log.Timber class CancelUploadWithIdUseCase( - private val workManager: WorkManager + private val workManager: WorkManager, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Params) { - workManager.cancelAllWorkByTag(params.upload.uploadId.toString()) + workManager.cancelAllWorkByTag(params.uploadId.toString()) - val uploadsStorageManager = UploadsStorageManager(MainApp.appContext.contentResolver) - uploadsStorageManager.removeUpload(params.upload) + transferRepository.removeTransferById(params.uploadId) - Timber.i("Upload with id ${params.upload.uploadId} has been cancelled.") + Timber.i("Upload with id ${params.uploadId} has been cancelled.") } data class Params( - val upload: OCUpload, + val uploadId: Long, ) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadFromAccountUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadsFromAccountUseCase.kt similarity index 66% rename from owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadFromAccountUseCase.kt rename to owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadsFromAccountUseCase.kt index ceb465cca29..04dea853992 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadFromAccountUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/CancelUploadsFromAccountUseCase.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,25 +18,25 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import androidx.work.WorkManager -import com.owncloud.android.MainApp -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase +import com.owncloud.android.domain.transfers.TransferRepository import timber.log.Timber -class CancelUploadFromAccountUseCase( - private val workManager: WorkManager -) : BaseUseCase() { +class CancelUploadsFromAccountUseCase( + private val workManager: WorkManager, + private val transferRepository: TransferRepository, +) : BaseUseCase() { override fun run(params: Params) { workManager.cancelAllWorkByTag(params.accountName) - val uploadsStorageManager = UploadsStorageManager(MainApp.appContext.contentResolver) - uploadsStorageManager.removeUploads(params.accountName) + transferRepository.removeAllTransfersFromAccount(params.accountName) - Timber.i("Uploads of ${params.accountName} has been cancelled.") + Timber.i("Uploads of ${params.accountName} have been cancelled.") } data class Params( diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryFailedUploadsForAccountUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryFailedUploadsForAccountUseCase.kt index 6e42ec6f392..7e061f06e04 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryFailedUploadsForAccountUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryFailedUploadsForAccountUseCase.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,24 +18,26 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import android.content.Context import android.net.Uri import androidx.documentfile.provider.DocumentFile -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.OCTransfer import timber.log.Timber class RetryFailedUploadsForAccountUseCase( private val context: Context, + private val retryUploadFromContentUriUseCase: RetryUploadFromContentUriUseCase, + private val retryUploadFromSystemUseCase: RetryUploadFromSystemUseCase, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Params) { - - val uploadsStorageManager = UploadsStorageManager(context.contentResolver) - val failedUploads = uploadsStorageManager.failedUploads + val failedUploads = transferRepository.getFailedTransfers() val failedUploadsForAccount = failedUploads.filter { it.accountName == params.accountName } if (failedUploadsForAccount.isEmpty()) { @@ -43,14 +47,14 @@ class RetryFailedUploadsForAccountUseCase( failedUploadsForAccount.forEach { upload -> if (isContentUri(context = context, upload = upload)) { - RetryUploadFromContentUriUseCase(context).execute(RetryUploadFromContentUriUseCase.Params(upload.uploadId)) + retryUploadFromContentUriUseCase.execute(RetryUploadFromContentUriUseCase.Params(upload.id!!)) } else { - RetryUploadFromSystemUseCase(context).execute(RetryUploadFromSystemUseCase.Params(upload.uploadId)) + retryUploadFromSystemUseCase.execute(RetryUploadFromSystemUseCase.Params(upload.id!!)) } } } - private fun isContentUri(context: Context, upload: OCUpload): Boolean { + private fun isContentUri(context: Context, upload: OCTransfer): Boolean { return DocumentFile.isDocumentUri(context, Uri.parse(upload.localPath)) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryFailedUploadsUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryFailedUploadsUseCase.kt index b0e2480dc3b..5d140efcb90 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryFailedUploadsUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryFailedUploadsUseCase.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,24 +18,26 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import android.content.Context import android.net.Uri import androidx.documentfile.provider.DocumentFile -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.OCTransfer import timber.log.Timber class RetryFailedUploadsUseCase( private val context: Context, + private val retryUploadFromContentUriUseCase: RetryUploadFromContentUriUseCase, + private val retryUploadFromSystemUseCase: RetryUploadFromSystemUseCase, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Unit) { - - val uploadsStorageManager = UploadsStorageManager(context.contentResolver) - val failedUploads = uploadsStorageManager.failedUploads + val failedUploads = transferRepository.getFailedTransfers() if (failedUploads.isEmpty()) { Timber.d("There are no failed uploads to retry.") @@ -41,14 +45,14 @@ class RetryFailedUploadsUseCase( } failedUploads.forEach { upload -> if (isContentUri(context = context, upload = upload)) { - RetryUploadFromContentUriUseCase(context).execute(RetryUploadFromContentUriUseCase.Params(upload.uploadId)) + retryUploadFromContentUriUseCase.execute(RetryUploadFromContentUriUseCase.Params(upload.id!!)) } else { - RetryUploadFromSystemUseCase(context).execute(RetryUploadFromSystemUseCase.Params(upload.uploadId)) + retryUploadFromSystemUseCase.execute(RetryUploadFromSystemUseCase.Params(upload.id!!)) } } } - private fun isContentUri(context: Context, upload: OCUpload): Boolean { + private fun isContentUri(context: Context, upload: OCTransfer): Boolean { return DocumentFile.isDocumentUri(context, Uri.parse(upload.localPath)) } diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromContentUriUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromContentUriUseCase.kt index a4bdebf4468..23a8f3b8f68 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromContentUriUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromContentUriUseCase.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,25 +18,23 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import android.content.Context import androidx.core.net.toUri import androidx.work.WorkManager -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase import com.owncloud.android.domain.camerauploads.model.UploadBehavior +import com.owncloud.android.domain.transfers.TransferRepository class RetryUploadFromContentUriUseCase( private val context: Context, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Params) { - - val uploadsStorageManager = UploadsStorageManager(context.contentResolver) - val failedUploads = uploadsStorageManager.failedUploads - val filteredUploads = failedUploads.filter { it.uploadId == params.uploadIdInStorageManager } - val uploadToRetry = filteredUploads.firstOrNull() + val uploadToRetry = transferRepository.getTransferById(params.uploadIdInStorageManager) uploadToRetry ?: return @@ -43,15 +43,14 @@ class RetryUploadFromContentUriUseCase( UploadFileFromContentUriUseCase.Params( accountName = uploadToRetry.accountName, contentUri = uploadToRetry.localPath.toUri(), - lastModifiedInSeconds = (uploadToRetry.uploadEndTimestamp / 1000).toString(), - behavior = UploadBehavior.fromLegacyLocalBehavior(uploadToRetry.localAction).name, + lastModifiedInSeconds = (uploadToRetry.transferEndTimestamp?.div(1000)).toString(), + behavior = UploadBehavior.fromLegacyLocalBehavior(uploadToRetry.localBehaviour).name, uploadPath = uploadToRetry.remotePath, - uploadIdInStorageManager = uploadToRetry.uploadId, + uploadIdInStorageManager = uploadToRetry.id!!, wifiOnly = false, chargingOnly = false ) ) - uploadsStorageManager.updateUpload(uploadToRetry.apply { uploadStatus = UploadsStorageManager.UploadStatus.UPLOAD_IN_PROGRESS }) } data class Params( diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromSystemUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromSystemUseCase.kt index c8007de92c4..e1e898a0326 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromSystemUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/RetryUploadFromSystemUseCase.kt @@ -2,6 +2,8 @@ * ownCloud Android client application * * @author Abel García de Prada + * @author Juan Carlos Garrote Gascón + * * Copyright (C) 2021 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify @@ -16,36 +18,30 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads -import android.content.Context -import androidx.work.WorkManager -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase import com.owncloud.android.domain.files.model.OCFile.Companion.PATH_SEPARATOR +import com.owncloud.android.domain.transfers.TransferRepository class RetryUploadFromSystemUseCase( - private val context: Context, + private val uploadFilesFromSystemUseCase: UploadFilesFromSystemUseCase, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Params) { - - val uploadsStorageManager = UploadsStorageManager(context.contentResolver) - val failedUploads = uploadsStorageManager.failedUploads - val filteredUploads = failedUploads.filter { it.uploadId == params.uploadIdInStorageManager } - val uploadToRetry = filteredUploads.firstOrNull() + val uploadToRetry = transferRepository.getTransferById(params.uploadIdInStorageManager) uploadToRetry ?: return - val workManager = WorkManager.getInstance(context) - UploadFilesFromSystemUseCase(workManager).execute( + uploadFilesFromSystemUseCase.execute( UploadFilesFromSystemUseCase.Params( accountName = uploadToRetry.accountName, listOfLocalPaths = listOf(uploadToRetry.localPath), uploadFolderPath = uploadToRetry.remotePath.trimEnd(PATH_SEPARATOR), ) ) - uploadsStorageManager.updateUpload(uploadToRetry.apply { uploadStatus = UploadsStorageManager.UploadStatus.UPLOAD_IN_PROGRESS }) } data class Params( diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileInConflictUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileInConflictUseCase.kt index e5a4e516ff8..2a4fc50f384 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileInConflictUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFileInConflictUseCase.kt @@ -2,6 +2,8 @@ * ownCloud Android client application * * @author Abel García de Prada + * @author Juan Carlos Garrote Gascón + * * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify @@ -16,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import androidx.work.Constraints @@ -23,11 +26,11 @@ import androidx.work.NetworkType import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import androidx.work.workDataOf -import com.owncloud.android.MainApp -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase import com.owncloud.android.domain.camerauploads.model.UploadBehavior +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferStatus import com.owncloud.android.workers.UploadFileFromFileSystemWorker import timber.log.Timber import java.io.File @@ -42,6 +45,7 @@ import java.util.UUID */ class UploadFileInConflictUseCase( private val workManager: WorkManager, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Params): UUID? { @@ -73,17 +77,18 @@ class UploadFileInConflictUseCase( uploadPath: String, accountName: String, ): Long { - val uploadStorageManager = UploadsStorageManager(MainApp.appContext.contentResolver) - - val ocUpload = OCUpload(localFile.absolutePath, uploadPath, accountName).apply { - fileSize = localFile.length() - isForceOverwrite = true + val ocTransfer = OCTransfer( + localPath = localFile.absolutePath, + remotePath = uploadPath, + accountName = accountName, + fileSize = localFile.length(), + status = TransferStatus.TRANSFER_QUEUED, + localBehaviour = UploadBehavior.COPY.ordinal, + forceOverwrite = true, createdBy = UploadEnqueuedBy.ENQUEUED_BY_USER.ordinal - localAction = UploadBehavior.COPY.ordinal - uploadStatus = UploadsStorageManager.UploadStatus.UPLOAD_IN_PROGRESS - } + ) - return uploadStorageManager.storeUpload(ocUpload).also { + return transferRepository.storeTransfer(ocTransfer).also { Timber.i("Upload of $uploadPath has been stored in the uploads database with id: $it") } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFilesFromSAFUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFilesFromSAFUseCase.kt index c8b2f8aa9ef..cbf5d212a55 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFilesFromSAFUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFilesFromSAFUseCase.kt @@ -2,30 +2,34 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. - *

+ * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, * as published by the Free Software Foundation. - *

+ * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. - *

+ * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import android.net.Uri import androidx.documentfile.provider.DocumentFile import androidx.work.WorkManager import com.owncloud.android.MainApp -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase import com.owncloud.android.domain.camerauploads.model.UploadBehavior +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferStatus import timber.log.Timber import java.io.File @@ -38,6 +42,7 @@ import java.io.File */ class UploadFilesFromSAFUseCase( private val workManager: WorkManager, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Params) { @@ -70,17 +75,18 @@ class UploadFilesFromSAFUseCase( uploadPath: String, accountName: String, ): Long { - val uploadStorageManager = UploadsStorageManager(MainApp.appContext.contentResolver) - - val ocUpload = OCUpload(documentFile.uri.toString(), uploadPath, accountName).apply { - fileSize = documentFile.length() - isForceOverwrite = false + val ocTransfer = OCTransfer( + localPath = documentFile.uri.toString(), + remotePath = uploadPath, + accountName = accountName, + fileSize = documentFile.length(), + status = TransferStatus.TRANSFER_QUEUED, + localBehaviour = UploadBehavior.COPY.ordinal, + forceOverwrite = false, createdBy = UploadEnqueuedBy.ENQUEUED_BY_USER.ordinal - localAction = UploadBehavior.COPY.ordinal - uploadStatus = UploadsStorageManager.UploadStatus.UPLOAD_IN_PROGRESS - } + ) - return uploadStorageManager.storeUpload(ocUpload).also { + return transferRepository.storeTransfer(ocTransfer).also { Timber.i("Upload of $uploadPath has been stored in the uploads database with id: $it") } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFilesFromSystemUseCase.kt b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFilesFromSystemUseCase.kt index 25803589acc..c9912a1d152 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFilesFromSystemUseCase.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/usecases/transfers/uploads/UploadFilesFromSystemUseCase.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.usecases.transfers.uploads import androidx.work.Constraints @@ -23,11 +26,11 @@ import androidx.work.NetworkType import androidx.work.OneTimeWorkRequestBuilder import androidx.work.WorkManager import androidx.work.workDataOf -import com.owncloud.android.MainApp -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager import com.owncloud.android.domain.BaseUseCase import com.owncloud.android.domain.camerauploads.model.UploadBehavior +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferStatus import com.owncloud.android.workers.UploadFileFromFileSystemWorker import timber.log.Timber import java.io.File @@ -46,6 +49,7 @@ import java.io.File */ class UploadFilesFromSystemUseCase( private val workManager: WorkManager, + private val transferRepository: TransferRepository, ) : BaseUseCase() { override fun run(params: Params) { @@ -78,17 +82,18 @@ class UploadFilesFromSystemUseCase( uploadPath: String, accountName: String, ): Long { - val uploadStorageManager = UploadsStorageManager(MainApp.appContext.contentResolver) - - val ocUpload = OCUpload(localFile.absolutePath, uploadPath, accountName).apply { - fileSize = localFile.length() - isForceOverwrite = false + val ocTransfer = OCTransfer( + localPath = localFile.absolutePath, + remotePath = uploadPath, + accountName = accountName, + fileSize = localFile.length(), + status = TransferStatus.TRANSFER_QUEUED, + localBehaviour = UploadBehavior.MOVE.ordinal, + forceOverwrite = false, createdBy = UploadEnqueuedBy.ENQUEUED_BY_USER.ordinal - localAction = UploadBehavior.MOVE.ordinal - uploadStatus = UploadsStorageManager.UploadStatus.UPLOAD_IN_PROGRESS - } + ) - return uploadStorageManager.storeUpload(ocUpload).also { + return transferRepository.storeTransfer(ocTransfer).also { Timber.i("Upload of $uploadPath has been stored in the uploads database with id: $it") } } diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/CameraUploadsWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/CameraUploadsWorker.kt index db8fc4dcc17..d034326e9c5 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/workers/CameraUploadsWorker.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/workers/CameraUploadsWorker.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.workers import android.content.Context @@ -26,15 +29,15 @@ import androidx.work.CoroutineWorker import androidx.work.WorkManager import androidx.work.WorkerParameters import com.owncloud.android.R -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager -import com.owncloud.android.datamodel.UploadsStorageManager.UploadStatus import com.owncloud.android.domain.UseCaseResult import com.owncloud.android.domain.camerauploads.model.FolderBackUpConfiguration import com.owncloud.android.domain.camerauploads.model.UploadBehavior import com.owncloud.android.domain.camerauploads.usecases.GetCameraUploadsConfigurationUseCase import com.owncloud.android.domain.camerauploads.usecases.SavePictureUploadsConfigurationUseCase import com.owncloud.android.domain.camerauploads.usecases.SaveVideoUploadsConfigurationUseCase +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferStatus import com.owncloud.android.presentation.ui.settings.SettingsActivity import com.owncloud.android.usecases.transfers.uploads.UploadEnqueuedBy import com.owncloud.android.usecases.transfers.uploads.UploadFileFromContentUriUseCase @@ -69,6 +72,8 @@ class CameraUploadsWorker( private val getCameraUploadsConfigurationUseCase: GetCameraUploadsConfigurationUseCase by inject() + private val transferRepository: TransferRepository by inject() + override suspend fun doWork(): Result { when (val useCaseResult = getCameraUploadsConfigurationUseCase.execute(Unit)) { @@ -285,16 +290,18 @@ class CameraUploadsWorker( behavior: UploadBehavior, createdByWorker: Int ): Long { - val uploadStorageManager = UploadsStorageManager(appContext.contentResolver) - - val ocUpload = OCUpload(documentFile.uri.toString(), uploadPath, accountName).apply { - fileSize = documentFile.length() - isForceOverwrite = false + val ocTransfer = OCTransfer( + localPath = documentFile.uri.toString(), + remotePath = uploadPath, + accountName = accountName, + fileSize = documentFile.length(), + status = TransferStatus.TRANSFER_QUEUED, + localBehaviour = behavior.toLegacyLocalBehavior(), + forceOverwrite = false, createdBy = createdByWorker - localAction = behavior.toLegacyLocalBehavior() - uploadStatus = UploadStatus.UPLOAD_IN_PROGRESS - } - return uploadStorageManager.storeUpload(ocUpload) + ) + + return transferRepository.storeTransfer(ocTransfer) } companion object { diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt index d6718233c49..849cd3ad199 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromContentUriWorker.kt @@ -2,7 +2,9 @@ * ownCloud Android client application * * @author Abel García de Prada - * Copyright (C) 2021 ownCloud GmbH. + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2, @@ -16,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.workers import android.accounts.Account @@ -29,20 +32,12 @@ import androidx.work.workDataOf import com.owncloud.android.R import com.owncloud.android.authentication.AccountUtils import com.owncloud.android.data.executeRemoteOperation -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager -import com.owncloud.android.db.UploadResult import com.owncloud.android.domain.camerauploads.model.UploadBehavior -import com.owncloud.android.domain.exceptions.ConflictException -import com.owncloud.android.domain.exceptions.FileNotFoundException -import com.owncloud.android.domain.exceptions.ForbiddenException import com.owncloud.android.domain.exceptions.LocalFileNotFoundException -import com.owncloud.android.domain.exceptions.NoConnectionWithServerException -import com.owncloud.android.domain.exceptions.QuotaExceededException -import com.owncloud.android.domain.exceptions.SSLRecoverablePeerUnverifiedException -import com.owncloud.android.domain.exceptions.ServiceUnavailableException -import com.owncloud.android.domain.exceptions.SpecificUnsupportedMediaTypeException import com.owncloud.android.domain.exceptions.UnauthorizedException +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.TransferResult +import com.owncloud.android.domain.transfers.model.TransferStatus import com.owncloud.android.extensions.parseError import com.owncloud.android.lib.common.OwnCloudAccount import com.owncloud.android.lib.common.OwnCloudClient @@ -60,6 +55,7 @@ import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch import org.koin.core.component.KoinComponent +import org.koin.core.component.inject import timber.log.Timber import java.io.File @@ -80,10 +76,14 @@ class UploadFileFromContentUriWorker( private var lastPercent = 0 + private val transferRepository: TransferRepository by inject() + override suspend fun doWork(): Result { if (!areParametersValid()) return Result.failure() + transferRepository.updateTransferStatusToInProgressById(uploadIdInStorageManager) + return try { checkDocumentFileExists() checkPermissionsToReadDocumentAreGranted() @@ -176,23 +176,19 @@ class UploadFileFromContentUriWorker( } private fun updateUploadsDatabaseWithResult(throwable: Throwable?) { - val uploadStorageManager = UploadsStorageManager(appContext.contentResolver) - - val ocUpload = OCUpload(contentUri.toString(), uploadPath, account.name).apply { - uploadStatus = getUploadStatusForThrowable(throwable) - uploadEndTimestamp = System.currentTimeMillis() - lastResult = getUploadResultFromThrowable(throwable) - uploadId = uploadIdInStorageManager - } - - uploadStorageManager.updateUpload(ocUpload) + transferRepository.updateTransferWhenFinished( + id = uploadIdInStorageManager, + status = getUploadStatusForThrowable(throwable), + transferEndTimestamp = System.currentTimeMillis(), + lastResult = TransferResult.fromThrowable(throwable) + ) } - private fun getUploadStatusForThrowable(throwable: Throwable?): UploadsStorageManager.UploadStatus { + private fun getUploadStatusForThrowable(throwable: Throwable?): TransferStatus { return if (throwable == null) { - UploadsStorageManager.UploadStatus.UPLOAD_SUCCEEDED + TransferStatus.TRANSFER_SUCCEEDED } else { - UploadsStorageManager.UploadStatus.UPLOAD_FAILED + TransferStatus.TRANSFER_FAILED } } @@ -221,24 +217,6 @@ class UploadFileFromContentUriWorker( ) } - private fun getUploadResultFromThrowable(throwable: Throwable?): UploadResult { - if (throwable == null) return UploadResult.UPLOADED - - return when (throwable) { - is LocalFileNotFoundException -> UploadResult.FOLDER_ERROR - is NoConnectionWithServerException -> UploadResult.NETWORK_CONNECTION - is UnauthorizedException -> UploadResult.CREDENTIAL_ERROR - is FileNotFoundException -> UploadResult.FILE_NOT_FOUND - is ConflictException -> UploadResult.CONFLICT_ERROR - is ForbiddenException -> UploadResult.PRIVILEGES_ERROR - is ServiceUnavailableException -> UploadResult.SERVICE_UNAVAILABLE - is QuotaExceededException -> UploadResult.QUOTA_EXCEEDED - is SpecificUnsupportedMediaTypeException -> UploadResult.SPECIFIC_UNSUPPORTED_MEDIA_TYPE - is SSLRecoverablePeerUnverifiedException -> UploadResult.SSL_RECOVERABLE_PEER_UNVERIFIED - else -> UploadResult.UNKNOWN - } - } - private fun getClientForThisUpload(): OwnCloudClient = SingleSessionManager.getDefaultSingleton() .getClientFor(OwnCloudAccount(AccountUtils.getOwnCloudAccountByName(appContext, account.name), appContext), appContext, SingleSessionManager.getConnectionValidator()) diff --git a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromFileSystemWorker.kt b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromFileSystemWorker.kt index bb35b74e825..30eec9b1f7d 100644 --- a/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromFileSystemWorker.kt +++ b/owncloudApp/src/main/java/com/owncloud/android/workers/UploadFileFromFileSystemWorker.kt @@ -2,6 +2,8 @@ * ownCloud Android client application * * @author Abel García de Prada + * @author Juan Carlos Garrote Gascón + * * Copyright (C) 2022 ownCloud GmbH. *

* This program is free software: you can redistribute it and/or modify @@ -16,6 +18,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ + package com.owncloud.android.workers import android.accounts.Account @@ -26,24 +29,17 @@ import androidx.work.workDataOf import com.owncloud.android.R import com.owncloud.android.authentication.AccountUtils import com.owncloud.android.data.executeRemoteOperation -import com.owncloud.android.datamodel.OCUpload -import com.owncloud.android.datamodel.UploadsStorageManager -import com.owncloud.android.db.UploadResult import com.owncloud.android.domain.camerauploads.model.UploadBehavior import com.owncloud.android.domain.capabilities.usecases.GetStoredCapabilitiesUseCase -import com.owncloud.android.domain.exceptions.ConflictException -import com.owncloud.android.domain.exceptions.FileNotFoundException -import com.owncloud.android.domain.exceptions.ForbiddenException import com.owncloud.android.domain.exceptions.LocalFileNotFoundException -import com.owncloud.android.domain.exceptions.NoConnectionWithServerException -import com.owncloud.android.domain.exceptions.QuotaExceededException -import com.owncloud.android.domain.exceptions.SSLRecoverablePeerUnverifiedException -import com.owncloud.android.domain.exceptions.ServiceUnavailableException -import com.owncloud.android.domain.exceptions.SpecificUnsupportedMediaTypeException import com.owncloud.android.domain.exceptions.UnauthorizedException import com.owncloud.android.domain.files.model.OCFile.Companion.PATH_SEPARATOR import com.owncloud.android.domain.files.usecases.GetFileByRemotePathUseCase import com.owncloud.android.domain.files.usecases.SaveFileOrFolderUseCase +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferResult +import com.owncloud.android.domain.transfers.model.TransferStatus import com.owncloud.android.extensions.parseError import com.owncloud.android.lib.common.OwnCloudAccount import com.owncloud.android.lib.common.OwnCloudClient @@ -82,7 +78,7 @@ class UploadFileFromFileSystemWorker( private lateinit var uploadPath: String private lateinit var mimetype: String private var uploadIdInStorageManager: Long = -1 - private lateinit var ocUpload: OCUpload + private lateinit var ocTransfer: OCTransfer private var fileSize: Long = 0 private lateinit var uploadFileOperation: UploadFileFromFileSystemOperation @@ -93,10 +89,14 @@ class UploadFileFromFileSystemWorker( private var lastPercent = 0 + private val transferRepository: TransferRepository by inject() + override suspend fun doWork(): Result { if (!areParametersValid()) return Result.failure() + transferRepository.updateTransferStatusToInProgressById(uploadIdInStorageManager) + return try { checkPermissionsToReadDocumentAreGranted() checkParentFolderExistence() @@ -121,14 +121,14 @@ class UploadFileFromFileSystemWorker( */ private fun updateFilesDatabaseWithNewEtag() { val currentTime = System.currentTimeMillis() - if (ocUpload.isForceOverwrite) { + if (ocTransfer.forceOverwrite) { val getFileByRemotePathUseCase: GetFileByRemotePathUseCase by inject() - val file = getFileByRemotePathUseCase.execute(GetFileByRemotePathUseCase.Params(account.name, ocUpload.remotePath)) - file.getDataOrNull()?.let { - it.copy( + val file = getFileByRemotePathUseCase.execute(GetFileByRemotePathUseCase.Params(account.name, ocTransfer.remotePath)) + file.getDataOrNull()?.let { ocFile -> + ocFile.copy( needsToUpdateThumbnail = true, etag = uploadFileOperation.etag, - length = (File(ocUpload.localPath).length()), + length = (File(ocTransfer.localPath).length()), lastSyncDateForData = currentTime, modifiedAtLastSyncForData = currentTime, etagInConflict = null @@ -153,17 +153,13 @@ class UploadFileFromFileSystemWorker( behavior = paramBehavior?.let { UploadBehavior.valueOf(it) } ?: return false lastModified = paramLastModified ?: return false uploadIdInStorageManager = paramUploadId.takeUnless { it == -1L } ?: return false - ocUpload = retrieveUploadInfoFromDatabase() ?: return false + ocTransfer = retrieveUploadInfoFromDatabase() ?: return false return true } - private fun retrieveUploadInfoFromDatabase(): OCUpload? { - val uploadStorageManager = UploadsStorageManager(appContext.contentResolver) - - val storedUploads = uploadStorageManager.allStoredUploads - - return storedUploads.find { uploadIdInStorageManager == it.uploadId }.also { + private fun retrieveUploadInfoFromDatabase(): OCTransfer? { + return transferRepository.getTransferById(uploadIdInStorageManager).also { if (it != null) { Timber.d("Upload with id ($uploadIdInStorageManager) has been found in database.") Timber.d("Upload info: $it") @@ -197,10 +193,10 @@ class UploadFileFromFileSystemWorker( } private fun checkNameCollisionOrGetAnAvailableOneInCase() { - if (ocUpload.isForceOverwrite) { + if (ocTransfer.forceOverwrite) { val getFileByRemotePathUseCase: GetFileByRemotePathUseCase by inject() - val useCaseResult = getFileByRemotePathUseCase.execute(GetFileByRemotePathUseCase.Params(ocUpload.accountName, ocUpload.remotePath)) + val useCaseResult = getFileByRemotePathUseCase.execute(GetFileByRemotePathUseCase.Params(ocTransfer.accountName, ocTransfer.remotePath)) eTagInConflict = useCaseResult.getDataOrNull()?.etagInConflict.orEmpty() @@ -292,23 +288,19 @@ class UploadFileFromFileSystemWorker( } private fun updateUploadsDatabaseWithResult(throwable: Throwable?) { - val uploadStorageManager = UploadsStorageManager(appContext.contentResolver) - - val ocUpload = OCUpload(fileSystemPath, uploadPath, account.name).apply { - uploadStatus = getUploadStatusForThrowable(throwable) - uploadEndTimestamp = System.currentTimeMillis() - lastResult = getUploadResultFromThrowable(throwable) - uploadId = uploadIdInStorageManager - } - - uploadStorageManager.updateUpload(ocUpload) + transferRepository.updateTransferWhenFinished( + id = uploadIdInStorageManager, + status = getUploadStatusForThrowable(throwable), + transferEndTimestamp = System.currentTimeMillis(), + lastResult = TransferResult.fromThrowable(throwable) + ) } - private fun getUploadStatusForThrowable(throwable: Throwable?): UploadsStorageManager.UploadStatus { + private fun getUploadStatusForThrowable(throwable: Throwable?): TransferStatus { return if (throwable == null) { - UploadsStorageManager.UploadStatus.UPLOAD_SUCCEEDED + TransferStatus.TRANSFER_SUCCEEDED } else { - UploadsStorageManager.UploadStatus.UPLOAD_FAILED + TransferStatus.TRANSFER_FAILED } } @@ -337,24 +329,6 @@ class UploadFileFromFileSystemWorker( ) } - private fun getUploadResultFromThrowable(throwable: Throwable?): UploadResult { - if (throwable == null) return UploadResult.UPLOADED - - return when (throwable) { - is LocalFileNotFoundException -> UploadResult.FOLDER_ERROR - is NoConnectionWithServerException -> UploadResult.NETWORK_CONNECTION - is UnauthorizedException -> UploadResult.CREDENTIAL_ERROR - is FileNotFoundException -> UploadResult.FILE_NOT_FOUND - is ConflictException -> UploadResult.CONFLICT_ERROR - is ForbiddenException -> UploadResult.PRIVILEGES_ERROR - is ServiceUnavailableException -> UploadResult.SERVICE_UNAVAILABLE - is QuotaExceededException -> UploadResult.QUOTA_EXCEEDED - is SpecificUnsupportedMediaTypeException -> UploadResult.SPECIFIC_UNSUPPORTED_MEDIA_TYPE - is SSLRecoverablePeerUnverifiedException -> UploadResult.SSL_RECOVERABLE_PEER_UNVERIFIED - else -> UploadResult.UNKNOWN - } - } - private fun getClientForThisUpload(): OwnCloudClient = SingleSessionManager.getDefaultSingleton() .getClientFor(OwnCloudAccount(AccountUtils.getOwnCloudAccountByName(appContext, account.name), appContext), appContext) diff --git a/owncloudData/schemas/com.owncloud.android.data.OwncloudDatabase/37.json b/owncloudData/schemas/com.owncloud.android.data.OwncloudDatabase/37.json index 2d78e30c5f1..f5656ed89be 100644 --- a/owncloudData/schemas/com.owncloud.android.data.OwncloudDatabase/37.json +++ b/owncloudData/schemas/com.owncloud.android.data.OwncloudDatabase/37.json @@ -2,7 +2,7 @@ "formatVersion": 1, "database": { "version": 37, - "identityHash": "421a3f1cccacb7dcb64727953f7d8616", + "identityHash": "38c32b00476bbb19c99051fd0c32d0ce", "entities": [ { "tableName": "folder_backup", @@ -571,12 +571,98 @@ }, "indices": [], "foreignKeys": [] + }, + { + "tableName": "transfers", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`localPath` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `accountName` TEXT NOT NULL, `fileSize` INTEGER NOT NULL, `status` INTEGER NOT NULL, `localBehaviour` INTEGER NOT NULL, `forceOverwrite` INTEGER NOT NULL, `transferEndTimestamp` INTEGER, `lastResult` INTEGER, `createdBy` INTEGER NOT NULL, `transferId` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)", + "fields": [ + { + "fieldPath": "localPath", + "columnName": "localPath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "remotePath", + "columnName": "remotePath", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "accountName", + "columnName": "accountName", + "affinity": "TEXT", + "notNull": true + }, + { + "fieldPath": "fileSize", + "columnName": "fileSize", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "status", + "columnName": "status", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "localBehaviour", + "columnName": "localBehaviour", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "forceOverwrite", + "columnName": "forceOverwrite", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "transferEndTimestamp", + "columnName": "transferEndTimestamp", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "lastResult", + "columnName": "lastResult", + "affinity": "INTEGER", + "notNull": false + }, + { + "fieldPath": "createdBy", + "columnName": "createdBy", + "affinity": "INTEGER", + "notNull": true + }, + { + "fieldPath": "transferId", + "columnName": "transferId", + "affinity": "TEXT", + "notNull": false + }, + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + } + ], + "primaryKey": { + "columnNames": [ + "id" + ], + "autoGenerate": true + }, + "indices": [], + "foreignKeys": [] } ], "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '421a3f1cccacb7dcb64727953f7d8616')" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '38c32b00476bbb19c99051fd0c32d0ce')" ] } } \ No newline at end of file diff --git a/owncloudData/src/main/java/com/owncloud/android/data/OwncloudDatabase.kt b/owncloudData/src/main/java/com/owncloud/android/data/OwncloudDatabase.kt index 66b6fad7830..17b67a06601 100644 --- a/owncloudData/src/main/java/com/owncloud/android/data/OwncloudDatabase.kt +++ b/owncloudData/src/main/java/com/owncloud/android/data/OwncloudDatabase.kt @@ -45,6 +45,8 @@ import com.owncloud.android.data.migrations.MIGRATION_35_36 import com.owncloud.android.data.migrations.MIGRATION_36_37 import com.owncloud.android.data.sharing.shares.db.OCShareDao import com.owncloud.android.data.sharing.shares.db.OCShareEntity +import com.owncloud.android.data.transfers.db.OCTransferEntity +import com.owncloud.android.data.transfers.db.TransferDao import com.owncloud.android.data.user.db.UserDao import com.owncloud.android.data.user.db.UserQuotaEntity @@ -55,6 +57,7 @@ import com.owncloud.android.data.user.db.UserQuotaEntity OCFileEntity::class, OCShareEntity::class, UserQuotaEntity::class, + OCTransferEntity::class, ], version = ProviderMeta.DB_VERSION, exportSchema = true @@ -65,6 +68,7 @@ abstract class OwncloudDatabase : RoomDatabase() { abstract fun folderBackUpDao(): FolderBackupDao abstract fun shareDao(): OCShareDao abstract fun userDao(): UserDao + abstract fun transferDao(): TransferDao companion object { @Volatile diff --git a/owncloudData/src/main/java/com/owncloud/android/data/ProviderMeta.java b/owncloudData/src/main/java/com/owncloud/android/data/ProviderMeta.java index 151c93ea176..f4fe04c35c6 100644 --- a/owncloudData/src/main/java/com/owncloud/android/data/ProviderMeta.java +++ b/owncloudData/src/main/java/com/owncloud/android/data/ProviderMeta.java @@ -42,6 +42,7 @@ static public class ProviderTableMeta implements BaseColumns { public static final String FILES_TABLE_NAME = "files"; public static final String USER_QUOTAS_TABLE_NAME = "user_quotas"; public static final String FOLDER_BACKUP_TABLE_NAME = "folder_backup"; + public static final String TRANSFERS_TABLE_NAME = "transfers"; // Columns of ocshares table public static final String OCSHARES_SHARE_TYPE = "share_type"; diff --git a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_37.kt b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_37.kt index bf2eec8b5a0..a0832a6a107 100644 --- a/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_37.kt +++ b/owncloudData/src/main/java/com/owncloud/android/data/migrations/Migration_37.kt @@ -24,5 +24,6 @@ import androidx.sqlite.db.SupportSQLiteDatabase val MIGRATION_36_37 = object : Migration(36, 37) { override fun migrate(database: SupportSQLiteDatabase) { database.execSQL("CREATE TABLE IF NOT EXISTS `files` (`id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `parentId` INTEGER, `owner` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `remoteId` TEXT, `length` INTEGER NOT NULL, `creationTimestamp` INTEGER, `modificationTimestamp` INTEGER NOT NULL, `mimeType` TEXT NOT NULL, `etag` TEXT, `permissions` TEXT, `privateLink` TEXT, `storagePath` TEXT, `name` TEXT, `treeEtag` TEXT, `keepInSync` INTEGER, `lastSyncDateForData` INTEGER, `fileShareViaLink` INTEGER, `lastSyncDateForProperties` INTEGER, `needsToUpdateThumbnail` INTEGER NOT NULL, `modifiedAtLastSyncForData` INTEGER, `etagInConflict` TEXT, `fileIsDownloading` INTEGER, `sharedWithSharee` INTEGER, `sharedByLink` INTEGER NOT NULL)") + database.execSQL("CREATE TABLE IF NOT EXISTS `transfers` (`localPath` TEXT NOT NULL, `remotePath` TEXT NOT NULL, `accountName` TEXT NOT NULL, `fileSize` INTEGER NOT NULL, `status` INTEGER NOT NULL, `localBehaviour` INTEGER NOT NULL, `forceOverwrite` INTEGER NOT NULL, `transferEndTimestamp` INTEGER, `lastResult` INTEGER, `createdBy` INTEGER NOT NULL, `transferId` TEXT, `id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL)") } } diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/LocalTransferDataSource.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/LocalTransferDataSource.kt new file mode 100644 index 00000000000..c24bb4b929c --- /dev/null +++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/LocalTransferDataSource.kt @@ -0,0 +1,47 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.data.transfers.datasources + +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferResult +import com.owncloud.android.domain.transfers.model.TransferStatus + +interface LocalTransferDataSource { + fun storeTransfer(transfer: OCTransfer): Long + fun updateTransfer(transfer: OCTransfer) + fun updateTransferStatusToInProgressById(id: Long) + fun updateTransferWhenFinished( + id: Long, + status: TransferStatus, + transferEndTimestamp: Long, + lastResult: TransferResult + ) + fun removeTransferById(id: Long) + fun removeAllTransfersFromAccount(accountName: String) + fun getTransferById(id: Long): OCTransfer? + fun getAllTransfers(): List + fun getLastTransferFor(remotePath: String, accountName: String): OCTransfer? + fun getCurrentAndPendingTransfers(): List + fun getFailedTransfers(): List + fun getFinishedTransfers(): List + fun clearFailedTransfers() + fun clearSuccessfulTransfers() +} diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSource.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSource.kt new file mode 100644 index 00000000000..fb5230441c3 --- /dev/null +++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/datasources/implementation/OCLocalTransferDataSource.kt @@ -0,0 +1,129 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.data.transfers.datasources.implementation + +import com.owncloud.android.data.transfers.datasources.LocalTransferDataSource +import com.owncloud.android.data.transfers.db.OCTransferEntity +import com.owncloud.android.data.transfers.db.TransferDao +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferResult +import com.owncloud.android.domain.transfers.model.TransferStatus + +class OCLocalTransferDataSource( + private val transferDao: TransferDao +) : LocalTransferDataSource { + override fun storeTransfer(transfer: OCTransfer): Long { + return transferDao.insert(transfer.toEntity()) + } + + override fun updateTransfer(transfer: OCTransfer) { + transferDao.insert(transfer.toEntity()) + } + + override fun updateTransferStatusToInProgressById(id: Long) { + transferDao.updateTransferStatusWithId(id, TransferStatus.TRANSFER_IN_PROGRESS.value) + } + + override fun updateTransferWhenFinished( + id: Long, + status: TransferStatus, + transferEndTimestamp: Long, + lastResult: TransferResult + ) { + transferDao.updateTransferWhenFinished(id, status.value, transferEndTimestamp, lastResult.value) + } + + override fun removeTransferById(id: Long) { + transferDao.deleteTransferWithId(id) + } + + override fun removeAllTransfersFromAccount(accountName: String) { + transferDao.deleteTransfersWithAccountName(accountName) + } + + override fun getTransferById(id: Long): OCTransfer? { + return transferDao.getTransferWithId(id)?.toModel() + } + + override fun getAllTransfers(): List { + return transferDao.getAllTransfers().map { it.toModel() } + } + + override fun getLastTransferFor(remotePath: String, accountName: String): OCTransfer? { + return transferDao.getLastTransferWithRemotePathAndAccountName(remotePath, accountName)?.toModel() + } + + override fun getCurrentAndPendingTransfers(): List { + return transferDao.getTransfersWithStatus( + listOf(TransferStatus.TRANSFER_IN_PROGRESS.value, TransferStatus.TRANSFER_QUEUED.value) + ).map { it.toModel() } + } + + override fun getFailedTransfers(): List { + return transferDao.getTransfersWithStatus( + listOf(TransferStatus.TRANSFER_FAILED.value) + ).map { it.toModel() } + } + + override fun getFinishedTransfers(): List { + return transferDao.getTransfersWithStatus( + listOf(TransferStatus.TRANSFER_SUCCEEDED.value) + ).map { it.toModel() } + } + + override fun clearFailedTransfers() { + transferDao.deleteTransfersWithStatus(TransferStatus.TRANSFER_FAILED.value) + } + + override fun clearSuccessfulTransfers() { + transferDao.deleteTransfersWithStatus(TransferStatus.TRANSFER_SUCCEEDED.value) + } + + private fun OCTransferEntity.toModel() = OCTransfer( + id = id, + localPath = localPath, + remotePath = remotePath, + accountName = accountName, + fileSize = fileSize, + status = TransferStatus.fromValue(status), + localBehaviour = localBehaviour, + forceOverwrite = forceOverwrite, + transferEndTimestamp = transferEndTimestamp, + lastResult = lastResult?.let { TransferResult.fromValue(it) }, + createdBy = createdBy, + transferId = transferId + ) + + private fun OCTransfer.toEntity() = OCTransferEntity( + localPath = localPath, + remotePath = remotePath, + accountName = accountName, + fileSize = fileSize, + status = status.value, + localBehaviour = localBehaviour, + forceOverwrite = forceOverwrite, + transferEndTimestamp = transferEndTimestamp, + lastResult = lastResult?.value, + createdBy = createdBy, + transferId = transferId + ).apply { this@toEntity.id?.let { this.id = it } } + +} diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/OCTransferEntity.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/OCTransferEntity.kt new file mode 100644 index 00000000000..f2fc9c2f927 --- /dev/null +++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/OCTransferEntity.kt @@ -0,0 +1,45 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.data.transfers.db + +import androidx.room.Entity +import androidx.room.PrimaryKey +import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.TRANSFERS_TABLE_NAME + +@Entity( + tableName = TRANSFERS_TABLE_NAME +) +data class OCTransferEntity( + val localPath: String, + val remotePath: String, + val accountName: String, + val fileSize: Long, + val status: Int, + val localBehaviour: Int, + val forceOverwrite: Boolean, + val transferEndTimestamp: Long? = null, + val lastResult: Int? = null, + val createdBy: Int, + val transferId: String? = null +) { + @PrimaryKey(autoGenerate = true) + var id: Long = 0 +} diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/TransferDao.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/TransferDao.kt new file mode 100644 index 00000000000..9641d358592 --- /dev/null +++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/db/TransferDao.kt @@ -0,0 +1,107 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.data.transfers.db + +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import com.owncloud.android.data.ProviderMeta.ProviderTableMeta.TRANSFERS_TABLE_NAME + +@Dao +abstract class TransferDao { + @Query(SELECT_TRANSFER_WITH_ID) + abstract fun getTransferWithId(id: Long): OCTransferEntity? + + @Query(SELECT_LAST_TRANSFER_WITH_REMOTE_PATH_AND_ACCOUNT_NAME) + abstract fun getLastTransferWithRemotePathAndAccountName(remotePath: String, accountName: String): OCTransferEntity? + + @Query(SELECT_TRANSFERS_WITH_STATUS) + abstract fun getTransfersWithStatus(status: List): List + + @Query(SELECT_ALL_TRANSFERS) + abstract fun getAllTransfers(): List + + @Insert(onConflict = OnConflictStrategy.REPLACE) + abstract fun insert(ocTransferEntity: OCTransferEntity): Long + + @Query(UPDATE_TRANSFER_STATUS_WITH_ID) + abstract fun updateTransferStatusWithId(id: Long, newStatus: Int) + + @Query(UPDATE_TRANSFER_WHEN_FINISHED) + abstract fun updateTransferWhenFinished(id: Long, status: Int, transferEndTimestamp: Long, lastResult: Int) + + @Query(DELETE_TRANSFER_WITH_ID) + abstract fun deleteTransferWithId(id: Long) + + @Query(DELETE_TRANSFERS_WITH_ACCOUNT_NAME) + abstract fun deleteTransfersWithAccountName(accountName: String) + + @Query(DELETE_TRANSFERS_WITH_STATUS) + abstract fun deleteTransfersWithStatus(status: Int) + + companion object { + private const val SELECT_TRANSFER_WITH_ID = + "SELECT * " + + "FROM $TRANSFERS_TABLE_NAME " + + "WHERE id = :id" + + private const val SELECT_LAST_TRANSFER_WITH_REMOTE_PATH_AND_ACCOUNT_NAME = + "SELECT * " + + "FROM $TRANSFERS_TABLE_NAME " + + "WHERE remotePath = :remotePath AND accountName = :accountName " + + "ORDER BY transferEndTimestamp DESC " + + "LIMIT 1" + + private const val SELECT_TRANSFERS_WITH_STATUS = + "SELECT * " + + "FROM $TRANSFERS_TABLE_NAME " + + "WHERE status IN (:status)" + + private const val SELECT_ALL_TRANSFERS = + "SELECT * " + + "FROM $TRANSFERS_TABLE_NAME " + + private const val UPDATE_TRANSFER_STATUS_WITH_ID = + "UPDATE $TRANSFERS_TABLE_NAME " + + "SET status = :newStatus " + + "WHERE id = :id" + + private const val UPDATE_TRANSFER_WHEN_FINISHED = + "UPDATE $TRANSFERS_TABLE_NAME " + + "SET status = :status, " + + "transferEndTimestamp = :transferEndTimestamp," + + "lastResult = :lastResult " + + "WHERE id = :id" + + private const val DELETE_TRANSFER_WITH_ID = + "DELETE FROM $TRANSFERS_TABLE_NAME " + + "WHERE id = :id" + + private const val DELETE_TRANSFERS_WITH_ACCOUNT_NAME = + "DELETE FROM $TRANSFERS_TABLE_NAME " + + "WHERE accountName = :accountName" + + private const val DELETE_TRANSFERS_WITH_STATUS = + "DELETE FROM $TRANSFERS_TABLE_NAME " + + "WHERE status = :status" + } +} diff --git a/owncloudData/src/main/java/com/owncloud/android/data/transfers/repository/OCTransferRepository.kt b/owncloudData/src/main/java/com/owncloud/android/data/transfers/repository/OCTransferRepository.kt new file mode 100644 index 00000000000..16103c337d5 --- /dev/null +++ b/owncloudData/src/main/java/com/owncloud/android/data/transfers/repository/OCTransferRepository.kt @@ -0,0 +1,85 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.data.transfers.repository + +import com.owncloud.android.data.transfers.datasources.LocalTransferDataSource +import com.owncloud.android.domain.transfers.TransferRepository +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferResult +import com.owncloud.android.domain.transfers.model.TransferStatus + +class OCTransferRepository( + private val localTransferDataSource: LocalTransferDataSource +) : TransferRepository { + override fun storeTransfer(transfer: OCTransfer) = + localTransferDataSource.storeTransfer(transfer = transfer) + + override fun updateTransfer(transfer: OCTransfer) = + localTransferDataSource.updateTransfer(transfer = transfer) + + override fun updateTransferStatusToInProgressById(id: Long) { + localTransferDataSource.updateTransferStatusToInProgressById(id = id) + } + + override fun updateTransferWhenFinished( + id: Long, + status: TransferStatus, + transferEndTimestamp: Long, + lastResult: TransferResult + ) { + localTransferDataSource.updateTransferWhenFinished( + id = id, + status = status, + transferEndTimestamp = transferEndTimestamp, + lastResult = lastResult + ) + } + + override fun removeTransferById(id: Long) = + localTransferDataSource.removeTransferById(id = id) + + override fun removeAllTransfersFromAccount(accountName: String) = + localTransferDataSource.removeAllTransfersFromAccount(accountName = accountName) + + override fun getTransferById(id: Long): OCTransfer? = + localTransferDataSource.getTransferById(id = id) + + override fun getAllTransfers(): List = + localTransferDataSource.getAllTransfers() + + override fun getLastTransferFor(remotePath: String, accountName: String) = + localTransferDataSource.getLastTransferFor(remotePath = remotePath, accountName = accountName) + + override fun getCurrentAndPendingTransfers() = + localTransferDataSource.getCurrentAndPendingTransfers() + + override fun getFailedTransfers() = + localTransferDataSource.getFailedTransfers() + + override fun getFinishedTransfers() = + localTransferDataSource.getFinishedTransfers() + + override fun clearFailedTransfers() = + localTransferDataSource.clearFailedTransfers() + + override fun clearSuccessfulTransfers() = + localTransferDataSource.clearSuccessfulTransfers() +} diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/TransferRepository.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/TransferRepository.kt new file mode 100644 index 00000000000..9ca4238ae1c --- /dev/null +++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/TransferRepository.kt @@ -0,0 +1,47 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.domain.transfers + +import com.owncloud.android.domain.transfers.model.OCTransfer +import com.owncloud.android.domain.transfers.model.TransferResult +import com.owncloud.android.domain.transfers.model.TransferStatus + +interface TransferRepository { + fun storeTransfer(transfer: OCTransfer): Long + fun updateTransfer(transfer: OCTransfer) + fun updateTransferStatusToInProgressById(id: Long) + fun updateTransferWhenFinished( + id: Long, + status: TransferStatus, + transferEndTimestamp: Long, + lastResult: TransferResult + ) + fun removeTransferById(id: Long) + fun removeAllTransfersFromAccount(accountName: String) + fun getTransferById(id: Long): OCTransfer? + fun getAllTransfers(): List + fun getLastTransferFor(remotePath: String, accountName: String): OCTransfer? + fun getCurrentAndPendingTransfers(): List + fun getFailedTransfers(): List + fun getFinishedTransfers(): List + fun clearFailedTransfers() + fun clearSuccessfulTransfers() +} diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/OCTransfer.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/OCTransfer.kt new file mode 100644 index 00000000000..a789373cd20 --- /dev/null +++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/OCTransfer.kt @@ -0,0 +1,46 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.domain.transfers.model + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize +import java.io.File + +@Parcelize +data class OCTransfer( + var id: Long? = null, + val localPath: String, + val remotePath: String, + val accountName: String, + val fileSize: Long, + var status: TransferStatus, + val localBehaviour: Int, + val forceOverwrite: Boolean, + val transferEndTimestamp: Long? = null, + val lastResult: TransferResult? = null, + val createdBy: Int, + val transferId: String? = null +) : Parcelable { + init { + if (!remotePath.startsWith(File.separator)) throw IllegalArgumentException("Remote path must be an absolute path in the local file system") + if (accountName.isEmpty()) throw IllegalArgumentException("Invalid account name") + } +} diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/TransferResult.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/TransferResult.kt new file mode 100644 index 00000000000..5986744fe4b --- /dev/null +++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/TransferResult.kt @@ -0,0 +1,96 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.domain.transfers.model + +import com.owncloud.android.domain.exceptions.ConflictException +import com.owncloud.android.domain.exceptions.FileNotFoundException +import com.owncloud.android.domain.exceptions.ForbiddenException +import com.owncloud.android.domain.exceptions.LocalFileNotFoundException +import com.owncloud.android.domain.exceptions.NoConnectionWithServerException +import com.owncloud.android.domain.exceptions.QuotaExceededException +import com.owncloud.android.domain.exceptions.SSLRecoverablePeerUnverifiedException +import com.owncloud.android.domain.exceptions.ServiceUnavailableException +import com.owncloud.android.domain.exceptions.SpecificUnsupportedMediaTypeException +import com.owncloud.android.domain.exceptions.UnauthorizedException + +enum class TransferResult constructor(val value: Int) { + UNKNOWN(value = -1), + UPLOADED(value = 0), + NETWORK_CONNECTION(value = 1), + CREDENTIAL_ERROR(value = 2), + FOLDER_ERROR(value = 3), + CONFLICT_ERROR(value = 4), + FILE_ERROR(value = 5), + PRIVILEGES_ERROR(value = 6), + CANCELLED(value = 7), + FILE_NOT_FOUND(value = 8), + DELAYED_FOR_WIFI(value = 9), + SERVICE_INTERRUPTED(value = 10), + SERVICE_UNAVAILABLE(value = 11), + QUOTA_EXCEEDED(value = 12), + SSL_RECOVERABLE_PEER_UNVERIFIED(value = 13), + SPECIFIC_FORBIDDEN(value = 14), + SPECIFIC_SERVICE_UNAVAILABLE(value = 15), + SPECIFIC_UNSUPPORTED_MEDIA_TYPE(value = 16); + + companion object { + fun fromValue(value: Int): TransferResult = + when (value) { + 0 -> UPLOADED + 1 -> NETWORK_CONNECTION + 2 -> CREDENTIAL_ERROR + 3 -> FOLDER_ERROR + 4 -> CONFLICT_ERROR + 5 -> FILE_ERROR + 6 -> PRIVILEGES_ERROR + 7 -> CANCELLED + 8 -> FILE_NOT_FOUND + 9 -> DELAYED_FOR_WIFI + 10 -> SERVICE_INTERRUPTED + 11 -> SERVICE_UNAVAILABLE + 12 -> QUOTA_EXCEEDED + 13 -> SSL_RECOVERABLE_PEER_UNVERIFIED + 14 -> SPECIFIC_FORBIDDEN + 15 -> SPECIFIC_SERVICE_UNAVAILABLE + 16 -> SPECIFIC_UNSUPPORTED_MEDIA_TYPE + else -> UNKNOWN + } + + fun fromThrowable(throwable: Throwable?): TransferResult { + if (throwable == null) return UPLOADED + + return when (throwable) { + is LocalFileNotFoundException -> FOLDER_ERROR + is NoConnectionWithServerException -> NETWORK_CONNECTION + is UnauthorizedException -> CREDENTIAL_ERROR + is FileNotFoundException -> FILE_NOT_FOUND + is ConflictException -> CONFLICT_ERROR + is ForbiddenException -> PRIVILEGES_ERROR + is ServiceUnavailableException -> SERVICE_UNAVAILABLE + is QuotaExceededException -> QUOTA_EXCEEDED + is SpecificUnsupportedMediaTypeException -> SPECIFIC_UNSUPPORTED_MEDIA_TYPE + is SSLRecoverablePeerUnverifiedException -> SSL_RECOVERABLE_PEER_UNVERIFIED + else -> UNKNOWN + } + } + + } +} diff --git a/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/TransferStatus.kt b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/TransferStatus.kt new file mode 100644 index 00000000000..3d6ef56fd98 --- /dev/null +++ b/owncloudDomain/src/main/java/com/owncloud/android/domain/transfers/model/TransferStatus.kt @@ -0,0 +1,38 @@ +/** + * ownCloud Android client application + * + * @author Juan Carlos Garrote Gascón + * + * Copyright (C) 2022 ownCloud GmbH. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package com.owncloud.android.domain.transfers.model + +enum class TransferStatus constructor(val value: Int) { + TRANSFER_QUEUED(value = 0), + TRANSFER_IN_PROGRESS(value = 1), + TRANSFER_FAILED(value = 2), + TRANSFER_SUCCEEDED(value = 3); + + companion object { + fun fromValue(value: Int): TransferStatus = + when (value) { + 0 -> TRANSFER_QUEUED + 1 -> TRANSFER_IN_PROGRESS + 2 -> TRANSFER_FAILED + else -> TRANSFER_SUCCEEDED + } + } +}