Explorar o código

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

David A. Velasco %!s(int64=12) %!d(string=hai) anos
pai
achega
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 {