@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; }
@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; }
/** * {@inheritDoc} * * <p>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(); }
private void determineLayout(final Iterable<MessagePartData> attachments, final int count) { Assert.isTrue(attachments != null); final boolean isRtl = AccessibilityUtil.isLayoutRtl(getRootView()); if (isRtl) { mCurrentLayout = ATTACHMENT_RTL_LAYOUTS_BY_COUNT[ Math.min(count, ATTACHMENT_RTL_LAYOUTS_BY_COUNT.length - 1)]; } else { mCurrentLayout = ATTACHMENT_LAYOUTS_BY_COUNT[Math.min(count, ATTACHMENT_LAYOUTS_BY_COUNT.length - 1)]; } // We must have a valid layout for the current configuration. Assert.notNull(mCurrentLayout); mPlusNumber = count - mCurrentLayout.tiles.size(); Assert.isTrue(mPlusNumber >= 0); }
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(); }
/** * 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(); }
// Process different result code from platform MMS service public static int getErrorResultStatus(int resultCode, int httpStatusCode) { Assert.isFalse(resultCode == Activity.RESULT_OK); switch (resultCode) { case SmsManager.MMS_ERROR_UNABLE_CONNECT_MMS: case SmsManager.MMS_ERROR_IO_ERROR: return MmsUtils.MMS_REQUEST_AUTO_RETRY; case SmsManager.MMS_ERROR_INVALID_APN: case SmsManager.MMS_ERROR_CONFIGURATION_ERROR: case SmsManager.MMS_ERROR_NO_DATA_NETWORK: case SmsManager.MMS_ERROR_UNSPECIFIED: return MmsUtils.MMS_REQUEST_MANUAL_RETRY; case SmsManager.MMS_ERROR_HTTP_FAILURE: if (httpStatusCode == 404) { return MmsUtils.MMS_REQUEST_NO_RETRY; } else { return MmsUtils.MMS_REQUEST_AUTO_RETRY; } default: return MmsUtils.MMS_REQUEST_MANUAL_RETRY; } }
/** * Process one apn * * @param apnValues Where we store the parsed apn * @throws IOException * @throws XmlPullParserException */ private void processApn(ContentValues apnValues) throws IOException, XmlPullParserException { Assert.notNull(apnValues); apnValues.clear(); // Collect all the attributes for (int i = 0; i < mInputParser.getAttributeCount(); i++) { final String key = APN_ATTRIBUTE_MAP.get(mInputParser.getAttributeName(i)); if (key != null) { apnValues.put(key, mInputParser.getAttributeValue(i)); } } // Set numeric to be canonicalized mcc/mnc like "310120", always 6 digits final String canonicalMccMnc = PhoneUtils.canonicalizeMccMnc( apnValues.getAsString(Telephony.Carriers.MCC), apnValues.getAsString(Telephony.Carriers.MNC)); apnValues.put(Telephony.Carriers.NUMERIC, canonicalMccMnc); // Some of the values should not be string type, converting them to desired types final String authType = apnValues.getAsString(Telephony.Carriers.AUTH_TYPE); if (authType != null) { apnValues.put(Telephony.Carriers.AUTH_TYPE, parseInt(authType, -1, "apn authtype")); } final String carrierEnabled = apnValues.getAsString(Telephony.Carriers.CARRIER_ENABLED); if (carrierEnabled != null) { apnValues.put( Telephony.Carriers.CARRIER_ENABLED, parseBoolean(carrierEnabled, null, "apn carrierEnabled")); } final String bearer = apnValues.getAsString(Telephony.Carriers.BEARER); if (bearer != null) { apnValues.put(Telephony.Carriers.BEARER, parseInt(bearer, 0, "apn bearer")); } // We are at the end tag if (mInputParser.next() != XmlPullParser.END_TAG) { throw new XmlPullParserException("Apn: expecting end tag @" + xmlParserDebugContext()); } // We are done parsing one APN, call the handler if (mApnHandler != null) { mApnHandler.process(apnValues); } }
private void buildViews( final Iterable<MessagePartData> attachments, final ArrayList<ViewWrapper> previousViews, final Rect transitionRect) { final LayoutInflater layoutInflater = LayoutInflater.from(getContext()); final int count = mCurrentLayout.tiles.size(); int i = 0; final Iterator<MessagePartData> iterator = attachments.iterator(); while (iterator.hasNext() && i < count) { final MessagePartData attachment = iterator.next(); ViewWrapper attachmentWrapper = null; // Try to recycle a previous view first for (int j = 0; j < previousViews.size(); j++) { final ViewWrapper previousView = previousViews.get(j); if (previousView.attachment.equals(attachment) && !(previousView.attachment instanceof PendingAttachmentData)) { attachmentWrapper = previousView; previousViews.remove(j); break; } } if (attachmentWrapper == null) { final View view = AttachmentPreviewFactory.createAttachmentPreview( layoutInflater, attachment, this, AttachmentPreviewFactory.TYPE_MULTIPLE, false /* startImageRequest */, mAttachmentClickListener); if (view == null) { // createAttachmentPreview can return null if something goes wrong (e.g. // attachment has unsupported contentType) continue; } if (view instanceof AsyncImageView && mImageViewDelayLoader != null) { AsyncImageView asyncImageView = (AsyncImageView) view; asyncImageView.setDelayLoader(mImageViewDelayLoader); } addView(view); attachmentWrapper = new ViewWrapper(view, attachment); // Help animate from single to multi by copying over the prev location if (count == 2 && i == 1 && transitionRect != null) { attachmentWrapper.prevLeft = transitionRect.left; attachmentWrapper.prevTop = transitionRect.top; attachmentWrapper.prevWidth = transitionRect.width(); attachmentWrapper.prevHeight = transitionRect.height(); } } i++; Assert.notNull(attachmentWrapper); mPreviewViews.add(attachmentWrapper); // The first view will animate in using PopupTransitionAnimation, but the remaining // views will slide from their previous position to their new position within the // layout if (i == 0) { AttachmentPreview.tryAnimateViewIn(attachment, attachmentWrapper.view); } attachmentWrapper.needsSlideAnimation = i > 0; } // Build the plus text view (e.g. "+2") for when there are more attachments than what // this layout can display. if (mPlusNumber > 0) { mPlusTextView = (TextView) layoutInflater.inflate(R.layout.attachment_more_text_view, null /* parent */); mPlusTextView.setText(getResources().getString(R.string.attachment_more_items, mPlusNumber)); addView(mPlusTextView); } }
public static ApnsXmlProcessor get(XmlPullParser parser) { Assert.notNull(parser); return new ApnsXmlProcessor(parser); }
/** * 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); }
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(); } }
@VisibleForTesting public void setDatabaseForTest(final DatabaseWrapper db) { Assert.isTrue(BugleApplication.isRunningTests()); mDatabaseWrapper = db; }