166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/*
266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Copyright (C) 2013 The Android Open Source Project
366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey *
466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * you may not use this file except in compliance with the License.
666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * You may obtain a copy of the License at
766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey *
866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey *
1066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Unless required by applicable law or agreed to in writing, software
1166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
1266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * See the License for the specific language governing permissions and
1466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * limitations under the License.
1566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */
1666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
1766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypackage com.android.documentsui;
1866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
1958efce36cd1b26006e08ddd696292bf06fc34c81Steve McKayimport static com.android.documentsui.Shared.TAG;
207aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey
2166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.AlertDialog;
2266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.Dialog;
2366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.DialogFragment;
2466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.app.FragmentManager;
257aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.content.ContentProviderClient;
2666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.ContentResolver;
2766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.Context;
2866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.DialogInterface;
2966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.content.DialogInterface.OnClickListener;
3066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.net.Uri;
316efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkeyimport android.os.AsyncTask;
3266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.os.Bundle;
33aeb16e2435f9975b9fa1fc4b747796647a21292eJeff Sharkeyimport android.provider.DocumentsContract;
34ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport android.provider.DocumentsContract.Document;
357e392b78451373c83367691b86ba14c8710d1030Steve McKayimport android.support.annotation.Nullable;
3694b486d32c10d5ffbd8627977ca4759c246ecf4bBen Kwaimport android.support.design.widget.Snackbar;
377aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkeyimport android.util.Log;
38a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKayimport android.view.KeyEvent;
39404168096789c6dde4db82dc6360a1a25e6ff636Aga Wronskaimport android.view.inputmethod.EditorInfo;
4066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.LayoutInflater;
4166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.view.View;
4266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeyimport android.widget.EditText;
43a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKayimport android.widget.TextView;
44a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKayimport android.widget.TextView.OnEditorActionListener;
4566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
46ae9b51bfa313c51a31af30875a71255d7b6d2e61Jeff Sharkeyimport com.android.documentsui.model.DocumentInfo;
4766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
4866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey/**
4966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey * Dialog to create a new directory.
5066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey */
5166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkeypublic class CreateDirectoryFragment extends DialogFragment {
5266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    private static final String TAG_CREATE_DIRECTORY = "create_directory";
5366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
5466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public static void show(FragmentManager fm) {
5566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final CreateDirectoryFragment dialog = new CreateDirectoryFragment();
5666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        dialog.show(fm, TAG_CREATE_DIRECTORY);
5766516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
5866516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
5966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    @Override
6066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    public Dialog onCreateDialog(Bundle savedInstanceState) {
6166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final Context context = getActivity();
6266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final ContentResolver resolver = context.getContentResolver();
6366516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
645527f6457ed78771fe27352533cdc0f7123bd6e6Tomasz Mikolajewski        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
6566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
6666516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
673b327ef9f9dec19612202b4b0b450966870a077fAga Wronska        final View view = dialogInflater.inflate(R.layout.dialog_file_name, null, false);
68a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay        final EditText editText = (EditText) view.findViewById(android.R.id.text1);
6966516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
7066516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        builder.setTitle(R.string.menu_create_dir);
7166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        builder.setView(view);
7266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
73a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay        builder.setPositiveButton(
74a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                android.R.string.ok,
75a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                new OnClickListener() {
76a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                    @Override
77a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                    public void onClick(DialogInterface dialog, int which) {
78a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                        createDirectory(editText.getText().toString());
79a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                    }
80a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                });
81d01571e6d4e1c403534e19142720530d324eac9bJeff Sharkey
8266516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey        builder.setNegativeButton(android.R.string.cancel, null);
83a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay        final AlertDialog dialog = builder.create();
84a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay
8502c532fb54ff1aaad0bdcbbd3f1fee21d4e5dcdeAga Wronska        // Workaround for the problem - virtual keyboard doesn't show on the phone.
8602c532fb54ff1aaad0bdcbbd3f1fee21d4e5dcdeAga Wronska        Shared.ensureKeyboardPresent(context, dialog);
8702c532fb54ff1aaad0bdcbbd3f1fee21d4e5dcdeAga Wronska
88a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay        editText.setOnEditorActionListener(
89a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                new OnEditorActionListener() {
90a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                    @Override
917e392b78451373c83367691b86ba14c8710d1030Steve McKay                    public boolean onEditorAction(
927e392b78451373c83367691b86ba14c8710d1030Steve McKay                            TextView view, int actionId, @Nullable KeyEvent event) {
93404168096789c6dde4db82dc6360a1a25e6ff636Aga Wronska                        if ((actionId == EditorInfo.IME_ACTION_DONE) || (event != null
947e392b78451373c83367691b86ba14c8710d1030Steve McKay                                && event.getKeyCode() == KeyEvent.KEYCODE_ENTER
95404168096789c6dde4db82dc6360a1a25e6ff636Aga Wronska                                && event.hasNoModifiers())) {
96a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                            createDirectory(editText.getText().toString());
97a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                            dialog.dismiss();
98a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                            return true;
99a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                        }
100a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                        return false;
101a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                    }
102a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                });
103a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay
104a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay
105a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay        return dialog;
106a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay    }
107a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay
108a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay    private void createDirectory(String name) {
109a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay        final BaseActivity activity = (BaseActivity) getActivity();
110a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay        final DocumentInfo cwd = activity.getCurrentDirectory();
11166516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey
112a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay        new CreateDirectoryTask(activity, cwd, name).executeOnExecutor(
113a521d0d318f867ee65d86b8749f6da3c13ebd9a4Steve McKay                ProviderExecutor.forAuthority(cwd.authority));
11466516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey    }
1156efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
1166efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    private class CreateDirectoryTask extends AsyncTask<Void, Void, DocumentInfo> {
117e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay        private final BaseActivity mActivity;
11878b137030864c028920046a38b5a040f5920fddfJeff Sharkey        private final DocumentInfo mCwd;
1196efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        private final String mDisplayName;
1206efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
12178b137030864c028920046a38b5a040f5920fddfJeff Sharkey        public CreateDirectoryTask(
122e934ce6f8430f50d1d22bccd3b341b982f5541eeSteve McKay                BaseActivity activity, DocumentInfo cwd, String displayName) {
12378b137030864c028920046a38b5a040f5920fddfJeff Sharkey            mActivity = activity;
12478b137030864c028920046a38b5a040f5920fddfJeff Sharkey            mCwd = cwd;
1256efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            mDisplayName = displayName;
1266efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
1276efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
1286efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
12904d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        protected void onPreExecute() {
13004d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey            mActivity.setPending(true);
13104d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        }
13204d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey
13304d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey        @Override
1346efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected DocumentInfo doInBackground(Void... params) {
13578b137030864c028920046a38b5a040f5920fddfJeff Sharkey            final ContentResolver resolver = mActivity.getContentResolver();
1367aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            ContentProviderClient client = null;
1376efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            try {
1387aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                client = DocumentsApplication.acquireUnstableProviderOrThrow(
13978b137030864c028920046a38b5a040f5920fddfJeff Sharkey                        resolver, mCwd.derivedUri.getAuthority());
1407aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                final Uri childUri = DocumentsContract.createDocument(
14178b137030864c028920046a38b5a040f5920fddfJeff Sharkey                        client, mCwd.derivedUri, Document.MIME_TYPE_DIR, mDisplayName);
1426efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return DocumentInfo.fromUri(resolver, childUri);
1437aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            } catch (Exception e) {
1447aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                Log.w(TAG, "Failed to create directory", e);
1456efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                return null;
1467aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey            } finally {
1477aa7601c09ab5d87cc15a0ed9a8f511d494a4cbcJeff Sharkey                ContentProviderClient.releaseQuietly(client);
1486efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
1496efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
1506efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey
1516efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        @Override
1526efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        protected void onPostExecute(DocumentInfo result) {
1536efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            if (result != null) {
1546efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey                // Navigate into newly created child
1556eaf3863c81779233c032b7f7fc5b90e94f5f70aSteve McKay                mActivity.onDirectoryCreated(result);
1564e8c7f61bea7c8a3dd750db13b6319a7bd84dc3cAga Wronska                Metrics.logCreateDirOperation(getContext());
1576efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            } else {
1584e8c7f61bea7c8a3dd750db13b6319a7bd84dc3cAga Wronska                Snackbars.makeSnackbar(mActivity, R.string.create_error, Snackbar.LENGTH_SHORT)
1594e8c7f61bea7c8a3dd750db13b6319a7bd84dc3cAga Wronska                        .show();
1604e8c7f61bea7c8a3dd750db13b6319a7bd84dc3cAga Wronska                Metrics.logCreateDirError(getContext());
1616efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey            }
16204d45a0bdd47c243ad7ccb179aa52a83e7bf45dbJeff Sharkey            mActivity.setPending(false);
1636efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey        }
1646efba22ce510352bb84910d6efc42fecafd31ed7Jeff Sharkey    }
16566516697a29cf00d93893a1011d3befc7c1ee37fJeff Sharkey}
166