1761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey/*
2761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * Copyright (C) 2013 The Android Open Source Project
3761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey *
4761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * Licensed under the Apache License, Version 2.0 (the "License");
5761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * you may not use this file except in compliance with the License.
6761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * You may obtain a copy of the License at
7761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey *
8761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey *      http://www.apache.org/licenses/LICENSE-2.0
9761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey *
10761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * Unless required by applicable law or agreed to in writing, software
11761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * distributed under the License is distributed on an "AS IS" BASIS,
12761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * See the License for the specific language governing permissions and
14761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * limitations under the License.
15761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey */
16761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
17761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeypackage com.android.documentsui;
18761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
19d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport static com.android.documentsui.base.Shared.TAG;
203fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey
21761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.app.AlertDialog;
22761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.app.Dialog;
23761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.app.DialogFragment;
24761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.app.FragmentManager;
253fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkeyimport android.content.ContentProviderClient;
26761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.content.ContentResolver;
27761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.content.Context;
28761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.content.DialogInterface;
29761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.content.DialogInterface.OnClickListener;
30761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.net.Uri;
319dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkeyimport android.os.AsyncTask;
32761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.os.Bundle;
33b6a7f2cd05f8c507dfac684aa4c693088e8c01c7Jeff Sharkeyimport android.provider.DocumentsContract;
34724deeb5558a517471e9bf7168b456e6daec62f8Jeff Sharkeyimport android.provider.DocumentsContract.Document;
35e9ec61ee67fa6ed49b56f0ae9af90e6d6f9b9f4eSteve McKayimport android.support.annotation.Nullable;
36c4693349d1a49dec8fd203f2c7adce18eee28b0aBen Kwaimport android.support.design.widget.Snackbar;
373fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkeyimport android.util.Log;
38ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKayimport android.view.KeyEvent;
39279ec317f58ac335abd7d0beab70401ef430d4fdAga Wronskaimport android.view.inputmethod.EditorInfo;
40761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.view.LayoutInflater;
41761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.view.View;
42761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeyimport android.widget.EditText;
43ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKayimport android.widget.TextView;
44ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKayimport android.widget.TextView.OnEditorActionListener;
45761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
46d080506e3aa8547605cd4783eb660775d7d2b8eeSteve McKayimport com.android.documentsui.base.DocumentInfo;
47d9caa6ab53aa784acaf241c0ded3c4ae2d342bf8Steve McKayimport com.android.documentsui.base.Shared;
48c8889af6757ecb348fb8fd6dadf84d67d3478cbfSteve McKayimport com.android.documentsui.ui.Snackbars;
49761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
50761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey/**
51761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey * Dialog to create a new directory.
52761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey */
53761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkeypublic class CreateDirectoryFragment extends DialogFragment {
54761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey    private static final String TAG_CREATE_DIRECTORY = "create_directory";
55761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
56761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey    public static void show(FragmentManager fm) {
57761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey        final CreateDirectoryFragment dialog = new CreateDirectoryFragment();
58761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey        dialog.show(fm, TAG_CREATE_DIRECTORY);
59761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey    }
60761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
61761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey    @Override
62761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey    public Dialog onCreateDialog(Bundle savedInstanceState) {
63761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey        final Context context = getActivity();
64761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey        final ContentResolver resolver = context.getContentResolver();
65761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
66137437e161f23b8a2ecea1cb9d5826c65b1d9537Tomasz Mikolajewski        final AlertDialog.Builder builder = new AlertDialog.Builder(context);
67761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey        final LayoutInflater dialogInflater = LayoutInflater.from(builder.getContext());
68761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
693c23718ad126b4cc4f0a80dd29f0d4e411ccc1d3Aga Wronska        final View view = dialogInflater.inflate(R.layout.dialog_file_name, null, false);
70ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay        final EditText editText = (EditText) view.findViewById(android.R.id.text1);
71761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
72761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey        builder.setTitle(R.string.menu_create_dir);
73761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey        builder.setView(view);
74761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
75ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay        builder.setPositiveButton(
76ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                android.R.string.ok,
77ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                new OnClickListener() {
78ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                    @Override
79ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                    public void onClick(DialogInterface dialog, int which) {
80ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                        createDirectory(editText.getText().toString());
81ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                    }
82ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                });
83f63b77709fb5b4de618e3699506f7710f62d551aJeff Sharkey
84761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey        builder.setNegativeButton(android.R.string.cancel, null);
85ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay        final AlertDialog dialog = builder.create();
86ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay
87741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska        // Workaround for the problem - virtual keyboard doesn't show on the phone.
88741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska        Shared.ensureKeyboardPresent(context, dialog);
89741ac6fffb3ee2441569412a28a1c4f3c2160d87Aga Wronska
90ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay        editText.setOnEditorActionListener(
91ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                new OnEditorActionListener() {
92ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                    @Override
93e9ec61ee67fa6ed49b56f0ae9af90e6d6f9b9f4eSteve McKay                    public boolean onEditorAction(
94e9ec61ee67fa6ed49b56f0ae9af90e6d6f9b9f4eSteve McKay                            TextView view, int actionId, @Nullable KeyEvent event) {
95279ec317f58ac335abd7d0beab70401ef430d4fdAga Wronska                        if ((actionId == EditorInfo.IME_ACTION_DONE) || (event != null
96e9ec61ee67fa6ed49b56f0ae9af90e6d6f9b9f4eSteve McKay                                && event.getKeyCode() == KeyEvent.KEYCODE_ENTER
97279ec317f58ac335abd7d0beab70401ef430d4fdAga Wronska                                && event.hasNoModifiers())) {
98ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                            createDirectory(editText.getText().toString());
99ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                            dialog.dismiss();
100ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                            return true;
101ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                        }
102ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                        return false;
103ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                    }
104ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                });
105ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay
106ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay
107ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay        return dialog;
108ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay    }
109ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay
110ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay    private void createDirectory(String name) {
111ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay        final BaseActivity activity = (BaseActivity) getActivity();
112ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay        final DocumentInfo cwd = activity.getCurrentDirectory();
113761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey
114ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay        new CreateDirectoryTask(activity, cwd, name).executeOnExecutor(
115ceeb3f7d93d1667243c2ad4b743e5c78add29261Steve McKay                ProviderExecutor.forAuthority(cwd.authority));
116761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey    }
1179dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
1189dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    private class CreateDirectoryTask extends AsyncTask<Void, Void, DocumentInfo> {
119d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay        private final BaseActivity mActivity;
1200aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey        private final DocumentInfo mCwd;
1219dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        private final String mDisplayName;
1229dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
1230aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey        public CreateDirectoryTask(
124d0a2a2c4e061da0de1b0008b841cacd9fc4416edSteve McKay                BaseActivity activity, DocumentInfo cwd, String displayName) {
1250aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey            mActivity = activity;
1260aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey            mCwd = cwd;
1279dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            mDisplayName = displayName;
1289dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
1299dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
1309dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        @Override
1314be51f196d60ba23856b646de3091364230258b0Jeff Sharkey        protected void onPreExecute() {
1324be51f196d60ba23856b646de3091364230258b0Jeff Sharkey            mActivity.setPending(true);
1334be51f196d60ba23856b646de3091364230258b0Jeff Sharkey        }
1344be51f196d60ba23856b646de3091364230258b0Jeff Sharkey
1354be51f196d60ba23856b646de3091364230258b0Jeff Sharkey        @Override
1369dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        protected DocumentInfo doInBackground(Void... params) {
1370aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey            final ContentResolver resolver = mActivity.getContentResolver();
1383fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            ContentProviderClient client = null;
1399dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            try {
1403fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                client = DocumentsApplication.acquireUnstableProviderOrThrow(
1410aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey                        resolver, mCwd.derivedUri.getAuthority());
1423fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                final Uri childUri = DocumentsContract.createDocument(
1430aa2692b5f9eb9d0a7b2cb763dcfb75bb728f31aJeff Sharkey                        client, mCwd.derivedUri, Document.MIME_TYPE_DIR, mDisplayName);
1449dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey                return DocumentInfo.fromUri(resolver, childUri);
1453fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            } catch (Exception e) {
1463fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                Log.w(TAG, "Failed to create directory", e);
1479dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey                return null;
1483fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey            } finally {
1493fd11777c7eab734919efa4d8e7755aef803c19fJeff Sharkey                ContentProviderClient.releaseQuietly(client);
1509dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            }
1519dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
1529dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey
1539dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        @Override
1549dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        protected void onPostExecute(DocumentInfo result) {
1559dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            if (result != null) {
1569dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey                // Navigate into newly created child
157351a749751bc501c9d7c0f03ee5b542f0e7a7d7cSteve McKay                mActivity.onDirectoryCreated(result);
15846a868a96931a097d098ce3b76068b4946e38662Aga Wronska                Metrics.logCreateDirOperation(getContext());
1599dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            } else {
16046a868a96931a097d098ce3b76068b4946e38662Aga Wronska                Snackbars.makeSnackbar(mActivity, R.string.create_error, Snackbar.LENGTH_SHORT)
16146a868a96931a097d098ce3b76068b4946e38662Aga Wronska                        .show();
16246a868a96931a097d098ce3b76068b4946e38662Aga Wronska                Metrics.logCreateDirError(getContext());
1639dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey            }
1644be51f196d60ba23856b646de3091364230258b0Jeff Sharkey            mActivity.setPending(false);
1659dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey        }
1669dd02629d12d05c2e77780dc6b9fcc7639192de6Jeff Sharkey    }
167761122118b2437aee3a44e9263b73766986c12b8Jeff Sharkey}
168