Merge remote-tracking branch 'upstream/develop' into triggerMediaScan
authortobiasKaminsky <tobias@kaminsky.me>
Wed, 22 Oct 2014 06:09:47 +0000 (08:09 +0200)
committertobiasKaminsky <tobias@kaminsky.me>
Wed, 22 Oct 2014 06:09:47 +0000 (08:09 +0200)
Conflicts:
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/com/owncloud/android/ui/preview/PreviewImageActivity.java
src/com/owncloud/android/ui/preview/PreviewImageFragment.java

1  2 
project.properties
src/com/owncloud/android/files/FileOperationsHelper.java
src/com/owncloud/android/ui/dialog/RemoveFileDialogFragment.java
src/com/owncloud/android/ui/fragment/OCFileListFragment.java
src/com/owncloud/android/ui/preview/PreviewImageActivity.java
src/com/owncloud/android/ui/preview/PreviewImageFragment.java

@@@ -10,3 -10,4 +10,4 @@@
  # Project target.
  target=android-19
  android.library.reference.1=actionbarsherlock/library
 -android.library.reference.2=owncloud-android-library
++android.library.reference.2=../android-library/android-library
index 0000000,e1ab195..65e8d83
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,298 +1,296 @@@
 -
+ /* ownCloud Android client application
+  *   Copyright (C) 2012-2014 ownCloud Inc.
+  *
+  *   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 <http://www.gnu.org/licenses/>.
+  *
+  */
+ package com.owncloud.android.files;
+ import org.apache.http.protocol.HTTP;
+ import android.accounts.Account;
+ import android.accounts.AccountManager;
+ import android.content.Intent;
++import android.media.MediaScannerConnection;
+ import android.net.Uri;
+ import android.support.v4.app.DialogFragment;
+ import android.webkit.MimeTypeMap;
+ import android.widget.Toast;
+ import com.owncloud.android.R;
+ import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
+ import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
 -    
 -    
