1/*
2 * Copyright (C) 2013 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
17package com.android.dialer.app.list;
18
19import static android.Manifest.permission.READ_CONTACTS;
20
21import android.app.Activity;
22import android.content.BroadcastReceiver;
23import android.content.Context;
24import android.content.Intent;
25import android.content.Loader;
26import android.content.pm.PackageManager;
27import android.database.Cursor;
28import android.net.Uri;
29import android.provider.ContactsContract.CommonDataKinds.Phone;
30import android.provider.ContactsContract.QuickContact;
31import android.support.v13.app.FragmentCompat;
32import android.view.LayoutInflater;
33import android.view.View;
34import android.view.ViewGroup;
35import android.widget.AdapterView;
36import com.android.contacts.common.list.ContactEntryListAdapter;
37import com.android.contacts.common.list.ContactEntryListFragment;
38import com.android.contacts.common.list.ContactListFilter;
39import com.android.contacts.common.list.DefaultContactListAdapter;
40import com.android.dialer.app.R;
41import com.android.dialer.common.LogUtil;
42import com.android.dialer.compat.CompatUtils;
43import com.android.dialer.logging.InteractionEvent;
44import com.android.dialer.logging.Logger;
45import com.android.dialer.util.DialerUtils;
46import com.android.dialer.util.IntentUtil;
47import com.android.dialer.util.PermissionsUtil;
48import com.android.dialer.widget.EmptyContentView;
49import com.android.dialer.widget.EmptyContentView.OnEmptyViewActionButtonClickedListener;
50import java.util.Arrays;
51
52/** Fragments to show all contacts with phone numbers. */
53public class AllContactsFragment extends ContactEntryListFragment<ContactEntryListAdapter>
54    implements OnEmptyViewActionButtonClickedListener,
55        FragmentCompat.OnRequestPermissionsResultCallback {
56
57  private static final int READ_CONTACTS_PERMISSION_REQUEST_CODE = 1;
58
59  private EmptyContentView mEmptyListView;
60
61  /**
62   * Listen to broadcast events about permissions in order to be notified if the READ_CONTACTS
63   * permission is granted via the UI in another fragment.
64   */
65  private BroadcastReceiver mReadContactsPermissionGrantedReceiver =
66      new BroadcastReceiver() {
67        @Override
68        public void onReceive(Context context, Intent intent) {
69          reloadData();
70        }
71      };
72
73  public AllContactsFragment() {
74    setQuickContactEnabled(false);
75    setAdjustSelectionBoundsEnabled(true);
76    setPhotoLoaderEnabled(true);
77    setSectionHeaderDisplayEnabled(true);
78    setDarkTheme(false);
79    setVisibleScrollbarEnabled(true);
80  }
81
82  @Override
83  public void onViewCreated(View view, android.os.Bundle savedInstanceState) {
84    super.onViewCreated(view, savedInstanceState);
85
86    mEmptyListView = (EmptyContentView) view.findViewById(R.id.empty_list_view);
87    mEmptyListView.setImage(R.drawable.empty_contacts);
88    mEmptyListView.setDescription(R.string.all_contacts_empty);
89    mEmptyListView.setActionClickedListener(this);
90    getListView().setEmptyView(mEmptyListView);
91    mEmptyListView.setVisibility(View.GONE);
92  }
93
94  @Override
95  public void onStart() {
96    super.onStart();
97    PermissionsUtil.registerPermissionReceiver(
98        getActivity(), mReadContactsPermissionGrantedReceiver, READ_CONTACTS);
99  }
100
101  @Override
102  public void onStop() {
103    PermissionsUtil.unregisterPermissionReceiver(
104        getActivity(), mReadContactsPermissionGrantedReceiver);
105    super.onStop();
106  }
107
108  @Override
109  protected void startLoading() {
110    if (PermissionsUtil.hasPermission(getActivity(), READ_CONTACTS)) {
111      super.startLoading();
112      mEmptyListView.setDescription(R.string.all_contacts_empty);
113      mEmptyListView.setActionLabel(R.string.all_contacts_empty_add_contact_action);
114    } else {
115      mEmptyListView.setDescription(R.string.permission_no_contacts);
116      mEmptyListView.setActionLabel(R.string.permission_single_turn_on);
117      mEmptyListView.setVisibility(View.VISIBLE);
118    }
119  }
120
121  @Override
122  public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
123    super.onLoadFinished(loader, data);
124
125    if (data == null || data.getCount() == 0) {
126      mEmptyListView.setVisibility(View.VISIBLE);
127    }
128  }
129
130  @Override
131  protected ContactEntryListAdapter createListAdapter() {
132    final DefaultContactListAdapter adapter =
133        new DefaultContactListAdapter(getActivity()) {
134          @Override
135          protected void bindView(View itemView, int partition, Cursor cursor, int position) {
136            super.bindView(itemView, partition, cursor, position);
137            itemView.setTag(this.getContactUri(partition, cursor));
138          }
139        };
140    adapter.setDisplayPhotos(true);
141    adapter.setFilter(
142        ContactListFilter.createFilterWithType(ContactListFilter.FILTER_TYPE_DEFAULT));
143    adapter.setSectionHeaderDisplayEnabled(isSectionHeaderDisplayEnabled());
144    return adapter;
145  }
146
147  @Override
148  protected View inflateView(LayoutInflater inflater, ViewGroup container) {
149    return inflater.inflate(R.layout.all_contacts_fragment, null);
150  }
151
152  @Override
153  public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
154    final Uri uri = (Uri) view.getTag();
155    if (uri != null) {
156      Logger.get(getContext())
157          .logInteraction(InteractionEvent.Type.OPEN_QUICK_CONTACT_FROM_ALL_CONTACTS_GENERAL);
158      if (CompatUtils.hasPrioritizedMimeType()) {
159        QuickContact.showQuickContact(getContext(), view, uri, null, Phone.CONTENT_ITEM_TYPE);
160      } else {
161        QuickContact.showQuickContact(getActivity(), view, uri, QuickContact.MODE_LARGE, null);
162      }
163    }
164  }
165
166  @Override
167  protected void onItemClick(int position, long id) {
168    // Do nothing. Implemented to satisfy ContactEntryListFragment.
169  }
170
171  @Override
172  public void onEmptyViewActionButtonClicked() {
173    final Activity activity = getActivity();
174    if (activity == null) {
175      return;
176    }
177
178    String[] deniedPermissions =
179        PermissionsUtil.getPermissionsCurrentlyDenied(
180            getContext(), PermissionsUtil.allContactsGroupPermissionsUsedInDialer);
181    if (deniedPermissions.length > 0) {
182      LogUtil.i(
183          "AllContactsFragment.onEmptyViewActionButtonClicked",
184          "Requesting permissions: " + Arrays.toString(deniedPermissions));
185      FragmentCompat.requestPermissions(
186          this, deniedPermissions, READ_CONTACTS_PERMISSION_REQUEST_CODE);
187    } else {
188      // Add new contact
189      DialerUtils.startActivityWithErrorToast(
190          activity, IntentUtil.getNewContactIntent(), R.string.add_contact_not_available);
191    }
192  }
193
194  @Override
195  public void onRequestPermissionsResult(
196      int requestCode, String[] permissions, int[] grantResults) {
197    if (requestCode == READ_CONTACTS_PERMISSION_REQUEST_CODE) {
198      if (grantResults.length >= 1 && PackageManager.PERMISSION_GRANTED == grantResults[0]) {
199        // Force a refresh of the data since we were missing the permission before this.
200        reloadData();
201      }
202    }
203  }
204}
205