Browse Source

Fixed 'keep both' action in conflicts dialog (both resulting file were linked to the same local file in the device)

David A. Velasco 12 years ago
parent
commit
195b009212

+ 2 - 3
src/com/owncloud/android/files/OwnCloudFileObserver.java

@@ -93,9 +93,8 @@ public class OwnCloudFileObserver extends FileObserver {
             // ISSUE 5: if the user is not running the app (this is a service!), this can be very intrusive; a notification should be preferred
             Intent i = new Intent(mContext, ConflictsResolveActivity.class);
             i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
-            i.putExtra("remotepath", file.getRemotePath());
-            i.putExtra("localpath", mPath);
-            i.putExtra("account", mOCAccount);
+            i.putExtra(ConflictsResolveActivity.EXTRA_FILE, file);
+            i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mOCAccount);
             mContext.startActivity(i);
         }
         // TODO save other errors in some point where the user can inspect them later;

+ 34 - 22
src/com/owncloud/android/files/services/FileUploader.java

@@ -38,6 +38,7 @@ import com.owncloud.android.operations.RemoteOperationResult;
 import com.owncloud.android.operations.UploadFileOperation;
 import com.owncloud.android.ui.activity.FileDetailActivity;
 import com.owncloud.android.ui.fragment.FileDetailFragment;
+import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.OwnCloudVersion;
 
 import eu.alefzero.webdav.OnDatatransferProgressListener;
