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.DialogInterface;
     22 import android.os.Bundle;
     23 import android.text.Editable;
     24 import android.text.TextWatcher;
     25 import android.view.LayoutInflater;
     26 import android.view.View;
     27 import android.view.ViewGroup;
     28 import android.view.WindowManager;
     29 import android.widget.AdapterView;
     30 import android.widget.ArrayAdapter;
     31 import android.widget.Button;
     32 import android.widget.EditText;
     33 import android.widget.ListView;
     34 
     35 import com.google.common.base.Preconditions;
     36 
     37 import java.util.ArrayList;
     38 
     39 /**
     40  *
     41  */
     42 public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresenter.AnswerUi>
     43         implements GlowPadWrapper.AnswerListener, AnswerPresenter.AnswerUi {
     44 
     45     /**
     46      * The popup showing the list of canned responses.
     47      *
     48      * This is an AlertDialog containing a ListView showing the possible choices.  This may be null
     49      * if the InCallScreen hasn't ever called showRespondViaSmsPopup() yet, or if the popup was
     50      * visible once but then got dismissed.
     51      */
     52     private Dialog mCannedResponsePopup = null;
     53 
     54     /**
     55      * The popup showing a text field for users to type in their custom message.
     56      */
     57     private AlertDialog mCustomMessagePopup = null;
     58 
     59     private ArrayAdapter<String> mTextResponsesAdapter = null;
     60 
     61     private GlowPadWrapper mGlowpad;
     62 
     63     public AnswerFragment() {
     64     }
     65 
     66     @Override
     67     public AnswerPresenter createPresenter() {
     68         return new AnswerPresenter();
     69     }
     70 
     71     @Override
     72     AnswerPresenter.AnswerUi getUi() {
     73         return this;
     74     }
     75 
     76     @Override
     77     public View onCreateView(LayoutInflater inflater, ViewGroup container,
     78             Bundle savedInstanceState) {
     79         mGlowpad = (GlowPadWrapper) inflater.inflate(R.layout.answer_fragment,
     80                 container, false);
     81 
     82         Log.d(this, "Creating view for answer fragment ", this);
     83         Log.d(this, "Created from activity", getActivity());
     84         mGlowpad.setAnswerListener(this);
     85 
     86         return mGlowpad;
     87     }
     88 
     89     @Override
     90     public void onDestroyView() {
     91         Log.d(this, "onDestroyView");
     92         if (mGlowpad != null) {
     93             mGlowpad.stopPing();
     94             mGlowpad = null;
     95         }
     96         super.onDestroyView();
     97     }
     98 
     99     @Override
    100     public void showAnswerUi(boolean show) {
    101         getView().setVisibility(show ? View.VISIBLE : View.GONE);
    102 
    103         Log.d(this, "Show answer UI: " + show);
    104         if (show) {
    105             mGlowpad.startPing();
    106         } else {
    107             mGlowpad.stopPing();
    108         }
    109     }
    110 
    111     @Override
    112     public void showTextButton(boolean show) {
    113         final int targetResourceId = show
    114                 ? R.array.incoming_call_widget_3way_targets
    115                 : R.array.incoming_call_widget_2way_targets;
    116 
    117         if (targetResourceId != mGlowpad.getTargetResourceId()) {
    118             if (show) {
    119                 // Answer, Decline, and Respond via SMS.
    120                 mGlowpad.setTargetResources(targetResourceId);
    121                 mGlowpad.setTargetDescriptionsResourceId(
    122                         R.array.incoming_call_widget_3way_target_descriptions);
    123                 mGlowpad.setDirectionDescriptionsResourceId(
    124                         R.array.incoming_call_widget_3way_direction_descriptions);
    125             } else {
    126                 // Answer or Decline.
    127                 mGlowpad.setTargetResources(targetResourceId);
    128                 mGlowpad.setTargetDescriptionsResourceId(
    129                         R.array.incoming_call_widget_2way_target_descriptions);
    130                 mGlowpad.setDirectionDescriptionsResourceId(
    131                         R.array.incoming_call_widget_2way_direction_descriptions);
    132             }
    133 
    134             mGlowpad.reset(false);
    135         }
    136     }
    137 
    138     @Override
    139     public void showMessageDialog() {
    140         final ListView lv = new ListView(getActivity());
    141 
    142         Preconditions.checkNotNull(mTextResponsesAdapter);
    143         lv.setAdapter(mTextResponsesAdapter);
    144         lv.setOnItemClickListener(new RespondViaSmsItemClickListener());
    145 
    146         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()).setCancelable(
    147                 true).setView(lv);
    148         builder.setOnCancelListener(new DialogInterface.OnCancelListener() {
    149             @Override
    150             public void onCancel(DialogInterface dialogInterface) {
    151                 if (mGlowpad != null) {
    152                     mGlowpad.startPing();
    153                 }
    154                 dismissCannedResponsePopup();
    155                 getPresenter().onDismissDialog();
    156             }
    157         });
    158         mCannedResponsePopup = builder.create();
    159         mCannedResponsePopup.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    160         mCannedResponsePopup.show();
    161     }
    162 
    163     private boolean isCannedResponsePopupShowing() {
    164         if (mCannedResponsePopup != null) {
    165             return mCannedResponsePopup.isShowing();
    166         }
    167         return false;
    168     }
    169 
    170     private boolean isCustomMessagePopupShowing() {
    171         if (mCustomMessagePopup != null) {
    172             return mCustomMessagePopup.isShowing();
    173         }
    174         return false;
    175     }
    176 
    177     /**
    178      * Dismiss the canned response list popup.
    179      *
    180      * This is safe to call even if the popup is already dismissed, and even if you never called
    181      * showRespondViaSmsPopup() in the first place.
    182      */
    183     private void dismissCannedResponsePopup() {
    184         if (mCannedResponsePopup != null) {
    185             mCannedResponsePopup.dismiss();  // safe even if already dismissed
    186             mCannedResponsePopup = null;
    187         }
    188     }
    189 
    190     /**
    191      * Dismiss the custom compose message popup.
    192      */
    193     private void dismissCustomMessagePopup() {
    194        if (mCustomMessagePopup != null) {
    195            mCustomMessagePopup.dismiss();
    196            mCustomMessagePopup = null;
    197        }
    198     }
    199 
    200     public void dismissPendingDialogues() {
    201         if (isCannedResponsePopupShowing()) {
    202             dismissCannedResponsePopup();
    203         }
    204 
    205         if (isCustomMessagePopupShowing()) {
    206             dismissCustomMessagePopup();
    207         }
    208     }
    209 
    210     public boolean hasPendingDialogs() {
    211         return !(mCannedResponsePopup == null && mCustomMessagePopup == null);
    212     }
    213 
    214     /**
    215      * Shows the custom message entry dialog.
    216      */
    217     public void showCustomMessageDialog() {
    218         // Create an alert dialog containing an EditText
    219         final EditText et = new EditText(getActivity());
    220         final AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()).setCancelable(
    221                 true).setView(et)
    222                 .setPositiveButton(R.string.custom_message_send,
    223                         new DialogInterface.OnClickListener() {
    224                     @Override
    225                     public void onClick(DialogInterface dialog, int which) {
    226                         // The order is arranged in a way that the popup will be destroyed when the
    227                         // InCallActivity is about to finish.
    228                         final String textMessage = et.getText().toString().trim();
    229                         dismissCustomMessagePopup();
    230                         getPresenter().rejectCallWithMessage(textMessage);
    231                     }
    232                 })
    233                 .setNegativeButton(R.string.custom_message_cancel,
    234                         new DialogInterface.OnClickListener() {
    235                     @Override
    236                     public void onClick(DialogInterface dialog, int which) {
    237                         dismissCustomMessagePopup();
    238                         getPresenter().onDismissDialog();
    239                     }
    240                 })
    241                 .setTitle(R.string.respond_via_sms_custom_message);
    242         mCustomMessagePopup = builder.create();
    243 
    244         // Enable/disable the send button based on whether there is a message in the EditText
    245         et.addTextChangedListener(new TextWatcher() {
    246             @Override
    247             public void beforeTextChanged(CharSequence s, int start, int count, int after) {
    248             }
    249 
    250             @Override
    251             public void onTextChanged(CharSequence s, int start, int before, int count) {
    252             }
    253 
    254             @Override
    255             public void afterTextChanged(Editable s) {
    256                 final Button sendButton = mCustomMessagePopup.getButton(
    257                         DialogInterface.BUTTON_POSITIVE);
    258                 sendButton.setEnabled(s != null && s.toString().trim().length() != 0);
    259             }
    260         });
    261 
    262         // Keyboard up, show the dialog
    263         mCustomMessagePopup.getWindow().setSoftInputMode(
    264                 WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_VISIBLE);
    265         mCustomMessagePopup.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
    266         mCustomMessagePopup.show();
    267 
    268         // Send button starts out disabled
    269         final Button sendButton = mCustomMessagePopup.getButton(DialogInterface.BUTTON_POSITIVE);
    270         sendButton.setEnabled(false);
    271     }
    272 
    273     @Override
    274     public void configureMessageDialog(ArrayList<String> textResponses) {
    275         final ArrayList<String> textResponsesForDisplay = new ArrayList<String>(textResponses);
    276 
    277         textResponsesForDisplay.add(getResources().getString(
    278                 R.string.respond_via_sms_custom_message));
    279         mTextResponsesAdapter = new ArrayAdapter<String>(getActivity(),
    280                 android.R.layout.simple_list_item_1, android.R.id.text1, textResponsesForDisplay);
    281     }
    282 
    283     @Override
    284     public void onAnswer() {
    285         getPresenter().onAnswer();
    286     }
    287 
    288     @Override
    289     public void onDecline() {
    290         getPresenter().onDecline();
    291     }
    292 
    293     @Override
    294     public void onText() {
    295         getPresenter().onText();
    296     }
    297 
    298     /**
    299      * OnItemClickListener for the "Respond via SMS" popup.
    300      */
    301     public class RespondViaSmsItemClickListener implements AdapterView.OnItemClickListener {
    302 
    303         /**
    304          * Handles the user selecting an item from the popup.
    305          */
    306         @Override
    307         public void onItemClick(AdapterView<?> parent,  // The ListView
    308                 View view,  // The TextView that was clicked
    309                 int position, long id) {
    310             Log.d(this, "RespondViaSmsItemClickListener.onItemClick(" + position + ")...");
    311             final String message = (String) parent.getItemAtPosition(position);
    312             Log.v(this, "- message: '" + message + "'");
    313             dismissCannedResponsePopup();
    314 
    315             // The "Custom" choice is a special case.
    316             // (For now, it's guaranteed to be the last item.)
    317             if (position == (parent.getCount() - 1)) {
    318                 // Show the custom message dialog
    319                 showCustomMessageDialog();
    320             } else {
    321                 getPresenter().rejectCallWithMessage(message);
    322             }
    323         }
    324     }
    325 }
    326