+ import com.owncloud.android.lib.common.accounts.AccountUtils.Constants;
+ import com.owncloud.android.lib.common.network.WebdavUtils;
+ import com.owncloud.android.lib.common.utils.Log_OC;
+ import com.owncloud.android.lib.resources.status.OwnCloudVersion;
+ import com.owncloud.android.services.OperationsService;
+ import com.owncloud.android.ui.activity.FileActivity;
+ import com.owncloud.android.ui.dialog.ShareLinkToDialog;
+ /**
+  * 
+  * @author masensio
+  * @author David A. Velasco
+  */
+ public class FileOperationsHelper {
+     private static final String TAG = FileOperationsHelper.class.getName();
+     
+     private static final String FTAG_CHOOSER_DIALOG = "CHOOSER_DIALOG"; 
+     protected FileActivity mFileActivity = null;
+     /// Identifier of operation in progress which result shouldn't be lost 
+     private long mWaitingForOpId = Long.MAX_VALUE;
+     
+     public FileOperationsHelper(FileActivity fileActivity) {
+         mFileActivity = fileActivity;
+     }
+     public void openFile(OCFile file) {
+         if (file != null) {
+             String storagePath = file.getStoragePath();
+             String encodedStoragePath = WebdavUtils.encodePath(storagePath);
+             
+             Intent intentForSavedMimeType = new Intent(Intent.ACTION_VIEW);
+             intentForSavedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), file.getMimetype());
+             intentForSavedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+             
+             Intent intentForGuessedMimeType = null;
+             if (storagePath.lastIndexOf('.') >= 0) {
+                 String guessedMimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
+                 if (guessedMimeType != null && !guessedMimeType.equals(file.getMimetype())) {
+                     intentForGuessedMimeType = new Intent(Intent.ACTION_VIEW);
+                     intentForGuessedMimeType.setDataAndType(Uri.parse("file://"+ encodedStoragePath), guessedMimeType);
+                     intentForGuessedMimeType.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+                 }
+             }
+             
+             Intent chooserIntent = null;
+             if (intentForGuessedMimeType != null) {
+                 chooserIntent = Intent.createChooser(intentForGuessedMimeType, mFileActivity.getString(R.string.actionbar_open_with));
+             } else {
+                 chooserIntent = Intent.createChooser(intentForSavedMimeType, mFileActivity.getString(R.string.actionbar_open_with));
+             }
+             
+             mFileActivity.startActivity(chooserIntent);
+             
+         } else {
+             Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
+         }
+     }
+     
+     
+     public void shareFileWithLink(OCFile file) {
+         
+         if (isSharedSupported()) {
+             if (file != null) {
+                 String link = "https://fake.url";
+                 Intent intent = createShareWithLinkIntent(link);
+                 String[] packagesToExclude = new String[] { mFileActivity.getPackageName() };
+                 DialogFragment chooserDialog = ShareLinkToDialog.newInstance(intent, packagesToExclude, file);
+                 chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
+                 
+             } else {
+                 Log_OC.wtf(TAG, "Trying to share a NULL OCFile");
+             }
+             
+         } else {
+             // Show a Message
+             Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG);
+             t.show();
+         }
+     }
+     
+     
+     public void shareFileWithLinkToApp(OCFile file, Intent sendIntent) {
+         
+         if (file != null) {
+             mFileActivity.showLoadingDialog();
+             
+             Intent service = new Intent(mFileActivity, OperationsService.class);
+             service.setAction(OperationsService.ACTION_CREATE_SHARE);
+             service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+             service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+             service.putExtra(OperationsService.EXTRA_SEND_INTENT, sendIntent);
+             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service);
+             
+         } else {
+             Log_OC.wtf(TAG, "Trying to open a NULL OCFile");
+         }
+     }
+     
+     
+     private Intent createShareWithLinkIntent(String link) {
+         Intent intentToShareLink = new Intent(Intent.ACTION_SEND);
+         intentToShareLink.putExtra(Intent.EXTRA_TEXT, link);
+         intentToShareLink.setType(HTTP.PLAIN_TEXT_TYPE);
+         return intentToShareLink; 
+     }
+     
+     
+     /**
+      *  @return 'True' if the server supports the Share API
+      */
+     public boolean isSharedSupported() {
+         if (mFileActivity.getAccount() != null) {
+             AccountManager accountManager = AccountManager.get(mFileActivity);
+             String version = accountManager.getUserData(mFileActivity.getAccount(), Constants.KEY_OC_VERSION);
+             return (new OwnCloudVersion(version)).isSharedSupported();
+         }
+         return false;
+     }
+     
+     
+     public void unshareFileWithLink(OCFile file) {
+         
+         if (isSharedSupported()) {
+             // Unshare the file
+             Intent service = new Intent(mFileActivity, OperationsService.class);
+             service.setAction(OperationsService.ACTION_UNSHARE);
+             service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+             service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+             mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service);
+             
+             mFileActivity.showLoadingDialog();
+             
+         } else {
+             // Show a Message
+             Toast t = Toast.makeText(mFileActivity, mFileActivity.getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG);
+             t.show();
+             
+         }
+     }
+     
+     public void sendDownloadedFile(OCFile file) {
+         if (file != null) {
+             Intent sendIntent = new Intent(android.content.Intent.ACTION_SEND);
+             // set MimeType
+             sendIntent.setType(file.getMimetype());
+             sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("file://" + file.getStoragePath()));
+             sendIntent.putExtra(Intent.ACTION_SEND, true);      // Send Action
+             
+             // Show dialog, without the own app
+             String[] packagesToExclude = new String[] { mFileActivity.getPackageName() };
+             DialogFragment chooserDialog = ShareLinkToDialog.newInstance(sendIntent, packagesToExclude, file);
+             chooserDialog.show(mFileActivity.getSupportFragmentManager(), FTAG_CHOOSER_DIALOG);
+         } else {
+             Log_OC.wtf(TAG, "Trying to send a NULL OCFile");
+         }
+     }
+     
+     
+     public void syncFile(OCFile file) {
+         // Sync file
+         Intent service = new Intent(mFileActivity, OperationsService.class);
+         service.setAction(OperationsService.ACTION_SYNC_FILE);
+         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath()); 
+         service.putExtra(OperationsService.EXTRA_SYNC_FILE_CONTENTS, true);
+         mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service);
+         
+         mFileActivity.showLoadingDialog();
+     }
+     
+     
+     public void renameFile(OCFile file, String newFilename) {
+         // RenameFile
+         Intent service = new Intent(mFileActivity, OperationsService.class);
+         service.setAction(OperationsService.ACTION_RENAME);
+         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+         service.putExtra(OperationsService.EXTRA_NEWNAME, newFilename);
+         mWaitingForOpId = mFileActivity.getOperationsServiceBinder().newOperation(service);
+         
+         mFileActivity.showLoadingDialog();
+     }
+     public void removeFile(OCFile file, boolean onlyLocalCopy) {
+         // RemoveFile
+         Intent service = new Intent(mFileActivity, OperationsService.class);
+         service.setAction(OperationsService.ACTION_REMOVE);
+         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
+         service.putExtra(OperationsService.EXTRA_REMOVE_ONLY_LOCAL, onlyLocalCopy);
+         mWaitingForOpId =  mFileActivity.getOperationsServiceBinder().newOperation(service);
+         
+         mFileActivity.showLoadingDialog();
+     }
+     
+     
+     public void createFolder(String remotePath, boolean createFullPath) {
+         // Create Folder
+         Intent service = new Intent(mFileActivity, OperationsService.class);
+         service.setAction(OperationsService.ACTION_CREATE_FOLDER);
+         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, remotePath);
+         service.putExtra(OperationsService.EXTRA_CREATE_FULL_PATH, createFullPath);
+         mWaitingForOpId =  mFileActivity.getOperationsServiceBinder().newOperation(service);
+         
+         mFileActivity.showLoadingDialog();
+     }
+     
+     public void cancelTransference(OCFile file) {
+         Account account = mFileActivity.getAccount();
+         FileDownloaderBinder downloaderBinder = mFileActivity.getFileDownloaderBinder();
+         FileUploaderBinder uploaderBinder =  mFileActivity.getFileUploaderBinder();
+         if (downloaderBinder != null && downloaderBinder.isDownloading(account, file)) {
+             // Remove etag for parent, if file is a keep_in_sync
+             if (file.keepInSync()) {
+                OCFile parent = mFileActivity.getStorageManager().getFileById(file.getParentId());
+                parent.setEtag("");
+                mFileActivity.getStorageManager().saveFile(parent);
+             }
+             
+             downloaderBinder.cancel(account, file);
+             
+         } else if (uploaderBinder != null && uploaderBinder.isUploading(account, file)) {
+             uploaderBinder.cancel(account, file);
+         }
+     }
+     /**
+      * Start move file operation
+      * @param newfile           File where it is going to be moved
+      * @param currentFile       File with the previous info
+      */
+     public void moveFile(OCFile newfile, OCFile currentFile) {
+         // Move files
+         Intent service = new Intent(mFileActivity, OperationsService.class);
+         service.setAction(OperationsService.ACTION_MOVE_FILE);
+         service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, newfile.getRemotePath());
+         service.putExtra(OperationsService.EXTRA_REMOTE_PATH, currentFile.getRemotePath());
+         service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
+         mWaitingForOpId =  mFileActivity.getOperationsServiceBinder().newOperation(service);
+         mFileActivity.showLoadingDialog();
+     }
+     public long getOpIdWaitingFor() {
+         return mWaitingForOpId;
+     }
+     public void setOpIdWaitingFor(long waitingForOpId) {
+         mWaitingForOpId = waitingForOpId;
+     }
+ }
index 0000000,a78584a..8158a5a
mode 000000,100644..100644
--- /dev/null
@@@ -1,0 -1,144 +1,158 @@@
 -           storageManager.saveFile(folder);
