• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)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
createPresenter()80     public AnswerPresenter createPresenter() {
81         return InCallPresenter.getInstance().getAnswerPresenter();
82     }
83 
84     @Override
getUi()85     public AnswerPresenter.AnswerUi getUi() {
86         return this;
87     }
88 
89     @Override
showMessageDialog()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 
isCannedResponsePopupShowing()114     private boolean isCannedResponsePopupShowing() {
115         if (mCannedResponsePopup != null) {
116             return mCannedResponsePopup.isShowing();
117         }
118         return false;
119     }
120 
isCustomMessagePopupShowing()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      */
dismissCannedResponsePopup()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      */
dismissCustomMessagePopup()144     private void dismissCustomMessagePopup() {
145         if (mCustomMessagePopup != null) {
146             mCustomMessagePopup.dismiss();
147             mCustomMessagePopup = null;
148         }
149     }
150 
dismissPendingDialogs()151     public void dismissPendingDialogs() {
152         if (isCannedResponsePopupShowing()) {
153             dismissCannedResponsePopup();
154         }
155 
156         if (isCustomMessagePopupShowing()) {
157             dismissCustomMessagePopup();
158         }
159     }
160 
hasPendingDialogs()161     public boolean hasPendingDialogs() {
162         return !(mCannedResponsePopup == null && mCustomMessagePopup == null);
163     }
164 
165     /**
166      * Shows the custom message entry dialog.
167      */
showCustomMessageDialog()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
configureMessageDialog(List<String> textResponses)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
getContext()243     public Context getContext() {
244         return getActivity();
245     }
246 
onAnswer(int videoState, Context context)247     public void onAnswer(int videoState, Context context) {
248         Log.d(this, "onAnswer videoState=" + videoState + " context=" + context);
249         getPresenter().onAnswer(videoState, context);
250     }
251 
onDecline(Context context)252     public void onDecline(Context context) {
253         getPresenter().onDecline(context);
254     }
255 
onDeclineUpgradeRequest(Context context)256     public void onDeclineUpgradeRequest(Context context) {
257         InCallPresenter.getInstance().declineUpgradeRequest(context);
258     }
259 
onText()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
onItemClick(AdapterView<?> parent, View view, int position, long id)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 
onShowAnswerUi(boolean shown)292     public void onShowAnswerUi(boolean shown) {
293         // Do Nothing
294     }
295 
showTargets(int targetSet)296     public void showTargets(int targetSet) {
297         // Do Nothing
298     }
299 
showTargets(int targetSet, int videoState)300     public void showTargets(int targetSet, int videoState) {
301         // Do Nothing
302     }
303 
onMessageDialogCancel()304     protected void onMessageDialogCancel() {
305         // Do nothing.
306     }
307 }
308