diff --git a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/FileChooserActivity.java b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/FileChooserActivity.java index e75ec3c6..51cf6d31 100644 --- a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/FileChooserActivity.java +++ b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/FileChooserActivity.java @@ -13,6 +13,9 @@ import group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileContra import group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileProvider; import group.pals.android.lib.ui.filechooser.utils.ui.Dlg; import group.pals.android.lib.ui.filechooser.utils.ui.Ui; + +import java.util.ArrayList; + import android.content.Context; import android.content.res.Configuration; import android.net.Uri; @@ -111,8 +114,9 @@ public class FileChooserActivity extends FragmentActivity { * Key to hold filter mode, can be one of * {@link BaseFile#FILTER_DIRECTORIES_ONLY}, * {@link BaseFile#FILTER_FILES_AND_DIRECTORIES}, - * {@link BaseFile#FILTER_FILES_ONLY}. Default is * {@link BaseFile#FILTER_FILES_ONLY}. + *

+ * Default is {@link BaseFile#FILTER_FILES_ONLY}. */ public static final String EXTRA_FILTER_MODE = CLASSNAME + ".filter_mode"; @@ -127,7 +131,7 @@ public class FileChooserActivity extends FragmentActivity { public static final String EXTRA_MAX_FILE_COUNT = CLASSNAME + ".max_file_count"; /** - * Key to hold multi-selection mode, default = {@code false} + * Key to hold multi-selection mode, default = {@code false}. */ public static final String EXTRA_MULTI_SELECTION = CLASSNAME + ".multi_selection"; @@ -148,7 +152,7 @@ public class FileChooserActivity extends FragmentActivity { public static final String EXTRA_NEGATIVE_REGEX_FILTER = CLASSNAME + ".negative_regex_filter"; /** - * Key to hold display-hidden-files, default = {@code false} + * Key to hold display-hidden-files, default = {@code false}. */ public static final String EXTRA_DISPLAY_HIDDEN_FILES = CLASSNAME + ".display_hidden_files"; @@ -190,16 +194,28 @@ public class FileChooserActivity extends FragmentActivity { // --------------------------------------------------------- /** - * Key to hold property save-dialog, default = {@code false} + * Key to hold property save-dialog, default = {@code false}. */ public static final String EXTRA_SAVE_DIALOG = CLASSNAME + ".save_dialog"; /** - * Key to hold default filename, default = {@code null} + * Key to hold default filename, default = {@code null}. */ public static final String EXTRA_DEFAULT_FILENAME = CLASSNAME + ".default_filename"; /** - * Key to hold results (can be one or multiple files) + * Key to hold default file extension (without the period prefix), + * default = {@code null}. + *

+ * Note that this will be compared to the user's input value as + * case-insensitive. For example if you provide "csv" and the user types + * "CSV" then it is OK to use "CSV". + */ + public static final String EXTRA_DEFAULT_FILE_EXT = CLASSNAME + + ".default_file_ext"; + + /** + * Key to hold results, which is an {@link ArrayList} of {@link Uri}. It can + * be one or multiple files. */ public static final String EXTRA_RESULTS = CLASSNAME + ".results"; diff --git a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/FragmentFiles.java b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/FragmentFiles.java index a6c866ff..31ca581e 100644 --- a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/FragmentFiles.java +++ b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/FragmentFiles.java @@ -19,6 +19,7 @@ import group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileContra import group.pals.android.lib.ui.filechooser.utils.E; import group.pals.android.lib.ui.filechooser.utils.EnvUtils; import group.pals.android.lib.ui.filechooser.utils.FileUtils; +import group.pals.android.lib.ui.filechooser.utils.Texts; import group.pals.android.lib.ui.filechooser.utils.Utils; import group.pals.android.lib.ui.filechooser.utils.history.History; import group.pals.android.lib.ui.filechooser.utils.history.HistoryFilter; @@ -35,6 +36,7 @@ import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; +import java.util.regex.Pattern; import android.Manifest; import android.annotation.SuppressLint; @@ -116,6 +118,7 @@ public class FragmentFiles extends Fragment implements */ private static final String[] EXTRAS_STRING = { FileChooserActivity.EXTRA_DEFAULT_FILENAME, + FileChooserActivity.EXTRA_DEFAULT_FILE_EXT, FileChooserActivity.EXTRA_FILE_PROVIDER_AUTHORITY, FileChooserActivity.EXTRA_NEGATIVE_REGEX_FILTER, FileChooserActivity.EXTRA_POSITIVE_REGEX_FILTER }; @@ -226,12 +229,12 @@ public class FragmentFiles extends Fragment implements private ViewGroup mViewAddressBar; private View mViewGroupFiles; private ViewGroup mViewFilesContainer; - private TextView mTxtFullDirName; + private TextView mTextFullDirName; private AbsListView mViewFiles; private TextView mFooterView; private View mViewLoading; private Button mBtnOk; - private EditText mTxtSaveas; + private EditText mTextSaveas; private ImageView mViewGoBack; private ImageView mViewGoForward; private GestureDetector mListviewFilesGestureDetector; @@ -314,7 +317,7 @@ public class FragmentFiles extends Fragment implements .findViewById(R.id.afc_view_locations); mViewLocationsContainer = (HorizontalScrollView) rootView .findViewById(R.id.afc_view_locations_container); - mTxtFullDirName = (TextView) rootView + mTextFullDirName = (TextView) rootView .findViewById(R.id.afc_textview_full_dir_name); mViewGroupFiles = rootView.findViewById(R.id.afc_viewgroup_files); mViewFilesContainer = (ViewGroup) rootView @@ -322,7 +325,7 @@ public class FragmentFiles extends Fragment implements mFooterView = (TextView) rootView .findViewById(R.id.afc_view_files_footer_view); mViewLoading = rootView.findViewById(R.id.afc_view_loading); - mTxtSaveas = (EditText) rootView + mTextSaveas = (EditText) rootView .findViewById(R.id.afc_textview_saveas_filename); mBtnOk = (Button) rootView.findViewById(R.id.afc_button_ok); @@ -586,7 +589,7 @@ public class FragmentFiles extends Fragment implements super.onPostExecute(result); if (!TextUtils.isEmpty(result)) - mTxtSaveas.setText(result); + mTextSaveas.setText(result); }// onPostExecute() }.execute(); @@ -766,11 +769,51 @@ public class FragmentFiles extends Fragment implements viewGroupFooterContainer.setVisibility(View.VISIBLE); viewGroupFooter.setVisibility(View.VISIBLE); - mTxtSaveas.setVisibility(View.VISIBLE); - mTxtSaveas.setText(getArguments().getString( + mTextSaveas.setVisibility(View.VISIBLE); + mTextSaveas.setText(getArguments().getString( FileChooserActivity.EXTRA_DEFAULT_FILENAME)); - mTxtSaveas - .setOnEditorActionListener(mTxtFilenameOnEditorActionListener); + mTextSaveas + .setOnEditorActionListener(new TextView.OnEditorActionListener() { + + @Override + public boolean onEditorAction(TextView v, int actionId, + KeyEvent event) { + if (actionId == EditorInfo.IME_ACTION_DONE) { + Ui.showSoftKeyboard(v, false); + mBtnOk.performClick(); + return true; + } + return false; + }// onEditorAction() + }); + mTextSaveas.addTextChangedListener(new TextWatcher() { + + @Override + public void onTextChanged(CharSequence s, int start, + int before, int count) { + /* + * Do nothing. + */ + }// onTextChanged() + + @Override + public void beforeTextChanged(CharSequence s, int start, + int count, int after) { + /* + * Do nothing. + */ + }// beforeTextChanged() + + @Override + public void afterTextChanged(Editable s) { + /* + * If the user taps a file, the tag is set to that file's + * URI. But if the user types the file name, we remove the + * tag. + */ + mTextSaveas.setTag(null); + }// afterTextChanged() + }); mBtnOk.setVisibility(View.VISIBLE); mBtnOk.setOnClickListener(mBtnOk_SaveDialog_OnClickListener); @@ -877,12 +920,16 @@ public class FragmentFiles extends Fragment implements @Override public void onLongPress(MotionEvent e) { - // do nothing + /* + * Do nothing. + */ }// onLongPress() @Override public boolean onSingleTapConfirmed(MotionEvent e) { - // do nothing + /* + * Do nothing. + */ return false; }// onSingleTapConfirmed() @@ -892,11 +939,11 @@ public class FragmentFiles extends Fragment implements if (mIsMultiSelection) return false; - Cursor data = getData(e); - if (data == null) + Cursor cursor = getData(e); + if (cursor == null) return false; - if (BaseFileProviderUtils.isDirectory(data) + if (BaseFileProviderUtils.isDirectory(cursor) && BaseFile.FILTER_FILES_ONLY == mFilterMode) return false; @@ -906,18 +953,25 @@ public class FragmentFiles extends Fragment implements */ if (mIsSaveDialog) { - if (BaseFileProviderUtils.isFile(data)) { - mTxtSaveas.setText(BaseFileProviderUtils - .getFileName(data)); - checkSaveasFilenameAndFinish(BaseFileProviderUtils - .getFileName(data)); + if (BaseFileProviderUtils.isFile(cursor)) { + mTextSaveas.setText(BaseFileProviderUtils + .getFileName(cursor)); + /* + * Always set tag after setting text, or tag + * will be reset to null. + */ + mTextSaveas.setTag(BaseFileProviderUtils + .getUri(cursor)); + checkSaveasFilenameAndFinish(); } else return false; } else - finish(BaseFileProviderUtils.getUri(data)); + finish(BaseFileProviderUtils.getUri(cursor)); }// double tap to choose files else { - // do nothing + /* + * Do nothing. + */ return false; }// single tap to choose files @@ -1661,15 +1715,43 @@ public class FragmentFiles extends Fragment implements /** * As the name means. - * - * @param filename - * the file name. */ - private void checkSaveasFilenameAndFinish(final String filename) { + private void checkSaveasFilenameAndFinish() { new LoadingDialog(getActivity(), false) { + String filename; + Uri fileUri; int fileType; + @Override + protected void onPreExecute() { + super.onPreExecute(); + + /* + * If the user tapped a file, its URI was stored here. If not, + * this is null. + */ + fileUri = (Uri) mTextSaveas.getTag(); + + /* + * File name and extension. + */ + filename = mTextSaveas.getText().toString().trim(); + if (fileUri == null + && getArguments().containsKey( + FileChooserActivity.EXTRA_DEFAULT_FILE_EXT)) { + if (!TextUtils.isEmpty(filename)) { + String ext = getArguments().getString( + FileChooserActivity.EXTRA_DEFAULT_FILE_EXT); + if (!filename.matches("(?si)^.+" + + Pattern.quote(Texts.C_PERIOD + ext) + "$")) { + filename += Texts.C_PERIOD + ext; + mTextSaveas.setText(filename); + } + } + } + }// onPreExecute() + @Override protected Uri doInBackground(Void... params) { if (!BaseFileProviderUtils.fileCanWrite(getActivity(), @@ -1677,19 +1759,20 @@ public class FragmentFiles extends Fragment implements publishProgress(getString(R.string.afc_msg_cannot_save_a_file_here)); return null; } - if (TextUtils.isEmpty(filename) - || !FileUtils.isFilenameValid(filename)) { + + if (fileUri == null && !FileUtils.isFilenameValid(filename)) { publishProgress(getString( R.string.afc_pmsg_filename_is_invalid, filename)); return null; } + if (fileUri == null) + fileUri = getCurrentLocation() + .buildUpon() + .appendQueryParameter(BaseFile.PARAM_APPEND_NAME, + filename).build(); final Cursor cursor = getActivity().getContentResolver().query( - getCurrentLocation() - .buildUpon() - .appendQueryParameter( - BaseFile.PARAM_APPEND_NAME, filename) - .build(), null, null, null, null); + fileUri, null, null, null, null); try { if (cursor == null || !cursor.moveToFirst()) return null; @@ -1982,12 +2065,12 @@ public class FragmentFiles extends Fragment implements R.dimen.afc_button_location_max_width) - btnLoc.getPaddingLeft() - btnLoc.getPaddingRight()) { - mTxtFullDirName.setText(progress[0] + mTextFullDirName.setText(progress[0] .getString(progress[0] .getColumnIndex(BaseFile.COLUMN_NAME))); - mTxtFullDirName.setVisibility(View.VISIBLE); + mTextFullDirName.setVisibility(View.VISIBLE); } else - mTxtFullDirName.setVisibility(View.GONE); + mTextFullDirName.setVisibility(View.GONE); }// if }// onProgressUpdate() @@ -2149,26 +2232,12 @@ public class FragmentFiles extends Fragment implements }// onLongClick() };// mBtnGoBackForwardOnLongClickListener - private final TextView.OnEditorActionListener mTxtFilenameOnEditorActionListener = new TextView.OnEditorActionListener() { - - @Override - public boolean onEditorAction(TextView v, int actionId, KeyEvent event) { - if (actionId == EditorInfo.IME_ACTION_DONE) { - Ui.showSoftKeyboard(v, false); - mBtnOk.performClick(); - return true; - } - return false; - }// onEditorAction() - };// mTxtFilenameOnEditorActionListener - private final View.OnClickListener mBtnOk_SaveDialog_OnClickListener = new View.OnClickListener() { @Override public void onClick(View v) { Ui.showSoftKeyboard(v, false); - String filename = mTxtSaveas.getText().toString().trim(); - checkSaveasFilenameAndFinish(filename); + checkSaveasFilenameAndFinish(); }// onClick() };// mBtnOk_SaveDialog_OnClickListener @@ -2227,11 +2296,19 @@ public class FragmentFiles extends Fragment implements return; } - if (mIsSaveDialog) - mTxtSaveas.setText(BaseFileProviderUtils.getFileName(cursor)); + if (mIsSaveDialog) { + mTextSaveas.setText(BaseFileProviderUtils.getFileName(cursor)); + /* + * Always set tag after setting text, or tag will be reset to + * null. + */ + mTextSaveas.setTag(BaseFileProviderUtils.getUri(cursor)); + } if (mDoubleTapToChooseFiles) { - // do nothing + /* + * Do nothing. + */ return; }// double tap to choose files else { @@ -2239,8 +2316,7 @@ public class FragmentFiles extends Fragment implements return; if (mIsSaveDialog) - checkSaveasFilenameAndFinish(BaseFileProviderUtils - .getFileName(cursor)); + checkSaveasFilenameAndFinish(); else finish(BaseFileProviderUtils.getUri(cursor)); }// single tap to choose files diff --git a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/BaseColumns.java b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/BaseColumns.java index 29ea8e7b..b7e3bc79 100644 --- a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/BaseColumns.java +++ b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/BaseColumns.java @@ -18,18 +18,18 @@ public interface BaseColumns extends android.provider.BaseColumns { /** * Column name for the creation timestamp. *

- * Type: {@code String} ({@code long} from {@link java.util.Date#getTime()} - * ). - *

+ * Type: {@code String} representing {@code long} from + * {@link java.util.Date#getTime()}. This is because SQLite doesn't handle + * Java's {@code long} well. */ public static final String COLUMN_CREATE_TIME = "create_time"; /** * Column name for the modification timestamp. *

- * Type: {@code String} ({@code long} from {@link java.util.Date#getTime()} - * ). - *

+ * Type: {@code String} representing {@code long} from + * {@link java.util.Date#getTime()}. This is because SQLite doesn't handle + * Java's {@code long} well. */ public static final String COLUMN_MODIFICATION_TIME = "modification_time"; diff --git a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/BaseFileProviderUtils.java b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/BaseFileProviderUtils.java index b7ea6d58..d06988fe 100644 --- a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/BaseFileProviderUtils.java +++ b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/BaseFileProviderUtils.java @@ -217,7 +217,7 @@ public class BaseFileProviderUtils { BaseFile.COLUMN_ICON_ID }; /** - * Creates new cursor which hold default properties of a base file for + * Creates new cursor which holds default properties of a base file for * client to access. * * @return the new empty cursor. The columns are @@ -495,9 +495,15 @@ public class BaseFileProviderUtils { * @return {@code true} or {@code false}. */ public static boolean fileCanRead(Cursor cursor) { - return cursor.getInt(cursor.getColumnIndex(BaseFile.COLUMN_CAN_READ)) != 0 - && (cursor.getInt(cursor.getColumnIndex(BaseFile.COLUMN_TYPE)) == BaseFile.FILE_TYPE_DIRECTORY || cursor - .getInt(cursor.getColumnIndex(BaseFile.COLUMN_TYPE)) == BaseFile.FILE_TYPE_FILE); + if (cursor.getInt(cursor.getColumnIndex(BaseFile.COLUMN_CAN_READ)) != 0) { + switch (cursor.getInt(cursor.getColumnIndex(BaseFile.COLUMN_TYPE))) { + case BaseFile.FILE_TYPE_DIRECTORY: + case BaseFile.FILE_TYPE_FILE: + return true; + } + } + + return false; }// fileCanRead() /** @@ -532,9 +538,15 @@ public class BaseFileProviderUtils { * @return {@code true} or {@code false}. */ public static boolean fileCanWrite(Cursor cursor) { - return cursor.getInt(cursor.getColumnIndex(BaseFile.COLUMN_CAN_WRITE)) != 0 - && (cursor.getInt(cursor.getColumnIndex(BaseFile.COLUMN_TYPE)) == BaseFile.FILE_TYPE_DIRECTORY || cursor - .getInt(cursor.getColumnIndex(BaseFile.COLUMN_TYPE)) == BaseFile.FILE_TYPE_FILE); + if (cursor.getInt(cursor.getColumnIndex(BaseFile.COLUMN_CAN_WRITE)) != 0) { + switch (cursor.getInt(cursor.getColumnIndex(BaseFile.COLUMN_TYPE))) { + case BaseFile.FILE_TYPE_DIRECTORY: + case BaseFile.FILE_TYPE_FILE: + return true; + } + } + + return false; }// fileCanWrite() /** diff --git a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/ProviderUtils.java b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/ProviderUtils.java index 27cdc2ed..944be962 100644 --- a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/ProviderUtils.java +++ b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/ProviderUtils.java @@ -73,8 +73,8 @@ public class ProviderUtils { */ public static boolean getBooleanQueryParam(Uri uri, String key) { String param = uri.getQueryParameter(key); - if (param == null || "false".equalsIgnoreCase(param) - || "0".equalsIgnoreCase(param)) + if (param == null || Boolean.FALSE.toString().equalsIgnoreCase(param) + || Integer.toString(0).equalsIgnoreCase(param)) return false; return true; }// getBooleanQueryParam() diff --git a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/localfile/LocalFileProvider.java b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/localfile/LocalFileProvider.java index 082b85d5..321bf4fe 100644 --- a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/localfile/LocalFileProvider.java +++ b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/providers/localfile/LocalFileProvider.java @@ -14,7 +14,7 @@ import group.pals.android.lib.ui.filechooser.providers.ProviderUtils; import group.pals.android.lib.ui.filechooser.providers.basefile.BaseFileContract.BaseFile; import group.pals.android.lib.ui.filechooser.providers.basefile.BaseFileProvider; import group.pals.android.lib.ui.filechooser.utils.FileUtils; -import group.pals.android.lib.ui.filechooser.utils.TextUtils; +import group.pals.android.lib.ui.filechooser.utils.Texts; import java.io.File; import java.io.FileFilter; @@ -507,8 +507,8 @@ public class LocalFileProvider extends BaseFileProvider { final boolean showHiddenFiles, final int filterMode, final int limit, String positiveRegex, String negativeRegex, final List results, final boolean hasMoreFiles[]) { - final Pattern positivePattern = TextUtils.compileRegex(positiveRegex); - final Pattern negativePattern = TextUtils.compileRegex(negativeRegex); + final Pattern positivePattern = Texts.compileRegex(positiveRegex); + final Pattern negativePattern = Texts.compileRegex(negativeRegex); hasMoreFiles[0] = false; try { diff --git a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/ui/LoadingDialog.java b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/ui/LoadingDialog.java index c46682f8..bb7defc6 100644 --- a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/ui/LoadingDialog.java +++ b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/ui/LoadingDialog.java @@ -95,7 +95,7 @@ public abstract class LoadingDialog extends /** * If you override this method, you must call {@code super.onPreExecute()} - * at very first of the method. + * at beginning of the method. */ @Override protected void onPreExecute() { @@ -121,7 +121,7 @@ public abstract class LoadingDialog extends /** * If you override this method, you must call - * {@code super.onPostExecute(result)} at the entry point of the method. + * {@code super.onPostExecute(result)} at beginning of the method. */ @Override protected void onPostExecute(Result result) { @@ -130,7 +130,7 @@ public abstract class LoadingDialog extends /** * If you override this method, you must call {@code super.onCancelled()} at - * the entry point of the method. + * beginning of the method. */ @Override protected void onCancelled() { diff --git a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/ui/bookmark/BookmarkFragment.java b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/ui/bookmark/BookmarkFragment.java index 16e82c35..cccc91e8 100644 --- a/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/ui/bookmark/BookmarkFragment.java +++ b/src/java/android-filechooser/code/src/group/pals/android/lib/ui/filechooser/utils/ui/bookmark/BookmarkFragment.java @@ -13,7 +13,7 @@ import group.pals.android.lib.ui.filechooser.prefs.DisplayPrefs; import group.pals.android.lib.ui.filechooser.providers.DbUtils; import group.pals.android.lib.ui.filechooser.providers.bookmark.BookmarkContract; import group.pals.android.lib.ui.filechooser.utils.EnvUtils; -import group.pals.android.lib.ui.filechooser.utils.TextUtils; +import group.pals.android.lib.ui.filechooser.utils.Texts; import group.pals.android.lib.ui.filechooser.utils.ui.ContextMenuUtils; import group.pals.android.lib.ui.filechooser.utils.ui.Dlg; import group.pals.android.lib.ui.filechooser.utils.ui.GestureUtils; @@ -515,7 +515,7 @@ public class BookmarkFragment extends DialogFragment implements .getColumnIndex(BookmarkContract.COLUMN_NAME)); ContextMenuUtils.showContextMenu(getActivity(), - R.drawable.afc_bookmarks_dark, TextUtils.quote(name), + R.drawable.afc_bookmarks_dark, Texts.quote(name), new Integer[] { R.string.afc_cmd_rename, R.string.afc_cmd_sort_by_name }, new ContextMenuUtils.OnMenuItemClickListener() {