Clean-up and small refactorings

Conflicts:
	src/com/owncloud/android/files/FileOperationsHelper.java
	src/com/owncloud/android/ui/fragment/ExtendedListFragment.java
This commit is contained in:
David A. Velasco 2016-07-07 15:12:02 +02:00 committed by Andy Scherzinger
parent fae65e5b1e
commit db6acc6868
18 changed files with 243 additions and 456 deletions

View file

@ -457,6 +457,16 @@
<string name="local_file_not_found_toast">The file was not found in the local file system</string>
<string name="confirmation_remove_files_alert">Do you really want to remove the selected items?</string>
<string name="confirmation_remove_folders_alert">Do you really want to remove the selected items and their contents?</string>
<string name="confirmation_remove_files">selected items</string>
<plurals name="items_selected_count">
<!--
As a developer, you should always supply "one" and "other"
strings. Your translators will know which strings are actually
needed for their language. Always include %d in "one" because
translators will need to use %d for languages where "one"
doesn't mean 1 (as explained above).
-->
<item quantity="one">%d selected</item>
<item quantity="other">%d selected</item>
</plurals>
</resources>

View file

@ -44,6 +44,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
return new OCFile(source);
}
@Override
public OCFile[] newArray(int size) {
return new OCFile[size];
}

View file

