blob: 15b81098b844fe4986abf8beddf410c4d617e5cc [file] [log] [blame]
/*
* Copyright (C) 2017 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License
*/
package com.android.dialer.speeddial;
import android.app.Dialog;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.VisibleForTesting;
import android.support.annotation.WorkerThread;
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.CheckBox;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
import com.android.dialer.callintent.CallInitiationType;
import com.android.dialer.callintent.CallIntentBuilder;
import com.android.dialer.common.Assert;
import com.android.dialer.common.LogUtil;
import com.android.dialer.common.concurrent.DefaultFutureCallback;
import com.android.dialer.common.concurrent.DialerExecutorComponent;
import com.android.dialer.logging.DialerImpression;
import com.android.dialer.logging.Logger;
import com.android.dialer.precall.PreCall;
import com.android.dialer.speeddial.database.SpeedDialEntry;
import com.android.dialer.speeddial.database.SpeedDialEntry.Channel;
import com.android.dialer.speeddial.database.SpeedDialEntryDatabaseHelper;
import com.android.dialer.speeddial.loader.SpeedDialUiItem;
import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.Futures;
import com.google.common.util.concurrent.ListenableFuture;
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 FRAGMENT_TAG = "disambig_dialog";
private final Set<String> phoneNumbers = new ArraySet<>();
private SpeedDialUiItem speedDialUiItem;
@VisibleForTesting public List<Channel> channels;
@VisibleForTesting public LinearLayout container;
@VisibleForTesting public CheckBox rememberThisChoice;
/** Show a disambiguation dialog for a starred contact without a favorite communication avenue. */
public static DisambigDialog show(SpeedDialUiItem speedDialUiItem, FragmentManager manager) {
DisambigDialog dialog = new DisambigDialog();
dialog.speedDialUiItem = speedDialUiItem;
dialog.channels = speedDialUiItem.channels();
dialog.show(manager, FRAGMENT_TAG);
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);
rememberThisChoice = view.findViewById(R.id.remember_this_choice_checkbox);
insertOptions(container.findViewById(R.id.communication_avenue_container), channels);
return new AlertDialog.Builder(getActivity()).setView(view).create();
}
@Override
public void onResume() {
super.onResume();
getDialog()
.getWindow()
.setLayout(
getContext().getResources().getDimensionPixelSize(R.dimen.disambig_dialog_width),
LayoutParams.WRAP_CONTENT);
}
@Override
public void onPause() {
super.onPause();
// TODO(calderwoodra): for simplicity, just dismiss the dialog on configuration change and
// consider changing this later.
dismiss();
}
/**
* Inflates and inserts the following in the dialog:
*
* <ul>
* <li>Header for each unique phone number
* <li>Clickable video option if the phone number is video reachable (ViLTE, Duo)
* <li>Clickable voice option
* </ul>
*/
private void insertOptions(LinearLayout container, List<Channel> channels) {
for (Channel channel : channels) {
// TODO(calderwoodra): use fuzzy number matcher
if (phoneNumbers.add(channel.number())) {
if (phoneNumbers.size() != 1) {
insertDivider(container);
}
insertHeader(container, channel.number(), channel.label());
}
insertOption(container, channel);
}
}
private void insertDivider(LinearLayout container) {
View view =
getActivity()
.getLayoutInflater()
.inflate(R.layout.disambig_dialog_divider, container, false);
container.addView(view);
}
private void insertHeader(LinearLayout container, String number, String label) {
View view =
getActivity()
.getLayoutInflater()
.inflate(R.layout.disambig_option_header_layout, container, false);
String secondaryInfo =
TextUtils.isEmpty(label)
? number
: getContext().getString(R.string.call_subject_type_and_number, label, number);
((TextView) view.findViewById(R.id.disambig_header_phone_label)).setText(secondaryInfo);
container.addView(view);
}
/** Inserts a group of options for a specific phone number. */
private void insertOption(LinearLayout container, Channel channel) {
View view =
getActivity()
.getLayoutInflater()
.inflate(R.layout.disambig_option_layout, container, false);
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);
}
container.addView(view);
}
private void onVideoOptionClicked(Channel channel) {
if (rememberThisChoice.isChecked()) {
Logger.get(getContext()).logImpression(DialerImpression.Type.FAVORITE_SET_VIDEO_DEFAULT);
setDefaultChannel(getContext().getApplicationContext(), speedDialUiItem, channel);
}
if (channel.technology() == Channel.DUO) {
Logger.get(getContext())
.logImpression(
DialerImpression.Type.LIGHTBRINGER_VIDEO_REQUESTED_FOR_FAVORITE_CONTACT_DISAMBIG);
}
PreCall.start(
getContext(),
new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL_DISAMBIG_DIALOG)
.setAllowAssistedDial(true)
.setIsVideoCall(true)
.setIsDuoCall(channel.technology() == Channel.DUO));
dismiss();
}
private void onVoiceOptionClicked(Channel channel) {
if (rememberThisChoice.isChecked()) {
Logger.get(getContext()).logImpression(DialerImpression.Type.FAVORITE_SET_VOICE_DEFAULT);
setDefaultChannel(getContext().getApplicationContext(), speedDialUiItem, channel);
}
PreCall.start(
getContext(),
new CallIntentBuilder(channel.number(), CallInitiationType.Type.SPEED_DIAL_DISAMBIG_DIALOG)
.setAllowAssistedDial(true));
dismiss();
}
private static void setDefaultChannel(Context appContext, SpeedDialUiItem item, Channel channel) {
LogUtil.enterBlock("DisambigDialog.setDefaultChannel");
ListenableFuture<Void> future =
DialerExecutorComponent.get(appContext)
.backgroundExecutor()
.submit(
() -> {
updateDatabaseEntry(appContext, item, channel);
return null;
});
Futures.addCallback(
future,
new DefaultFutureCallback<>(),
DialerExecutorComponent.get(appContext).backgroundExecutor());
}
@WorkerThread
private static void updateDatabaseEntry(
Context appContext, SpeedDialUiItem item, Channel channel) {
Assert.isWorkerThread();
SpeedDialEntry entry =
SpeedDialEntry.builder()
.setId(item.speedDialEntryId())
.setContactId(item.contactId())
.setLookupKey(item.lookupKey())
.setDefaultChannel(channel)
.build();
new SpeedDialEntryDatabaseHelper(appContext).update(ImmutableList.of(entry));
}
}