| /* |
| * Copyright (C) 2017 The Android Open Source Project |
| * Copyright (C) 2023 The LineageOS 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.calldetails; |
| |
| import android.content.Context; |
| import android.content.Intent; |
| import android.net.Uri; |
| import android.telecom.PhoneAccount; |
| import android.text.TextUtils; |
| import android.view.View; |
| import android.view.View.OnClickListener; |
| import android.view.View.OnLongClickListener; |
| import android.widget.ImageView; |
| import android.widget.QuickContactBadge; |
| import android.widget.RelativeLayout; |
| import android.widget.TextView; |
| |
| import androidx.recyclerview.widget.RecyclerView; |
| |
| import com.android.dialer.R; |
| import com.android.dialer.app.AccountSelectionActivity; |
| import com.android.dialer.calldetails.CallDetailsActivityCommon.AssistedDialingNumberParseWorker; |
| import com.android.dialer.calldetails.CallDetailsEntries.CallDetailsEntry; |
| import com.android.dialer.callintent.CallInitiationType; |
| import com.android.dialer.calllogutils.CallbackActionHelper.CallbackAction; |
| import com.android.dialer.common.Assert; |
| import com.android.dialer.common.LogUtil; |
| import com.android.dialer.common.concurrent.DialerExecutor.FailureListener; |
| import com.android.dialer.common.concurrent.DialerExecutor.SuccessListener; |
| import com.android.dialer.compat.telephony.TelephonyManagerCompat; |
| import com.android.dialer.contactphoto.ContactPhotoManager; |
| import com.android.dialer.dialercontact.DialerContact; |
| import com.android.dialer.glidephotomanager.GlidePhotoManagerComponent; |
| import com.android.dialer.phonenumberutil.PhoneNumberHelper; |
| import com.android.dialer.util.DialerUtils; |
| import com.android.dialer.widget.BidiTextView; |
| |
| /** |
| * ViewHolder for the header in {@link OldCallDetailsActivity} or {@link CallDetailsActivity}. |
| * |
| * <p>The header contains contact info and the primary callback button. |
| */ |
| public class CallDetailsHeaderViewHolder extends RecyclerView.ViewHolder |
| implements OnClickListener, OnLongClickListener, FailureListener { |
| |
| private final CallDetailsHeaderListener callDetailsHeaderListener; |
| private final ImageView callbackButton; |
| private final BidiTextView nameView; |
| private final BidiTextView numberView; |
| private final TextView networkView; |
| private final QuickContactBadge contactPhoto; |
| private final Context context; |
| private final TextView assistedDialingInternationalDirectDialCodeAndCountryCodeText; |
| private final RelativeLayout assistedDialingContainer; |
| |
| private final String number; |
| private final String postDialDigits; |
| |
| private @CallbackAction int callbackAction; |
| |
| CallDetailsHeaderViewHolder( |
| View container, |
| String number, |
| String postDialDigits, |
| CallDetailsHeaderListener callDetailsHeaderListener) { |
| super(container); |
| context = container.getContext(); |
| callbackButton = container.findViewById(R.id.call_back_button); |
| nameView = container.findViewById(R.id.contact_name); |
| numberView = container.findViewById(R.id.phone_number); |
| networkView = container.findViewById(R.id.network); |
| contactPhoto = container.findViewById(R.id.quick_contact_photo); |
| assistedDialingInternationalDirectDialCodeAndCountryCodeText = |
| container.findViewById(R.id.assisted_dialing_text); |
| assistedDialingContainer = container.findViewById(R.id.assisted_dialing_container); |
| |
| assistedDialingContainer.setOnClickListener( |
| callDetailsHeaderListener::openAssistedDialingSettings); |
| |
| callbackButton.setOnClickListener(this); |
| callbackButton.setOnLongClickListener(this); |
| |
| this.number = number; |
| this.postDialDigits = postDialDigits; |
| this.callDetailsHeaderListener = callDetailsHeaderListener; |
| } |
| |
| private boolean hasAssistedDialingFeature(Integer features) { |
| return (features & TelephonyManagerCompat.FEATURES_ASSISTED_DIALING) |
| == TelephonyManagerCompat.FEATURES_ASSISTED_DIALING; |
| } |
| |
| void updateAssistedDialingInfo(CallDetailsEntry callDetailsEntry) { |
| |
| if (callDetailsEntry != null && hasAssistedDialingFeature(callDetailsEntry.getFeatures())) { |
| showAssistedDialingContainer(true); |
| callDetailsHeaderListener.createAssistedDialerNumberParserTask( |
| new CallDetailsActivityCommon.AssistedDialingNumberParseWorker(), |
| this::updateAssistedDialingText, |
| this::onFailure); |
| |
| } else { |
| showAssistedDialingContainer(false); |
| } |
| } |
| |
| private void showAssistedDialingContainer(boolean shouldShowContainer) { |
| if (shouldShowContainer) { |
| assistedDialingContainer.setVisibility(View.VISIBLE); |
| } else { |
| LogUtil.i( |
| "CallDetailsHeaderViewHolder.updateAssistedDialingInfo", |
| "hiding assisted dialing ui elements"); |
| assistedDialingContainer.setVisibility(View.GONE); |
| } |
| } |
| |
| private void updateAssistedDialingText(Integer countryCode) { |
| |
| // Try and handle any poorly formed inputs. |
| if (countryCode <= 0) { |
| onFailure(new IllegalStateException()); |
| return; |
| } |
| |
| LogUtil.i( |
| "CallDetailsHeaderViewHolder.updateAssistedDialingText", "Updating Assisted Dialing Text"); |
| assistedDialingInternationalDirectDialCodeAndCountryCodeText.setText( |
| context.getString( |
| R.string.assisted_dialing_country_code_entry, String.valueOf(countryCode))); |
| } |
| |
| @Override |
| public void onFailure(Throwable unused) { |
| assistedDialingInternationalDirectDialCodeAndCountryCodeText.setText( |
| R.string.assisted_dialing_country_code_entry_failure); |
| } |
| |
| /** Populates the contact info fields based on the current contact information. */ |
| void updateContactInfo(DialerContact contact, @CallbackAction int callbackAction) { |
| ContactPhotoManager.getInstance(context) |
| .loadDialerThumbnailOrPhoto( |
| contactPhoto, |
| contact.getContactUri().isEmpty() ? null : Uri.parse(contact.getContactUri()), |
| contact.getPhotoId(), |
| contact.getPhotoUri().isEmpty() ? null : Uri.parse(contact.getPhotoUri()), |
| contact.getNameOrNumber(), |
| contact.getContactType()); |
| |
| // Hide the secondary text of the header by default. |
| // We will show it if needed (see below). |
| numberView.setVisibility(View.GONE); |
| numberView.setText(null); |
| |
| if (PhoneNumberHelper.isLocalEmergencyNumber(context, contact.getNumber())) { |
| nameView.setText(context.getResources().getString(R.string.emergency_number)); |
| } else { |
| nameView.setText(contact.getNameOrNumber()); |
| if (!TextUtils.isEmpty(contact.getDisplayNumber())) { |
| numberView.setVisibility(View.VISIBLE); |
| String secondaryInfo = |
| TextUtils.isEmpty(contact.getNumberLabel()) |
| ? contact.getDisplayNumber() |
| : context.getString( |
| com.android.dialer.contacts.resources.R.string.call_subject_type_and_number, |
| contact.getNumberLabel(), |
| contact.getDisplayNumber()); |
| numberView.setText(secondaryInfo); |
| } |
| } |
| |
| if (!TextUtils.isEmpty(contact.getSimDetails().getNetwork())) { |
| networkView.setVisibility(View.VISIBLE); |
| networkView.setText(contact.getSimDetails().getNetwork()); |
| if (contact.getSimDetails().getColor() != PhoneAccount.NO_HIGHLIGHT_COLOR) { |
| networkView.setTextColor(contact.getSimDetails().getColor()); |
| } |
| } |
| |
| setCallbackAction(callbackAction); |
| } |
| |
| void updateContactInfo(CallDetailsHeaderInfo headerInfo, @CallbackAction int callbackAction) { |
| GlidePhotoManagerComponent.get(context) |
| .glidePhotoManager() |
| .loadQuickContactBadge(contactPhoto, headerInfo.getPhotoInfo()); |
| |
| nameView.setText(headerInfo.getPrimaryText()); |
| if (!headerInfo.getSecondaryText().isEmpty()) { |
| numberView.setVisibility(View.VISIBLE); |
| numberView.setText(headerInfo.getSecondaryText()); |
| } else { |
| numberView.setVisibility(View.GONE); |
| numberView.setText(null); |
| } |
| |
| setCallbackAction(callbackAction); |
| } |
| |
| private void setCallbackAction(@CallbackAction int callbackAction) { |
| this.callbackAction = callbackAction; |
| switch (callbackAction) { |
| case CallbackAction.IMS_VIDEO: |
| callbackButton.setVisibility(View.VISIBLE); |
| callbackButton.setImageResource(R.drawable.quantum_ic_videocam_vd_theme_24); |
| break; |
| case CallbackAction.VOICE: |
| callbackButton.setVisibility(View.VISIBLE); |
| callbackButton.setImageResource(R.drawable.quantum_ic_call_vd_theme_24); |
| break; |
| case CallbackAction.NONE: |
| callbackButton.setVisibility(View.GONE); |
| break; |
| default: |
| throw Assert.createIllegalStateFailException("Invalid action: " + callbackAction); |
| } |
| } |
| |
| @Override |
| public void onClick(View view) { |
| if (view == callbackButton) { |
| switch (callbackAction) { |
| case CallbackAction.IMS_VIDEO: |
| callDetailsHeaderListener.placeImsVideoCall(number); |
| break; |
| case CallbackAction.VOICE: |
| callDetailsHeaderListener.placeVoiceCall(number, postDialDigits); |
| break; |
| case CallbackAction.NONE: |
| default: |
| throw Assert.createIllegalStateFailException("Invalid action: " + callbackAction); |
| } |
| } else { |
| throw Assert.createIllegalStateFailException("View OnClickListener not implemented: " + view); |
| } |
| } |
| |
| @Override |
| public boolean onLongClick(View view) { |
| if (view == callbackButton) { |
| Intent intent = AccountSelectionActivity.createIntent(view.getContext(), |
| number, CallInitiationType.Type.CALL_DETAILS); |
| if (intent != null) { |
| DialerUtils.startActivityWithErrorToast(view.getContext(), intent); |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /** Listener for the call details header */ |
| interface CallDetailsHeaderListener { |
| |
| /** Places an IMS video call. */ |
| void placeImsVideoCall(String phoneNumber); |
| |
| /** Place a traditional voice call. */ |
| void placeVoiceCall(String phoneNumber, String postDialDigits); |
| |
| /** Access the Assisted Dialing settings * */ |
| void openAssistedDialingSettings(View view); |
| |
| void createAssistedDialerNumberParserTask( |
| AssistedDialingNumberParseWorker worker, |
| SuccessListener<Integer> onSuccess, |
| FailureListener onFailure); |
| } |
| } |