|
@@ -17,17 +17,49 @@
|
|
|
*/
|
|
|
package com.owncloud.android.ui.fragment;
|
|
|
|
|
|
+import java.io.File;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+
|
|
|
+import com.owncloud.android.AccountUtils;
|
|
|
+import com.owncloud.android.R;
|
|
|
import com.owncloud.android.datamodel.DataStorageManager;
|
|
|
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.network.OwnCloudClientUtils;
|
|
|
+import com.owncloud.android.operations.OnRemoteOperationListener;
|
|
|
+import com.owncloud.android.operations.RemoteOperation;
|
|
|
+import com.owncloud.android.operations.RemoveFileOperation;
|
|
|
+import com.owncloud.android.operations.RenameFileOperation;
|
|
|
+import com.owncloud.android.operations.SynchronizeFileOperation;
|
|
|
import com.owncloud.android.ui.FragmentListView;
|
|
|
+import com.owncloud.android.ui.activity.FileDisplayActivity;
|
|
|
import com.owncloud.android.ui.activity.TransferServiceGetter;
|
|
|
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 eu.alefzero.webdav.WebdavClient;
|
|
|
+import eu.alefzero.webdav.WebdavUtils;
|
|
|
|
|
|
+import android.accounts.Account;
|
|
|
import android.app.Activity;
|
|
|
+import android.content.ActivityNotFoundException;
|
|
|
+import android.content.Intent;
|
|
|
+import android.net.Uri;
|
|
|
import android.os.Bundle;
|
|
|
+import android.os.Handler;
|
|
|
import android.util.Log;
|
|
|
+import android.view.ContextMenu;
|
|
|
+import android.view.MenuInflater;
|
|
|
+import android.view.MenuItem;
|
|
|
import android.view.View;
|
|
|
+import android.webkit.MimeTypeMap;
|
|
|
import android.widget.AdapterView;
|
|
|
+import android.widget.Toast;
|
|
|
+import android.widget.AdapterView.AdapterContextMenuInfo;
|
|
|
|
|
|
/**
|
|
|
* A Fragment that lists all files and folders in a given path.
|
|
@@ -35,7 +67,7 @@ import android.widget.AdapterView;
|
|
|
* @author Bartek Przybylski
|
|
|
*
|
|
|
*/
|
|
|
-public class OCFileListFragment extends FragmentListView {
|
|
|
+public class OCFileListFragment extends FragmentListView implements EditNameDialogListener, ConfirmationDialogFragmentListener {
|
|
|
private static final String TAG = "FileListFragment";
|
|
|
private static final String SAVED_LIST_POSITION = "LIST_POSITION";
|
|
|
|
|
@@ -43,6 +75,9 @@ public class OCFileListFragment extends FragmentListView {
|
|
|
|
|
|
private OCFile mFile = null;
|
|
|
private FileListListAdapter mAdapter;
|
|
|
+
|
|
|
+ private Handler mHandler;
|
|
|
+ private OCFile mTargetFile;
|
|
|
|
|
|
|
|
|
/**
|
|
@@ -76,6 +111,11 @@ public class OCFileListFragment extends FragmentListView {
|
|
|
setReferencePosition(position);
|
|
|
}
|
|
|
|
|
|
+ registerForContextMenu(getListView());
|
|
|
+ getListView().setOnCreateContextMenuListener(this);
|
|
|
+
|
|
|
+ mHandler = new Handler();
|
|
|
+
|
|
|
Log.i(TAG, "onActivityCreated() stop");
|
|
|
}
|
|
|
|
|
@@ -112,6 +152,197 @@ public class OCFileListFragment extends FragmentListView {
|
|
|
}
|
|
|
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * {@inheritDoc}
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
|
|
|
+ super.onCreateContextMenu(menu, v, menuInfo);
|
|
|
+ MenuInflater inflater = getActivity().getMenuInflater();
|
|
|
+ inflater.inflate(R.menu.file_context_menu, menu);
|
|
|
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) menuInfo;
|
|
|
+ OCFile targetFile = (OCFile) mAdapter.getItem(info.position);
|
|
|
+ List<Integer> toHide = new ArrayList<Integer>();
|
|
|
+ List<Integer> toDisable = new ArrayList<Integer>();
|
|
|
+
|
|
|
+ MenuItem item = null;
|
|
|
+ if (targetFile.isDirectory()) {
|
|
|
+ // contextual menu for folders
|
|
|
+ toHide.add(R.id.open_file_item);
|
|
|
+ toHide.add(R.id.download_file_item);
|
|
|
+ toHide.add(R.id.cancel_download_item);
|
|
|
+ toHide.add(R.id.cancel_upload_item);
|
|
|
+ if ( mContainerActivity.getFileDownloaderBinder().isDownloading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile) ||
|
|
|
+ mContainerActivity.getFileUploaderBinder().isUploading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile) ) {
|
|
|
+ toDisable.add(R.id.rename_file_item);
|
|
|
+ toDisable.add(R.id.remove_file_item);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } else {
|
|
|
+ // contextual menu for regular files
|
|
|
+ if (targetFile.isDown()) {
|
|
|
+ toHide.add(R.id.cancel_download_item);
|
|
|
+ toHide.add(R.id.cancel_upload_item);
|
|
|
+ item = menu.findItem(R.id.download_file_item);
|
|
|
+ if (item != null) {
|
|
|
+ item.setTitle(R.string.filedetails_sync_file);
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ toHide.add(R.id.open_file_item);
|
|
|
+ }
|
|
|
+ if ( mContainerActivity.getFileDownloaderBinder().isDownloading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)) {
|
|
|
+ toHide.add(R.id.download_file_item);
|
|
|
+ toHide.add(R.id.cancel_upload_item);
|
|
|
+ toDisable.add(R.id.open_file_item);
|
|
|
+ toDisable.add(R.id.rename_file_item);
|
|
|
+ toDisable.add(R.id.remove_file_item);
|
|
|
+
|
|
|
+ } else if ( mContainerActivity.getFileUploaderBinder().isUploading(AccountUtils.getCurrentOwnCloudAccount(getActivity()), targetFile)) {
|
|
|
+ toHide.add(R.id.download_file_item);
|
|
|
+ toHide.add(R.id.cancel_download_item);
|
|
|
+ toDisable.add(R.id.open_file_item);
|
|
|
+ toDisable.add(R.id.rename_file_item);
|
|
|
+ toDisable.add(R.id.remove_file_item);
|
|
|
+
|
|
|
+ } else {
|
|
|
+ toHide.add(R.id.cancel_download_item);
|
|
|
+ toHide.add(R.id.cancel_upload_item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i : toHide) {
|
|
|
+ item = menu.findItem(i);
|
|
|
+ if (item != null) {
|
|
|
+ item.setVisible(false);
|
|
|
+ item.setEnabled(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ for (int i : toDisable) {
|
|
|
+ item = menu.findItem(i);
|
|
|
+ if (item != null) {
|
|
|
+ item.setEnabled(false);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * {@inhericDoc}
|
|
|
+ */
|
|
|
+ @Override
|
|
|
+ public boolean onContextItemSelected (MenuItem item) {
|
|
|
+ AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
|
|
|
+ mTargetFile = (OCFile) mAdapter.getItem(info.position);
|
|
|
+ switch (item.getItemId()) {
|
|
|
+ case R.id.rename_file_item: {
|
|
|
+ EditNameDialog dialog = EditNameDialog.newInstance(getString(R.string.rename_dialog_title), mTargetFile.getFileName(), this);
|
|
|
+ dialog.show(getFragmentManager(), EditNameDialog.TAG);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ case R.id.remove_file_item: {
|
|
|
+ int messageStringId = R.string.confirmation_remove_alert;
|
|
|
+ int posBtnStringId = R.string.confirmation_remove_remote;
|
|
|
+ int neuBtnStringId = -1;
|
|
|
+ if (mTargetFile.isDirectory()) {
|
|
|
+ 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);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ case R.id.open_file_item: {
|
|
|
+ String storagePath = mTargetFile.getStoragePath();
|
|
|
+ String encodedStoragePath = WebdavUtils.encodePath(storagePath);
|
|
|
+ try {
|
|
|
+ Intent i = new Intent(Intent.ACTION_VIEW);
|
|
|
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mTargetFile.getMimetype());
|
|
|
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
|
+ startActivity(i);
|
|
|
+
|
|
|
+ } catch (Throwable t) {
|
|
|
+ Log.e(TAG, "Fail when trying to open with the mimeType provided from the ownCloud server: " + mTargetFile.getMimetype());
|
|
|
+ boolean toastIt = true;
|
|
|
+ String mimeType = "";
|
|
|
+ try {
|
|
|
+ Intent i = new Intent(Intent.ACTION_VIEW);
|
|
|
+ mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(storagePath.substring(storagePath.lastIndexOf('.') + 1));
|
|
|
+ if (mimeType == null || !mimeType.equals(mTargetFile.getMimetype())) {
|
|
|
+ if (mimeType != null) {
|
|
|
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), mimeType);
|
|
|
+ } else {
|
|
|
+ // desperate try
|
|
|
+ i.setDataAndType(Uri.parse("file://"+ encodedStoragePath), "*/*");
|
|
|
+ }
|
|
|
+ i.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
|
|
|
+ startActivity(i);
|
|
|
+ toastIt = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (IndexOutOfBoundsException e) {
|
|
|
+ Log.e(TAG, "Trying to find out MIME type of a file without extension: " + storagePath);
|
|
|
+
|
|
|
+ } catch (ActivityNotFoundException e) {
|
|
|
+ Log.e(TAG, "No activity found to handle: " + storagePath + " with MIME type " + mimeType + " obtained from extension");
|
|
|
+
|
|
|
+ } catch (Throwable th) {
|
|
|
+ Log.e(TAG, "Unexpected problem when opening: " + storagePath, th);
|
|
|
+
|
|
|
+ } finally {
|
|
|
+ if (toastIt) {
|
|
|
+ Toast.makeText(getActivity(), "There is no application to handle file " + mTargetFile.getFileName(), Toast.LENGTH_SHORT).show();
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ case R.id.download_file_item: {
|
|
|
+ Account account = AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity());
|
|
|
+ RemoteOperation operation = new SynchronizeFileOperation(mTargetFile, null, mContainerActivity.getStorageManager(), account, true, false, getSherlockActivity());
|
|
|
+ WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(account, getSherlockActivity().getApplicationContext());
|
|
|
+ operation.execute(wc, mContainerActivity, mHandler);
|
|
|
+ getSherlockActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ case R.id.cancel_download_item: {
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ case R.id.cancel_upload_item: {
|
|
|
+ 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);
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ default:
|
|
|
+ return super.onContextItemSelected(item);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
/**
|
|
|
* Call this, when the user presses the up button
|
|
@@ -186,7 +417,7 @@ public class OCFileListFragment extends FragmentListView {
|
|
|
*
|
|
|
* @author David A. Velasco
|
|
|
*/
|
|
|
- public interface ContainerActivity extends TransferServiceGetter {
|
|
|
+ public interface ContainerActivity extends TransferServiceGetter, OnRemoteOperationListener {
|
|
|
|
|
|
/**
|
|
|
* Callback method invoked when a directory is clicked by the user on the files list
|
|
@@ -216,6 +447,77 @@ public class OCFileListFragment extends FragmentListView {
|
|
|
public OCFile getInitialDirectory();
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
+ * 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.d(TAG, "name edit dialog dismissed with new name " + newFilename);
|
|
|
+ RemoteOperation operation = new RenameFileOperation(mTargetFile,
|
|
|
+ AccountUtils.getCurrentOwnCloudAccount(getActivity()),
|
|
|
+ newFilename,
|
|
|
+ mContainerActivity.getStorageManager());
|
|
|
+ WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
|
|
|
+ operation.execute(wc, mContainerActivity, mHandler);
|
|
|
+ getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onConfirmation(String callerTag) {
|
|
|
+ if (callerTag.equals(FileDetailFragment.FTAG_CONFIRMATION)) {
|
|
|
+ if (mContainerActivity.getStorageManager().getFileById(mTargetFile.getFileId()) != null) {
|
|
|
+ RemoteOperation operation = new RemoveFileOperation( mTargetFile,
|
|
|
+ true,
|
|
|
+ mContainerActivity.getStorageManager());
|
|
|
+ WebdavClient wc = OwnCloudClientUtils.createOwnCloudClient(AccountUtils.getCurrentOwnCloudAccount(getSherlockActivity()), getSherlockActivity().getApplicationContext());
|
|
|
+ operation.execute(wc, mContainerActivity, mHandler);
|
|
|
+
|
|
|
+ getActivity().showDialog(FileDisplayActivity.DIALOG_SHORT_WAIT);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onNeutral(String callerTag) {
|
|
|
+ File f = null;
|
|
|
+ if (mTargetFile.isDirectory()) {
|
|
|
+ // TODO run in a secondary thread?
|
|
|
+ mContainerActivity.getStorageManager().removeDirectory(mTargetFile, false, true);
|
|
|
+
|
|
|
+ } else if (mTargetFile.isDown() && (f = new File(mTargetFile.getStoragePath())).exists()) {
|
|
|
+ f.delete();
|
|
|
+ mTargetFile.setStoragePath(null);
|
|
|
+ mContainerActivity.getStorageManager().saveFile(mTargetFile);
|
|
|
+ }
|
|
|
+ listDirectory();
|
|
|
+ mContainerActivity.onTransferStateChanged(mTargetFile, false, false);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void onCancel(String callerTag) {
|
|
|
+ Log.d(TAG, "REMOVAL CANCELED");
|
|
|
+ }
|
|
|
+
|
|
|
|
|
|
}
|