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 package com.android.dialer.app.list; 17 18 import android.app.Activity; 19 import android.os.Bundle; 20 import android.support.v7.app.ActionBar; 21 import android.support.v7.app.AppCompatActivity; 22 import android.telephony.PhoneNumberUtils; 23 import android.text.Editable; 24 import android.text.TextUtils; 25 import android.text.TextWatcher; 26 import android.util.TypedValue; 27 import android.view.View; 28 import android.widget.AdapterView; 29 import android.widget.EditText; 30 import android.widget.Toast; 31 import com.android.contacts.common.list.ContactEntryListAdapter; 32 import com.android.contacts.common.util.ContactDisplayUtils; 33 import com.android.dialer.app.R; 34 import com.android.dialer.app.widget.SearchEditTextLayout; 35 import com.android.dialer.blocking.BlockNumberDialogFragment; 36 import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler; 37 import com.android.dialer.blocking.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener; 38 import com.android.dialer.common.LogUtil; 39 import com.android.dialer.location.GeoUtil; 40 import com.android.dialer.logging.InteractionEvent; 41 import com.android.dialer.logging.Logger; 42 43 public class BlockedListSearchFragment extends RegularSearchFragment 44 implements BlockNumberDialogFragment.Callback { 45 46 private final TextWatcher mPhoneSearchQueryTextListener = 47 new TextWatcher() { 48 @Override 49 public void beforeTextChanged(CharSequence s, int start, int count, int after) {} 50 51 @Override 52 public void onTextChanged(CharSequence s, int start, int before, int count) { 53 setQueryString(s.toString()); 54 } 55 56 @Override 57 public void afterTextChanged(Editable s) {} 58 }; 59 private final SearchEditTextLayout.Callback mSearchLayoutCallback = 60 new SearchEditTextLayout.Callback() { 61 @Override 62 public void onBackButtonClicked() { 63 getActivity().onBackPressed(); 64 } 65 66 @Override 67 public void onSearchViewClicked() {} 68 }; 69 private FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler; 70 private EditText mSearchView; 71 72 @Override 73 public void onCreate(Bundle savedInstanceState) { 74 super.onCreate(savedInstanceState); 75 76 setShowEmptyListForNullQuery(true); 77 /* 78 * Pass in the empty string here so ContactEntryListFragment#setQueryString interprets it as 79 * an empty search query, rather than as an uninitalized value. In the latter case, the 80 * adapter returned by #createListAdapter is used, which populates the view with contacts. 81 * Passing in the empty string forces ContactEntryListFragment to interpret it as an empty 82 * query, which results in showing an empty view 83 */ 84 setQueryString(getQueryString() == null ? "" : getQueryString()); 85 mFilteredNumberAsyncQueryHandler = new FilteredNumberAsyncQueryHandler(getContext()); 86 } 87 88 @Override 89 public void onResume() { 90 super.onResume(); 91 92 ActionBar actionBar = ((AppCompatActivity) getActivity()).getSupportActionBar(); 93 actionBar.setCustomView(R.layout.search_edittext); 94 actionBar.setDisplayShowCustomEnabled(true); 95 actionBar.setDisplayHomeAsUpEnabled(false); 96 actionBar.setDisplayShowHomeEnabled(false); 97 98 final SearchEditTextLayout searchEditTextLayout = 99 (SearchEditTextLayout) actionBar.getCustomView().findViewById(R.id.search_view_container); 100 searchEditTextLayout.expand(false, true); 101 searchEditTextLayout.setCallback(mSearchLayoutCallback); 102 searchEditTextLayout.setBackgroundDrawable(null); 103 104 mSearchView = (EditText) searchEditTextLayout.findViewById(R.id.search_view); 105 mSearchView.addTextChangedListener(mPhoneSearchQueryTextListener); 106 mSearchView.setHint(R.string.block_number_search_hint); 107 108 searchEditTextLayout 109 .findViewById(R.id.search_box_expanded) 110 .setBackgroundColor(getContext().getResources().getColor(android.R.color.white)); 111 112 if (!TextUtils.isEmpty(getQueryString())) { 113 mSearchView.setText(getQueryString()); 114 } 115 116 // TODO: Don't set custom text size; use default search text size. 117 mSearchView.setTextSize( 118 TypedValue.COMPLEX_UNIT_PX, 119 getResources().getDimension(R.dimen.blocked_number_search_text_size)); 120 } 121 122 @Override 123 protected ContactEntryListAdapter createListAdapter() { 124 BlockedListSearchAdapter adapter = new BlockedListSearchAdapter(getActivity()); 125 adapter.setDisplayPhotos(true); 126 // Don't show SIP addresses. 127 adapter.setUseCallableUri(false); 128 // Keep in sync with the queryString set in #onCreate 129 adapter.setQueryString(getQueryString() == null ? "" : getQueryString()); 130 return adapter; 131 } 132 133 @Override 134 public void onItemClick(AdapterView<?> parent, View view, int position, long id) { 135 super.onItemClick(parent, view, position, id); 136 final int adapterPosition = position - getListView().getHeaderViewsCount(); 137 final BlockedListSearchAdapter adapter = (BlockedListSearchAdapter) getAdapter(); 138 final int shortcutType = adapter.getShortcutTypeFromPosition(adapterPosition); 139 final Integer blockId = (Integer) view.getTag(R.id.block_id); 140 final String number; 141 switch (shortcutType) { 142 case DialerPhoneNumberListAdapter.SHORTCUT_INVALID: 143 // Handles click on a search result, either contact or nearby places result. 144 number = adapter.getPhoneNumber(adapterPosition); 145 blockContactNumber(number, blockId); 146 break; 147 case DialerPhoneNumberListAdapter.SHORTCUT_BLOCK_NUMBER: 148 // Handles click on 'Block number' shortcut to add the user query as a number. 149 number = adapter.getQueryString(); 150 blockNumber(number); 151 break; 152 default: 153 LogUtil.w( 154 "BlockedListSearchFragment.onItemClick", 155 "ignoring unsupported shortcut type: " + shortcutType); 156 break; 157 } 158 } 159 160 @Override 161 protected void onItemClick(int position, long id) { 162 // Prevent SearchFragment.onItemClicked from being called. 163 } 164 165 private void blockNumber(final String number) { 166 final String countryIso = GeoUtil.getCurrentCountryIso(getContext()); 167 final OnCheckBlockedListener onCheckListener = 168 new OnCheckBlockedListener() { 169 @Override 170 public void onCheckComplete(Integer id) { 171 if (id == null) { 172 BlockNumberDialogFragment.show( 173 id, 174 number, 175 countryIso, 176 PhoneNumberUtils.formatNumber(number, countryIso), 177 R.id.blocked_numbers_activity_container, 178 getFragmentManager(), 179 BlockedListSearchFragment.this); 180 } else if (id == FilteredNumberAsyncQueryHandler.INVALID_ID) { 181 Toast.makeText( 182 getContext(), 183 ContactDisplayUtils.getTtsSpannedPhoneNumber( 184 getResources(), R.string.invalidNumber, number), 185 Toast.LENGTH_SHORT) 186 .show(); 187 } else { 188 Toast.makeText( 189 getContext(), 190 ContactDisplayUtils.getTtsSpannedPhoneNumber( 191 getResources(), R.string.alreadyBlocked, number), 192 Toast.LENGTH_SHORT) 193 .show(); 194 } 195 } 196 }; 197 mFilteredNumberAsyncQueryHandler.isBlockedNumber(onCheckListener, number, countryIso); 198 } 199 200 @Override 201 public void onFilterNumberSuccess() { 202 Logger.get(getContext()).logInteraction(InteractionEvent.Type.BLOCK_NUMBER_MANAGEMENT_SCREEN); 203 goBack(); 204 } 205 206 @Override 207 public void onUnfilterNumberSuccess() { 208 LogUtil.e( 209 "BlockedListSearchFragment.onUnfilterNumberSuccess", 210 "unblocked a number from the BlockedListSearchFragment"); 211 goBack(); 212 } 213 214 private void goBack() { 215 Activity activity = getActivity(); 216 if (activity == null) { 217 return; 218 } 219 activity.onBackPressed(); 220 } 221 222 @Override 223 public void onChangeFilteredNumberUndo() { 224 getAdapter().notifyDataSetChanged(); 225 } 226 227 private void blockContactNumber(final String number, final Integer blockId) { 228 if (blockId != null) { 229 Toast.makeText( 230 getContext(), 231 ContactDisplayUtils.getTtsSpannedPhoneNumber( 232 getResources(), R.string.alreadyBlocked, number), 233 Toast.LENGTH_SHORT) 234 .show(); 235 return; 236 } 237 238 BlockNumberDialogFragment.show( 239 blockId, 240 number, 241 GeoUtil.getCurrentCountryIso(getContext()), 242 number, 243 R.id.blocked_numbers_activity_container, 244 getFragmentManager(), 245 this); 246 } 247 } 248