@@ -418,11 +419,12 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
      */
     private void saveUploadedFile() {
         OCFile file = mCurrentUpload.getFile();
+        long syncDate = System.currentTimeMillis();
+        file.setLastSyncDateForData(syncDate);
         
         /// new PROPFIND to keep data consistent with server in theory, should return the same we already have
         PropFindMethod propfind = null;
         RemoteOperationResult result = null;
-        long syncDate = System.currentTimeMillis();
         try {
           propfind = new PropFindMethod(mUploadClient.getBaseUri() + WebdavUtils.encodePath(mCurrentUpload.getRemotePath()));
           int status = mUploadClient.executeMethod(propfind);
@@ -431,11 +433,8 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
               MultiStatus resp = propfind.getResponseBodyAsMultiStatus();
               WebdavEntry we = new WebdavEntry(resp.getResponses()[0],
                                                mUploadClient.getBaseUri().getPath());
-              OCFile newFile = fillOCFile(we);
-              newFile.setStoragePath(file.getStoragePath());
-              newFile.setKeepInSync(file.keepInSync());
-              newFile.setLastSyncDateForProperties(syncDate);
-              file = newFile;
+              updateOCFile(file, we);
+              file.setLastSyncDateForProperties(syncDate);
               
           } else {
               mUploadClient.exhaustResponse(propfind.getResponseBodyAsStream());
@@ -453,34 +452,47 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
                 propfind.releaseConnection();
         }
 
-        file.setLastSyncDateForData(syncDate);  // this is right, no matter if the PROPFIND was successful or not
         
-        if (!result.isSuccess() && !mCurrentUpload.getRemotePath().equals(file.getRemotePath())) {
-            // true when the file was automatically renamed to avoid an overwrite ; yes, this is a bit obscure...
-            OCFile newFile = new OCFile(mCurrentUpload.getRemotePath());
-            newFile.setCreationTimestamp(file.getCreationTimestamp());
-            newFile.setFileLength(file.getFileLength());
-            newFile.setMimetype(file.getMimetype());
-            newFile.setModificationTimestamp(file.getModificationTimestamp());
-            newFile.setLastSyncDateForProperties(file.getLastSyncDateForProperties());
-            newFile.setStoragePath(file.getStoragePath());
-            newFile.setKeepInSync(file.keepInSync());
-            // newFile.setEtag(file.getEtag())
-            file = newFile;
+        if (mCurrentUpload.wasRenamed()) {
+            OCFile oldFile = mCurrentUpload.getOldFile();
+            if (!oldFile.fileExists()) {
+                // just a name coincidence
+                file.setStoragePath(oldFile.getStoragePath());
+                
+            } else {
+                // conflict resolved with 'Keep both' by the user
+                File localFile = new File(oldFile.getStoragePath());
+                File newLocalFile = new File(FileStorageUtils.getDefaultSavePathFor(mCurrentUpload.getAccount().name, file));
+                boolean renameSuccessed = localFile.renameTo(newLocalFile);
+                if (renameSuccessed) {
+                    file.setStoragePath(newLocalFile.getAbsolutePath());
+                    
+                } else {
+                    // poor solution
+                    Log.d(TAG, "DAMN IT: local rename failed after uploading a file with a new name already existing both in the remote account and the local database (should be due to a conflict solved with 'keep both'");
+                    file.setStoragePath(null);
+                        // not so fine:
+                        //      - local file will be kept there as 'trash' until is download (and overwritten) again from the server;
+                        //      - user will see as 'not down' a file that was just upload
+                        // BUT:
+                        //      - no loss of data happened
+                        //      - when the user downloads again the renamed and original file from the server, local file names and contents will be correctly synchronized with names and contents in server
+                }
+                oldFile.setStoragePath(null);
+                mStorageManager.saveFile(oldFile);
+            }
         }
         
         mStorageManager.saveFile(file);
     }
 
     
-    private OCFile fillOCFile(WebdavEntry we) {
-        OCFile file = new OCFile(we.decodedPath());
+    private void updateOCFile(OCFile file, WebdavEntry we) {
         file.setCreationTimestamp(we.createTimestamp());
         file.setFileLength(we.contentLength());
         file.setMimetype(we.contentType());
         file.setModificationTimestamp(we.modifiedTimesamp());
         // file.setEtag(mCurrentDownload.getEtag());    // TODO Etag, where available
-        return file;
     }
     
     

+ 34 - 3
src/com/owncloud/android/operations/UploadFileOperation.java

@@ -50,13 +50,16 @@ public class UploadFileOperation extends RemoteOperation {
 
     private Account mAccount;
     private OCFile mFile;
+    private OCFile mOldFile;
     private String mRemotePath = null;
     private boolean mIsInstant = false;
     private boolean mRemoteFolderToBeCreated = false;
     private boolean mForceOverwrite = false;
+    private boolean mWasRenamed = false;
     PutMethod mPutMethod = null;
     private Set<OnDatatransferProgressListener> mDataTransferListeners = new HashSet<OnDatatransferProgressListener>();
     private final AtomicBoolean mCancellationRequested = new AtomicBoolean(false);
+
     
     public UploadFileOperation( Account account,
                                 OCFile file,
@@ -86,13 +89,16 @@ public class UploadFileOperation extends RemoteOperation {
         return mFile;
     }
     
+    public OCFile getOldFile() {
+        return mOldFile; 
+    }
+    
     public String getStoragePath() {
         return mFile.getStoragePath();
     }
 
     public String getRemotePath() {
-        //return mFile.getRemotePath(); // DON'T MAKE THIS ; the remotePath used can be different to mFile.getRemotePath() if mForceOverwrite is 'false'; see run(...)
-        return mRemotePath;
+        return mFile.getRemotePath(); 
     }
 
     public String getMimeType() {
@@ -115,6 +121,9 @@ public class UploadFileOperation extends RemoteOperation {
         return mForceOverwrite;
     }
     
+    public boolean wasRenamed() {
+        return mWasRenamed;
+    }
     
     public Set<OnDatatransferProgressListener> getDataTransferListeners() {
         return mDataTransferListeners;
@@ -132,7 +141,11 @@ public class UploadFileOperation extends RemoteOperation {
         try {
             /// rename the file to upload, if necessary
             if (!mForceOverwrite) {
-                mRemotePath = getAvailableRemotePath(client, mRemotePath);
+                String remotePath = getAvailableRemotePath(client, mRemotePath);
+                mWasRenamed = !remotePath.equals(mRemotePath);
+                if (mWasRenamed) {
+                   createNewOCFile(remotePath);
+                }
             }
         
             /// perform the upload
@@ -162,6 +175,24 @@ public class UploadFileOperation extends RemoteOperation {
     }
 
     
+    private void createNewOCFile(String newRemotePath) {
+        // a new OCFile instance must be created for a new remote path
+        OCFile newFile = new OCFile(newRemotePath);
+        newFile.setCreationTimestamp(mFile.getCreationTimestamp());
+        newFile.setFileLength(mFile.getFileLength());
+        newFile.setMimetype(mFile.getMimetype());
+        newFile.setModificationTimestamp(mFile.getModificationTimestamp());
+        // newFile.setEtag(mFile.getEtag())
+        newFile.setKeepInSync(mFile.keepInSync());
+        newFile.setLastSyncDateForProperties(mFile.getLastSyncDateForProperties());
+        newFile.setLastSyncDateForData(mFile.getLastSyncDateForData());
+        newFile.setStoragePath(mFile.getStoragePath());
+        newFile.setParentId(mFile.getParentId());
+        mOldFile = mFile;
+        mFile = newFile;
+    }
+
+
     public boolean isSuccess(int status) {
         return ((status == HttpStatus.SC_OK || status == HttpStatus.SC_CREATED || status == HttpStatus.SC_NO_CONTENT));
     }

+ 16 - 8
src/com/owncloud/android/ui/activity/ConflictsResolveActivity.java

@@ -19,6 +19,7 @@
 package com.owncloud.android.ui.activity;
 
 import com.actionbarsherlock.app.SherlockFragmentActivity;
+import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.files.services.FileUploader;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog;
 import com.owncloud.android.ui.dialog.ConflictsResolveDialog.Decision;
@@ -38,21 +39,27 @@ import android.util.Log;
  */
 public class ConflictsResolveActivity extends SherlockFragmentActivity implements OnConflictDecisionMadeListener {
 
+    public static final String EXTRA_FILE = "FILE";
+    public static final String EXTRA_ACCOUNT = "ACCOUNT";
+
     private String TAG = ConflictsResolveActivity.class.getSimpleName();
     
-    private String mRemotePath;
+    //private String mRemotePath;
     
-    private String mLocalPath;
+    //private String mLocalPath;
     
+    private OCFile mFile;
     private Account mOCAccount;
     
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mRemotePath = getIntent().getStringExtra("remotepath");
-        mLocalPath = getIntent().getStringExtra("localpath");
-        mOCAccount = getIntent().getParcelableExtra("account");
-        ConflictsResolveDialog d = ConflictsResolveDialog.newInstance(mRemotePath, this);
+        
+        //mRemotePath = getIntent().getStringExtra("remotepath");
+        //mLocalPath = getIntent().getStringExtra("localpath");
+        mFile = getIntent().getParcelableExtra(EXTRA_FILE);
+        mOCAccount = getIntent().getParcelableExtra(EXTRA_ACCOUNT);
+        ConflictsResolveDialog d = ConflictsResolveDialog.newInstance(mFile.getRemotePath(), this);
         d.showDialog(this);
     }
 
@@ -73,8 +80,9 @@ public class ConflictsResolveActivity extends SherlockFragmentActivity implement
                 return;
         }
         i.putExtra(FileUploader.KEY_ACCOUNT, mOCAccount);
-        i.putExtra(FileUploader.KEY_REMOTE_FILE, mRemotePath);
-        i.putExtra(FileUploader.KEY_LOCAL_FILE, mLocalPath);
+        //i.putExtra(FileUploader.KEY_REMOTE_FILE, mRemotePath);
+        //i.putExtra(FileUploader.KEY_LOCAL_FILE, mLocalPath);
+        i.putExtra(FileUploader.KEY_FILE, mFile);
         i.putExtra(FileUploader.KEY_UPLOAD_TYPE, FileUploader.UPLOAD_SINGLE_FILE);
         
         startService(i);

+ 2 - 4
src/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -992,10 +992,8 @@ public class FileDetailFragment extends SherlockFragment implements
         if (!result.isSuccess()) {
             if (result.getCode() == ResultCode.SYNC_CONFLICT) {
                 Intent i = new Intent(getActivity(), ConflictsResolveActivity.class);
-                //i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK);
-                i.putExtra("remotepath", mFile.getRemotePath());
-                i.putExtra("localpath", mFile.getStoragePath());
-                i.putExtra("account", mAccount);
+                i.putExtra(ConflictsResolveActivity.EXTRA_FILE, mFile);
+                i.putExtra(ConflictsResolveActivity.EXTRA_ACCOUNT, mAccount);
                 startActivity(i);
                 
             } else {