Add more descriptive UI for conflicts while renaming.
Test: updated existing rename conflict test and ran all
Bug: 31647077
Change-Id: I013bb9348e4691aea42f41f58af83e18e8ca106d
diff --git a/src/com/android/documentsui/dirlist/DirectoryFragment.java b/src/com/android/documentsui/dirlist/DirectoryFragment.java
index 0aaa12a..eae5187 100644
--- a/src/com/android/documentsui/dirlist/DirectoryFragment.java
+++ b/src/com/android/documentsui/dirlist/DirectoryFragment.java
@@ -817,7 +817,7 @@
// Model must be accessed in UI thread, since underlying cursor is not threadsafe.
List<DocumentInfo> docs = mModel.getDocuments(selected);
- RenameDocumentFragment.show(getFragmentManager(), docs.get(0));
+ RenameDocumentFragment.show(getFragmentManager(), docs.get(0), mModel::hasFileWithName);
}
private boolean isDocumentEnabled(String mimeType, int flags) {
diff --git a/src/com/android/documentsui/dirlist/Model.java b/src/com/android/documentsui/dirlist/Model.java
index 7a76098..9ba8b5c 100644
--- a/src/com/android/documentsui/dirlist/Model.java
+++ b/src/com/android/documentsui/dirlist/Model.java
@@ -45,8 +45,10 @@
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.function.Predicate;
/**
@@ -82,12 +84,14 @@
private static final String TAG = "Model";
+ /** Maps Model ID to cursor positions, for looking up items by Model ID. */
+ private final Map<String, Integer> mPositions = new HashMap<>();
+ private final Set<String> mFileNames = new HashSet<>();
+
private boolean mIsLoading;
private List<EventListener<Update>> mUpdateListeners = new ArrayList<>();
@Nullable private Cursor mCursor;
private int mCursorCount;
- /** Maps Model ID to cursor positions, for looking up items by Model ID. */
- private Map<String, Integer> mPositions = new HashMap<>();
private String mIds[] = new String[0];
@Nullable String info;
@@ -133,6 +137,7 @@
error = null;
doc = null;
mIsLoading = false;
+ mFileNames.clear();
notifyUpdateListeners();
}
@@ -174,7 +179,7 @@
*/
private void updateModelData() {
mIds = new String[mCursorCount];
-
+ mFileNames.clear();
mCursor.moveToPosition(-1);
for (int pos = 0; pos < mCursorCount; ++pos) {
if (!mCursor.moveToNext()) {
@@ -191,6 +196,7 @@
} else {
mIds[pos] = getCursorString(mCursor, Document.COLUMN_DOCUMENT_ID);
}
+ mFileNames.add(getCursorString(mCursor, Document.COLUMN_DISPLAY_NAME));
}
// Populate the positions.
@@ -200,6 +206,10 @@
}
}
+ public boolean hasFileWithName(String name) {
+ return mFileNames.contains(name);
+ }
+
public @Nullable Cursor getItem(String modelId) {
Integer pos = mPositions.get(modelId);
if (pos == null) {
diff --git a/src/com/android/documentsui/dirlist/RenameDocumentFragment.java b/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
index ec91fe6..e2b87ea 100644
--- a/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
+++ b/src/com/android/documentsui/dirlist/RenameDocumentFragment.java
@@ -33,11 +33,13 @@
import android.provider.DocumentsContract;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
+import android.support.design.widget.TextInputLayout;
import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
@@ -50,6 +52,8 @@
import com.android.documentsui.base.Shared;
import com.android.documentsui.ui.Snackbars;
+import java.util.function.Predicate;
+
/**
* Dialog to rename file or directory.
*/
@@ -57,10 +61,15 @@
private static final String TAG_RENAME_DOCUMENT = "rename_document";
private DocumentInfo mDocument;
private EditText mEditText;
+ private TextInputLayout mRenameInputWrapper;
+ private Predicate<String> mHasFileNamed;
+ private @Nullable DialogInterface mDialog;
- public static void show(FragmentManager fm, DocumentInfo document) {
+ public static void show(
+ FragmentManager fm, DocumentInfo document, Predicate<String> hasFileNamed) {
final RenameDocumentFragment dialog = new RenameDocumentFragment();
dialog.mDocument = document;
+ dialog.mHasFileNamed = hasFileNamed;
dialog.show(fm, TAG_RENAME_DOCUMENT);
}
@@ -77,22 +86,16 @@
View view = dialogInflater.inflate(R.layout.dialog_file_name, null, false);
mEditText = (EditText) view.findViewById(android.R.id.text1);
+ mRenameInputWrapper = (TextInputLayout) view.findViewById(R.id.rename_input_wrapper);
builder.setTitle(R.string.menu_rename);
builder.setView(view);
-
- builder.setPositiveButton(
- android.R.string.ok,
- new OnClickListener() {
- @Override
- public void onClick(DialogInterface dialog, int which) {
- renameDocuments(mEditText.getText().toString());
- }
- });
-
+ builder.setPositiveButton(android.R.string.ok, null);
builder.setNegativeButton(android.R.string.cancel, null);
final AlertDialog dialog = builder.create();
+ dialog.setOnShowListener(this::onShowDialog);
+
// Workaround for the problem - virtual keyboard doesn't show on the phone.
Shared.ensureKeyboardPresent(context, dialog);
@@ -105,8 +108,6 @@
&& event.getKeyCode() == KeyEvent.KEYCODE_ENTER
&& event.hasNoModifiers())) {
renameDocuments(mEditText.getText().toString());
- dialog.dismiss();
- return true;
}
return false;
}
@@ -114,6 +115,16 @@
return dialog;
}
+ private void onShowDialog(DialogInterface dialog){
+ mDialog = dialog;
+ Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
+ button.setOnClickListener(this::onClickDialog);
+ }
+
+ private void onClickDialog(View view) {
+ renameDocuments(mEditText.getText().toString());
+ }
+
/**
* Sets/Restores the data.
* @param savedInstanceState
@@ -182,12 +193,16 @@
private void renameDocuments(String newDisplayName) {
BaseActivity activity = (BaseActivity) getActivity();
- if (isValidDocumentName(newDisplayName)) {
- new RenameDocumentsTask(activity, newDisplayName).execute(mDocument);
- } else {
+ if (!isValidDocumentName(newDisplayName)) {
Log.w(TAG, "Failed to rename file - invalid name:" + newDisplayName);
Snackbars.makeSnackbar(getActivity(), R.string.rename_error,
Snackbar.LENGTH_SHORT).show();
+ } else if (mHasFileNamed.test(newDisplayName)){
+ mRenameInputWrapper.setError(getContext().getString(R.string.name_conflict));
+ selectFileName(mEditText);
+ Metrics.logRenameFileError(getContext());
+ } else {
+ new RenameDocumentsTask(activity, newDisplayName).execute(mDocument);
}
}
@@ -234,6 +249,9 @@
Snackbars.showRenameFailed(mActivity);
Metrics.logRenameFileError(getContext());
}
+ if (mDialog != null) {
+ mDialog.dismiss();
+ }
mActivity.setPending(false);
}
}