/* * Copyright (C) 2013 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.incallui; import android.app.AlertDialog; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.ListView; import com.android.dialer.R; import java.util.ArrayList; import java.util.List; /** * Provides only common interface and functions. Should be derived to implement the actual UI. */ public abstract class AnswerFragment extends BaseFragment implements AnswerPresenter.AnswerUi { public static final int TARGET_SET_FOR_AUDIO_WITHOUT_SMS = 0; public static final int TARGET_SET_FOR_AUDIO_WITH_SMS = 1; public static final int TARGET_SET_FOR_VIDEO_WITHOUT_SMS = 2; public static final int TARGET_SET_FOR_VIDEO_WITH_SMS = 3; public static final int TARGET_SET_FOR_VIDEO_ACCEPT_REJECT_REQUEST = 4; /** * This fragment implement no UI at all. Derived class should do it. */ @Override public abstract View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState); /** * The popup showing the list of canned responses. * * This is an AlertDialog containing a ListView showing the possible choices. This may be null * if the InCallScreen hasn't ever called showRespondViaSmsPopup() yet, or if the popup was * visible once but then got dismissed. */ private Dialog mCannedResponsePopup = null; /** * The popup showing a text field for users to type in their custom message. */ private AlertDialog mCustomMessagePopup = null; private ArrayAdapter mSmsResponsesAdapter; private final List mSmsResponses = new ArrayList<>(); @Override public AnswerPresenter createPresenter() { return InCallPresenter.getInstance().getAnswerPresenter(); } @Override public AnswerPresenter.AnswerUi getUi() { return this; } @Override public void showMessageDialog() { final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); mSmsResponsesAdapter = new ArrayAdapter<>(builder.getContext(), android.R.layout.simple_list_item_1, android.R.id.text1, mSmsResponses); final ListView lv = new ListView(getActivity()); lv.setAdapter(mSmsResponsesAdapter); lv.setOnItemClickListener(new RespondViaSmsItemClickListener()); builder.setCancelable(true).setView(lv).setOnCancelListener( new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialogInterface) { onMessageDialogCancel(); dismissCannedResponsePopup(); getPresenter().onDismissDialog(); } }); mCannedResponsePopup = builder.create(); mCannedResponsePopup.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); mCannedResponsePopup.show(); } private boolean isCannedResponsePopupShowing() { if (mCannedResponsePopup != null) { return mCannedResponsePopup.isShowing(); } return false; } private boolean isCustomMessagePopupShowing() { if (mCustomMessagePopup != null) { return mCustomMessagePopup.isShowing(); } return false; } /** * Dismiss the canned response list popup. * * This is safe to call even if the popup is already dismissed, and even if you never called * showRespondViaSmsPopup() in the first place. */ protected void dismissCannedResponsePopup() { if (mCannedResponsePopup != null) { mCannedResponsePopup.dismiss(); // safe even if already dismissed mCannedResponsePopup = null; } } /** * Dismiss the custom compose message popup. */ private void dismissCustomMessagePopup() { if (mCustomMessagePopup != null) { mCustomMessagePopup.dismiss(); mCustomMessagePopup = null; } } public void dismissPendingDialogs() { if (isCannedResponsePopupShowing()) { dismissCannedResponsePopup(); } if (isCustomMessagePopupShowing()) { dismissCustomMessagePopup(); } } public boolean hasPendingDialogs() { return !(mCannedResponsePopup == null && mCustomMessagePopup == null); } /** * Shows the custom message entry dialog. */ public void showCustomMessageDialog() { // Create an alert dialog containing an EditText final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); final EditText et = new EditText(builder.getContext()); builder.setCancelable(true).setView(et) .setPositiveButton(R.string.custom_message_send, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // The order is arranged in a way that the popup will be destroyed // when the InCallActivity is about to finish. final String textMessage = et.getText().toString().trim(); dismissCustomMessagePopup(); getPresenter().rejectCallWithMessage(textMessage); } }) .setNegativeButton(R.string.custom_message_cancel, new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dismissCustomMessagePopup(); getPresenter().onDismissDialog(); } }) .setOnCancelListener(new DialogInterface.OnCancelListener() { @Override public void onCancel(DialogInterface dialogInterface) { dismissCustomMessagePopup(); getPresenter().onDismissDialog(); } }) .setTitle(R.string.respond_via_sms_custom_message); mCustomMessagePopup = builder.create(); // Enable/disable the send button based on whether there is a message in the EditText et.addTextChangedListener(new TextWatcher() { @Override public void beforeTextChanged(CharSequence s, int start, int count, int after) { } @Override public void onTextChanged(CharSequence s, int start, int before, int count) { } @Override public void afterTextChanged(Editable s) { final Button sendButton = mCustomMessagePopup.getButton( DialogInterface.BUTTON_POSITIVE); sendButton.setEnabled(s != null && s.toString().trim().length() != 0); } }); // Keyboard up, show the dialog mCustomMessagePopup.getWindow().setSoftInputMode( WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE); mCustomMessagePopup.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED); mCustomMessagePopup.show(); // Send button starts out disabled final Button sendButton = mCustomMessagePopup.getButton(DialogInterface.BUTTON_POSITIVE); sendButton.setEnabled(false); } @Override public void configureMessageDialog(List textResponses) { mSmsResponses.clear(); mSmsResponses.addAll(textResponses); mSmsResponses.add(getResources().getString( R.string.respond_via_sms_custom_message)); if (mSmsResponsesAdapter != null) { mSmsResponsesAdapter.notifyDataSetChanged(); } } @Override public Context getContext() { return getActivity(); } public void onAnswer(int videoState, Context context) { Log.d(this, "onAnswer videoState=" + videoState + " context=" + context); getPresenter().onAnswer(videoState, context); } public void onDecline(Context context) { getPresenter().onDecline(context); } public void onDeclineUpgradeRequest(Context context) { InCallPresenter.getInstance().declineUpgradeRequest(context); } public void onText() { getPresenter().onText(); } /** * OnItemClickListener for the "Respond via SMS" popup. */ public class RespondViaSmsItemClickListener implements AdapterView.OnItemClickListener { /** * Handles the user selecting an item from the popup. */ @Override public void onItemClick(AdapterView parent, // The ListView View view, // The TextView that was clicked int position, long id) { Log.d(this, "RespondViaSmsItemClickListener.onItemClick(" + position + ")..."); final String message = (String) parent.getItemAtPosition(position); Log.v(this, "- message: '" + message + "'"); dismissCannedResponsePopup(); // The "Custom" choice is a special case. // (For now, it's guaranteed to be the last item.) if (position == (parent.getCount() - 1)) { // Show the custom message dialog showCustomMessageDialog(); } else { getPresenter().rejectCallWithMessage(message); } } } public void onShowAnswerUi(boolean shown) { // Do Nothing } public void showTargets(int targetSet) { // Do Nothing } public void showTargets(int targetSet, int videoState) { // Do Nothing } protected void onMessageDialogCancel() { // Do nothing. } }