| /* |
| * Copyright (C) 2015 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.messaging.ui.contact; |
| |
| import android.app.Activity; |
| import android.app.Fragment; |
| import android.database.Cursor; |
| import android.graphics.Rect; |
| import android.os.Bundle; |
| import android.support.v7.app.ActionBar; |
| import android.support.v7.widget.Toolbar; |
| import android.support.v7.widget.Toolbar.OnMenuItemClickListener; |
| import android.text.Editable; |
| import android.text.InputType; |
| import android.text.TextUtils; |
| import android.text.TextWatcher; |
| import android.transition.Explode; |
| import android.transition.Transition; |
| import android.transition.Transition.EpicenterCallback; |
| import android.transition.TransitionManager; |
| import android.view.LayoutInflater; |
| import android.view.Menu; |
| import android.view.MenuItem; |
| import android.view.View; |
| import android.view.View.OnClickListener; |
| import android.view.ViewGroup; |
| |
| import com.android.messaging.R; |
| import com.android.messaging.datamodel.DataModel; |
| import com.android.messaging.datamodel.action.ActionMonitor; |
| import com.android.messaging.datamodel.action.GetOrCreateConversationAction; |
| import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionListener; |
| import com.android.messaging.datamodel.action.GetOrCreateConversationAction.GetOrCreateConversationActionMonitor; |
| import com.android.messaging.datamodel.binding.Binding; |
| import com.android.messaging.datamodel.binding.BindingBase; |
| import com.android.messaging.datamodel.data.ContactListItemData; |
| import com.android.messaging.datamodel.data.ContactPickerData; |
| import com.android.messaging.datamodel.data.ContactPickerData.ContactPickerDataListener; |
| import com.android.messaging.datamodel.data.ParticipantData; |
| import com.android.messaging.ui.CustomHeaderPagerViewHolder; |
| import com.android.messaging.ui.CustomHeaderViewPager; |
| import com.android.messaging.ui.animation.ViewGroupItemVerticalExplodeAnimation; |
| import com.android.messaging.ui.contact.ContactRecipientAutoCompleteView.ContactChipsChangeListener; |
| import com.android.messaging.util.Assert; |
| import com.android.messaging.util.Assert.RunsOnMainThread; |
| import com.android.messaging.util.ContactUtil; |
| import com.android.messaging.util.ImeUtil; |
| import com.android.messaging.util.LogUtil; |
| import com.android.messaging.util.OsUtil; |
| import com.android.messaging.util.PhoneUtils; |
| import com.android.messaging.util.UiUtils; |
| import com.google.common.annotations.VisibleForTesting; |
| |
| import java.util.ArrayList; |
| import java.util.Set; |
| |
| |
| /** |
| * Shows lists of contacts to start conversations with. |
| */ |
| public class ContactPickerFragment extends Fragment implements ContactPickerDataListener, |
| ContactListItemView.HostInterface, ContactChipsChangeListener, OnMenuItemClickListener, |
| GetOrCreateConversationActionListener { |
| public static final String FRAGMENT_TAG = "contactpicker"; |
| |
| // Undefined contact picker mode. We should never be in this state after the host activity has |
| // been created. |
| public static final int MODE_UNDEFINED = 0; |
| |
| // The initial contact picker mode for starting a new conversation with one contact. |
| public static final int MODE_PICK_INITIAL_CONTACT = 1; |
| |
| // The contact picker mode where one initial contact has been picked and we are showing |
| // only the chips edit box. |
| public static final int MODE_CHIPS_ONLY = 2; |
| |
| // The contact picker mode for picking more contacts after starting the initial 1-1. |
| public static final int MODE_PICK_MORE_CONTACTS = 3; |
| |
| // The contact picker mode when max number of participants is reached. |
| public static final int MODE_PICK_MAX_PARTICIPANTS = 4; |
| |
| public interface ContactPickerFragmentHost { |
| void onGetOrCreateNewConversation(String conversationId); |
| void onBackButtonPressed(); |
| void onInitiateAddMoreParticipants(); |
| void onParticipantCountChanged(boolean canAddMoreParticipants); |
| void invalidateActionBar(); |
| } |
| |
| @VisibleForTesting |
| final Binding<ContactPickerData> mBinding = BindingBase.createBinding(this); |
| |
| private ContactPickerFragmentHost mHost; |
| private ContactRecipientAutoCompleteView mRecipientTextView; |
| private CustomHeaderViewPager mCustomHeaderViewPager; |
| private AllContactsListViewHolder mAllContactsListViewHolder; |
| private FrequentContactsListViewHolder mFrequentContactsListViewHolder; |
| private View mRootView; |
| private View mPendingExplodeView; |
| private View mComposeDivider; |
| private Toolbar mToolbar; |
| private int mContactPickingMode = MODE_UNDEFINED; |
| |
| // Keeps track of the currently selected phone numbers in the chips view to enable fast lookup. |
| private Set<String> mSelectedPhoneNumbers = null; |
| |
| /** |
| * {@inheritDoc} from Fragment |
| */ |
| @Override |
| public void onCreate(final Bundle savedInstanceState) { |
| super.onCreate(savedInstanceState); |
| mAllContactsListViewHolder = new AllContactsListViewHolder(getActivity(), this); |
| mFrequentContactsListViewHolder = new FrequentContactsListViewHolder(getActivity(), this); |
| |
| if (ContactUtil.hasReadContactsPermission()) { |
| mBinding.bind(DataModel.get().createContactPickerData(getActivity(), this)); |
| mBinding.getData().init(getLoaderManager(), mBinding); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} from Fragment |
| */ |
| @Override |
| public View onCreateView(final LayoutInflater inflater, final ViewGroup container, |
| final Bundle savedInstanceState) { |
| final View view = inflater.inflate(R.layout.contact_picker_fragment, container, false); |
| mRecipientTextView = (ContactRecipientAutoCompleteView) |
| view.findViewById(R.id.recipient_text_view); |
| mRecipientTextView.setThreshold(0); |
| mRecipientTextView.setDropDownAnchor(R.id.compose_contact_divider); |
| |
| mRecipientTextView.setContactChipsListener(this); |
| mRecipientTextView.setDropdownChipLayouter(new ContactDropdownLayouter(inflater, |
| getActivity(), this)); |
| mRecipientTextView.setAdapter(new ContactRecipientAdapter(getActivity(), this)); |
| mRecipientTextView.addTextChangedListener(new TextWatcher() { |
| @Override |
| public void onTextChanged(final CharSequence s, final int start, final int before, |
| final int count) { |
| } |
| |
| @Override |
| public void beforeTextChanged(final CharSequence s, final int start, final int count, |
| final int after) { |
| } |
| |
| @Override |
| public void afterTextChanged(final Editable s) { |
| updateTextInputButtonsVisibility(); |
| } |
| }); |
| |
| final CustomHeaderPagerViewHolder[] viewHolders = { |
| mFrequentContactsListViewHolder, |
| mAllContactsListViewHolder }; |
| |
| mCustomHeaderViewPager = (CustomHeaderViewPager) view.findViewById(R.id.contact_pager); |
| mCustomHeaderViewPager.setViewHolders(viewHolders); |
| mCustomHeaderViewPager.setViewPagerTabHeight(CustomHeaderViewPager.DEFAULT_TAB_STRIP_SIZE); |
| mCustomHeaderViewPager.setBackgroundColor(getResources() |
| .getColor(R.color.contact_picker_background)); |
| |
| // The view pager defaults to the frequent contacts page. |
| mCustomHeaderViewPager.setCurrentItem(0); |
| |
| mToolbar = (Toolbar) view.findViewById(R.id.toolbar); |
| mToolbar.setNavigationIcon(R.drawable.ic_arrow_back_light); |
| mToolbar.setNavigationContentDescription(R.string.back); |
| mToolbar.setNavigationOnClickListener(new OnClickListener() { |
| @Override |
| public void onClick(final View v) { |
| mHost.onBackButtonPressed(); |
| } |
| }); |
| |
| mToolbar.inflateMenu(R.menu.compose_menu); |
| mToolbar.setOnMenuItemClickListener(this); |
| |
| mComposeDivider = view.findViewById(R.id.compose_contact_divider); |
| mRootView = view; |
| return view; |
| } |
| |
| /** |
| * {@inheritDoc} |
| * |
| * Called when the host activity has been created. At this point, the host activity should |
| * have set the contact picking mode for us so that we may update our visuals. |
| */ |
| @Override |
| public void onActivityCreated(final Bundle savedInstanceState) { |
| super.onActivityCreated(savedInstanceState); |
| Assert.isTrue(mContactPickingMode != MODE_UNDEFINED); |
| updateVisualsForContactPickingMode(false /* animate */); |
| mHost.invalidateActionBar(); |
| } |
| |
| @Override |
| public void onDestroy() { |
| super.onDestroy(); |
| // We could not have bound to the data if the permission was denied. |
| if (mBinding.isBound()) { |
| mBinding.unbind(); |
| } |
| |
| if (mMonitor != null) { |
| mMonitor.unregister(); |
| } |
| mMonitor = null; |
| } |
| |
| @Override |
| public boolean onMenuItemClick(final MenuItem menuItem) { |
| switch (menuItem.getItemId()) { |
| case R.id.action_ime_dialpad_toggle: |
| final int baseInputType = InputType.TYPE_TEXT_FLAG_MULTI_LINE; |
| if ((mRecipientTextView.getInputType() & InputType.TYPE_CLASS_PHONE) != |
| InputType.TYPE_CLASS_PHONE) { |
| mRecipientTextView.setInputType(baseInputType | InputType.TYPE_CLASS_PHONE); |
| menuItem.setIcon(R.drawable.ic_ime_light); |
| } else { |
| mRecipientTextView.setInputType(baseInputType | InputType.TYPE_CLASS_TEXT); |
| menuItem.setIcon(R.drawable.ic_numeric_dialpad); |
| } |
| ImeUtil.get().showImeKeyboard(getActivity(), mRecipientTextView); |
| return true; |
| |
| case R.id.action_add_more_participants: |
| mHost.onInitiateAddMoreParticipants(); |
| return true; |
| |
| case R.id.action_confirm_participants: |
| maybeGetOrCreateConversation(); |
| return true; |
| |
| case R.id.action_delete_text: |
| Assert.equals(MODE_PICK_INITIAL_CONTACT, mContactPickingMode); |
| mRecipientTextView.setText(""); |
| return true; |
| } |
| return false; |
| } |
| |
| @Override // From ContactPickerDataListener |
| public void onAllContactsCursorUpdated(final Cursor data) { |
| mBinding.ensureBound(); |
| mAllContactsListViewHolder.onContactsCursorUpdated(data); |
| } |
| |
| @Override // From ContactPickerDataListener |
| public void onFrequentContactsCursorUpdated(final Cursor data) { |
| mBinding.ensureBound(); |
| mFrequentContactsListViewHolder.onContactsCursorUpdated(data); |
| if (data != null && data.getCount() == 0) { |
| // Show the all contacts list when there's no frequents. |
| mCustomHeaderViewPager.setCurrentItem(1); |
| } |
| } |
| |
| @Override // From ContactListItemView.HostInterface |
| public void onContactListItemClicked(final ContactListItemData item, |
| final ContactListItemView view) { |
| if (!isContactSelected(item)) { |
| if (mContactPickingMode == MODE_PICK_INITIAL_CONTACT) { |
| mPendingExplodeView = view; |
| } |
| mRecipientTextView.appendRecipientEntry(item.getRecipientEntry()); |
| } else if (mContactPickingMode != MODE_PICK_INITIAL_CONTACT) { |
| mRecipientTextView.removeRecipientEntry(item.getRecipientEntry()); |
| } |
| } |
| |
| @Override // From ContactListItemView.HostInterface |
| public boolean isContactSelected(final ContactListItemData item) { |
| return mSelectedPhoneNumbers != null && |
| mSelectedPhoneNumbers.contains(PhoneUtils.getDefault().getCanonicalBySystemLocale( |
| item.getRecipientEntry().getDestination())); |
| } |
| |
| /** |
| * Call this immediately after attaching the fragment, or when there's a ui state change that |
| * changes our host (i.e. restore from saved instance state). |
| */ |
| public void setHost(final ContactPickerFragmentHost host) { |
| mHost = host; |
| } |
| |
| public void setContactPickingMode(final int mode, final boolean animate) { |
| if (mContactPickingMode != mode) { |
| // Guard against impossible transitions. |
| Assert.isTrue( |
| // We may start from undefined mode to any mode when we are restoring state. |
| (mContactPickingMode == MODE_UNDEFINED) || |
| (mContactPickingMode == MODE_PICK_INITIAL_CONTACT && mode == MODE_CHIPS_ONLY) || |
| (mContactPickingMode == MODE_CHIPS_ONLY && mode == MODE_PICK_MORE_CONTACTS) || |
| (mContactPickingMode == MODE_PICK_MORE_CONTACTS |
| && mode == MODE_PICK_MAX_PARTICIPANTS) || |
| (mContactPickingMode == MODE_PICK_MAX_PARTICIPANTS |
| && mode == MODE_PICK_MORE_CONTACTS)); |
| |
| mContactPickingMode = mode; |
| updateVisualsForContactPickingMode(animate); |
| } |
| } |
| |
| private void showImeKeyboard() { |
| Assert.notNull(mRecipientTextView); |
| mRecipientTextView.requestFocus(); |
| |
| // showImeKeyboard() won't work until the layout is ready, so wait until layout is complete |
| // before showing the soft keyboard. |
| UiUtils.doOnceAfterLayoutChange(mRootView, new Runnable() { |
| @Override |
| public void run() { |
| final Activity activity = getActivity(); |
| if (activity != null) { |
| ImeUtil.get().showImeKeyboard(activity, mRecipientTextView); |
| } |
| } |
| }); |
| mRecipientTextView.invalidate(); |
| } |
| |
| private void updateVisualsForContactPickingMode(final boolean animate) { |
| // Don't update visuals if the visuals haven't been inflated yet. |
| if (mRootView != null) { |
| final Menu menu = mToolbar.getMenu(); |
| final MenuItem addMoreParticipantsItem = menu.findItem( |
| R.id.action_add_more_participants); |
| final MenuItem confirmParticipantsItem = menu.findItem( |
| R.id.action_confirm_participants); |
| switch (mContactPickingMode) { |
| case MODE_PICK_INITIAL_CONTACT: |
| addMoreParticipantsItem.setVisible(false); |
| confirmParticipantsItem.setVisible(false); |
| mCustomHeaderViewPager.setVisibility(View.VISIBLE); |
| mComposeDivider.setVisibility(View.INVISIBLE); |
| mRecipientTextView.setEnabled(true); |
| showImeKeyboard(); |
| break; |
| |
| case MODE_CHIPS_ONLY: |
| if (animate) { |
| if (mPendingExplodeView == null) { |
| // The user didn't click on any contact item, so use the toolbar as |
| // the view to "explode." |
| mPendingExplodeView = mToolbar; |
| } |
| startExplodeTransitionForContactLists(false /* show */); |
| |
| ViewGroupItemVerticalExplodeAnimation.startAnimationForView( |
| mCustomHeaderViewPager, mPendingExplodeView, mRootView, |
| true /* snapshotView */, UiUtils.COMPOSE_TRANSITION_DURATION); |
| showHideContactPagerWithAnimation(false /* show */); |
| } else { |
| mCustomHeaderViewPager.setVisibility(View.GONE); |
| } |
| |
| addMoreParticipantsItem.setVisible(true); |
| confirmParticipantsItem.setVisible(false); |
| mComposeDivider.setVisibility(View.VISIBLE); |
| mRecipientTextView.setEnabled(true); |
| break; |
| |
| case MODE_PICK_MORE_CONTACTS: |
| if (animate) { |
| // Correctly set the start visibility state for the view pager and |
| // individual list items (hidden initially), so that the transition |
| // manager can properly track the visibility change for the explode. |
| mCustomHeaderViewPager.setVisibility(View.VISIBLE); |
| toggleContactListItemsVisibilityForPendingTransition(false /* show */); |
| startExplodeTransitionForContactLists(true /* show */); |
| } |
| addMoreParticipantsItem.setVisible(false); |
| confirmParticipantsItem.setVisible(true); |
| mCustomHeaderViewPager.setVisibility(View.VISIBLE); |
| mComposeDivider.setVisibility(View.INVISIBLE); |
| mRecipientTextView.setEnabled(true); |
| showImeKeyboard(); |
| break; |
| |
| case MODE_PICK_MAX_PARTICIPANTS: |
| addMoreParticipantsItem.setVisible(false); |
| confirmParticipantsItem.setVisible(true); |
| mCustomHeaderViewPager.setVisibility(View.VISIBLE); |
| mComposeDivider.setVisibility(View.INVISIBLE); |
| // TODO: Verify that this is okay for accessibility |
| mRecipientTextView.setEnabled(false); |
| break; |
| |
| default: |
| Assert.fail("Unsupported contact picker mode!"); |
| break; |
| } |
| updateTextInputButtonsVisibility(); |
| } |
| } |
| |
| private void updateTextInputButtonsVisibility() { |
| final Menu menu = mToolbar.getMenu(); |
| final MenuItem keypadToggleItem = menu.findItem(R.id.action_ime_dialpad_toggle); |
| final MenuItem deleteTextItem = menu.findItem(R.id.action_delete_text); |
| if (mContactPickingMode == MODE_PICK_INITIAL_CONTACT) { |
| if (TextUtils.isEmpty(mRecipientTextView.getText())) { |
| deleteTextItem.setVisible(false); |
| keypadToggleItem.setVisible(true); |
| } else { |
| deleteTextItem.setVisible(true); |
| keypadToggleItem.setVisible(false); |
| } |
| } else { |
| deleteTextItem.setVisible(false); |
| keypadToggleItem.setVisible(false); |
| } |
| } |
| |
| private void maybeGetOrCreateConversation() { |
| final ArrayList<ParticipantData> participants = |
| mRecipientTextView.getRecipientParticipantDataForConversationCreation(); |
| if (ContactPickerData.isTooManyParticipants(participants.size())) { |
| UiUtils.showToast(R.string.too_many_participants); |
| } else if (participants.size() > 0 && mMonitor == null) { |
| mMonitor = GetOrCreateConversationAction.getOrCreateConversation(participants, |
| null, this); |
| } |
| } |
| |
| /** |
| * Watches changes in contact chips to determine possible state transitions (e.g. creating |
| * the initial conversation, adding more participants or finish the current conversation) |
| */ |
| @Override |
| public void onContactChipsChanged(final int oldCount, final int newCount) { |
| Assert.isTrue(oldCount != newCount); |
| if (mContactPickingMode == MODE_PICK_INITIAL_CONTACT) { |
| // Initial picking mode. Start a conversation once a recipient has been picked. |
| maybeGetOrCreateConversation(); |
| } else if (mContactPickingMode == MODE_CHIPS_ONLY) { |
| // oldCount == 0 means we are restoring from savedInstanceState to add the existing |
| // chips, don't switch to "add more participants" mode in this case. |
| if (oldCount > 0 && mRecipientTextView.isFocused()) { |
| // Chips only mode. The user may have picked an additional contact or deleted the |
| // only existing contact. Either way, switch to picking more participants mode. |
| mHost.onInitiateAddMoreParticipants(); |
| } |
| } |
| mHost.onParticipantCountChanged(ContactPickerData.getCanAddMoreParticipants(newCount)); |
| |
| // Refresh our local copy of the selected chips set to keep it up-to-date. |
| mSelectedPhoneNumbers = mRecipientTextView.getSelectedDestinations(); |
| invalidateContactLists(); |
| } |
| |
| /** |
| * Listens for notification that invalid contacts have been removed during resolving them. |
| * These contacts were not local contacts, valid email, or valid phone numbers |
| */ |
| @Override |
| public void onInvalidContactChipsPruned(final int prunedCount) { |
| Assert.isTrue(prunedCount > 0); |
| UiUtils.showToast(R.plurals.add_invalid_contact_error, prunedCount); |
| } |
| |
| /** |
| * Listens for notification that the user has pressed enter/done on the keyboard with all |
| * contacts in place and we should create or go to the existing conversation now |
| */ |
| @Override |
| public void onEntryComplete() { |
| if (mContactPickingMode == MODE_PICK_INITIAL_CONTACT || |
| mContactPickingMode == MODE_PICK_MORE_CONTACTS || |
| mContactPickingMode == MODE_PICK_MAX_PARTICIPANTS) { |
| // Avoid multiple calls to create in race cases (hit done right after selecting contact) |
| maybeGetOrCreateConversation(); |
| } |
| } |
| |
| private void invalidateContactLists() { |
| mAllContactsListViewHolder.invalidateList(); |
| mFrequentContactsListViewHolder.invalidateList(); |
| } |
| |
| /** |
| * Kicks off a scene transition that animates visibility changes of individual contact list |
| * items via explode animation. |
| * @param show whether the contact lists are to be shown or hidden. |
| */ |
| private void startExplodeTransitionForContactLists(final boolean show) { |
| if (!OsUtil.isAtLeastL()) { |
| // Explode animation is not supported pre-L. |
| return; |
| } |
| final Explode transition = new Explode(); |
| final Rect epicenter = mPendingExplodeView == null ? null : |
| UiUtils.getMeasuredBoundsOnScreen(mPendingExplodeView); |
| transition.setDuration(UiUtils.COMPOSE_TRANSITION_DURATION); |
| transition.setInterpolator(UiUtils.EASE_IN_INTERPOLATOR); |
| transition.setEpicenterCallback(new EpicenterCallback() { |
| @Override |
| public Rect onGetEpicenter(final Transition transition) { |
| return epicenter; |
| } |
| }); |
| |
| // Kick off the delayed scene explode transition. Anything happens after this line in this |
| // method before the next frame will be tracked by the transition manager for visibility |
| // changes and animated accordingly. |
| TransitionManager.beginDelayedTransition(mCustomHeaderViewPager, |
| transition); |
| |
| toggleContactListItemsVisibilityForPendingTransition(show); |
| } |
| |
| /** |
| * Toggle the visibility of contact list items in the contact lists for them to be tracked by |
| * the transition manager for pending explode transition. |
| */ |
| private void toggleContactListItemsVisibilityForPendingTransition(final boolean show) { |
| if (!OsUtil.isAtLeastL()) { |
| // Explode animation is not supported pre-L. |
| return; |
| } |
| mAllContactsListViewHolder.toggleVisibilityForPendingTransition(show, mPendingExplodeView); |
| mFrequentContactsListViewHolder.toggleVisibilityForPendingTransition(show, |
| mPendingExplodeView); |
| } |
| |
| private void showHideContactPagerWithAnimation(final boolean show) { |
| final boolean isPagerVisible = (mCustomHeaderViewPager.getVisibility() == View.VISIBLE); |
| if (show == isPagerVisible) { |
| return; |
| } |
| |
| mCustomHeaderViewPager.animate().alpha(show ? 1F : 0F) |
| .setStartDelay(!show ? UiUtils.COMPOSE_TRANSITION_DURATION : 0) |
| .withStartAction(new Runnable() { |
| @Override |
| public void run() { |
| mCustomHeaderViewPager.setVisibility(View.VISIBLE); |
| mCustomHeaderViewPager.setAlpha(show ? 0F : 1F); |
| } |
| }) |
| .withEndAction(new Runnable() { |
| @Override |
| public void run() { |
| mCustomHeaderViewPager.setVisibility(show ? View.VISIBLE : View.GONE); |
| mCustomHeaderViewPager.setAlpha(1F); |
| } |
| }); |
| } |
| |
| @Override |
| public void onContactCustomColorLoaded(final ContactPickerData data) { |
| mBinding.ensureBound(data); |
| invalidateContactLists(); |
| } |
| |
| public void updateActionBar(final ActionBar actionBar) { |
| // Hide the action bar for contact picker mode. The custom ToolBar containing chips UI |
| // etc. will take the spot of the action bar. |
| actionBar.hide(); |
| UiUtils.setStatusBarColor(getActivity(), |
| getResources().getColor(R.color.compose_notification_bar_background)); |
| } |
| |
| private GetOrCreateConversationActionMonitor mMonitor; |
| |
| @Override |
| @RunsOnMainThread |
| public void onGetOrCreateConversationSucceeded(final ActionMonitor monitor, |
| final Object data, final String conversationId) { |
| Assert.isTrue(monitor == mMonitor); |
| Assert.isTrue(conversationId != null); |
| |
| mRecipientTextView.setInputType(InputType.TYPE_TEXT_FLAG_MULTI_LINE | |
| InputType.TYPE_CLASS_TEXT); |
| mHost.onGetOrCreateNewConversation(conversationId); |
| |
| mMonitor = null; |
| } |
| |
| @Override |
| @RunsOnMainThread |
| public void onGetOrCreateConversationFailed(final ActionMonitor monitor, |
| final Object data) { |
| Assert.isTrue(monitor == mMonitor); |
| LogUtil.e(LogUtil.BUGLE_TAG, "onGetOrCreateConversationFailed"); |
| mMonitor = null; |
| } |
| } |