Merge remote-tracking branch 'origin/master' into dev

This commit is contained in:
Tobias Kaminsky 2024-09-20 02:30:59 +02:00
commit 73adb880c7
6 changed files with 78 additions and 13 deletions

View file

@ -39,6 +39,8 @@ import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import java.io.File import java.io.File
import java.util.concurrent.CompletableFuture
import java.util.concurrent.ExecutionException
import java.util.concurrent.Semaphore import java.util.concurrent.Semaphore
import javax.inject.Inject import javax.inject.Inject
@ -57,6 +59,8 @@ class FileUploadHelper {
@Inject @Inject
lateinit var fileStorageManager: FileDataStorageManager lateinit var fileStorageManager: FileDataStorageManager
private val ioScope = CoroutineScope(Dispatchers.IO)
init { init {
MainApp.getAppComponent().inject(this) MainApp.getAppComponent().inject(this)
} }
@ -231,6 +235,7 @@ class FileUploadHelper {
} }
fun cancelFileUpload(remotePath: String, accountName: String) { fun cancelFileUpload(remotePath: String, accountName: String) {
ioScope.launch {
val upload = uploadsStorageManager.getUploadByRemotePath(remotePath) val upload = uploadsStorageManager.getUploadByRemotePath(remotePath)
if (upload != null) { if (upload != null) {
cancelFileUploads(listOf(upload), accountName) cancelFileUploads(listOf(upload), accountName)
@ -238,6 +243,7 @@ class FileUploadHelper {
Log_OC.e(TAG, "Error cancelling current upload because upload does not exist!") Log_OC.e(TAG, "Error cancelling current upload because upload does not exist!")
} }
} }
}
fun cancelFileUploads(uploads: List<OCUpload>, accountName: String) { fun cancelFileUploads(uploads: List<OCUpload>, accountName: String) {
for (upload in uploads) { for (upload in uploads) {
@ -266,8 +272,21 @@ class FileUploadHelper {
return false return false
} }
val upload: OCUpload = uploadsStorageManager.getUploadByRemotePath(file.remotePath) ?: return false val uploadCompletableFuture = CompletableFuture.supplyAsync {
return upload.uploadStatus == UploadStatus.UPLOAD_IN_PROGRESS uploadsStorageManager.getUploadByRemotePath(file.remotePath)
}
return try {
val upload = uploadCompletableFuture.get()
if (upload != null) {
upload.uploadStatus == UploadStatus.UPLOAD_IN_PROGRESS
} else {
false
}
} catch (e: ExecutionException) {
false
} catch (e: InterruptedException) {
false
}
} }
private fun checkConnectivity(connectivityService: ConnectivityService): Boolean { private fun checkConnectivity(connectivityService: ConnectivityService): Boolean {

View file

@ -10,6 +10,7 @@ package com.nextcloud.client.jobs.upload
import android.app.PendingIntent import android.app.PendingIntent
import android.content.Context import android.content.Context
import com.nextcloud.client.jobs.notification.WorkerNotificationManager import com.nextcloud.client.jobs.notification.WorkerNotificationManager
import com.nextcloud.utils.extensions.isFileSpecificError
import com.owncloud.android.R import com.owncloud.android.R
import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.operations.UploadFileOperation import com.owncloud.android.operations.UploadFileOperation
@ -107,7 +108,11 @@ class UploadNotificationManager(private val context: Context, viewThemeUtils: Vi
setContentText(errorMessage) setContentText(errorMessage)
} }
if (resultCode.isFileSpecificError()) {
showNewNotification(uploadFileOperation) showNewNotification(uploadFileOperation)
} else {
showNotification()
}
} }
private fun getFailedResultTitleId(resultCode: RemoteOperationResult.ResultCode): Int { private fun getFailedResultTitleId(resultCode: RemoteOperationResult.ResultCode): Int {

View file

@ -0,0 +1,18 @@
/*
* Nextcloud - Android Client
*
* SPDX-FileCopyrightText: 2024 Alper Ozturk <alper.ozturk@nextcloud.com>
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
package com.nextcloud.utils.extensions
import androidx.fragment.app.Fragment
inline fun <reified T : Any> Fragment.typedActivity(): T? {
return if (isAdded && activity != null && activity is T) {
activity as T
} else {
null
}
}

View file

@ -14,6 +14,7 @@ import com.owncloud.android.datamodel.FileDataStorageManager
import com.owncloud.android.datamodel.OCFile import com.owncloud.android.datamodel.OCFile
import com.owncloud.android.lib.common.operations.RemoteOperation import com.owncloud.android.lib.common.operations.RemoteOperation
import com.owncloud.android.lib.common.operations.RemoteOperationResult import com.owncloud.android.lib.common.operations.RemoteOperationResult
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode
import com.owncloud.android.lib.resources.files.model.RemoteFile import com.owncloud.android.lib.resources.files.model.RemoteFile
import com.owncloud.android.utils.ErrorMessageAdapter import com.owncloud.android.utils.ErrorMessageAdapter
import com.owncloud.android.utils.FileStorageUtils import com.owncloud.android.utils.FileStorageUtils
@ -46,6 +47,28 @@ fun RemoteOperationResult<*>?.getConflictedRemoteIdsWithOfflineOperations(
return result.ifEmpty { null } return result.ifEmpty { null }
} }
fun ResultCode.isFileSpecificError(): Boolean {
val errorCodes = listOf(
ResultCode.INSTANCE_NOT_CONFIGURED,
ResultCode.QUOTA_EXCEEDED,
ResultCode.LOCAL_STORAGE_FULL,
ResultCode.WRONG_CONNECTION,
ResultCode.UNAUTHORIZED,
ResultCode.OK_NO_SSL,
ResultCode.MAINTENANCE_MODE,
ResultCode.UNTRUSTED_DOMAIN,
ResultCode.ACCOUNT_NOT_THE_SAME,
ResultCode.ACCOUNT_EXCEPTION,
ResultCode.ACCOUNT_NOT_NEW,
ResultCode.ACCOUNT_NOT_FOUND,
ResultCode.ACCOUNT_USES_STANDARD_PASSWORD,
ResultCode.INCORRECT_ADDRESS,
ResultCode.BAD_OC_VERSION
)
return !errorCodes.contains(this)
}
@Suppress("Deprecation") @Suppress("Deprecation")
fun RemoteOperationResult<*>?.toOCFile(): List<OCFile>? { fun RemoteOperationResult<*>?.toOCFile(): List<OCFile>? {
return if (this?.isSuccess == true) { return if (this?.isSuccess == true) {

View file

@ -27,6 +27,7 @@ import com.nextcloud.client.account.CurrentAccountProvider
import com.nextcloud.client.di.Injectable import com.nextcloud.client.di.Injectable
import com.nextcloud.client.network.ConnectivityService import com.nextcloud.client.network.ConnectivityService
import com.nextcloud.utils.extensions.getParcelableArgument import com.nextcloud.utils.extensions.getParcelableArgument
import com.nextcloud.utils.extensions.typedActivity
import com.nextcloud.utils.fileNameValidator.FileNameValidator import com.nextcloud.utils.fileNameValidator.FileNameValidator
import com.owncloud.android.R import com.owncloud.android.R
import com.owncloud.android.databinding.EditBoxDialogBinding import com.owncloud.android.databinding.EditBoxDialogBinding
@ -185,7 +186,7 @@ class CreateFolderDialogFragment : DialogFragment(), DialogInterface.OnClickList
val path = parentFolder?.decryptedRemotePath + newFolderName + OCFile.PATH_SEPARATOR val path = parentFolder?.decryptedRemotePath + newFolderName + OCFile.PATH_SEPARATOR
lifecycleScope.launch(Dispatchers.IO) { lifecycleScope.launch(Dispatchers.IO) {
if (connectivityService.isNetworkAndServerAvailable()) { if (connectivityService.isNetworkAndServerAvailable()) {
(requireActivity() as ComponentsGetter).fileOperationsHelper.createFolder(path) typedActivity<ComponentsGetter>()?.fileOperationsHelper?.createFolder(path)
} else { } else {
Log_OC.d(TAG, "Network not available, creating offline operation") Log_OC.d(TAG, "Network not available, creating offline operation")
fileDataStorageManager.addCreateFolderOfflineOperation( fileDataStorageManager.addCreateFolderOfflineOperation(
@ -196,8 +197,7 @@ class CreateFolderDialogFragment : DialogFragment(), DialogInterface.OnClickList
) )
launch(Dispatchers.Main) { launch(Dispatchers.Main) {
val fileDisplayActivity = requireActivity() as? FileDisplayActivity (requireActivity() as? FileDisplayActivity)?.syncAndUpdateFolder(true)
fileDisplayActivity?.syncAndUpdateFolder(true)
} }
} }
} }

View file

@ -9,7 +9,7 @@
~ SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es> ~ SPDX-FileCopyrightText: 2013 David A. Velasco <dvelasco@solidgear.es>
~ SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only) ~ SPDX-License-Identifier: GPL-2.0-only AND (AGPL-3.0-or-later OR GPL-2.0-only)
--> -->
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/top" android:id="@+id/top"
@ -119,4 +119,4 @@
android:src="@drawable/ic_image_outline" /> android:src="@drawable/ic_image_outline" />
</FrameLayout> </FrameLayout>
</FrameLayout> </androidx.coordinatorlayout.widget.CoordinatorLayout>