Merge "Add blocked number indicator to search screen for adding a blocked number." into ub-contactsdialer-a-dev
diff --git a/res/values/colors.xml b/res/values/colors.xml
index ad493e1..e80ee69 100644
--- a/res/values/colors.xml
+++ b/res/values/colors.xml
@@ -111,6 +111,7 @@
     <color name="delete_icon_tint">#6D6D6D</color>
     <color name="blocked_number_background">#E0E0E0</color>
     <color name="blocked_number_accent_color">#42A5F5</color>
+    <color name="blocked_number_block_color">#F44336</color>
 
     <!-- Colors for onboarding flow -->
     <color name="onboarding_primary_text_color">#ffffff</color>
diff --git a/res/values/ids.xml b/res/values/ids.xml
index 14a2e59..f850327 100644
--- a/res/values/ids.xml
+++ b/res/values/ids.xml
@@ -21,4 +21,5 @@
     <item type="id" name="context_menu_edit_before_call" />
     <item type="id" name="context_menu_block_number" />
     <item type="id" name="settings_header_sounds_and_vibration" />
+    <item type="id" name="block_id" />
 </resources>
diff --git a/src/com/android/dialer/filterednumber/BlockedNumberSearchActivity.java b/src/com/android/dialer/filterednumber/BlockedNumberSearchActivity.java
index a8cbfb3..11c0ac4 100644
--- a/src/com/android/dialer/filterednumber/BlockedNumberSearchActivity.java
+++ b/src/com/android/dialer/filterednumber/BlockedNumberSearchActivity.java
@@ -36,14 +36,14 @@
 import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
 import com.android.dialer.R;
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.list.BlockedListSearchAdapter;
 import com.android.dialer.list.OnListFragmentScrolledListener;
 import com.android.dialer.list.BlockedListSearchFragment;
 import com.android.dialer.list.SearchFragment;
 import com.android.dialer.widget.SearchEditTextLayout;
 
 public class BlockedNumberSearchActivity extends AppCompatActivity
-        implements SearchFragment.HostInterface, OnPhoneNumberPickerActionListener {
-    private static final String TAG = "BlockedNumberSearch";
+        implements SearchFragment.HostInterface {
     private static final String TAG_BLOCKED_SEARCH_FRAGMENT = "blocked_search";
 
     private FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler;
@@ -115,7 +115,7 @@
             return;
         }
         final FragmentTransaction transaction = getFragmentManager().beginTransaction();
-        SearchFragment fragment = (SearchFragment) getFragmentManager()
+        BlockedListSearchFragment fragment = (BlockedListSearchFragment) getFragmentManager()
                 .findFragmentByTag(TAG_BLOCKED_SEARCH_FRAGMENT);
         if (fragment == null) {
             fragment = new BlockedListSearchFragment();
@@ -125,6 +125,8 @@
         }
         fragment.setHasOptionsMenu(false);
         fragment.setShowEmptyListForNullQuery(true);
+        fragment.setDirectorySearchEnabled(false);
+        fragment.setFilteredNumberAsyncQueryHandler(mFilteredNumberAsyncQueryHandler);
         transaction.commit();
     }
 
@@ -132,65 +134,6 @@
     public void onAttachFragment(Fragment fragment) {
         if (fragment instanceof BlockedListSearchFragment) {
             mSearchFragment = (BlockedListSearchFragment) fragment;
-            mSearchFragment.setOnPhoneNumberPickerActionListener(this);
-        }
-    }
-
-    @Override
-    public void onPickDataUri(Uri dataUri, int callInitiationType) {
-        Log.w(TAG, "onPickDataUri unsupported, ignoring.");
-    }
-
-    @Override
-    public void onPickPhoneNumber(String phoneNumber, boolean isVideoCall, int callInitiationType) {
-        blockNumber(phoneNumber);
-    }
-
-    @Override
-    public void onShortcutIntentCreated(Intent intent) {
-        Log.w(TAG, "Unsupported intent has come (" + intent + "). Ignoring.");
-    }
-
-    @Override
-    public void onHomeInActionBarSelected() {
-    }
-
-    private void blockNumber(final String number) {
-        final String countryIso = GeoUtil.getCurrentCountryIso(BlockedNumberSearchActivity.this);
-        final IndeterminateProgressDialog progressDialog =
-                IndeterminateProgressDialog.show(getFragmentManager(),
-                        getString(R.string.checkingNumber, number), null, 500);
-        final String normalizedNumber =
-                FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
-        if (normalizedNumber == null) {
-            progressDialog.dismiss();
-            Toast.makeText(
-                    BlockedNumberSearchActivity.this, getString(R.string.invalidNumber, number),
-                    Toast.LENGTH_SHORT).show();
-        } else {
-            final FilteredNumberAsyncQueryHandler.OnCheckBlockedListener onCheckListener =
-                    new FilteredNumberAsyncQueryHandler.OnCheckBlockedListener() {
-                        @Override
-                        public void onCheckComplete(Integer id) {
-                            progressDialog.dismiss();
-                            if (id == null) {
-                                final FilterNumberDialogFragment newFragment =
-                                        FilterNumberDialogFragment.newInstance(id, normalizedNumber,
-                                                number, countryIso, number);
-                                newFragment.setQueryHandler(mFilteredNumberAsyncQueryHandler);
-                                newFragment.setParentView(
-                                        findViewById(R.id.search_activity_container));
-                                newFragment.show(getFragmentManager(),
-                                        FilterNumberDialogFragment.BLOCK_DIALOG_FRAGMENT);
-                            } else {
-                                Toast.makeText(BlockedNumberSearchActivity.this,
-                                        getString(R.string.alreadyBlocked, number),
-                                        Toast.LENGTH_SHORT).show();
-                            }
-                        }
-                    };
-            mFilteredNumberAsyncQueryHandler.startBlockedQuery(
-                    onCheckListener, normalizedNumber, number, countryIso);
         }
     }
 
