blob: 7c67719b010a04b0df3bbe22a3b50f8d5680d124 [file] [log] [blame]
/*
* 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.telecom.VideoProfile;
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.google.common.base.Preconditions;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.List;
/**
*
*/
public class AnswerFragment extends BaseFragment<AnswerPresenter, AnswerPresenter.AnswerUi>
implements GlowPadWrapper.AnswerListener, 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;
/**
* 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<String> mSmsResponsesAdapter;
private final List<String> mSmsResponses = new ArrayList<>();
private GlowPadWrapper mGlowpad;
public AnswerFragment() {
}
@Override
public AnswerPresenter createPresenter() {
return InCallPresenter.getInstance().getAnswerPresenter();
}
@Override
public AnswerPresenter.AnswerUi getUi() {
return this;
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
mGlowpad = (GlowPadWrapper) inflater.inflate(R.layout.answer_fragment,
container, false);
Log.d(this, "Creating view for answer fragment ", this);
Log.d(this, "Created from activity", getActivity());
mGlowpad.setAnswerListener(this);
return mGlowpad;
}
@Override
public void onDestroyView() {
Log.d(this, "onDestroyView");
if (mGlowpad != null) {
mGlowpad.stopPing();
mGlowpad = null;
}
super.onDestroyView();
}
@Override
public void onShowAnswerUi(boolean shown) {
Log.d(this, "Show answer UI: " + shown);
if (shown) {
mGlowpad.startPing();
} else {
mGlowpad.stopPing();
}
}
/**
* Sets targets on the glowpad according to target set identified by the parameter.
* @param targetSet Integer identifying the set of targets to use.
*/
public void showTargets(int targetSet) {
showTargets(targetSet, VideoProfile.STATE_BIDIRECTIONAL);
}
/**
* Sets targets on the glowpad according to target set identified by the parameter.
* @param targetSet Integer identifying the set of targets to use.
*/
@Override
public void showTargets(int targetSet, int videoState) {
final int targetResourceId;
final int targetDescriptionsResourceId;
final int directionDescriptionsResourceId;
final int handleDrawableResourceId;
mGlowpad.setVideoState(videoState);
switch (targetSet) {
case TARGET_SET_FOR_AUDIO_WITH_SMS:
targetResourceId = R.array.incoming_call_widget_audio_with_sms_targets;
targetDescriptionsResourceId =
R.array.incoming_call_widget_audio_with_sms_target_descriptions;
directionDescriptionsResourceId =
R.array.incoming_call_widget_audio_with_sms_direction_descriptions;
handleDrawableResourceId = R.drawable.ic_incall_audio_handle;
break;
case TARGET_SET_FOR_VIDEO_WITHOUT_SMS:
targetResourceId = R.array.incoming_call_widget_video_without_sms_targets;
targetDescriptionsResourceId =
R.array.incoming_call_widget_video_without_sms_target_descriptions;
directionDescriptionsResourceId =
R.array.incoming_call_widget_video_without_sms_direction_descriptions;
handleDrawableResourceId = R.drawable.ic_incall_video_handle;
break;
case TARGET_SET_FOR_VIDEO_WITH_SMS:
targetResourceId = R.array.incoming_call_widget_video_with_sms_targets;
targetDescriptionsResourceId =
R.array.incoming_call_widget_video_with_sms_target_descriptions;
directionDescriptionsResourceId =
R.array.incoming_call_widget_video_with_sms_direction_descriptions;
handleDrawableResourceId = R.drawable.ic_incall_video_handle;
break;
case TARGET_SET_FOR_VIDEO_ACCEPT_REJECT_REQUEST:
targetResourceId =
R.array.incoming_call_widget_video_request_targets;
targetDescriptionsResourceId =
R.array.incoming_call_widget_video_request_target_descriptions;
directionDescriptionsResourceId = R.array
.incoming_call_widget_video_request_target_direction_descriptions;
handleDrawableResourceId = R.drawable.ic_incall_video_handle;
break;
case TARGET_SET_FOR_AUDIO_WITHOUT_SMS:
default:
targetResourceId = R.array.incoming_call_widget_audio_without_sms_targets;
targetDescriptionsResourceId =
R.array.incoming_call_widget_audio_without_sms_target_descriptions;
directionDescriptionsResourceId =
R.array.incoming_call_widget_audio_without_sms_direction_descriptions;
handleDrawableResourceId = R.drawable.ic_incall_audio_handle;
break;
}
if (targetResourceId != mGlowpad.getTargetResourceId()) {
mGlowpad.setTargetResources(targetResourceId);
mGlowpad.setTargetDescriptionsResourceId(targetDescriptionsResourceId);
mGlowpad.setDirectionDescriptionsResourceId(directionDescriptionsResourceId);
mGlowpad.setHandleDrawable(handleDrawableResourceId);
mGlowpad.reset(false);
}
}
@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) {
if (mGlowpad != null) {
mGlowpad.startPing();
}
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.
*/
private 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<String> 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();
}
@Override
public void onAnswer(int videoState, Context context) {
Log.d(this, "onAnswer videoState=" + videoState + " context=" + context);
getPresenter().onAnswer(videoState, context);
}
@Override
public void onDecline(Context context) {
getPresenter().onDecline(context);
}
@Override
public void onDeclineUpgradeRequest(Context context) {
InCallPresenter.getInstance().declineUpgradeRequest(context);
}
@Override
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);
}
}
}
}