+ /* ownCloud Android client application
+  *   Copyright (C) 2014 ownCloud Inc.
+  *
+  *   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 <http://www.gnu.org/licenses/>.
+  *
+  */
+ package com.owncloud.android.ui.dialog;
+ /**
+  *  Dialog requiring confirmation before removing a given OCFile.  
+  * 
+  *  Triggers the removal according to the user response. 
+  *  
+  *  @author David A. Velasco
+  */
++import java.io.File;
+ import java.util.Vector;
+ import com.owncloud.android.R;
+ import com.owncloud.android.datamodel.FileDataStorageManager;
+ import com.owncloud.android.datamodel.OCFile;
+ import com.owncloud.android.ui.activity.ComponentsGetter;
+ import com.owncloud.android.ui.dialog.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
+ import android.app.Dialog;
++import android.media.MediaScannerConnection;
+ import android.os.Bundle;
+ public class RemoveFileDialogFragment extends ConfirmationDialogFragment 
+ implements ConfirmationDialogFragmentListener {
+     private static final String ARG_TARGET_FILE = "TARGET_FILE";
+     /**
+      * Public factory method to create new RemoveFileDialogFragment instances.
+      * 
+      * @param file            File to remove.
+      * @return                Dialog ready to show.
+      */
+     public static RemoveFileDialogFragment newInstance(OCFile file) {
+         RemoveFileDialogFragment frag = new RemoveFileDialogFragment();
+         Bundle args = new Bundle();
+         
+         int messageStringId = R.string.confirmation_remove_alert;
+         
+         int posBtn = R.string.confirmation_remove_remote;
+         int neuBtn = -1;
+         if (file.isFolder()) {
+             messageStringId = R.string.confirmation_remove_folder_alert;
+             posBtn = R.string.confirmation_remove_remote_and_local;
+             neuBtn = R.string.confirmation_remove_folder_local;
+         } else if (file.isDown()) {
+             posBtn = R.string.confirmation_remove_remote_and_local;
+             neuBtn = R.string.confirmation_remove_local;
+         }
+         
+         
+         args.putInt(ARG_CONF_RESOURCE_ID, messageStringId);
+         args.putStringArray(ARG_CONF_ARGUMENTS, new String[]{file.getFileName()});
+         args.putInt(ARG_POSITIVE_BTN_RES, posBtn);
+         args.putInt(ARG_NEUTRAL_BTN_RES, neuBtn);
+         args.putInt(ARG_NEGATIVE_BTN_RES, R.string.common_cancel);
+         args.putParcelable(ARG_TARGET_FILE, file);
+         frag.setArguments(args);
+         
+         return frag;
+     }
+     private OCFile mTargetFile;
+     
+     @Override
+     public Dialog onCreateDialog(Bundle savedInstanceState) {
+         Dialog dialog = super.onCreateDialog(savedInstanceState);
+         mTargetFile = getArguments().getParcelable(ARG_TARGET_FILE);
+         
+         setOnConfirmationListener(this);
+         
+         return dialog;
+     }    
+     /**
+      * Performs the removal of the target file, both locally and in the server.
+      */
+     @Override
+     public void onConfirmation(String callerTag) {
+         ComponentsGetter cg = (ComponentsGetter)getSherlockActivity();
+         FileDataStorageManager storageManager = cg.getStorageManager();
+         if (storageManager.getFileById(mTargetFile.getFileId()) != null) {
++            String path = new File(mTargetFile.getStoragePath()).getParent();
+             cg.getFileOperationsHelper().removeFile(mTargetFile, false);
++            triggerMediaScan(path);
+         }
+     }
+     
+     /**
+      * Performs the removal of the local copy of the target file
+      */
+     @Override
+     public void onNeutral(String callerTag) {
++        String path = new File(mTargetFile.getStoragePath()).getParent();
+         ComponentsGetter cg = (ComponentsGetter)getSherlockActivity();
+         cg.getFileOperationsHelper()
+             .removeFile(mTargetFile, true);
+         
+         FileDataStorageManager storageManager = cg.getStorageManager();
+         
+         boolean containsKeepInSync = false;
+         if (mTargetFile.isFolder()) {
+             Vector<OCFile> files = storageManager.getFolderContent(mTargetFile);
+             for(OCFile file: files) {
+                 containsKeepInSync = file.keepInSync() || containsKeepInSync;
+                 if (containsKeepInSync)
+                     break;
+             }
+         }
+         // Remove etag for parent, if file is a keep_in_sync 
+         // or is a folder and contains keep_in_sync        
+         if (mTargetFile.keepInSync() || containsKeepInSync) {
+             OCFile folder = null;
+             if (mTargetFile.isFolder()) {
+                 folder = mTargetFile;
+             } else {
+                 folder = storageManager.getFileById(mTargetFile.getParentId());
+             }
+             
+            folder.setEtag("");
 -}
++           storageManager.saveFile(folder);  
+         }
++        
++        // Trigger MediaScan
++        triggerMediaScan(path);
+     }
+     @Override
+     public void onCancel(String callerTag) {
+         // nothing to do here
+     }
+     
++    private void triggerMediaScan(String path){
++        MediaScannerConnection.scanFile(
++                getActivity().getApplicationContext(), 
++                new String[]{path}, 
++                null,null);
++    }
++}
  package com.owncloud.android.ui.fragment;
  
  import java.io.File;