@ -27,7 +27,6 @@ import android.view.MenuItem;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.services.FileDownloader;
import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder;
import com.owncloud.android.files.services.FileUploader.FileUploaderBinder;
import com.owncloud.android.lib.resources.status.OCCapability;
@ -56,8 +55,7 @@ public class FileMenuFilter {
*
* @param targetFiles List of {@link OCFile} file targets of the action to filter in the {@link Menu}.
* @param account ownCloud {@link Account} holding targetFile.
* @param cg Accessor to app components, needed to access the
* {@link FileUploader} and {@link FileDownloader} services
* @param cg Accessor to app components, needed to access synchronization services
* @param context Android {@link Context}, needed to access build setup resources.
*/
public FileMenuFilter(List<OCFile> targetFiles, Account account, ComponentsGetter cg,
@ -73,8 +71,7 @@ public class FileMenuFilter {
*
* @param targetFile {@link OCFile} target of the action to filter in the {@link Menu}.
* @param account ownCloud {@link Account} holding targetFile.
* @param cg Accessor to app components, needed to access the
* {@link FileUploader} and {@link FileDownloader} services
* @param cg Accessor to app components, needed to access synchronization services
* @param context Android {@link Context}, needed to access build setup resources.
*/
public FileMenuFilter(OCFile targetFile, Account account, ComponentsGetter cg,
@ -122,20 +119,7 @@ public class FileMenuFilter {
* @param toHide List to save the options that must be shown in the menu.
*/
private void filter(List<Integer> toShow, List <Integer> toHide) {
boolean synchronizing = false;
if (mComponentsGetter != null && !mFiles.isEmpty() && mAccount != null) {
OperationsServiceBinder opsBinder = mComponentsGetter.getOperationsServiceBinder();
FileUploaderBinder uploaderBinder = mComponentsGetter.getFileUploaderBinder();
FileDownloaderBinder downloaderBinder = mComponentsGetter.getFileDownloaderBinder();
synchronizing = (
// comparing local and remote
(opsBinder != null && opsBinder.isSynchronizing(mAccount, mFiles)) ||
// downloading
(downloaderBinder != null && downloaderBinder.isDownloading(mAccount, mFiles)) ||
// uploading
(uploaderBinder != null && uploaderBinder.isUploading(mAccount, mFiles))
);
}
boolean synchronizing = anyFileSynchronizing();
/// decision is taken for each possible action on a file in the menu
@ -148,7 +132,7 @@ public class FileMenuFilter {
}
// RENAME
if (!isSingleSelect() || synchronizing) {
if (!isSingleSelection() || synchronizing) {
toHide.add(R.id.action_rename_file);
} else {
@ -207,7 +191,7 @@ public class FileMenuFilter {
(capability.getFilesSharingApiEnabled().isTrue() ||
capability.getFilesSharingApiEnabled().isUnknown()
);
if ((!shareViaLinkAllowed && !shareWithUsersAllowed) || !isSingleSelect() || !shareApiEnabled) {
if ((!shareViaLinkAllowed && !shareWithUsersAllowed) || !isSingleSelection() || !shareApiEnabled) {
toHide.add(R.id.action_share_file);
} else {
toShow.add(R.id.action_share_file);
@ -245,12 +229,57 @@ public class FileMenuFilter {
}
private boolean isSingleSelect() {
private boolean anyFileSynchronizing() {
boolean synchronizing = false;
if (mComponentsGetter != null && !mFiles.isEmpty() && mAccount != null) {
OperationsServiceBinder opsBinder = mComponentsGetter.getOperationsServiceBinder();
FileUploaderBinder uploaderBinder = mComponentsGetter.getFileUploaderBinder();
FileDownloaderBinder downloaderBinder = mComponentsGetter.getFileDownloaderBinder();
synchronizing = (
anyFileSynchronizing(opsBinder) || // comparing local and remote
anyFileDownloading(downloaderBinder) ||
anyFileUploading(uploaderBinder)
);
}
return synchronizing;
}
private boolean anyFileSynchronizing(OperationsServiceBinder opsBinder) {
boolean synchronizing = false;
if (opsBinder != null) {
for (int i=0; !synchronizing && i < mFiles.size(); i++) {
synchronizing = opsBinder.isSynchronizing(mAccount, mFiles.get(i));
}
}
return synchronizing;
}
private boolean anyFileDownloading(FileDownloaderBinder downloaderBinder) {
boolean downloading = false;
if (downloaderBinder != null) {
for (int i=0; !downloading && i < mFiles.size(); i++) {
downloading = downloaderBinder.isDownloading(mAccount, mFiles.get(i));
}
}
return downloading;
}
private boolean anyFileUploading(FileUploaderBinder uploaderBinder) {
boolean uploading = false;
if (uploaderBinder != null) {
for (int i=0; !uploading && i < mFiles.size(); i++) {
uploading = uploaderBinder.isUploading(mAccount, mFiles.get(i));
}
}
return uploading;
}
private boolean isSingleSelection() {
return mFiles.size() == SINGLE_SELECT_ITEMS;
}
private boolean isSingleFile() {
return isSingleSelect() && !mFiles.get(0).isFolder();
return isSingleSelection() && !mFiles.get(0).isFolder();
}
private boolean allFiles() {

View file

@ -552,36 +552,37 @@ public class FileOperationsHelper {
}
/**
* Start move file operation
* Start operations to move on or several files
*
* @param newfile File where it is going to be moved
* @param currentFile File with the previous info
* @param files Files to move
* @param targetFolder Folder where the files while be moved into
*/
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().queueNewOperation(service);
public void moveFiles(Collection<OCFile> files, OCFile targetFolder) {
for (OCFile file : files) {
Intent service = new Intent(mFileActivity, OperationsService.class);
service.setAction(OperationsService.ACTION_MOVE_FILE);
service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, targetFolder.getRemotePath());
service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
}
}
/**
* Start copy file operation
*
* @param newfile File where it is going to be moved
* @param currentFile File with the previous info
* @param files Files to move
* @param targetFolder Folder where the files while be copied into
*/
public void copyFile(OCFile newfile, OCFile currentFile) {
// Copy files
Intent service = new Intent(mFileActivity, OperationsService.class);
service.setAction(OperationsService.ACTION_COPY_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().queueNewOperation(service);
public void copyFiles(Collection<OCFile> files, OCFile targetFolder) {
for (OCFile file : files) {
Intent service = new Intent(mFileActivity, OperationsService.class);
service.setAction(OperationsService.ACTION_COPY_FILE);
service.putExtra(OperationsService.EXTRA_NEW_PARENT_PATH, targetFolder.getRemotePath());
service.putExtra(OperationsService.EXTRA_REMOTE_PATH, file.getRemotePath());
service.putExtra(OperationsService.EXTRA_ACCOUNT, mFileActivity.getAccount());
mWaitingForOpId = mFileActivity.getOperationsServiceBinder().queueNewOperation(service);
}
mFileActivity.showLoadingDialog(mFileActivity.getApplicationContext().
getString(R.string.wait_a_moment));

View file

@ -50,10 +50,10 @@ import com.owncloud.android.lib.common.operations.RemoteOperationResult;
import com.owncloud.android.lib.common.operations.RemoteOperationResult.ResultCode;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.lib.resources.files.FileUtils;
import com.owncloud.android.ui.notifications.NotificationUtils;
import com.owncloud.android.operations.DownloadFileOperation;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.notifications.NotificationUtils;
import com.owncloud.android.ui.preview.PreviewImageActivity;
import com.owncloud.android.ui.preview.PreviewImageFragment;
import com.owncloud.android.utils.ErrorMessageAdapter;
@ -62,7 +62,6 @@ import java.io.File;
import java.util.AbstractList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
@ -302,26 +301,6 @@ public class FileDownloader extends Service
return (mPendingDownloads.contains(account.name, file.getRemotePath()));
}
/**
* Returns True when the file described by 'file' in the ownCloud account 'account'
* is downloading or waiting to download.
*
* If 'file' is a directory, returns 'true' if any of its descendant files is downloading or
* waiting to download.
*
* @param account ownCloud account where the remote file is stored.
* @param files A list of files that could contains someone in the queue of downloads.
*/
public boolean isDownloading(Account account, List<OCFile> files) {
if (account == null || files.isEmpty()) return false;
for(OCFile file: files) {
if(mPendingDownloads.contains(account.name, file.getRemotePath())) {
return true;
}
}
return false;
}
/**
* Adds a listener interested in the progress of the download for a concrete file.

View file

@ -70,7 +70,6 @@ import com.owncloud.android.utils.ErrorMessageAdapter;
import java.util.AbstractList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Vector;
@ -735,26 +734,6 @@ public class FileUploader extends Service
);
}
/**
* Returns True when the file described by 'file' is being uploaded to
* the ownCloud account 'account' or waiting for it
*
* If 'file' is a directory, returns 'true' if some of its descendant files
* is uploading or waiting to upload.
*
* @param account ownCloud account where the remote file will be stored.
* @param files A list of files that could contains someone in the queue of pending uploads
*/
public boolean isUploading(Account account, List<OCFile> files) {
if (account == null || files.isEmpty()) return false;
for(OCFile file: files) {
if(mPendingUploads.contains(account.name, file.getRemotePath())) {
return true;
}
}
return false;
}
/**
* Adds a listener interested in the progress of the upload for a concrete file.

View file

@ -387,26 +387,6 @@ public class OperationsService extends Service {
return mSyncFolderHandler.isSynchronizing(account, file.getRemotePath());
}
/**
* Returns True when the file described by 'file' in the ownCloud account 'account' is
* downloading or waiting to download.
*
* If 'file' is a directory, returns 'true' if some of its descendant files is downloading
* or waiting to download.
*
* @param account ownCloud account where the remote file is stored.
* @param files List of files to check if something is synchronizing
* / downloading / uploading inside.
*/
public boolean isSynchronizing(Account account, List<OCFile> files) {
for(OCFile file: files) {
if(isSynchronizing(account, file)) {
return true;
}
}
return false;
}
}

View file

@ -330,6 +330,9 @@ public class FileDisplayActivity extends HookActivity
private void createMinFragments() {
OCFileListFragment listOfFiles = new OCFileListFragment();
Bundle args = new Bundle();
args.putBoolean(OCFileListFragment.ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
listOfFiles.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
transaction.add(R.id.left_fragment_container, listOfFiles, TAG_LIST_OF_FILES);
transaction.commit();
@ -657,12 +660,11 @@ public class FileDisplayActivity extends HookActivity
} else if (requestCode == REQUEST_CODE__MOVE_FILES && resultCode == RESULT_OK) {
final Intent fData = data;
final int fResultCode = resultCode;
getHandler().postDelayed(
new Runnable() {
@Override
public void run() {
requestMoveOperation(fData, fResultCode);
requestMoveOperation(fData);
}
},
DELAY_TO_REQUEST_OPERATIONS_LATER
@ -676,7 +678,7 @@ public class FileDisplayActivity extends HookActivity
new Runnable() {
@Override
public void run() {
requestCopyOperation(fData, fResultCode);
requestCopyOperation(fData);
}
},
DELAY_TO_REQUEST_OPERATIONS_LATER
@ -762,32 +764,22 @@ public class FileDisplayActivity extends HookActivity
* Request the operation for moving the file/folder from one path to another
*
* @param data Intent received
* @param resultCode Result code received
*/
private void requestMoveOperation(Intent data, int resultCode) {
OCFile folderToMoveAt = (OCFile) data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
private void requestMoveOperation(Intent data) {
OCFile folderToMoveAt = data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
ArrayList<OCFile> files = data.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
for (Parcelable file : files) {
getFileOperationsHelper().moveFile(folderToMoveAt, (OCFile) file);
}
getFileOperationsHelper().moveFiles(files, folderToMoveAt);
}
/**
* Request the operation for copying the file/folder from one path to another
*
* @param data Intent received
* @param resultCode Result code received
*/
private void requestCopyOperation(Intent data, int resultCode) {
private void requestCopyOperation(Intent data) {
OCFile folderToMoveAt = data.getParcelableExtra(FolderPickerActivity.EXTRA_FOLDER);
ArrayList<OCFile> files = data.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
for (Parcelable file : files) {
getFileOperationsHelper().copyFile(folderToMoveAt, (OCFile) file);
}
getFileOperationsHelper().copyFiles(files, folderToMoveAt);
}
@Override

View file

@ -60,13 +60,10 @@ import java.util.ArrayList;
public class FolderPickerActivity extends FileActivity implements FileFragment.ContainerActivity,
OnClickListener, OnEnforceableRefreshListener {
public static final String EXTRA_FOLDER = UploadFilesActivity.class.getCanonicalName()
public static final String EXTRA_FOLDER = FolderPickerActivity.class.getCanonicalName()
+ ".EXTRA_FOLDER";
public static final String EXTRA_FILE = UploadFilesActivity.class.getCanonicalName()
+ ".EXTRA_FILE";
public static final String EXTRA_FILES = UploadFilesActivity.class.getCanonicalName()
public static final String EXTRA_FILES = FolderPickerActivity.class.getCanonicalName()
+ ".EXTRA_FILES";
//TODO: Think something better
private SyncBroadcastReceiver mSyncBroadcastReceiver;
@ -151,7 +148,6 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
OCFileListFragment listOfFiles = new OCFileListFragment();
Bundle args = new Bundle();
args.putBoolean(OCFileListFragment.ARG_JUST_FOLDERS, true);
args.putBoolean(OCFileListFragment.ARG_ALLOW_CONTEXTUAL_ACTIONS, false);
args.putBoolean(OCFileListFragment.ARG_HIDE_FAB, true);
listOfFiles.setArguments(args);
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
@ -373,17 +369,11 @@ public class FolderPickerActivity extends FileActivity implements FileFragment.C
finish();
} else if (v == mChooseBtn) {
Intent i = getIntent();
Parcelable targetFile = i.getParcelableExtra(FolderPickerActivity.EXTRA_FILE);
ArrayList<Parcelable> targetFiles = i.getParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES);
Intent data = new Intent();
data.putExtra(EXTRA_FOLDER, getCurrentFolder());
if (targetFile != null) {
data.putExtra(EXTRA_FILE, targetFile);
}
if (targetFiles != null){
data.putParcelableArrayListExtra(EXTRA_FILES, targetFiles);
}
data.putParcelableArrayListExtra(EXTRA_FILES, targetFiles);
setResult(RESULT_OK, data);
finish();

View file

@ -468,11 +468,6 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
}
private CharSequence showRelativeTimestamp(OCFile file) {
return DisplayUtils.getRelativeDateTimeString(mContext, file.getModificationTimestamp(),
DateUtils.SECOND_IN_MILLIS, DateUtils.WEEK_IN_MILLIS, 0);
}
public void setGridMode(boolean gridMode) {
mGridMode = gridMode;
}
@ -481,7 +476,7 @@ public class FileListListAdapter extends BaseAdapter implements ListAdapter {
return mSelection.contains(getItemId(position));
}
public void setNewSelection(int position, boolean checked) {
public void updateSelection(int position, boolean checked) {
if (checked) {
mSelection.add(getItemId(position));
notifyDataSetChanged();

View file

@ -1,109 +0,0 @@
/**
* ownCloud Android client application
*
* @author David A. Velasco
* Copyright (C) 2015 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.
*/
import android.app.Dialog;
import android.os.Bundle;
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;
public class RemoveFileDialogFragment extends ConfirmationDialogFragment
implements ConfirmationDialogFragmentListener {
private OCFile mTargetFile;
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 = (file.isFolder()) ?
R.string.confirmation_remove_folder_alert :
R.string.confirmation_remove_file_alert;
int localRemoveButton = (!file.isFavorite() && (file.isFolder() || file.isDown())) ?
R.string.confirmation_remove_local :
-1;
args.putInt(ARG_MESSAGE_RESOURCE_ID, messageStringId);
args.putStringArray(ARG_MESSAGE_ARGUMENTS, new String[]{file.getFileName()});
args.putInt(ARG_POSITIVE_BTN_RES, R.string.common_yes);
args.putInt(ARG_NEUTRAL_BTN_RES, R.string.common_no);
args.putInt(ARG_NEGATIVE_BTN_RES, localRemoveButton);
args.putParcelable(ARG_TARGET_FILE, file);
frag.setArguments(args);
return frag;
}
@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)getActivity();
FileDataStorageManager storageManager = cg.getStorageManager();
if (storageManager.getFileById(mTargetFile.getFileId()) != null) {
cg.getFileOperationsHelper().removeFile(mTargetFile, false);
}
}
/**
* Performs the removal of the local copy of the target file
*/
@Override
public void onCancel(String callerTag) {
ComponentsGetter cg = (ComponentsGetter)getActivity();
cg.getFileOperationsHelper().removeFile(mTargetFile, true);
}
@Override
public void onNeutral(String callerTag) {
// nothing to do here
}
}

View file

@ -21,16 +21,14 @@
package com.owncloud.android.ui.dialog;
/**
* Dialog requiring confirmation before removing a given OCFile.
* Dialog requiring confirmation before removing a collection of given OCFiles.
*
* Triggers the removal according to the user response.
*/
import android.app.Dialog;
import android.content.res.Resources;
import android.os.Bundle;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
@ -38,7 +36,6 @@ import com.owncloud.android.ui.activity.ComponentsGetter;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
import java.util.ArrayList;
import java.util.Vector;
public class RemoveFilesDialogFragment extends ConfirmationDialogFragment
implements ConfirmationDialogFragmentListener {
@ -48,7 +45,7 @@ implements ConfirmationDialogFragmentListener {
private static final String ARG_TARGET_FILES = "TARGET_FILES";
/**
* Public factory method to create new RemoveFileDialogFragment instances.
* Public factory method to create new RemoveFilesDialogFragment instances.
*
* @param files Files to remove.
* @return Dialog ready to show.
@ -56,6 +53,7 @@ implements ConfirmationDialogFragmentListener {
public static RemoveFilesDialogFragment newInstance(ArrayList<OCFile> files) {
RemoveFilesDialogFragment frag = new RemoveFilesDialogFragment();
Bundle args = new Bundle();
int messageStringId;
boolean containsFolder = false;
boolean containsDown = false;
@ -66,16 +64,30 @@ implements ConfirmationDialogFragmentListener {
if (file.isFavorite()) containsFavorite = true;
}
int messageStringId = (containsFolder) ?
R.string.confirmation_remove_folders_alert :
R.string.confirmation_remove_files_alert;
if (files.size() == 1) {
// choose message for a single file
OCFile file = files.get(0);
messageStringId = (file.isFolder()) ?
R.string.confirmation_remove_folder_alert :
R.string.confirmation_remove_file_alert;
} else {
// choose message for more than one file
messageStringId = (containsFolder) ?
R.string.confirmation_remove_folders_alert :
R.string.confirmation_remove_files_alert;
}
int localRemoveButton = (!containsFavorite && (containsFolder || containsDown)) ?
R.string.confirmation_remove_local :
-1;
args.putInt(ARG_MESSAGE_RESOURCE_ID, messageStringId);
args.putStringArray(ARG_MESSAGE_ARGUMENTS, new String[]{MainApp.getAppContext().getString(R.string.confirmation_remove_files)});
if (files.size() == 1) {
args.putStringArray(ARG_MESSAGE_ARGUMENTS, new String[]{files.get(0).getFileName()});
}
args.putInt(ARG_POSITIVE_BTN_RES, R.string.common_yes);
args.putInt(ARG_NEUTRAL_BTN_RES, R.string.common_no);
args.putInt(ARG_NEGATIVE_BTN_RES, localRemoveButton);
@ -85,6 +97,20 @@ implements ConfirmationDialogFragmentListener {
return frag;
}
/**
* Convenience factory method to create new RemoveFilesDialogFragment instances for a single file
*
* @param file File to remove.
* @return Dialog ready to show.
*/
public static RemoveFilesDialogFragment newInstance(OCFile file) {
ArrayList<OCFile> list = new ArrayList<>();
list.add(file);
return newInstance(list);
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
Dialog dialog = super.onCreateDialog(savedInstanceState);
@ -115,37 +141,8 @@ implements ConfirmationDialogFragmentListener {
@Override
public void onCancel(String callerTag) {
ComponentsGetter cg = (ComponentsGetter) getActivity();
for (OCFile targetFile : mTargetFiles) {
cg.getFileOperationsHelper().removeFile(targetFile, true);
FileDataStorageManager storageManager = cg.getStorageManager();
boolean containsFavorite = false;
if (targetFile.isFolder()) {
// TODO Enable when "On Device" is recovered ?
Vector<OCFile> files = storageManager.getFolderContent(targetFile/*, false*/);
for (OCFile file : files) {
containsFavorite = file.isFavorite() || containsFavorite;
if (containsFavorite)
break;
}
}
// Remove etag for parent, if file is a favorite
// or is a folder and contains favorite
if (targetFile.isFavorite() || containsFavorite) {
OCFile folder = null;
if (targetFile.isFolder()) {
folder = targetFile;
} else {
folder = storageManager.getFileById(targetFile.getParentId());
}
folder.setEtag("");
storageManager.saveFile(folder);
}
}
}

View file

@ -174,7 +174,6 @@ public class ExtendedListFragment extends Fragment
mGridView = (GridViewWithHeaderAndFooter) (v.findViewById(R.id.grid_root));
mGridView.setNumColumns(GridView.AUTO_FIT);
mGridView.setOnItemClickListener(this);
mGridView.setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
mGridFooterView = inflater.inflate(R.layout.list_footer, null, false);

View file

@ -48,7 +48,7 @@ import com.owncloud.android.lib.common.network.OnDatatransferProgressListener;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.MimetypeIconUtil;
@ -255,7 +255,7 @@ public class FileDetailFragment extends FileFragment implements OnClickListener
return true;
}
case R.id.action_remove_file: {
RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(getFile());
dialog.show(getFragmentManager(), FTAG_CONFIRMATION);
return true;
}

View file

@ -22,7 +22,6 @@
*/
package com.owncloud.android.ui.fragment;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
@ -30,7 +29,6 @@ import android.os.Build;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.support.v4.widget.SwipeRefreshLayout;
import android.util.SparseBooleanArray;
import android.view.ActionMode;
import android.view.LayoutInflater;
import android.view.Menu;
@ -38,9 +36,10 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.widget.AbsListView;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
@ -59,8 +58,6 @@ import com.owncloud.android.ui.activity.UploadFilesActivity;
import com.owncloud.android.ui.adapter.FileListListAdapter;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.CreateFolderDialogFragment;
import com.owncloud.android.ui.dialog.FileActionsDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.dialog.RenameFileDialogFragment;
import com.owncloud.android.ui.preview.PreviewImageFragment;
@ -104,7 +101,7 @@ public class OCFileListFragment extends ExtendedListFragment {
private int mStatusBarColorActionMode;
private int mStatusBarColor;
private boolean hideFab = true;
private boolean mHideFab = true;
private boolean miniFabClicked = false;
private ActionMode mActiveActionMode;
@ -113,28 +110,27 @@ public class OCFileListFragment extends ExtendedListFragment {
super.onCreate(savedInstanceState);
setHasOptionsMenu(true);
mStatusBarColorActionMode = getResources().getColor(R.color.action_mode_status_bar_background);
mStatusBarColor = getResources().getColor(R.color.primary_dark);
}
/**
* {@inheritDoc}
*/
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
public void onAttach(Context context) {
super.onAttach(context);
Log_OC.e(TAG, "onAttach");
try {
mContainerActivity = (FileFragment.ContainerActivity) activity;
mContainerActivity = (FileFragment.ContainerActivity) context;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement " +
throw new ClassCastException(context.toString() + " must implement " +
FileFragment.ContainerActivity.class.getSimpleName());
}
try {
setOnRefreshListener((OnEnforceableRefreshListener) activity);
setOnRefreshListener((OnEnforceableRefreshListener) context);
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString() + " must implement " +
throw new ClassCastException(context.toString() + " must implement " +
SwipeRefreshLayout.OnRefreshListener.class.getSimpleName());
}
}
@ -146,7 +142,11 @@ public class OCFileListFragment extends ExtendedListFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
Log_OC.i(TAG, "onCreateView() start");
View v = super.onCreateView(inflater, container, savedInstanceState);
Bundle args = getArguments();
boolean allowContextualActions = (args != null) && args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, false);
if (allowContextualActions) {
setChoiceModeAsMultipleModal();
}
Log_OC.i(TAG, "onCreateView() end");
return v;
}
@ -178,7 +178,7 @@ public class OCFileListFragment extends ExtendedListFragment {
}
Bundle args = getArguments();
mJustFolders = (args == null) ? false : args.getBoolean(ARG_JUST_FOLDERS, false);
mJustFolders = (args != null) && args.getBoolean(ARG_JUST_FOLDERS, false);
mAdapter = new FileListListAdapter(
mJustFolders,
getActivity(),
@ -187,10 +187,8 @@ public class OCFileListFragment extends ExtendedListFragment {
mAdapter.restoreSelectionState(savedInstanceState);
setListAdapter(mAdapter);
registerLongClickListener();
hideFab = (args != null) && args.getBoolean(ARG_HIDE_FAB, false);
if (hideFab) {
mHideFab = (args != null) && args.getBoolean(ARG_HIDE_FAB, false);
if (mHideFab) {
setFabEnabled(false);
} else {
setFabEnabled(true);
@ -343,12 +341,15 @@ public class OCFileListFragment extends ExtendedListFragment {
com.getbase.floatingactionbutton.R.id.fab_label)).setVisibility(View.GONE);
}
private void registerLongClickListener() {
private void setChoiceModeAsMultipleModal() {
setChoiceMode(ListView.CHOICE_MODE_MULTIPLE_MODAL);
setMultiChoiceModeListener(new AbsListView.MultiChoiceModeListener() {
@Override
public void onItemCheckedStateChanged(ActionMode mode, int position, long id, boolean checked) {
mAdapter.setNewSelection(position, checked);
mAdapter.updateSelection(position, checked);
mode.invalidate();
}
@ -356,12 +357,15 @@ public class OCFileListFragment extends ExtendedListFragment {
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
mActiveActionMode = mode;
createContextActionBar(menu);
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.file_actions_menu, menu);
mode.invalidate();
//set gray color
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(mStatusBarColorActionMode);
Window w = getActivity().getWindow();
mStatusBarColor = w.getStatusBarColor();
w.setStatusBarColor(mStatusBarColorActionMode);
}
// hide FAB in multi selection mode
@ -372,22 +376,23 @@ public class OCFileListFragment extends ExtendedListFragment {
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
final int checkedCount = getListView().getCheckedItemCount();
mode.setTitle(checkedCount + " selected");
String title = getResources().getQuantityString(
R.plurals.items_selected_count,
checkedCount,
checkedCount
);
mode.setTitle(title);
if (checkedCount > 0) {
List<OCFile> targetFiles = mAdapter.getCheckedItems();
if (mContainerActivity.getStorageManager() != null) {
FileMenuFilter mf = new FileMenuFilter(
targetFiles,
mContainerActivity.getStorageManager().getAccount(),
mContainerActivity,
getActivity()
);
mf.filter(menu);
}
FileMenuFilter mf = new FileMenuFilter(
targetFiles,
((FileActivity) getActivity()).getAccount(),
mContainerActivity,
getActivity()
);
mf.filter(menu);
}
return true;
}
@ -400,16 +405,16 @@ public class OCFileListFragment extends ExtendedListFragment {
@Override
public void onDestroyActionMode(ActionMode mode) {
mActiveActionMode = null;
getListView().clearChoices();
//getListView().clearChoices();
mAdapter.clearSelection();
// reset to primary dark color
// reset to previous color
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
getActivity().getWindow().setStatusBarColor(mStatusBarColor);
}
// show FAB on multi selection mode exit
if(!hideFab) {
if(!mHideFab) {
setFabEnabled(true);
}
}
@ -519,148 +524,87 @@ public class OCFileListFragment extends ExtendedListFragment {
}
/**
* Create the context bar with the file actions
* @param menu
* Start the appropriate action(s) on the currently selected files given menu selected by the user.
*
* @param menuId Identifier of the action menu selected by the user
* @return 'true' if the menu selection started any action, 'false' otherwise.
*/
public void createContextActionBar(Menu menu) {
Bundle args = getArguments();
boolean allowContextualActions =
(args == null) ? true : args.getBoolean(ARG_ALLOW_CONTEXTUAL_ACTIONS, true);
if (allowContextualActions) {
MenuInflater inflater = getActivity().getMenuInflater();
inflater.inflate(R.menu.file_actions_menu, menu);
}
}
public boolean onFileActionChosen(int menuId) {
final ArrayList<OCFile> checkedItems = mAdapter.getCheckedItems();
if (checkedItems.size() == 1){
OCFile mTargetFile = checkedItems.get(0);
final ArrayList<OCFile> checkedFiles = mAdapter.getCheckedItems();
if (checkedFiles.size() <= 0) return false;
if (checkedFiles.size() == 1) {
/// action only possible on a single file
OCFile singleFile = checkedFiles.get(0);
switch (menuId) {
case R.id.action_share_file: {
mContainerActivity.getFileOperationsHelper().showShareFile(mTargetFile);
mContainerActivity.getFileOperationsHelper().showShareFile(singleFile);
return true;
}
case R.id.action_open_file_with: {
mContainerActivity.getFileOperationsHelper().openFile(mTargetFile);
mContainerActivity.getFileOperationsHelper().openFile(singleFile);
return true;
}
case R.id.action_rename_file: {
RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(mTargetFile);
RenameFileDialogFragment dialog = RenameFileDialogFragment.newInstance(singleFile);
dialog.show(getFragmentManager(), FileDetailFragment.FTAG_RENAME_FILE);
return true;
}
case R.id.action_remove_file: {
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: {
mContainerActivity.getFileOperationsHelper().syncFile(mTargetFile);
return true;
}
case R.id.action_cancel_sync: {
((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFile);
return true;
}
case R.id.action_see_details: {
mContainerActivity.showDetails(mTargetFile);
mContainerActivity.showDetails(singleFile);
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);
if (!singleFile.isDown()) { // Download the file
Log_OC.d(TAG, singleFile.getRemotePath() + " : File must be downloaded");
((FileDisplayActivity) mContainerActivity).startDownloadForSending(singleFile);
} else {
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(mTargetFile);
mContainerActivity.getFileOperationsHelper().sendDownloadedFile(singleFile);
}
return true;
}
case R.id.action_move: {
Intent action = new Intent(getActivity(), FolderPickerActivity.class);
ArrayList files = new ArrayList();
files.add(mTargetFile);
action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, files);
getActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__MOVE_FILES);
return true;
}
case R.id.action_favorite_file: {
mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, true);
return true;
}
case R.id.action_unfavorite_file: {
mContainerActivity.getFileOperationsHelper().toggleFavorite(mTargetFile, false);
return true;
}
case R.id.action_copy:
Intent action = new Intent(getActivity(), FolderPickerActivity.class);
ArrayList files = new ArrayList();
files.add(mTargetFile);
action.putExtra(FolderPickerActivity.EXTRA_FILES, files);
getActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__COPY_FILES);
return true;
default:
return false;
}
} else {
ArrayList<OCFile> mTargetFiles = checkedItems;
switch (menuId) {
case R.id.action_remove_file: {
RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(mTargetFiles);
dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
return true;
}
case R.id.action_download_file:
case R.id.action_sync_file: {
mContainerActivity.getFileOperationsHelper().syncFiles(mTargetFiles);
return true;
}
case R.id.action_cancel_sync: {
((FileDisplayActivity) mContainerActivity).cancelTransference(mTargetFiles);
return true;
}
case R.id.action_move: {
Intent action = new Intent(getActivity(), FolderPickerActivity.class);
action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
getActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__MOVE_FILES);
return true;
}
case R.id.action_favorite_file: {
mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, true);
return true;
}
case R.id.action_unfavorite_file: {
mContainerActivity.getFileOperationsHelper().toggleFavorites(mTargetFiles, false);
return true;
}
case R.id.action_copy:
Intent action = new Intent(getActivity(), FolderPickerActivity.class);
action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, mTargetFiles);
getActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__COPY_FILES);
return true;
default:
return false;
}
}
}
/**
* {@inhericDoc}
*/
@Override
public boolean onContextItemSelected (MenuItem item) {
AdapterContextMenuInfo info = (AdapterContextMenuInfo) item.getMenuInfo();
boolean matched = onFileActionChosen(item.getItemId());
if(!matched) {
return super.onContextItemSelected(item);
} else {
return matched;
/// actions possible on a batch of files
switch (menuId) {
case R.id.action_remove_file: {
RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(checkedFiles);
dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
return true;
}
case R.id.action_download_file:
case R.id.action_sync_file: {
mContainerActivity.getFileOperationsHelper().syncFiles(checkedFiles);
return true;
}
case R.id.action_cancel_sync: {
((FileDisplayActivity) mContainerActivity).cancelTransference(checkedFiles);
return true;
}
case R.id.action_favorite_file: {
mContainerActivity.getFileOperationsHelper().toggleFavorites(checkedFiles, true);
return true;
}
case R.id.action_unfavorite_file: {
mContainerActivity.getFileOperationsHelper().toggleFavorites(checkedFiles, false);
return true;
}
case R.id.action_move: {
Intent action = new Intent(getActivity(), FolderPickerActivity.class);
action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, checkedFiles);
getActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__MOVE_FILES);
return true;
}
case R.id.action_copy:
Intent action = new Intent(getActivity(), FolderPickerActivity.class);
action.putParcelableArrayListExtra(FolderPickerActivity.EXTRA_FILES, checkedFiles);
getActivity().startActivityForResult(action, FileDisplayActivity.REQUEST_CODE__COPY_FILES);
return true;
default:
return false;
}
}

View file

@ -46,7 +46,7 @@ import com.owncloud.android.datamodel.OCFile;
import com.owncloud.android.files.FileMenuFilter;
import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import com.owncloud.android.utils.BitmapUtils;
import com.owncloud.android.utils.DisplayUtils;
@ -294,7 +294,7 @@ public class PreviewImageFragment extends FileFragment {
return true;
}
case R.id.action_remove_file: {
RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(getFile());
dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
return true;
}

View file

@ -59,7 +59,7 @@ import com.owncloud.android.media.MediaService;
import com.owncloud.android.media.MediaServiceBinder;
import com.owncloud.android.ui.activity.FileActivity;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.fragment.FileFragment;
@ -357,7 +357,7 @@ public class PreviewMediaFragment extends FileFragment implements
return true;
}
case R.id.action_remove_file: {
RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(getFile());
dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
return true;
}

View file

@ -40,7 +40,7 @@ import com.owncloud.android.lib.common.utils.Log_OC;
import com.owncloud.android.ui.activity.FileDisplayActivity;
import com.owncloud.android.ui.dialog.ConfirmationDialogFragment;
import com.owncloud.android.ui.dialog.LoadingDialog;
import com.owncloud.android.ui.dialog.RemoveFileDialogFragment;
import com.owncloud.android.ui.dialog.RemoveFilesDialogFragment;
import com.owncloud.android.ui.fragment.FileFragment;
import java.io.BufferedWriter;
@ -340,7 +340,7 @@ public class PreviewTextFragment extends FileFragment {
return true;
}
case R.id.action_remove_file: {
RemoveFileDialogFragment dialog = RemoveFileDialogFragment.newInstance(getFile());
RemoveFilesDialogFragment dialog = RemoveFilesDialogFragment.newInstance(getFile());
dialog.show(getFragmentManager(), ConfirmationDialogFragment.FTAG_CONFIRMATION);
return true;
}