Home | History | Annotate | Download | only in incallui
      1 /*
      2  * Copyright (C) 2013 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License
     15  */
     16 
     17 package com.android.incallui;
     18 
     19 import android.app.AlertDialog;
     20 import android.app.Dialog;
     21 import android.content.Context;
     22 import android.content.DialogInterface;
     23 import android.os.Bundle;
     24 import android.text.Editable;
     25 import android.text.TextWatcher;
     26 import android.view.LayoutInflater;
     27 import android.view.View;
     28 import android.view.ViewGroup;
     29 import android.view.WindowManager;
     30 import android.widget.AdapterView;
     31 import android.widget.ArrayAdapter;
     32 import android.widget.Button;
     33 import android.widget.EditText;
     34 import android.widget.ListView;
     35 
     36 import com.android.dialer.R;
     37 
     38 import java.util.ArrayList;
     39 import java.util.List;
     40 
     41 
     42 /**
     43  * Provides only common interface and functions. Should be derived to implement the actual UI.
     44  */
     45 public abstract class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresenter.AnswerUi>
     46         implements AnswerPresenter.AnswerUi {
     47 
     48     public static final int TARGET_SET_FOR_AUDIO_WITHOUT_SMS = 0;
     49     public static final int TARGET_SET_FOR_AUDIO_WITH_SMS = 1;
     50     public static final int TARGET_SET_FOR_VIDEO_WITHOUT_SMS = 2;
     51     public static final int TARGET_SET_FOR_VIDEO_WITH_SMS = 3;
     52     public static final int TARGET_SET_FOR_VIDEO_ACCEPT_REJECT_REQUEST = 4;
     53 
     54     /**
     55      * This fragment implement no UI at all. Derived class should do it.
     56      */
     57     @Override
     58     public abstract View onCreateView(LayoutInflater inflater, ViewGroup container,
     59             Bundle savedInstanceState);
     60 
     61     /**
     62      * The popup showing the list of canned responses.
     63      *
     64      * This is an AlertDialog containing a ListView showing the possible choices.  This may be null
     65      * if the InCallScreen hasn't ever called showRespondViaSmsPopup() yet, or if the popup was
     66      * visible once but then got dismissed.
     67      */
     68     private Dialog mCannedResponsePopup = null;
     69 
     70     /**
     71      * The popup showing a text field for users to type in their custom message.
     72      */
     73     private AlertDialog mCustomMessagePopup = null;
     74 
     75     private ArrayAdapter<String> mSmsResponsesAdapter;
     76 
     77     private final List<String> mSmsResponses = new ArrayList<>();
     78 
     79     @Override
     80     public AnswerPresenter createPresenter() {
     81         return InCallPresenter.getInstance().getAnswerPresenter();
     82     }
     83 
     84     @Override
     85     public AnswerPresenter.AnswerUi getUi() {
     86         return this;
     87     }
     88 
     89     @Override
     90     public void showMessageDialog() {
     91         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
     92 
     93         mSmsResponsesAdapter = new ArrayAdapter<>(builder.getContext(),
     94                 android.R.layout.simple_list_item_1, android.R.id.text1, mSmsResponses);
     95 
     96         final ListView lv = new ListView(getActivity());
     97         lv.setAdapter(mSmsResponsesAdapter);
     98         lv.setOnItemClickListener(new RespondViaSmsItemClickListener());
     99 
    100         builder.setCancelable(true).setView(lv).setOnCancelListener(
    101                 new DialogInterface.OnCancelListener() {
    102                     @Override
    103                     public void onCancel(DialogInterface dialogInterface) {
    104                         onMessageDialogCancel();
    105                         dismissCannedResponsePopup();
    106                         getPresenter().onDismissDialog();
    107                     }
    108                 });
    109         mCannedResponsePopup = builder.create();
    110         mCannedResponsePopup.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    111         mCannedResponsePopup.show();
    112     }
    113 
    114     private boolean isCannedResponsePopupShowing() {
    115         if (mCannedResponsePopup != null) {
    116             return mCannedResponsePopup.isShowing();
    117         }
    118         return false;
    119     }
    120 
    121     private boolean isCustomMessagePopupShowing() {
    122         if (mCustomMessagePopup != null) {
    123             return mCustomMessagePopup.isShowing();
    124         }
    125         return false;
    126     }
    127 
    128     /**
    129      * Dismiss the canned response list popup.
    130      *
    131      * This is safe to call even if the popup is already dismissed, and even if you never called
    132      * showRespondViaSmsPopup() in the first place.
    133      */
    134     protected void dismissCannedResponsePopup() {
    135         if (mCannedResponsePopup != null) {
    136             mCannedResponsePopup.dismiss();  // safe even if already dismissed
    137             mCannedResponsePopup = null;
    138         }
    139     }
    140 
    141     /**
    142      * Dismiss the custom compose message popup.
    143      */
    144     private void dismissCustomMessagePopup() {
    145         if (mCustomMessagePopup != null) {
    146             mCustomMessagePopup.dismiss();
    147             mCustomMessagePopup = null;
    148         }
    149     }
    150 
    151     public void dismissPendingDialogs() {
    152         if (isCannedResponsePopupShowing()) {
    153             dismissCannedResponsePopup();
    154         }
    155 
    156         if (isCustomMessagePopupShowing()) {
    157             dismissCustomMessagePopup();
    158         }
    159     }
    160 
    161     public boolean hasPendingDialogs() {
    162         return !(mCannedResponsePopup == null && mCustomMessagePopup == null);
    163     }
    164 
    165     /**
    166      * Shows the custom message entry dialog.
    167      */
    168     public void showCustomMessageDialog() {
    169         // Create an alert dialog containing an EditText
    170         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
    171         final EditText et = new EditText(builder.getContext());
    172         builder.setCancelable(true).setView(et)
    173                 .setPositiveButton(R.string.custom_message_send,
    174                         new DialogInterface.OnClickListener() {
    175                             @Override
    176                             public void onClick(DialogInterface dialog, int which) {
    177                                 // The order is arranged in a way that the popup will be destroyed
    178                                 // when the InCallActivity is about to finish.
    179                                 final String textMessage = et.getText().toString().trim();
    180                                 dismissCustomMessagePopup();
    181                                 getPresenter().rejectCallWithMessage(textMessage);
    182                             }
    183                         })
    184                 .setNegativeButton(R.string.custom_message_cancel,
    185                         new DialogInterface.OnClickListener() {
    186                             @Override
    187                             public void onClick(DialogInterface dialog, int which) {
    188                                 dismissCustomMessagePopup();
    189                                 getPresenter().onDismissDialog();
    190                             }
    191                         })
    192                 .setOnCancelListener(new DialogInterface.OnCancelListener() {
    193                     @Override
    194                     public void onCancel(DialogInterface dialogInterface) {
    195                         dismissCustomMessagePopup();
    196                         getPresenter().onDismissDialog();
    197                     }
    198                 })
    199                 .setTitle(R.string.respond_via_sms_custom_message);
    200         mCustomMessagePopup = builder.create();
    201 
    202         // Enable/disable the send button based on whether there is a message in the EditText
    203         et.addTextChangedListener(new TextWatcher() {
    204             @Override
    205             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    206             }
    207 
    208             @Override
    209             public void onTextChanged(CharSequence s, int start, int before, int count) {
    210             }
    211 
    212             @Override
    213             public void afterTextChanged(Editable s) {
    214                 final Button sendButton = mCustomMessagePopup.getButton(
    215                         DialogInterface.BUTTON_POSITIVE);
    216                 sendButton.setEnabled(s != null && s.toString().trim().length() != 0);
    217             }
    218         });
    219 
    220         // Keyboard up, show the dialog
    221         mCustomMessagePopup.getWindow().setSoftInputMode(
    222                 WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    223         mCustomMessagePopup.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    224         mCustomMessagePopup.show();
    225 
    226         // Send button starts out disabled
    227         final Button sendButton = mCustomMessagePopup.getButton(DialogInterface.BUTTON_POSITIVE);
    228         sendButton.setEnabled(false);
    229     }
    230 
    231     @Override
    232     public void configureMessageDialog(List<String> textResponses) {
    233         mSmsResponses.clear();
    234         mSmsResponses.addAll(textResponses);
    235         mSmsResponses.add(getResources().getString(
    236                 R.string.respond_via_sms_custom_message));
    237         if (mSmsResponsesAdapter != null) {
    238             mSmsResponsesAdapter.notifyDataSetChanged();
    239         }
    240     }
    241 
    242     @Override
    243     public Context getContext() {
    244         return getActivity();
    245     }
    246 
    247     public void onAnswer(int videoState, Context context) {
    248         Log.d(this, "onAnswer videoState=" + videoState + " context=" + context);
    249         getPresenter().onAnswer(videoState, context);
    250     }
    251 
    252     public void onDecline(Context context) {
    253         getPresenter().onDecline(context);
    254     }
    255 
    256     public void onDeclineUpgradeRequest(Context context) {
    257         InCallPresenter.getInstance().declineUpgradeRequest(context);
    258     }
    259 
    260     public void onText() {
    261         getPresenter().onText();
    262     }
    263 
    264     /**
    265      * OnItemClickListener for the "Respond via SMS" popup.
    266      */
    267     public class RespondViaSmsItemClickListener implements AdapterView.OnItemClickListener {
    268 
    269         /**
    270          * Handles the user selecting an item from the popup.
    271          */
    272         @Override
    273         public void onItemClick(AdapterView<?> parent,  // The ListView
    274                 View view,  // The TextView that was clicked
    275                 int position, long id) {
    276             Log.d(this, "RespondViaSmsItemClickListener.onItemClick(" + position + ")...");
    277             final String message = (String) parent.getItemAtPosition(position);
    278             Log.v(this, "- message: '" + message + "'");
    279             dismissCannedResponsePopup();
    280 
    281             // The "Custom" choice is a special case.
    282             // (For now, it's guaranteed to be the last item.)
    283             if (position == (parent.getCount() - 1)) {
    284                 // Show the custom message dialog
    285                 showCustomMessageDialog();
    286             } else {
    287                 getPresenter().rejectCallWithMessage(message);
    288             }
    289         }
    290     }
    291 
    292     public void onShowAnswerUi(boolean shown) {
    293         // Do Nothing
    294     }
    295 
    296     public void showTargets(int targetSet) {
    297         // Do Nothing
    298     }
    299 
    300     public void showTargets(int targetSet, int videoState) {
    301         // Do Nothing
    302     }
    303 
    304     protected void onMessageDialogCancel() {
    305         // Do nothing.
    306     }
    307 }
    308