- import java.util.ArrayList;
- import java.util.List;
  
- import com.owncloud.android.Log_OC;
++import android.accounts.Account;
+ import android.app.Activity;
+ import android.content.Intent;
++import android.media.MediaScannerConnection;
+ import android.os.Bundle;
++import android.os.Handler;
+ import android.support.v4.widget.SwipeRefreshLayout;
+ import android.view.ContextMenu;
+ import android.view.MenuInflater;
+ import android.view.MenuItem;
+ import android.view.View;
+ import android.widget.AdapterView;
+ import android.widget.AdapterView.AdapterContextMenuInfo;
  import com.owncloud.android.R;
 +import com.owncloud.android.authentication.AccountUtils;
  import com.owncloud.android.datamodel.FileDataStorageManager;
  import com.owncloud.android.datamodel.OCFile;
- import com.owncloud.android.files.FileHandler;
+ import com.owncloud.android.files.FileMenuFilter;
 +import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
 +import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
- import com.owncloud.android.operations.OnRemoteOperationListener;
- import com.owncloud.android.operations.RemoteOperation;
+ import com.owncloud.android.lib.common.utils.Log_OC;
 +import com.owncloud.android.operations.RemoveFileOperation;
 +import com.owncloud.android.operations.RenameFileOperation;
- import com.owncloud.android.operations.SynchronizeFileOperation;
  import com.owncloud.android.ui.activity.FileDisplayActivity;
