1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License
15  */
16 
17 package com.android.contacts.activities;
18 
19 import com.android.contacts.R;
20 import com.android.contacts.common.activity.RequestPermissionsActivity;
21 import com.android.contacts.common.model.RawContactDeltaList;
22 import com.android.contacts.detail.PhotoSelectionHandler;
23 import com.android.contacts.editor.CompactContactEditorFragment;
24 import com.android.contacts.editor.CompactPhotoSelectionFragment;
25 import com.android.contacts.editor.PhotoSourceDialogFragment;
26 
27 import android.app.FragmentTransaction;
28 import android.content.Intent;
29 import android.net.Uri;
30 import android.os.Bundle;
31 
32 import java.io.FileNotFoundException;
33 import java.util.ArrayList;
34 
35 /**
36  * Contact editor with only the most important fields displayed initially.
37  */
38 public class CompactContactEditorActivity extends ContactEditorBaseActivity implements
39         PhotoSourceDialogFragment.Listener, CompactPhotoSelectionFragment.Listener {
40 
41     private static final String TAG_COMPACT_EDITOR = "compact_editor";
42     private static final String TAG_PHOTO_SELECTION = "photo_selector";
43 
44     private static final String STATE_PHOTO_MODE = "photo_mode";
45     private static final String STATE_IS_PHOTO_SELECTION = "is_photo_selection";
46     private static final String STATE_ACTION_BAR_TITLE = "action_bar_title";
47     private static final String STATE_PHOTO_URI = "photo_uri";
48 
49     /**
50      * Displays a PopupWindow with photo edit options.
51      */
52     private final class CompactPhotoSelectionHandler extends PhotoSelectionHandler {
53 
54         /**
55          * Receiver of photo edit option callbacks.
56          */
57         private final class CompactPhotoActionListener extends PhotoActionListener {
58 
59             @Override
onRemovePictureChosen()60             public void onRemovePictureChosen() {
61                 getEditorFragment().removePhoto();
62                 if (mIsPhotoSelection) {
63                     showEditorFragment();
64                 }
65             }
66 
67             @Override
onPhotoSelected(Uri uri)68             public void onPhotoSelected(Uri uri) throws FileNotFoundException {
69                 mPhotoUri = uri;
70                 getEditorFragment().updatePhoto(uri);
71                 if (mIsPhotoSelection) {
72                     showEditorFragment();
73                 }
74 
75                 // Re-create the photo handler the next time we need it so that additional photo
76                 // selections create a new temp file (and don't hit the one that was just added
77                 // to the cache).
78                 mPhotoSelectionHandler = null;
79             }
80 
81             @Override
getCurrentPhotoUri()82             public Uri getCurrentPhotoUri() {
83                 return mPhotoUri;
84             }
85 
86             @Override
onPhotoSelectionDismissed()87             public void onPhotoSelectionDismissed() {
88                 if (mIsPhotoSelection) {
89                     showEditorFragment();
90                 }
91             }
92         }
93 
94         private final CompactPhotoActionListener mPhotoActionListener;
95         private boolean mIsPhotoSelection;
96 
CompactPhotoSelectionHandler(int photoMode, boolean isPhotoSelection)97         public CompactPhotoSelectionHandler(int photoMode, boolean isPhotoSelection) {
98             // We pass a null changeAnchorView since we are overriding onClick so that we
99             // can show the photo options in a dialog instead of a ListPopupWindow (which would
100             // be anchored at changeAnchorView).
101 
102             // TODO: empty raw contact delta list
103             super(CompactContactEditorActivity.this, /* changeAnchorView =*/ null, photoMode,
104                     /* isDirectoryContact =*/ false, new RawContactDeltaList());
105             mPhotoActionListener = new CompactPhotoActionListener();
106             mIsPhotoSelection = isPhotoSelection;
107         }
108 
109         @Override
getListener()110         public PhotoActionListener getListener() {
111             return mPhotoActionListener;
112         }
113 
114         @Override
startPhotoActivity(Intent intent, int requestCode, Uri photoUri)115         protected void startPhotoActivity(Intent intent, int requestCode, Uri photoUri) {
116             mPhotoUri = photoUri;
117             startActivityForResult(intent, requestCode);
118         }
119     }
120 
121     private CompactPhotoSelectionFragment mPhotoSelectionFragment;
122     private CompactPhotoSelectionHandler mPhotoSelectionHandler;
123     private Uri mPhotoUri;
124     private int mPhotoMode;
125     private boolean mIsPhotoSelection;
126 
127     @Override
onCreate(Bundle savedState)128     public void onCreate(Bundle savedState) {
129         super.onCreate(savedState);
130 
131         if (RequestPermissionsActivity.startPermissionActivity(this)) {
132             return;
133         }
134 
135         setContentView(R.layout.compact_contact_editor_activity);
136 
137         if (savedState == null) {
138             // Create the editor and photo selection fragments
139             mFragment = new CompactContactEditorFragment();
140             mPhotoSelectionFragment = new CompactPhotoSelectionFragment();
141             getFragmentManager().beginTransaction()
142                     .add(R.id.fragment_container, getEditorFragment(), TAG_COMPACT_EDITOR)
143                     .add(R.id.fragment_container, mPhotoSelectionFragment, TAG_PHOTO_SELECTION)
144                     .hide(mPhotoSelectionFragment)
145                     .commit();
146         } else {
147             // Restore state
148             mPhotoMode = savedState.getInt(STATE_PHOTO_MODE);
149             mIsPhotoSelection = savedState.getBoolean(STATE_IS_PHOTO_SELECTION);
150             mActionBarTitleResId = savedState.getInt(STATE_ACTION_BAR_TITLE);
151             mPhotoUri = Uri.parse(savedState.getString(STATE_PHOTO_URI));
152 
153             // Show/hide the editor and photo selection fragments (w/o animations)
154             mFragment = (CompactContactEditorFragment) getFragmentManager()
155                     .findFragmentByTag(TAG_COMPACT_EDITOR);
156             mPhotoSelectionFragment = (CompactPhotoSelectionFragment) getFragmentManager()
157                     .findFragmentByTag(TAG_PHOTO_SELECTION);
158             final FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
159             if (mIsPhotoSelection) {
160                 fragmentTransaction.hide(getEditorFragment()).show(mPhotoSelectionFragment);
161                 getActionBar().setTitle(getResources().getString(R.string.photo_picker_title));
162             } else {
163                 fragmentTransaction.show(getEditorFragment()).hide(mPhotoSelectionFragment);
164                 getActionBar().setTitle(getResources().getString(mActionBarTitleResId));
165             }
166             fragmentTransaction.commit();
167         }
168 
169         // Set listeners
170         mFragment.setListener(mFragmentListener);
171         mPhotoSelectionFragment.setListener(this);
172 
173         // Load editor data (even if it's hidden)
174         final String action = getIntent().getAction();
175         final Uri uri = Intent.ACTION_EDIT.equals(action) ? getIntent().getData() : null;
176         mFragment.load(action, uri, getIntent().getExtras());
177     }
178 
onSaveInstanceState(Bundle outState)179     protected void onSaveInstanceState(Bundle outState) {
180         super.onSaveInstanceState(outState);
181         outState.putInt(STATE_PHOTO_MODE, mPhotoMode);
182         outState.putBoolean(STATE_IS_PHOTO_SELECTION, mIsPhotoSelection);
183         outState.putInt(STATE_ACTION_BAR_TITLE, mActionBarTitleResId);
184         outState.putString(STATE_PHOTO_URI,
185                 mPhotoUri != null ? mPhotoUri.toString() : Uri.EMPTY.toString());
186     }
187 
188     @Override
onActivityResult(int requestCode, int resultCode, Intent data)189     public void onActivityResult(int requestCode, int resultCode, Intent data) {
190         if (mPhotoSelectionHandler == null) {
191             mPhotoSelectionHandler = (CompactPhotoSelectionHandler) getPhotoSelectionHandler();
192         }
193         if (mPhotoSelectionHandler.handlePhotoActivityResult(requestCode, resultCode, data)) {
194             return;
195         }
196         super.onActivityResult(requestCode, resultCode, data);
197     }
198 
199     @Override
onBackPressed()200     public void onBackPressed() {
201         if (mIsPhotoSelection) {
202             mIsPhotoSelection = false;
203             showEditorFragment();
204         } else {
205             super.onBackPressed();
206         }
207     }
208 
209     /**
210      * Displays photos from all raw contacts, clicking one set it as the super primary photo.
211      */
selectPhoto(ArrayList<CompactPhotoSelectionFragment.Photo> photos, int photoMode)212     public void selectPhoto(ArrayList<CompactPhotoSelectionFragment.Photo> photos, int photoMode) {
213         mPhotoMode = photoMode;
214         mIsPhotoSelection = true;
215         mPhotoSelectionFragment.setPhotos(photos, photoMode);
216         showPhotoSelectionFragment();
217     }
218 
219     /**
220      * Opens a dialog showing options for the user to change their photo (take, choose, or remove
221      * photo).
222      */
changePhoto(int photoMode)223     public void changePhoto(int photoMode) {
224         mPhotoMode = photoMode;
225         mIsPhotoSelection = false;
226         PhotoSourceDialogFragment.show(this, mPhotoMode);
227     }
228 
showPhotoSelectionFragment()229     private void showPhotoSelectionFragment() {
230         getFragmentManager().beginTransaction()
231                 .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
232                 .hide(getEditorFragment())
233                 .show(mPhotoSelectionFragment)
234                 .commit();
235         getActionBar().setTitle(getResources().getString(R.string.photo_picker_title));
236     }
237 
showEditorFragment()238     private void showEditorFragment() {
239         getFragmentManager().beginTransaction()
240                 .setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out)
241                 .hide(mPhotoSelectionFragment)
242                 .show((CompactContactEditorFragment) mFragment)
243                 .commit();
244         getActionBar().setTitle(getResources().getString(mActionBarTitleResId));
245         mIsPhotoSelection = false;
246     }
247 
248     @Override
onRemovePictureChosen()249     public void onRemovePictureChosen() {
250         getPhotoSelectionHandler().getListener().onRemovePictureChosen();
251     }
252 
253     @Override
onTakePhotoChosen()254     public void onTakePhotoChosen() {
255         getPhotoSelectionHandler().getListener().onTakePhotoChosen();
256     }
257 
258     @Override
onPickFromGalleryChosen()259     public void onPickFromGalleryChosen() {
260         getPhotoSelectionHandler().getListener().onPickFromGalleryChosen();
261     }
262 
263     @Override
onPhotoSelected(CompactPhotoSelectionFragment.Photo photo)264     public void onPhotoSelected(CompactPhotoSelectionFragment.Photo photo) {
265         getEditorFragment().setPrimaryPhoto(photo);
266         showEditorFragment();
267     }
268 
getPhotoSelectionHandler()269     private PhotoSelectionHandler getPhotoSelectionHandler() {
270         if (mPhotoSelectionHandler == null) {
271             mPhotoSelectionHandler = new CompactPhotoSelectionHandler(
272                     mPhotoMode, mIsPhotoSelection);
273         }
274         return mPhotoSelectionHandler;
275     }
276 
getEditorFragment()277     private CompactContactEditorFragment getEditorFragment() {
278         return (CompactContactEditorFragment) mFragment;
279     }
280 }
281