From a5f86bb8e89f2fdca4b6db947fe63eb7af1bf73e Mon Sep 17 00:00:00 2001 From: calderwoodra Date: Tue, 10 Apr 2018 15:16:16 -0700 Subject: Implement the disambig dialog for favorite contacts. Bug: 36841782,77760800 Test: DisambigDialogTest PiperOrigin-RevId: 192354880 Change-Id: Ie7e9f0e3994d871ce6c90e4028131204ccb0a32a --- .../android/dialer/speeddial/DisambigDialog.java | 183 ++++++--------------- .../dialer/speeddial/SpeedDialFragment.java | 2 +- .../res/layout/disambig_option_header_layout.xml | 40 +++++ .../res/layout/disambig_option_layout.xml | 100 +++-------- .../speeddial/res/layout/favorite_item_layout.xml | 7 +- .../speeddial/res/layout/fragment_speed_dial.xml | 2 - .../res/layout/speed_dial_header_layout.xml | 2 + .../speeddial/res/layout/suggestion_row_layout.xml | 12 +- 8 files changed, 126 insertions(+), 222 deletions(-) create mode 100644 java/com/android/dialer/speeddial/res/layout/disambig_option_header_layout.xml diff --git a/java/com/android/dialer/speeddial/DisambigDialog.java b/java/com/android/dialer/speeddial/DisambigDialog.java index 1ee26f595..2a8200274 100644 --- a/java/com/android/dialer/speeddial/DisambigDialog.java +++ b/java/com/android/dialer/speeddial/DisambigDialog.java @@ -17,59 +17,47 @@ package com.android.dialer.speeddial; import android.app.Dialog; -import android.content.ContentResolver; -import android.content.res.Resources; -import android.database.Cursor; import android.os.Bundle; -import android.provider.ContactsContract.CommonDataKinds.Phone; -import android.support.annotation.Nullable; import android.support.annotation.VisibleForTesting; import android.support.v4.app.DialogFragment; import android.support.v4.app.FragmentManager; import android.support.v7.app.AlertDialog; -import android.text.TextUtils; import android.util.ArraySet; import android.view.LayoutInflater; import android.view.View; +import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; import com.android.dialer.callintent.CallInitiationType; import com.android.dialer.callintent.CallIntentBuilder; -import com.android.dialer.common.LogUtil; -import com.android.dialer.common.concurrent.DialerExecutor.Worker; -import com.android.dialer.duo.DuoComponent; import com.android.dialer.precall.PreCall; -import java.util.ArrayList; -import java.util.Arrays; +import com.android.dialer.speeddial.database.SpeedDialEntry.Channel; +import java.util.List; import java.util.Set; /** Disambiguation dialog for favorite contacts in {@link SpeedDialFragment}. */ public class DisambigDialog extends DialogFragment { - @VisibleForTesting public static final String DISAMBIG_DIALOG_TAG = "disambig_dialog"; - - @SuppressWarnings("unused") - private static final String DISAMBIG_DIALOG_WORKER_TAG = "disambig_dialog_worker"; - private final Set phoneNumbers = new ArraySet<>(); - private LinearLayout container; - @SuppressWarnings("unused") - private String lookupKey; + @VisibleForTesting public List channels; + @VisibleForTesting public LinearLayout container; /** Show a disambiguation dialog for a starred contact without a favorite communication avenue. */ - public static DisambigDialog show(String lookupKey, FragmentManager manager) { + public static DisambigDialog show(List channels, FragmentManager manager) { DisambigDialog dialog = new DisambigDialog(); - dialog.lookupKey = lookupKey; - dialog.show(manager, DISAMBIG_DIALOG_TAG); + dialog.channels = channels; + dialog.show(manager, null); return dialog; } @Override public Dialog onCreateDialog(Bundle savedInstanceState) { LayoutInflater inflater = getActivity().getLayoutInflater(); + // TODO(calderwoodra): set max height of the scrollview. Might need to override onMeasure. View view = inflater.inflate(R.layout.disambig_dialog_layout, null, false); container = view.findViewById(R.id.communication_avenue_container); + insertOptions(container.findViewById(R.id.communication_avenue_container), channels); return new AlertDialog.Builder(getActivity()).setView(view).create(); } @@ -90,135 +78,68 @@ public class DisambigDialog extends DialogFragment { *
  • Clickable voice option * */ - @SuppressWarnings("unused") - private void insertOptions(Cursor cursor) { - if (!cursorIsValid(cursor)) { - dismiss(); - return; - } - - do { - String number = cursor.getString(LookupContactInfoWorker.NUMBER_INDEX); - // TODO(calderwoodra): improve this to include fuzzy matching - if (phoneNumbers.add(number)) { - insertOption( - number, - getLabel(getContext().getResources(), cursor), - isVideoReachable(cursor, number)); + private void insertOptions(LinearLayout container, List channels) { + for (Channel channel : channels) { + // TODO(calderwoodra): use fuzzy number matcher + if (phoneNumbers.add(channel.number())) { + insertHeader(container, channel.number(), channel.label()); } - } while (cursor.moveToNext()); - cursor.close(); - // TODO(calderwoodra): set max height of the scrollview. Might need to override onMeasure. + insertOption(container, channel); + } } - /** Returns true if the given number is ViLTE reachable or Duo reachable. */ - private boolean isVideoReachable(Cursor cursor, String number) { - boolean isVideoReachable = cursor.getInt(LookupContactInfoWorker.PHONE_PRESENCE_INDEX) == 1; - if (!isVideoReachable) { - isVideoReachable = DuoComponent.get(getContext()).getDuo().isReachable(getContext(), number); - } - return isVideoReachable; + private void insertHeader(LinearLayout container, String number, String phoneType) { + View view = + getActivity() + .getLayoutInflater() + .inflate(R.layout.disambig_option_header_layout, container, false); + ((TextView) view.findViewById(R.id.disambig_header_phone_type)).setText(phoneType); + ((TextView) view.findViewById(R.id.disambig_header_phone_number)).setText(number); + container.addView(view); } /** Inserts a group of options for a specific phone number. */ - private void insertOption(String number, String phoneType, boolean isVideoReachable) { + private void insertOption(LinearLayout container, Channel channel) { View view = getActivity() .getLayoutInflater() .inflate(R.layout.disambig_option_layout, container, false); - ((TextView) view.findViewById(R.id.phone_type)).setText(phoneType); - ((TextView) view.findViewById(R.id.phone_number)).setText(number); - - if (isVideoReachable) { - View videoOption = view.findViewById(R.id.video_call_container); - videoOption.setOnClickListener(v -> onVideoOptionClicked(number)); - videoOption.setVisibility(View.VISIBLE); + if (channel.isVideoTechnology()) { + View videoOption = view.findViewById(R.id.option_container); + videoOption.setOnClickListener(v -> onVideoOptionClicked(channel)); + videoOption.setContentDescription( + getActivity().getString(R.string.disambig_option_video_call)); + ((ImageView) view.findViewById(R.id.disambig_option_image)) + .setImageResource(R.drawable.quantum_ic_videocam_vd_theme_24); + ((TextView) view.findViewById(R.id.disambig_option_text)) + .setText(R.string.disambig_option_video_call); + } else { + View voiceOption = view.findViewById(R.id.option_container); + voiceOption.setOnClickListener(v -> onVoiceOptionClicked(channel)); + voiceOption.setContentDescription( + getActivity().getString(R.string.disambig_option_voice_call)); + ((ImageView) view.findViewById(R.id.disambig_option_image)) + .setImageResource(R.drawable.quantum_ic_phone_vd_theme_24); + ((TextView) view.findViewById(R.id.disambig_option_text)) + .setText(R.string.disambig_option_voice_call); } - View voiceOption = view.findViewById(R.id.voice_call_container); - voiceOption.setOnClickListener(v -> onVoiceOptionClicked(number)); container.addView(view); } - private void onVideoOptionClicked(String number) { + private void onVideoOptionClicked(Channel channel) { // TODO(calderwoodra): save this option if remember is checked // TODO(calderwoodra): place a duo call if possible PreCall.start( getContext(), - new CallIntentBuilder(number, CallInitiationType.Type.SPEED_DIAL).setIsVideoCall(true)); + new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL) + .setIsVideoCall(true)); + dismiss(); } - private void onVoiceOptionClicked(String number) { + private void onVoiceOptionClicked(Channel channel) { // TODO(calderwoodra): save this option if remember is checked - PreCall.start(getContext(), new CallIntentBuilder(number, CallInitiationType.Type.SPEED_DIAL)); - } - - // TODO(calderwoodra): handle CNAP and cequint types. - // TODO(calderwoodra): unify this into a utility method with CallLogAdapter#getNumberType - private static String getLabel(Resources resources, Cursor cursor) { - int numberType = cursor.getInt(LookupContactInfoWorker.PHONE_TYPE_INDEX); - String numberLabel = cursor.getString(LookupContactInfoWorker.PHONE_LABEL_INDEX); - - // Returns empty label instead of "custom" if the custom label is empty. - if (numberType == Phone.TYPE_CUSTOM && TextUtils.isEmpty(numberLabel)) { - return ""; - } - return (String) Phone.getTypeLabel(resources, numberType, numberLabel); - } - - // Checks if the cursor is valid and logs an error if there are any issues. - private static boolean cursorIsValid(Cursor cursor) { - if (cursor == null) { - LogUtil.e("DisambigDialog.insertOptions", "cursor null."); - return false; - } else if (cursor.isClosed()) { - LogUtil.e("DisambigDialog.insertOptions", "cursor closed."); - cursor.close(); - return false; - } else if (!cursor.moveToFirst()) { - LogUtil.e("DisambigDialog.insertOptions", "cursor empty."); - cursor.close(); - return false; - } - return true; - } - - private static class LookupContactInfoWorker implements Worker { - - static final int NUMBER_INDEX = 0; - static final int PHONE_TYPE_INDEX = 1; - static final int PHONE_LABEL_INDEX = 2; - static final int PHONE_PRESENCE_INDEX = 3; - - private static final String[] projection = - new String[] {Phone.NUMBER, Phone.TYPE, Phone.LABEL, Phone.CARRIER_PRESENCE}; - private final ContentResolver resolver; - - LookupContactInfoWorker(ContentResolver resolver) { - this.resolver = resolver; - } - - @Nullable - @Override - public Cursor doInBackground(@Nullable String lookupKey) throws Throwable { - if (TextUtils.isEmpty(lookupKey)) { - LogUtil.e("LookupConctactInfoWorker.doInBackground", "contact id unsest."); - return null; - } - return resolver.query( - Phone.CONTENT_URI, projection, Phone.LOOKUP_KEY + " = ?", new String[] {lookupKey}, null); - } - } - - @VisibleForTesting - public static String[] getProjectionForTesting() { - ArrayList projection = - new ArrayList<>(Arrays.asList(LookupContactInfoWorker.projection)); - projection.add(Phone.LOOKUP_KEY); - return projection.toArray(new String[projection.size()]); - } - - @VisibleForTesting - public LinearLayout getContainer() { - return container; + PreCall.start( + getContext(), new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL)); + dismiss(); } } diff --git a/java/com/android/dialer/speeddial/SpeedDialFragment.java b/java/com/android/dialer/speeddial/SpeedDialFragment.java index d1f195be1..3cf6cb9b9 100644 --- a/java/com/android/dialer/speeddial/SpeedDialFragment.java +++ b/java/com/android/dialer/speeddial/SpeedDialFragment.java @@ -120,7 +120,7 @@ public class SpeedDialFragment extends Fragment { @Override public void onAmbiguousContactClicked(List channels) { - // TODO(calderwoodra): implement the disambig dialog with channels + DisambigDialog.show(channels, getChildFragmentManager()); } @Override diff --git a/java/com/android/dialer/speeddial/res/layout/disambig_option_header_layout.xml b/java/com/android/dialer/speeddial/res/layout/disambig_option_header_layout.xml new file mode 100644 index 000000000..d331a0a6e --- /dev/null +++ b/java/com/android/dialer/speeddial/res/layout/disambig_option_header_layout.xml @@ -0,0 +1,40 @@ + + + + + + + + diff --git a/java/com/android/dialer/speeddial/res/layout/disambig_option_layout.xml b/java/com/android/dialer/speeddial/res/layout/disambig_option_layout.xml index 097ac4084..62f6ab5e1 100644 --- a/java/com/android/dialer/speeddial/res/layout/disambig_option_layout.xml +++ b/java/com/android/dialer/speeddial/res/layout/disambig_option_layout.xml @@ -15,89 +15,27 @@ ~ limitations under the License --> - - - - - - - - - + + + + - - - - - - - - - - - - + android:layout_marginStart="12dp" + android:layout_gravity="center_vertical" + style="@style/PrimaryText"/> \ No newline at end of file diff --git a/java/com/android/dialer/speeddial/res/layout/favorite_item_layout.xml b/java/com/android/dialer/speeddial/res/layout/favorite_item_layout.xml index b4af686b7..d4fa07d90 100644 --- a/java/com/android/dialer/speeddial/res/layout/favorite_item_layout.xml +++ b/java/com/android/dialer/speeddial/res/layout/favorite_item_layout.xml @@ -32,8 +32,7 @@ + android:layout_height="match_parent"/> \ No newline at end of file diff --git a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml index 9f2dec931..67ef877ca 100644 --- a/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml +++ b/java/com/android/dialer/speeddial/res/layout/fragment_speed_dial.xml @@ -19,8 +19,6 @@ android:id="@+id/speed_dial_recycler_view" android:layout_width="match_parent" android:layout_height="match_parent" - android:paddingStart="16dp" - android:paddingEnd="16dp" android:clipToPadding="false" android:background="@color/background_dialer_light" android:paddingBottom="@dimen/floating_action_button_list_bottom_padding"/> diff --git a/java/com/android/dialer/speeddial/res/layout/speed_dial_header_layout.xml b/java/com/android/dialer/speeddial/res/layout/speed_dial_header_layout.xml index 0a84b41e6..15c00e45b 100644 --- a/java/com/android/dialer/speeddial/res/layout/speed_dial_header_layout.xml +++ b/java/com/android/dialer/speeddial/res/layout/speed_dial_header_layout.xml @@ -17,6 +17,8 @@ + android:minHeight="72dp" + android:background="?android:attr/selectableItemBackground"> + android:layout_centerVertical="true" + android:layout_marginStart="16dp"/> + android:layout_toEndOf="@+id/avatar" + android:layout_toStartOf="@+id/overflow" + android:layout_marginStart="8dp">