- import com.owncloud.android.ui.activity.TransferServiceGetter;
+ import com.owncloud.android.ui.activity.MoveActivity;
+ import com.owncloud.android.ui.activity.OnEnforceableRefreshListener;
  import com.owncloud.android.ui.adapter.FileListListAdapter;
- import com.owncloud.android.ui.dialog.EditNameDialog;
- import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
- import com.owncloud.android.ui.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
+ import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
+ import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
+ import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
  import com.owncloud.android.ui.preview.PreviewImageFragment;
  import com.owncloud.android.ui.preview.PreviewMediaFragment;
  
@@@ -73,8 -71,8 +79,9 @@@ public class OCFileListFragment extend
      private OCFile mFile = null;
      private FileListListAdapter mAdapter;
      
 +    private Handler mHandler;
      private OCFile mTargetFile;
      
      /**
       * {@inheritDoc}
                  return true;
              }
              case R.id.action_remove_file: {
-                 int messageStringId = R.string.confirmation_remove_alert;
-                 int posBtnStringId = R.string.confirmation_remove_remote;
-                 int neuBtnStringId = -1;
-                 if (mTargetFile.isFolder()) {
-                     messageStringId = R.string.confirmation_remove_folder_alert;
-                     posBtnStringId = R.string.confirmation_remove_remote_and_local;
-                     neuBtnStringId = R.string.confirmation_remove_folder_local;
-                 } else if (mTargetFile.isDown()) {
-                     posBtnStringId = R.string.confirmation_remove_remote_and_local;
-                     neuBtnStringId = R.string.confirmation_remove_local;
-                 }
-                 ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
-                         messageStringId,
-                         new String[]{mTargetFile.getFileName()},
-                         posBtnStringId,
-                         neuBtnStringId,
-                         R.string.common_cancel);
-                 confDialog.setOnConfirmationListener(this);
-                 confDialog.show(getFragmentManager(), FileDetailFragment.FTAG_CONFIRMATION);
+                 RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(mTargetFile);
+                 dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
                  return true;
              }
+             case R.id.action_download_file: 
              case R.id.action_sync_file: {
-                 Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
-                 RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, getSherlockActivity());
-                 operation.execute(account, getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
-                 ((FileDisplayActivity) getSherlockActivity()).showLoadingDialog();
+                 mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
++                triggerMediaScan(mTargetFile.getStoragePath());
                  return true;
              }
-             case R.id.action_cancel_download: {
-                 FileDownloaderBinder downloaderBinder = mContainerActivity.getFileDownloaderBinder();
-                 Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
-                 if (downloaderBinder != null && downloaderBinder.isDownloading(account, mTargetFile)) {
-                     downloaderBinder.cancel(account, mTargetFile);
-                     listDirectory();
-                     mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
-                 }
+             case R.id.action_cancel_download:
+             case R.id.action_cancel_upload: {
+                 ((FileDisplayActivity)mContainerActivity).cancelTransference(mTargetFile);
                  return true;
              }
-             case R.id.action_cancel_upload: {
-                 FileUploaderBinder uploaderBinder = mContainerActivity.getFileUploaderBinder();
-                 Account account = AccountUtils.getCurrentOwnCloudAccount(getActivity());
-                 if (uploaderBinder != null && uploaderBinder.isUploading(account, mTargetFile)) {
-                     uploaderBinder.cancel(account, mTargetFile);
-                     listDirectory();
-                     mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
+             case R.id.action_see_details: {
+                 mContainerActivity.showDetails(mTargetFile);
+                 return true;
+             }
+             case R.id.action_send_file: {
+                 // Obtain the file
+                 if (!mTargetFile.isDown()) {  // Download the file
+                     Log_OC.d(TAG, mTargetFile.getRemotePath() + " : File must be downloaded");
+                     ((FileDisplayActivity)mContainerActivity).startDownloadForSending(mTargetFile);
+                     
+                 } else {
+                     mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
                  }
                  return true;
              }
                  return super.onContextItemSelected(item); 
          }
      }
 +    
  
      /**
       * Use this to query the {@link OCFile} that is currently
       * being displayed by this fragment
              mFile = directory;
          }
      }
-     
-     
-     
-     /**
-      * Interface to implement by any Activity that includes some instance of FileListFragment
-      * 
-      * @author David A. Velasco
-      */
-     public interface ContainerActivity extends TransferServiceGetter, OnRemoteOperationListener, FileHandler {
-         /**
-          * Callback method invoked when a the user browsed into a different folder through the list of files
-          *  
-          * @param file
-          */
-         public void onBrowsedDownTo(OCFile folder);
-         
-         public void startDownloadForPreview(OCFile file);
-         public void startMediaPreview(OCFile file, int i, boolean b);
-         public void startImagePreview(OCFile file);
-         
-         public void startSyncFolderOperation(OCFile folder);
-         /**
-          * Getter for the current DataStorageManager in the container activity
-          */
-         public FileDataStorageManager getStorageManager();
-         
-         
-         /**
-          * Callback method invoked when a the 'transfer state' of a file changes.
-          * 
-          * This happens when a download or upload is started or ended for a file.
-          * 
-          * This method is necessary by now to update the user interface of the double-pane layout in tablets
-          * because methods {@link FileDownloaderBinder#isDownloading(Account, OCFile)} and {@link FileUploaderBinder#isUploading(Account, OCFile)}
-          * won't provide the needed response before the method where this is called finishes. 
-          * 
-          * TODO Remove this when the transfer state of a file is kept in the database (other thing TODO)
-          * 
-          * @param file          OCFile which state changed.
-          * @param downloading   Flag signaling if the file is now downloading.
-          * @param uploading     Flag signaling if the file is now uploading.
-          */
-         public void onTransferStateChanged(OCFile file, boolean downloading, boolean uploading);
-         
-     }
-     
-     
-     @Override
-     public void onDismiss(EditNameDialog dialog) {
-         if (dialog.getResult()) {
-             String newFilename = dialog.getNewFilename();
-             Log_OC.d(TAG, "name edit dialog dismissed with new name " + newFilename);
-             RemoteOperation operation = new RenameFileOperation(mTargetFile, 
-                                                                 AccountUtils.getCurrentOwnCloudAccount(getActivity()), 
-                                                                 newFilename, 
-                                                                 mContainerActivity.getStorageManager());
-             operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
-             ((FileDisplayActivity) getActivity()).showLoadingDialog();
-         }
-     }
  
