Эх сурвалжийг харах

Merge pull request #12413 from nextcloud/11974-excessive-file-upload-conflicts-after-update-to-3260-not-before

Remove user notification for autoupload edge cases
Tobias Kaminsky 1 жил өмнө
parent
commit
d499675303

+ 23 - 0
app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadHelper.kt

@@ -39,7 +39,11 @@ import com.owncloud.android.db.OCUpload
 import com.owncloud.android.db.UploadResult
 import com.owncloud.android.files.services.NameCollisionPolicy
 import com.owncloud.android.lib.common.network.OnDatatransferProgressListener
+import com.owncloud.android.lib.common.operations.RemoteOperationResult
 import com.owncloud.android.lib.common.utils.Log_OC
+import com.owncloud.android.lib.resources.files.ReadFileRemoteOperation
+import com.owncloud.android.lib.resources.files.model.RemoteFile
+import com.owncloud.android.utils.FileUtil
 import java.io.File
 import javax.inject.Inject
 
@@ -255,6 +259,25 @@ class FileUploadHelper {
         }
     }
 
+    @Suppress("MagicNumber")
+    fun isSameFileOnRemote(user: User, localFile: File, remotePath: String, context: Context): Boolean {
+        // Compare remote file to local file
+        val localLastModifiedTimestamp = localFile.lastModified() / 1000 // remote file timestamp in milli not micro sec
+        val localCreationTimestamp = FileUtil.getCreationTimestamp(localFile)
+        val localSize: Long = localFile.length()
+
+        val operation = ReadFileRemoteOperation(remotePath)
+        val result: RemoteOperationResult<*> = operation.execute(user, context)
+        if (result.isSuccess) {
+            val remoteFile = result.data[0] as RemoteFile
+            return remoteFile.size == localSize &&
+                localCreationTimestamp != null &&
+                localCreationTimestamp == remoteFile.creationTimestamp &&
+                remoteFile.modifiedTimestamp == localLastModifiedTimestamp * 1000
+        }
+        return false
+    }
+
     class UploadNotificationActionReceiver : BroadcastReceiver() {
         override fun onReceive(context: Context, intent: Intent) {
             val accountName = intent.getStringExtra(FileUploadWorker.EXTRA_ACCOUNT_NAME)

+ 8 - 0
app/src/main/java/com/nextcloud/client/jobs/upload/FileUploadWorker.kt

@@ -259,6 +259,14 @@ class FileUploadWorker(
             return
         }
 
+        // Only notify if it is not same file on remote that causes conflict
+        if (uploadResult.code == ResultCode.SYNC_CONFLICT && FileUploadHelper().isSameFileOnRemote(
+                uploadFileOperation.user, File(uploadFileOperation.storagePath), uploadFileOperation.remotePath, context
+            )
+        ) {
+            return
+        }
+
         val notDelayed = uploadResult.code !in setOf(
             ResultCode.DELAYED_FOR_WIFI,
             ResultCode.DELAYED_FOR_CHARGING,

+ 21 - 0
app/src/main/java/com/owncloud/android/datamodel/UploadsStorageManager.java

@@ -34,6 +34,7 @@ import android.os.RemoteException;
 
 import com.nextcloud.client.account.CurrentAccountProvider;
 import com.nextcloud.client.account.User;
+import com.nextcloud.client.jobs.upload.FileUploadHelper;
 import com.nextcloud.client.jobs.upload.FileUploadWorker;
 import com.owncloud.android.MainApp;
 import com.owncloud.android.db.OCUpload;
@@ -44,6 +45,7 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.operations.UploadFileOperation;
 
+import java.io.File;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
@@ -737,6 +739,25 @@ public class UploadsStorageManager extends Observable {
                     upload.getRemotePath(),
                     localPath
                                   );
+            } else if (uploadResult.getCode() == RemoteOperationResult.ResultCode.SYNC_CONFLICT &&
+                new FileUploadHelper().isSameFileOnRemote(
+                    upload.getUser(), new File(upload.getStoragePath()), upload.getRemotePath(), upload.getContext())) {
+
+                updateUploadStatus(
+                    upload.getOCUploadId(),
+                    UploadStatus.UPLOAD_SUCCEEDED,
+                    UploadResult.SAME_FILE_CONFLICT,
+                    upload.getRemotePath(),
+                    localPath
+                                  );
+            } else if (uploadResult.getCode() == RemoteOperationResult.ResultCode.LOCAL_FILE_NOT_FOUND) {
+                updateUploadStatus(
+                    upload.getOCUploadId(),
+                    UploadStatus.UPLOAD_SUCCEEDED,
+                    UploadResult.FILE_NOT_FOUND,
+                    upload.getRemotePath(),
+                    localPath
+                                  );
             } else {
                 updateUploadStatus(
                     upload.getOCUploadId(),

+ 4 - 1
app/src/main/java/com/owncloud/android/db/UploadResult.java

@@ -45,7 +45,8 @@ public enum UploadResult {
     SYNC_CONFLICT(19),
     CANNOT_CREATE_FILE(20),
     LOCAL_STORAGE_NOT_COPIED(21),
-    QUOTA_EXCEEDED(22);
+    QUOTA_EXCEEDED(22),
+    SAME_FILE_CONFLICT(23);
 
     private final int value;
 
@@ -107,6 +108,8 @@ public enum UploadResult {
                 return LOCAL_STORAGE_NOT_COPIED;
             case 22:
                 return QUOTA_EXCEEDED;
+            case 23:
+                return SAME_FILE_CONFLICT;
         }
         return UNKNOWN;
     }

+ 18 - 1
app/src/main/java/com/owncloud/android/ui/adapter/UploadListAdapter.java

@@ -29,6 +29,7 @@ import android.content.ActivityNotFoundException;
 import android.content.Context;
 import android.content.Intent;
 import android.graphics.Bitmap;
+import android.graphics.Typeface;
 import android.graphics.drawable.Drawable;
 import android.net.Uri;
 import android.text.format.DateUtils;
@@ -259,6 +260,7 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
         itemViewHolder.binding.uploadRemotePath.setVisibility(View.VISIBLE);
         itemViewHolder.binding.uploadFileSize.setVisibility(View.VISIBLE);
         itemViewHolder.binding.uploadStatus.setVisibility(View.VISIBLE);
+        itemViewHolder.binding.uploadStatus.setTypeface(null, Typeface.NORMAL);
         itemViewHolder.binding.uploadProgressBar.setVisibility(View.GONE);
 
         // Update information depending of upload details
@@ -300,6 +302,15 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
             case UPLOAD_FAILED -> itemViewHolder.binding.uploadDate.setVisibility(View.GONE);
             case UPLOAD_SUCCEEDED -> itemViewHolder.binding.uploadStatus.setVisibility(View.GONE);
         }
+
+        // show status if same file conflict or local file deleted
+        if (item.getUploadStatus() == UploadStatus.UPLOAD_SUCCEEDED && item.getLastResult() != UploadResult.UPLOADED){
+            itemViewHolder.binding.uploadStatus.setVisibility(View.VISIBLE);
+            itemViewHolder.binding.uploadStatus.setTypeface(null, Typeface.BOLD);
+            itemViewHolder.binding.uploadDate.setVisibility(View.GONE);
+            itemViewHolder.binding.uploadFileSize.setVisibility(View.GONE);
+        }
+
         itemViewHolder.binding.uploadStatus.setText(status);
 
         // bind listeners to perform actions
@@ -612,7 +623,13 @@ public class UploadListAdapter extends SectionedRecyclerViewAdapter<SectionedVie
                 break;
 
             case UPLOAD_SUCCEEDED:
-                status = parentActivity.getString(R.string.uploads_view_upload_status_succeeded);
+                if (upload.getLastResult() == UploadResult.SAME_FILE_CONFLICT){
+                    status = parentActivity.getString(R.string.uploads_view_upload_status_succeeded_same_file);
+                }else if (upload.getLastResult() == UploadResult.FILE_NOT_FOUND) {
+                    status = getUploadFailedStatusText(upload.getLastResult());
+                } else {
+                    status = parentActivity.getString(R.string.uploads_view_upload_status_succeeded);
+                }
                 break;
 
             case UPLOAD_FAILED:

+ 1 - 0
app/src/main/res/values/strings.xml

@@ -153,6 +153,7 @@
     <string name="uploads_view_group_failed_uploads">Failed/pending restart</string>
     <string name="uploads_view_group_finished_uploads">Uploaded</string>
     <string name="uploads_view_upload_status_succeeded">Completed</string>
+    <string name="uploads_view_upload_status_succeeded_same_file">Same file found on remote, skipping upload</string>
     <string name="uploads_view_upload_status_cancelled">Cancelled</string>
     <string name="uploads_view_upload_status_failed_connection_error">Connection error</string>
     <string name="uploads_view_upload_status_failed_credentials_error">Credentials error</string>