diff --git a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
index e9a88c8..1b95387 100644
--- a/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
+++ b/src/com/android/dialer/filterednumber/FilterNumberDialogFragment.java
@@ -21,6 +21,7 @@
 import android.app.DialogFragment;
 import android.content.ContentValues;
 import android.content.DialogInterface;
+import android.content.res.Resources;
 import android.net.Uri;
 import android.os.Bundle;
 import android.support.design.widget.Snackbar;
@@ -28,6 +29,8 @@
 
 import com.android.dialer.R;
 import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnBlockNumberListener;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnUnblockNumberListener;
 
 public class FilterNumberDialogFragment extends DialogFragment {
     public static final String BLOCK_DIALOG_FRAGMENT = "blockUnblockNumberDialog";
@@ -40,6 +43,23 @@
 
     private FilteredNumberAsyncQueryHandler mHandler;
     private View mParentView;
+    private OnBlockListener mOnBlockListener;
+    private OnUndoBlockListener mOnUndoBlockListener;
+
+    public interface OnBlockListener {
+        /**
+         * Invoked after inserting a blocked number.
+         * @param uri The uri of the newly created row.
+         */
+        public void onBlockComplete(Uri uri);
+    }
+
+    public interface OnUndoBlockListener {
+        /**
+         * Invoked on undoing the blocking of a number.
+         */
+        public void onUndoBlockComplete();
+    }
 
     public void setQueryHandler (FilteredNumberAsyncQueryHandler filteredNumberAsyncQueryHandler) {
         mHandler = filteredNumberAsyncQueryHandler;
@@ -49,6 +69,14 @@
         mParentView = view;
     }
 
+    public void setOnBlockListener(OnBlockListener listener) {
+        mOnBlockListener = listener;
+    }
+
+    public void setOnUndoBlockListener(OnUndoBlockListener listener) {
+        mOnUndoBlockListener = listener;
+    }
+
     public static FilterNumberDialogFragment newInstance(Integer blockId, String normalizedNumber,
         String number, String countryIso, String displayNumber) {
         final FilterNumberDialogFragment fragment = new FilterNumberDialogFragment();
@@ -95,50 +123,62 @@
         return builder.create();
     }
 
-    public void blockNumber() {
-        final String displayNumber = getArguments().getString(ARG_DISPLAY_NUMBER);
-        final String message = getString(R.string.snackbar_number_blocked, displayNumber);
-        final String undoMessage = getString(R.string.snackbar_number_unblocked, displayNumber);
-        final FilteredNumberAsyncQueryHandler.OnUnblockNumberListener undoListener =
-                new FilteredNumberAsyncQueryHandler.OnUnblockNumberListener() {
-                    @Override
-                    public void onUnblockComplete(int rows, ContentValues values) {
-                        Snackbar.make(mParentView, undoMessage, Snackbar.LENGTH_LONG).show();
-                    }
-                };
+    private String getBlockedMessage(String displayNumber) {
+        return getString(R.string.snackbar_number_blocked, displayNumber);
+    }
 
-        mHandler.blockNumber(
-                new FilteredNumberAsyncQueryHandler.OnBlockNumberListener() {
-                    @Override
-                    public void onBlockComplete(final Uri uri) {
-                        Snackbar.make(mParentView, message, Snackbar.LENGTH_LONG)
-                                .setAction(R.string.block_number_undo,
-                                        // Delete the newly created row on 'undo'.
-                                        new View.OnClickListener() {
-                                            @Override
-                                            public void onClick(View view) {
-                                                mHandler.unblock(undoListener, uri);
-                                            }
-                                        })
-                                .show();
-                    }
-                }, getArguments().getString(ARG_NORMALIZED_NUMBER),
+    private String getUnblockedMessage(String displayNumber) {
+        return getString(R.string.snackbar_number_unblocked, displayNumber);
+    }
+
+    private void blockNumber() {
+        final String displayNumber = getArguments().getString(ARG_DISPLAY_NUMBER);
+        final String message = getBlockedMessage(displayNumber);
+        final String undoMessage = getUnblockedMessage(displayNumber);
+        final OnUnblockNumberListener onUndoListener = new OnUnblockNumberListener() {
+            @Override
+            public void onUnblockComplete(int rows, ContentValues values) {
+                Snackbar.make(mParentView, undoMessage, Snackbar.LENGTH_LONG).show();
+                if (mOnUndoBlockListener != null) {
+                    mOnUndoBlockListener.onUndoBlockComplete();
+                }
+            }
+        };
+        final OnBlockNumberListener onBlockNumberListener = new OnBlockNumberListener() {
+            @Override
+            public void onBlockComplete(final Uri uri) {
+                Snackbar.make(mParentView, message, Snackbar.LENGTH_LONG)
+                        .setAction(R.string.block_number_undo,
+                                // Delete the newly created row on 'undo'.
+                                new View.OnClickListener() {
+                                    @Override
+                                    public void onClick(View view) {
+                                        mHandler.unblock(onUndoListener, uri);
+                                    }
+                                })
+                        .show();
+                if (mOnBlockListener != null) {
+                    mOnBlockListener.onBlockComplete(uri);
+                }
+            }
+        };
+        mHandler.blockNumber(onBlockNumberListener, getArguments().getString(ARG_NORMALIZED_NUMBER),
                 getArguments().getString(ARG_NUMBER), getArguments().getString(ARG_COUNTRY_ISO));
     }
 
-    public void unblockNumber() {
+    private void unblockNumber() {
         final String displayNumber = getArguments().getString(ARG_DISPLAY_NUMBER);
-        final String message = getString(R.string.snackbar_number_unblocked, displayNumber);
-        final String undoMessage = getString(R.string.snackbar_number_blocked, displayNumber);
-        final FilteredNumberAsyncQueryHandler.OnBlockNumberListener undoListener =
-                new FilteredNumberAsyncQueryHandler.OnBlockNumberListener() {
+        final String message = getUnblockedMessage(displayNumber);
+        final String undoMessage = getBlockedMessage(displayNumber);
+        final OnBlockNumberListener undoListener =
+                new OnBlockNumberListener() {
                     @Override
                     public void onBlockComplete(final Uri uri) {
                         Snackbar.make(mParentView, undoMessage, Snackbar.LENGTH_LONG).show();
                     }
                 };
         mHandler.unblock(
-                new FilteredNumberAsyncQueryHandler.OnUnblockNumberListener() {
+                new OnUnblockNumberListener() {
                     @Override
                     public void onUnblockComplete(int rows, final ContentValues values) {
                         Snackbar.make(mParentView, message, Snackbar.LENGTH_LONG)
diff --git a/src/com/android/dialer/list/BlockedListSearchAdapter.java b/src/com/android/dialer/list/BlockedListSearchAdapter.java
index 52e0c64..7ae24e4 100644
--- a/src/com/android/dialer/list/BlockedListSearchAdapter.java
+++ b/src/com/android/dialer/list/BlockedListSearchAdapter.java
@@ -16,20 +16,74 @@
 package com.android.dialer.list;
 
 import android.content.Context;
+import android.content.res.Resources;
+import android.database.Cursor;
+import android.graphics.Color;
+import android.view.View;
+
+import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.list.ContactListItemView;
+import com.android.dialer.R;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
 
 /**
  * List adapter to display search results for adding a blocked number.
  */
 public class BlockedListSearchAdapter extends RegularSearchListAdapter {
 
+    private Resources mResources;
+    private FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler;
+
     public BlockedListSearchAdapter(Context context) {
         super(context);
+        mResources = context.getResources();
         disableAllShortcuts();
         setShortcutEnabled(SHORTCUT_BLOCK_NUMBER, true);
     }
 
+    public void setFilteredNumberAsyncQueryHandler(FilteredNumberAsyncQueryHandler handler) {
+        mFilteredNumberAsyncQueryHandler = handler;
+    }
+
     @Override
     protected boolean isChanged(boolean showNumberShortcuts) {
         return setShortcutEnabled(SHORTCUT_BLOCK_NUMBER, showNumberShortcuts || mIsQuerySipAddress);
     }
+
+    public void setViewBlocked(ContactListItemView view, Integer id) {
+        view.setTag(R.id.block_id, id);
+        final int textColor = mResources.getColor(R.color.blocked_number_block_color);
+        view.getDataView().setTextColor(textColor);
+        view.getLabelView().setTextColor(textColor);
+        //TODO: Add icon
+    }
+
+    public void setViewUnblocked(ContactListItemView view) {
+        view.setTag(R.id.block_id, null);
+        final int textColor = mResources.getColor(R.color.dialtacts_secondary_text_color);
+        view.getDataView().setTextColor(textColor);
+        view.getLabelView().setTextColor(textColor);
+        //TODO: Remove icon
+    }
+
+    @Override
+    protected void bindView(View itemView, int partition, Cursor cursor, int position) {
+        super.bindView(itemView, partition, cursor, position);
+        final ContactListItemView view = (ContactListItemView) itemView;
+        final String number = getPhoneNumber(position);
+        final String countryIso = GeoUtil.getCurrentCountryIso(mContext);
+        final String normalizedNumber =
+                FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
+        final FilteredNumberAsyncQueryHandler.OnCheckBlockedListener onCheckListener =
+                new FilteredNumberAsyncQueryHandler.OnCheckBlockedListener() {
+                    @Override
+                    public void onCheckComplete(Integer id) {
+                        if (id != null) {
+                            setViewBlocked(view, id);
+                        }
+                    }
+                };
+        mFilteredNumberAsyncQueryHandler.startBlockedQuery(
+                onCheckListener, normalizedNumber, number, countryIso);
+    }
 }
\ No newline at end of file
diff --git a/src/com/android/dialer/list/BlockedListSearchFragment.java b/src/com/android/dialer/list/BlockedListSearchFragment.java
index d025772..7494372 100644
--- a/src/com/android/dialer/list/BlockedListSearchFragment.java
+++ b/src/com/android/dialer/list/BlockedListSearchFragment.java
@@ -15,48 +15,138 @@
  */
 package com.android.dialer.list;
 
+import android.content.ContentUris;
+import android.content.ContentValues;
+import android.net.Uri;
 import android.util.Log;
+import android.view.View;
+import android.widget.AdapterView;
+import android.widget.Toast;
 
+import com.android.contacts.common.GeoUtil;
+import com.android.contacts.common.dialog.IndeterminateProgressDialog;
 import com.android.contacts.common.list.ContactEntryListAdapter;
-import com.android.contacts.common.list.OnPhoneNumberPickerActionListener;
+import com.android.contacts.common.list.ContactListItemView;
+import com.android.dialer.R;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler;
+import com.android.dialer.database.FilteredNumberAsyncQueryHandler.OnCheckBlockedListener;
+import com.android.dialer.filterednumber.FilterNumberDialogFragment;
 
 public class BlockedListSearchFragment extends RegularSearchFragment {
     private static final String TAG = BlockedListSearchFragment.class.getSimpleName();
 
+    private FilteredNumberAsyncQueryHandler mFilteredNumberAsyncQueryHandler;
+
+    public void setFilteredNumberAsyncQueryHandler(FilteredNumberAsyncQueryHandler handler) {
+        mFilteredNumberAsyncQueryHandler = handler;
+    }
+
     @Override
     protected ContactEntryListAdapter createListAdapter() {
         BlockedListSearchAdapter adapter = new BlockedListSearchAdapter(getActivity());
         adapter.setDisplayPhotos(true);
         adapter.setUseCallableUri(usesCallableUri());
+        adapter.setFilteredNumberAsyncQueryHandler(mFilteredNumberAsyncQueryHandler);
         return adapter;
     }
 
     @Override
-    protected void onItemClick(int position, long id) {
-        final DialerPhoneNumberListAdapter adapter = (DialerPhoneNumberListAdapter) getAdapter();
-        final int shortcutType = adapter.getShortcutTypeFromPosition(position);
-        final OnPhoneNumberPickerActionListener listener = getOnPhoneNumberPickerListener();
+    public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
+        super.onItemClick(parent, view, position, id);
+        final int adapterPosition = position - getListView().getHeaderViewsCount();
+        final BlockedListSearchAdapter adapter = (BlockedListSearchAdapter) getAdapter();
+        final int shortcutType = adapter.getShortcutTypeFromPosition(adapterPosition);
+        final Integer blockId = (Integer) view.getTag(R.id.block_id);
         final String number;
-
-        if (listener == null) {
-            Log.d(TAG, "getOnPhoneNumberPickerListener() returned null in onItemClick.");
-            return;
-        }
-
         switch (shortcutType) {
             case DialerPhoneNumberListAdapter.SHORTCUT_INVALID:
                 // Handles click on a search result, either contact or nearby places result.
-                number = adapter.getPhoneNumber(position);
-                listener.onPickPhoneNumber(number, false, getCallInitiationType(false));
+                number = adapter.getPhoneNumber(adapterPosition);
+                blockContactNumber(adapter, (ContactListItemView) view, number, blockId);
                 break;
             case DialerPhoneNumberListAdapter.SHORTCUT_BLOCK_NUMBER:
                 // Handles click on 'Block number' shortcut to add the user query as a number.
                 number = adapter.getQueryString();
-                listener.onPickPhoneNumber(number, false, getCallInitiationType(false));
+                blockNumber(number);
                 break;
             default:
                 Log.w(TAG, "Ignoring unsupported shortcut type: " + shortcutType);
                 break;
         }
     }
+
+    // Prevent SearchFragment.onItemClicked from being called.
+    @Override
+    protected void onItemClick(int position, long id) {
+    }
+
+    private void blockNumber(final String number) {
+        final String countryIso = GeoUtil.getCurrentCountryIso(getContext());
+        final IndeterminateProgressDialog progressDialog =
+                IndeterminateProgressDialog.show(getFragmentManager(),
+                        getString(R.string.checkingNumber, number), null, 500);
+        final String normalizedNumber =
+                FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
+        if (normalizedNumber == null) {
+            progressDialog.dismiss();
+            Toast.makeText(getContext(), getString(R.string.invalidNumber, number),
+                    Toast.LENGTH_SHORT).show();
+            return;
+        }
+        final OnCheckBlockedListener onCheckListener = new OnCheckBlockedListener() {
+            @Override
+            public void onCheckComplete(Integer id) {
+                progressDialog.dismiss();
+                if (id == null) {
+                    final FilterNumberDialogFragment newFragment = FilterNumberDialogFragment
+                            .newInstance(id, normalizedNumber, number, countryIso, number);
+                    newFragment.setQueryHandler(mFilteredNumberAsyncQueryHandler);
+                    newFragment.setParentView(
+                            getActivity().findViewById(R.id.search_activity_container));
+                    newFragment.show(
+                            getFragmentManager(), FilterNumberDialogFragment.BLOCK_DIALOG_FRAGMENT);
+                } else {
+                    Toast.makeText(getContext(), getString(R.string.alreadyBlocked, number),
+                            Toast.LENGTH_SHORT).show();
+                }
+            }
+        };
+        mFilteredNumberAsyncQueryHandler.startBlockedQuery(
+                onCheckListener, normalizedNumber, number, countryIso);
+    }
+
+    private void blockContactNumber(final BlockedListSearchAdapter adapter,
+                                    final ContactListItemView view, final String number,
+                                    final Integer blockId) {
+        final String countryIso = GeoUtil.getCurrentCountryIso(getContext());
+        final String normalizedNumber =
+                FilteredNumberAsyncQueryHandler.getNormalizedNumber(number, countryIso);
+        if (normalizedNumber == null) {
+            Toast.makeText(getContext(), getString(R.string.invalidNumber, number),
+                    Toast.LENGTH_SHORT).show();
+            return;
+        }
+        if (blockId != null) {
+            Toast.makeText(getContext(), getString(R.string.alreadyBlocked, number),
+                    Toast.LENGTH_SHORT).show();
+            return;
+        }
+        final FilterNumberDialogFragment newFragment = FilterNumberDialogFragment
+                .newInstance(blockId, normalizedNumber, number, countryIso, number);
+        newFragment.setQueryHandler(mFilteredNumberAsyncQueryHandler);
+        newFragment.setParentView(getActivity().findViewById(R.id.search_activity_container));
+        newFragment.setOnUndoBlockListener(new FilterNumberDialogFragment.OnUndoBlockListener() {
+            @Override
+            public void onUndoBlockComplete() {
+                adapter.setViewUnblocked(view);
+            }
+        });
+        newFragment.setOnBlockListener(new FilterNumberDialogFragment.OnBlockListener() {
+            @Override
+            public void onBlockComplete(Uri uri) {
+                adapter.setViewBlocked(view, Long.valueOf(ContentUris.parseId(uri)).intValue());
+            }
+        });
+        newFragment.show(getFragmentManager(), FilterNumberDialogFragment.BLOCK_DIALOG_FRAGMENT);
+    }
 }