-     
-     @Override
-     public void onConfirmation(String callerTag) {
-         if (callerTag.equals(FileDetailFragment.FTAG_CONFIRMATION)) {
-             if (mContainerActivity.getStorageManager().getFileById(mTargetFile.getFileId()) != null) {
-                 String path = new File(mTargetFile.getStoragePath()).getParent();
-                 RemoteOperation operation = new RemoveFileOperation( mTargetFile, 
-                                                                     true, 
-                                                                     mContainerActivity.getStorageManager());
-                 operation.execute(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity(), mContainerActivity, mHandler, getSherlockActivity());
-                 
-                 ((FileDisplayActivity) getActivity()).showLoadingDialog();
-                 
-                 triggerMediaScan(path);
-             }
-         }
-     }
-     
-     @Override
-     public void onNeutral(String callerTag) {
-         String path = new File(mTargetFile.getStoragePath()).getParent();
-         mContainerActivity.getStorageManager().removeFile(mTargetFile, false, true);    // TODO perform in background task / new thread
-         
-         triggerMediaScan(path);
-         
-         listDirectory();
-         mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
-     }
-     
-     @Override
-     public void onCancel(String callerTag) {
-         Log_OC.d(TAG, "REMOVAL CANCELED");
-     }
-     
 +    private void triggerMediaScan(String path){
 +        MediaScannerConnection.scanFile(
 +                getActivity().getApplicationContext(), 
 +                new String[]{path}, 
 +                null,null);
 +    }
  }
@@@ -22,18 -23,15 +23,18 @@@ import android.content.Context
  import android.content.Intent;
  import android.content.IntentFilter;
  import android.content.ServiceConnection;
 +import android.media.MediaScannerConnection;
 +import android.media.MediaScannerConnection.OnScanCompletedListener;
 +import android.net.Uri;
+ import android.content.SharedPreferences;
+ import android.os.Build;
  import android.os.Bundle;
+ import android.os.Handler;
  import android.os.IBinder;
- import android.support.v4.app.Fragment;
- import android.support.v4.app.FragmentManager;
- import android.support.v4.app.FragmentTransaction;
+ import android.os.Message;
+ import android.preference.PreferenceManager;
  import android.support.v4.view.ViewPager;
- import android.view.MotionEvent;
  import android.view.View;
- import android.view.View.OnTouchListener;
  
  import com.actionbarsherlock.app.ActionBar;
  import com.actionbarsherlock.view.MenuItem;
@@@ -349,80 -328,7 +328,7 @@@ public class PreviewImageFragment exten
          finish();
      }
      
-     
-     /**
-      * Starts a the removal of the previewed file.
-      * 
-      * Shows a confirmation dialog. The action continues in {@link #onConfirmation(String)} , {@link #onNeutral(String)} or {@link #onCancel(String)},
-      * depending upon the user selection in the dialog. 
-      */
-     private void removeFile() {
-         ConfirmationDialogFragment confDialog = ConfirmationDialogFragment.newInstance(
-                 R.string.confirmation_remove_alert,
-                 new String[]{getFile().getFileName()},
-                 R.string.confirmation_remove_remote_and_local,
-                 R.string.confirmation_remove_local,
-                 R.string.common_cancel);
-         confDialog.setOnConfirmationListener(this);
-         confDialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
-     }
-     
-     /**
-      * Performs the removal of the previewed file, both locally and in the server.
-      */
-     @Override
-     public void onConfirmation(String callerTag) {
-         if (mStorageManager.getFileById(getFile().getFileId()) != null) {   // check that the file is still there;
-             String path = new File(getFile().getStoragePath()).getParent();
-             mLastRemoteOperation = new RemoveFileOperation( getFile(),      // TODO we need to review the interface with RemoteOperations, and use OCFile IDs instead of OCFile objects as parameters
-                                                             true, 
-                                                             mStorageManager);
-             mLastRemoteOperation.execute(mAccount, getSherlockActivity(), this, mHandler, getSherlockActivity());
-             
-             ((PreviewImageActivity) getActivity()).showLoadingDialog();
-             
-             triggerMediaScan(path);
-         }
-     }
-     
-     
-     /**
-      * Removes the file from local storage
-      */
-     @Override
-     public void onNeutral(String callerTag) {
-         // TODO this code should be made in a secondary thread,
-         OCFile file = getFile();
-         if (file.isDown()) {   // checks it is still there
-             File f = new File(file.getStoragePath());
-             String path = f.getParent();
-             f.delete();
-             
-             triggerMediaScan(path);
-             
-             file.setStoragePath(null);
-             mStorageManager.saveFile(file);
-             finish();
-         }
-     }
-     
-     /**
-      * User cancelled the removal action.
-      */
-     @Override
-     public void onCancel(String callerTag) {
-         // nothing to do here
-     }
-     
-     private void triggerMediaScan(String path){
-         MediaScannerConnection.scanFile(
-                 getActivity().getApplicationContext(), 
-                 new String[]{path}, 
-                 null,null);
-     }
--    
 +
      private class BitmapLoader extends AsyncTask<String, Void, Bitmap> {
  
          /**