1d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/* 2d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Copyright (C) 2015 The Android Open Source Project 3d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 4d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Licensed under the Apache License, Version 2.0 (the "License"); 5d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * you may not use this file except in compliance with the License. 6d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * You may obtain a copy of the License at 7d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 8d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * http://www.apache.org/licenses/LICENSE-2.0 9d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 10d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Unless required by applicable law or agreed to in writing, software 11d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * distributed under the License is distributed on an "AS IS" BASIS, 12d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * See the License for the specific language governing permissions and 14d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * limitations under the License. 15d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 16d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpackage com.android.messaging.ui.conversation; 17d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 18d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.Context; 19d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.content.res.Resources; 20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.database.Cursor; 21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.Rect; 22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.graphics.drawable.Drawable; 23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.net.Uri; 24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.support.annotation.Nullable; 25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.Spanned; 26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.TextUtils; 27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.format.DateUtils; 28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.format.Formatter; 29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.style.URLSpan; 30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.text.util.Linkify; 31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.AttributeSet; 32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.util.DisplayMetrics; 33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.Gravity; 34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.LayoutInflater; 35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.MotionEvent; 36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.View; 37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.ViewGroup; 38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.view.WindowManager; 39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.FrameLayout; 40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.ImageView.ScaleType; 41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.LinearLayout; 42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.widget.TextView; 43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.R; 45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.DataModel; 46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.ConversationMessageData; 47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.MessageData; 48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.MessagePartData; 49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.data.SubscriptionListData.SubscriptionListEntry; 50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.media.ImageRequestDescriptor; 51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.media.MessagePartImageRequestDescriptor; 52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.datamodel.media.UriImageRequestDescriptor; 53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.sms.MmsUtils; 54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.AsyncImageView; 55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.AsyncImageView.AsyncImageViewDelayLoader; 56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.AudioAttachmentView; 57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.ContactIconView; 58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.ConversationDrawables; 59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.MultiAttachmentLayout; 60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.MultiAttachmentLayout.OnAttachmentClickListener; 61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.PersonItemView; 62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.UIIntents; 63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.ui.VideoThumbnailView; 64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.AccessibilityUtil; 65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert; 66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.AvatarUriUtil; 67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.ContentType; 68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.ImageUtils; 69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.OsUtil; 70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.PhoneUtils; 71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.UiUtils; 72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.YouTubeUtil; 73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.base.Predicate; 74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.Collections; 76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.Comparator; 77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.List; 78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/** 80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * The view for a single entry in a conversation. 81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddpublic class ConversationMessageView extends FrameLayout implements View.OnClickListener, 83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd View.OnLongClickListener, OnAttachmentClickListener { 84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public interface ConversationMessageViewHost { 85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean onAttachmentClick(ConversationMessageView view, MessagePartData attachment, 86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Rect imageBounds, boolean longPress); 87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd SubscriptionListEntry getSubscriptionEntryForSelfParticipant(String selfParticipantId, 88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean excludeDefault); 89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final ConversationMessageData mData; 92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private LinearLayout mMessageAttachmentsView; 94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private MultiAttachmentLayout mMultiAttachmentView; 95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private AsyncImageView mMessageImageView; 96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private TextView mMessageTextView; 97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean mMessageTextHasLinks; 98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean mMessageHasYouTubeLink; 99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private TextView mStatusTextView; 100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private TextView mTitleTextView; 101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private TextView mMmsInfoTextView; 102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private LinearLayout mMessageTitleLayout; 103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private TextView mSenderNameTextView; 104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ContactIconView mContactIconView; 105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ConversationMessageBubbleView mMessageBubble; 106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private View mSubjectView; 107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private TextView mSubjectLabel; 108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private TextView mSubjectText; 109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private View mDeliveredBadge; 110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ViewGroup mMessageMetadataView; 111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ViewGroup mMessageTextAndInfoView; 112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private TextView mSimNameView; 113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean mOneOnOne; 115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private ConversationMessageViewHost mHost; 116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ConversationMessageView(final Context context, final AttributeSet attrs) { 118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd super(context, attrs); 119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // TODO: we should switch to using Binding and DataModel factory methods. 120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData = new ConversationMessageData(); 121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected void onFinishInflate() { 125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactIconView = (ContactIconView) findViewById(R.id.conversation_icon); 126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactIconView.setOnLongClickListener(new OnLongClickListener() { 127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean onLongClick(final View view) { 129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ConversationMessageView.this.performLongClick(); 130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }); 133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageAttachmentsView = (LinearLayout) findViewById(R.id.message_attachments); 135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMultiAttachmentView = (MultiAttachmentLayout) findViewById(R.id.multiple_attachments); 136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMultiAttachmentView.setOnAttachmentClickListener(this); 137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView = (AsyncImageView) findViewById(R.id.message_image); 139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setOnClickListener(this); 140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setOnLongClickListener(this); 141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView = (TextView) findViewById(R.id.message_text); 143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView.setOnClickListener(this); 144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd IgnoreLinkLongClickHelper.ignoreLinkLongClick(mMessageTextView, this); 145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mStatusTextView = (TextView) findViewById(R.id.message_status); 147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mTitleTextView = (TextView) findViewById(R.id.message_title); 148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMmsInfoTextView = (TextView) findViewById(R.id.mms_info); 149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTitleLayout = (LinearLayout) findViewById(R.id.message_title_layout); 150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSenderNameTextView = (TextView) findViewById(R.id.message_sender_name); 151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageBubble = (ConversationMessageBubbleView) findViewById(R.id.message_content); 152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSubjectView = findViewById(R.id.subject_container); 153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSubjectLabel = (TextView) mSubjectView.findViewById(R.id.subject_label); 154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSubjectText = (TextView) mSubjectView.findViewById(R.id.subject_text); 155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mDeliveredBadge = findViewById(R.id.smsDeliveredBadge); 156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageMetadataView = (ViewGroup) findViewById(R.id.message_metadata); 157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextAndInfoView = (ViewGroup) findViewById(R.id.message_text_and_info); 158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSimNameView = (TextView) findViewById(R.id.sim_name); 159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) { 163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int horizontalSpace = MeasureSpec.getSize(widthMeasureSpec); 164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int iconSize = getResources() 165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getDimensionPixelSize(R.dimen.conversation_message_contact_icon_size); 166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int unspecifiedMeasureSpec = MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED); 168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int iconMeasureSpec = MeasureSpec.makeMeasureSpec(iconSize, MeasureSpec.EXACTLY); 169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactIconView.measure(iconMeasureSpec, iconMeasureSpec); 171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int arrowWidth = 173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd getResources().getDimensionPixelSize(R.dimen.message_bubble_arrow_width); 174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We need to subtract contact icon width twice from the horizontal space to get 176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the max leftover space because we want the message bubble to extend no further than the 177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // starting position of the message bubble in the opposite direction. 178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int maxLeftoverSpace = horizontalSpace - mContactIconView.getMeasuredWidth() * 2 179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd - arrowWidth - getPaddingLeft() - getPaddingRight(); 180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int messageContentWidthMeasureSpec = MeasureSpec.makeMeasureSpec(maxLeftoverSpace, 181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MeasureSpec.AT_MOST); 182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageBubble.measure(messageContentWidthMeasureSpec, unspecifiedMeasureSpec); 184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int maxHeight = Math.max(mContactIconView.getMeasuredHeight(), 186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageBubble.getMeasuredHeight()); 187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setMeasuredDimension(horizontalSpace, maxHeight + getPaddingBottom() + getPaddingTop()); 188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd protected void onLayout(final boolean changed, final int left, final int top, final int right, 192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int bottom) { 193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean isRtl = AccessibilityUtil.isLayoutRtl(this); 194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int iconWidth = mContactIconView.getMeasuredWidth(); 196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int iconHeight = mContactIconView.getMeasuredHeight(); 197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int iconTop = getPaddingTop(); 198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int contentWidth = (right -left) - iconWidth - getPaddingLeft() - getPaddingRight(); 199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int contentHeight = mMessageBubble.getMeasuredHeight(); 200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int contentTop = iconTop; 201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int iconLeft; 203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int contentLeft; 204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mData.getIsIncoming()) { 205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isRtl) { 206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd iconLeft = (right - left) - getPaddingRight() - iconWidth; 207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentLeft = iconLeft - contentWidth; 208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd iconLeft = getPaddingLeft(); 210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentLeft = iconLeft + iconWidth; 211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isRtl) { 214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd iconLeft = getPaddingLeft(); 215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentLeft = iconLeft + iconWidth; 216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd iconLeft = (right - left) - getPaddingRight() - iconWidth; 218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentLeft = iconLeft - contentWidth; 219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactIconView.layout(iconLeft, iconTop, iconLeft + iconWidth, iconTop + iconHeight); 223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageBubble.layout(contentLeft, contentTop, contentLeft + contentWidth, 225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentTop + contentHeight); 226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Fills in the data associated with this view. 230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param cursor The cursor from a MessageList that this view is in, pointing to its entry. 232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void bind(final Cursor cursor) { 234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bind(cursor, true, null); 235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Fills in the data associated with this view. 239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param cursor The cursor from a MessageList that this view is in, pointing to its entry. 241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param oneOnOne Whether this is a 1:1 conversation 242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void bind(final Cursor cursor, 244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean oneOnOne, final String selectedMessageId) { 245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mOneOnOne = oneOnOne; 246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update our UI model 248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.bind(cursor); 249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setSelected(TextUtils.equals(mData.getMessageId(), selectedMessageId)); 250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update text and image content for the view. 252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateViewContent(); 253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update colors and layout parameters for the view. 255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateViewAppearance(); 256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateContentDescription(); 258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void setHost(final ConversationMessageViewHost host) { 261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mHost = host; 262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Sets a delay loader instance to manage loading / resuming of image attachments. 266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void setImageViewDelayLoader(final AsyncImageViewDelayLoader delayLoader) { 268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.notNull(mMessageImageView); 269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setDelayLoader(delayLoader); 270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMultiAttachmentView.setImageViewDelayLoader(delayLoader); 271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ConversationMessageData getData() { 274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return mData; 275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns whether we should show simplified visual style for the message view (i.e. hide the 279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * avatar and bubble arrow, reduce padding). 280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean shouldShowSimplifiedVisualStyle() { 282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return mData.getCanClusterWithPreviousMessage(); 283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns whether we need to show message bubble arrow. We don't show arrow if the message 287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * contains media attachments or if shouldShowSimplifiedVisualStyle() is true. 288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean shouldShowMessageBubbleArrow() { 290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return !shouldShowSimplifiedVisualStyle() 291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd && !(mData.hasAttachments() || mMessageHasYouTubeLink); 292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Returns whether we need to show a message bubble for text content. 296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean shouldShowMessageTextBubble() { 298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mData.hasText()) { 299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String subjectText = MmsUtils.cleanseMmsSubject(getResources(), 302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getMmsSubject()); 303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!TextUtils.isEmpty(subjectText)) { 304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateViewContent() { 310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateMessageContent(); 311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int titleResId = -1; 312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int statusResId = -1; 313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String statusText = null; 314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd switch(mData.getStatus()) { 315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING: 316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING: 317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD: 318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD: 319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd titleResId = R.string.message_title_downloading; 320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_downloading; 321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD: 324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!OsUtil.isSecondaryUser()) { 325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd titleResId = R.string.message_title_manual_download; 326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isSelected()) { 327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_download_action; 328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_download; 330d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 331d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 332d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 333d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 334d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE: 335d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!OsUtil.isSecondaryUser()) { 336d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd titleResId = R.string.message_title_download_failed; 337d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_download_error; 338d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 339d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 340d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 341d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED: 342d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!OsUtil.isSecondaryUser()) { 343d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd titleResId = R.string.message_title_download_failed; 344d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isSelected()) { 345d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_download_action; 346d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 347d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_download; 348d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 349d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 350d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 351d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 352d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND: 353d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_SENDING: 354d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_sending; 355d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 356d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 357d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_RESENDING: 358d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY: 359d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_send_retrying; 360d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 361d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 362d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER: 363d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_send_failed_emergency_number; 364d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 365d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 366d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_FAILED: 367d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // don't show the error state unless we're the default sms app 368d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (PhoneUtils.getDefault().isDefaultSmsApp()) { 369d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isSelected()) { 370d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = R.string.message_status_resend; 371d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 372d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusResId = MmsUtils.mapRawStatusToErrorResourceId( 373d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getStatus(), mData.getRawTelephonyStatus()); 374d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 375d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 376d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 377d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // FALL THROUGH HERE 378d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 379d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_COMPLETE: 380d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_COMPLETE: 381d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd default: 382d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!mData.getCanClusterWithNextMessage()) { 383d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusText = mData.getFormattedReceivedTimeStamp(); 384d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 385d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 386d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 387d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 388d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean titleVisible = (titleResId >= 0); 389d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (titleVisible) { 390d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String titleText = getResources().getString(titleResId); 391d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mTitleTextView.setText(titleText); 392d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 393d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String mmsInfoText = getResources().getString( 394d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.string.mms_info, 395d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Formatter.formatFileSize(getContext(), mData.getSmsMessageSize()), 396d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DateUtils.formatDateTime( 397d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd getContext(), 398d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getMmsExpiry(), 399d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DateUtils.FORMAT_SHOW_DATE | 400d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DateUtils.FORMAT_SHOW_TIME | 401d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DateUtils.FORMAT_NUMERIC_DATE | 402d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd DateUtils.FORMAT_NO_YEAR)); 403d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMmsInfoTextView.setText(mmsInfoText); 404d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTitleLayout.setVisibility(View.VISIBLE); 405d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 406d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTitleLayout.setVisibility(View.GONE); 407d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 408d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 409d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String subjectText = MmsUtils.cleanseMmsSubject(getResources(), 410d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getMmsSubject()); 411d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean subjectVisible = !TextUtils.isEmpty(subjectText); 412d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 413d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean senderNameVisible = !mOneOnOne && !mData.getCanClusterWithNextMessage() 414d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd && mData.getIsIncoming(); 415d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (senderNameVisible) { 416d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSenderNameTextView.setText(mData.getSenderDisplayName()); 417d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSenderNameTextView.setVisibility(View.VISIBLE); 418d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 419d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSenderNameTextView.setVisibility(View.GONE); 420d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 421d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 422d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (statusResId >= 0) { 423d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusText = getResources().getString(statusResId); 424d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 425d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 426d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We set the text even if the view will be GONE for accessibility 427d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mStatusTextView.setText(statusText); 428d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean statusVisible = !TextUtils.isEmpty(statusText); 429d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (statusVisible) { 430d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mStatusTextView.setVisibility(View.VISIBLE); 431d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 432d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mStatusTextView.setVisibility(View.GONE); 433d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 434d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 435d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean deliveredBadgeVisible = 436d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getStatus() == MessageData.BUGLE_STATUS_OUTGOING_DELIVERED; 437d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mDeliveredBadge.setVisibility(deliveredBadgeVisible ? View.VISIBLE : View.GONE); 438d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 439d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update the sim indicator. 440d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean showSimIconAsIncoming = mData.getIsIncoming() && 441d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (!mData.hasAttachments() || shouldShowMessageTextBubble()); 442d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final SubscriptionListEntry subscriptionEntry = 443d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mHost.getSubscriptionEntryForSelfParticipant(mData.getSelfParticipantId(), 444d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd true /* excludeDefault */); 445d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean simNameVisible = subscriptionEntry != null && 446d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd !TextUtils.isEmpty(subscriptionEntry.displayName) && 447d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd !mData.getCanClusterWithNextMessage(); 448d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (simNameVisible) { 449d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String simNameText = mData.getIsIncoming() ? getResources().getString( 450d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.string.incoming_sim_name_text, subscriptionEntry.displayName) : 451d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subscriptionEntry.displayName; 452d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSimNameView.setText(simNameText); 453d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSimNameView.setTextColor(showSimIconAsIncoming ? getResources().getColor( 454d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.color.timestamp_text_incoming) : subscriptionEntry.displayColor); 455d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSimNameView.setVisibility(VISIBLE); 456d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 457d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSimNameView.setText(null); 458d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSimNameView.setVisibility(GONE); 459d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 460d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 461d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean metadataVisible = senderNameVisible || statusVisible 462d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || deliveredBadgeVisible || simNameVisible; 463d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageMetadataView.setVisibility(metadataVisible ? View.VISIBLE : View.GONE); 464d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 465d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean messageTextAndOrInfoVisible = titleVisible || subjectVisible 466d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd || mData.hasText() || metadataVisible; 467d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextAndInfoView.setVisibility( 468d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageTextAndOrInfoVisible ? View.VISIBLE : View.GONE); 469d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 470d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (shouldShowSimplifiedVisualStyle()) { 471d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactIconView.setVisibility(View.GONE); 472d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactIconView.setImageResourceUri(null); 473d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 474d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactIconView.setVisibility(View.VISIBLE); 475d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Uri avatarUri = AvatarUriUtil.createAvatarUri( 476d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getSenderProfilePhotoUri(), 477d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getSenderFullName(), 478d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getSenderNormalizedDestination(), 479d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getSenderContactLookupKey()); 480d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mContactIconView.setImageResourceUri(avatarUri, mData.getSenderContactId(), 481d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getSenderContactLookupKey(), mData.getSenderNormalizedDestination()); 482d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 483d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 484d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 485d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateMessageContent() { 486d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We must update the text before the attachments since we search the text to see if we 487d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // should make a preview youtube image in the attachments 488d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateMessageText(); 489d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateMessageAttachments(); 490d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateMessageSubject(); 491d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageBubble.bind(mData); 492d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 493d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 494d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateMessageAttachments() { 495d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Bind video, audio, and VCard attachments. If there are multiple, they stack vertically. 496d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bindAttachmentsOfSameType(sVideoFilter, 497d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.layout.message_video_attachment, mVideoViewBinder, VideoThumbnailView.class); 498d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bindAttachmentsOfSameType(sAudioFilter, 499d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.layout.message_audio_attachment, mAudioViewBinder, AudioAttachmentView.class); 500d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd bindAttachmentsOfSameType(sVCardFilter, 501d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.layout.message_vcard_attachment, mVCardViewBinder, PersonItemView.class); 502d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 503d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Bind image attachments. If there are multiple, they are shown in a collage view. 504d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final List<MessagePartData> imageParts = mData.getAttachments(sImageFilter); 505d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (imageParts.size() > 1) { 506d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Collections.sort(imageParts, sImageComparator); 507d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMultiAttachmentView.bindAttachments(imageParts, null, imageParts.size()); 508d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMultiAttachmentView.setVisibility(View.VISIBLE); 509d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 510d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMultiAttachmentView.setVisibility(View.GONE); 511d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 512d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 513d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // In the case that we have no image attachments and exactly one youtube link in a message 514d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // then we will show a preview. 515d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String youtubeThumbnailUrl = null; 516d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String originalYoutubeLink = null; 517d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mMessageTextHasLinks && imageParts.size() == 0) { 518d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd CharSequence messageTextWithSpans = mMessageTextView.getText(); 519d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final URLSpan[] spans = ((Spanned) messageTextWithSpans).getSpans(0, 520d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageTextWithSpans.length(), URLSpan.class); 521d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (URLSpan span : spans) { 522d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String url = span.getURL(); 523d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String youtubeLinkForUrl = YouTubeUtil.getYoutubePreviewImageLink(url); 524d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!TextUtils.isEmpty(youtubeLinkForUrl)) { 525d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (TextUtils.isEmpty(youtubeThumbnailUrl)) { 526d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Save the youtube link if we don't already have one 527d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd youtubeThumbnailUrl = youtubeLinkForUrl; 528d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd originalYoutubeLink = url; 529d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 530d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We already have a youtube link. This means we have two youtube links so 531d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // we shall show none. 532d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd youtubeThumbnailUrl = null; 533d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd originalYoutubeLink = null; 534d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 535d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 536d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 537d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 538d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 539d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We need to keep track if we have a youtube link in the message so that we will not show 540d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the arrow 541d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageHasYouTubeLink = !TextUtils.isEmpty(youtubeThumbnailUrl); 542d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 543d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We will show the message image view if there is one attachment or one youtube link 544d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (imageParts.size() == 1 || mMessageHasYouTubeLink) { 545d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Get the display metrics for a hint for how large to pull the image data into 546d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final WindowManager windowManager = (WindowManager) getContext(). 547d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd getSystemService(Context.WINDOW_SERVICE); 548d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final DisplayMetrics displayMetrics = new DisplayMetrics(); 549d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd windowManager.getDefaultDisplay().getMetrics(displayMetrics); 550d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 551d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int iconSize = getResources() 552d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getDimensionPixelSize(R.dimen.conversation_message_contact_icon_size); 553d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int desiredWidth = displayMetrics.widthPixels - iconSize - iconSize; 554d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 555d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (imageParts.size() == 1) { 556d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final MessagePartData imagePart = imageParts.get(0); 557d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If the image is big, we want to scale it down to save memory since we're going to 558d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // scale it down to fit into the bubble width. We don't constrain the height. 559d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ImageRequestDescriptor imageRequest = 560d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new MessagePartImageRequestDescriptor(imagePart, 561d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd desiredWidth, 562d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagePartData.UNSPECIFIED_SIZE, 563d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd false); 564d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd adjustImageViewBounds(imagePart); 565d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setImageResourceId(imageRequest); 566d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setTag(imagePart); 567d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 568d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Youtube Thumbnail image 569d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ImageRequestDescriptor imageRequest = 570d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new UriImageRequestDescriptor(Uri.parse(youtubeThumbnailUrl), desiredWidth, 571d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd MessagePartData.UNSPECIFIED_SIZE, true /* allowCompression */, 572d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd true /* isStatic */, false /* cropToCircle */, 573d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ImageUtils.DEFAULT_CIRCLE_BACKGROUND_COLOR /* circleBackgroundColor */, 574d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ImageUtils.DEFAULT_CIRCLE_STROKE_COLOR /* circleStrokeColor */); 575d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setImageResourceId(imageRequest); 576d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setTag(originalYoutubeLink); 577d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 578d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setVisibility(View.VISIBLE); 579d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 580d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setImageResourceId(null); 581d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setVisibility(View.GONE); 582d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 583d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 584d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Show the message attachments container if any of its children are visible 585d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean attachmentsVisible = false; 586d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0, size = mMessageAttachmentsView.getChildCount(); i < size; i++) { 587d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final View attachmentView = mMessageAttachmentsView.getChildAt(i); 588d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (attachmentView.getVisibility() == View.VISIBLE) { 589d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd attachmentsVisible = true; 590d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 591d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 592d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 593d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageAttachmentsView.setVisibility(attachmentsVisible ? View.VISIBLE : View.GONE); 594d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 595d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 596d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void bindAttachmentsOfSameType(final Predicate<MessagePartData> attachmentTypeFilter, 597d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int attachmentViewLayoutRes, final AttachmentViewBinder viewBinder, 598d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Class<?> attachmentViewClass) { 599d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final LayoutInflater layoutInflater = LayoutInflater.from(getContext()); 600d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 601d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Iterate through all attachments of a particular type (video, audio, etc). 602d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Find the first attachment index that matches the given type if possible. 603d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int attachmentViewIndex = -1; 604d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd View existingAttachmentView; 605d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd do { 606d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd existingAttachmentView = mMessageAttachmentsView.getChildAt(++attachmentViewIndex); 607d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } while (existingAttachmentView != null && 608d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd !(attachmentViewClass.isInstance(existingAttachmentView))); 609d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 610d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (final MessagePartData attachment : mData.getAttachments(attachmentTypeFilter)) { 611d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd View attachmentView = mMessageAttachmentsView.getChildAt(attachmentViewIndex); 612d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!attachmentViewClass.isInstance(attachmentView)) { 613d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd attachmentView = layoutInflater.inflate(attachmentViewLayoutRes, 614d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageAttachmentsView, false /* attachToRoot */); 615d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd attachmentView.setOnClickListener(this); 616d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd attachmentView.setOnLongClickListener(this); 617d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageAttachmentsView.addView(attachmentView, attachmentViewIndex); 618d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 619d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd viewBinder.bindView(attachmentView, attachment); 620d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd attachmentView.setTag(attachment); 621d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd attachmentView.setVisibility(View.VISIBLE); 622d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd attachmentViewIndex++; 623d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 624d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If there are unused views left over, unbind or remove them. 625d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd while (attachmentViewIndex < mMessageAttachmentsView.getChildCount()) { 626d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final View attachmentView = mMessageAttachmentsView.getChildAt(attachmentViewIndex); 627d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (attachmentViewClass.isInstance(attachmentView)) { 628d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageAttachmentsView.removeViewAt(attachmentViewIndex); 629d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 630d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // No more views of this type; we're done. 631d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 632d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 633d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 634d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 635d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 636d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateMessageSubject() { 637d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String subjectText = MmsUtils.cleanseMmsSubject(getResources(), 638d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.getMmsSubject()); 639d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean subjectVisible = !TextUtils.isEmpty(subjectText); 640d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 641d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (subjectVisible) { 642d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSubjectText.setText(subjectText); 643d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSubjectView.setVisibility(View.VISIBLE); 644d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 645d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSubjectView.setVisibility(View.GONE); 646d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 647d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 648d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 649d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateMessageText() { 650d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final String text = mData.getText(); 651d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (!TextUtils.isEmpty(text)) { 652d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView.setText(text); 653d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Linkify phone numbers, web urls, emails, and map addresses to allow users to 654d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // click on them and take the default intent. 655d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextHasLinks = Linkify.addLinks(mMessageTextView, Linkify.ALL); 656d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView.setVisibility(View.VISIBLE); 657d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 658d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView.setVisibility(View.GONE); 659d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextHasLinks = false; 660d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 661d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 662d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 663d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateViewAppearance() { 664d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Resources res = getResources(); 665d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ConversationDrawables drawableProvider = ConversationDrawables.get(); 666d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean incoming = mData.getIsIncoming(); 667d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean outgoing = !incoming; 668d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final boolean showArrow = shouldShowMessageBubbleArrow(); 669d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 670d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int messageTopPaddingClustered = 671d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd res.getDimensionPixelSize(R.dimen.message_padding_same_author); 672d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int messageTopPaddingDefault = 673d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd res.getDimensionPixelSize(R.dimen.message_padding_default); 674d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int arrowWidth = res.getDimensionPixelOffset(R.dimen.message_bubble_arrow_width); 675d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int messageTextMinHeightDefault = res.getDimensionPixelSize( 676d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.dimen.conversation_message_contact_icon_size); 677d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int messageTextLeftRightPadding = res.getDimensionPixelOffset( 678d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.dimen.message_text_left_right_padding); 679d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int textTopPaddingDefault = res.getDimensionPixelOffset( 680d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.dimen.message_text_top_padding); 681d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int textBottomPaddingDefault = res.getDimensionPixelOffset( 682d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.dimen.message_text_bottom_padding); 683d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 684d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // These values depend on whether the message has text, attachments, or both. 685d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We intentionally don't set defaults, so the compiler will tell us if we forget 686d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // to set one of them, or if we set one more than once. 687d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int contentLeftPadding, contentRightPadding; 688d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Drawable textBackground; 689d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int textMinHeight; 690d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int textTopMargin; 691d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int textTopPadding, textBottomPadding; 692d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int textLeftPadding, textRightPadding; 693d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 694d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mData.hasAttachments()) { 695d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (shouldShowMessageTextBubble()) { 696d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Text and attachment(s) 697d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentLeftPadding = incoming ? arrowWidth : 0; 698d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentRightPadding = outgoing ? arrowWidth : 0; 699d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textBackground = drawableProvider.getBubbleDrawable( 700d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd isSelected(), 701d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd incoming, 702d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd false /* needArrow */, 703d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.hasIncomingErrorStatus()); 704d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textMinHeight = messageTextMinHeightDefault; 705d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textTopMargin = messageTopPaddingClustered; 706d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textTopPadding = textTopPaddingDefault; 707d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textBottomPadding = textBottomPaddingDefault; 708d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textLeftPadding = messageTextLeftRightPadding; 709d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textRightPadding = messageTextLeftRightPadding; 710d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 711d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Attachment(s) only 712d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentLeftPadding = incoming ? arrowWidth : 0; 713d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentRightPadding = outgoing ? arrowWidth : 0; 714d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textBackground = null; 715d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textMinHeight = 0; 716d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textTopMargin = 0; 717d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textTopPadding = 0; 718d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textBottomPadding = 0; 719d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textLeftPadding = 0; 720d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textRightPadding = 0; 721d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 722d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 723d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Text only 724d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentLeftPadding = (!showArrow && incoming) ? arrowWidth : 0; 725d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd contentRightPadding = (!showArrow && outgoing) ? arrowWidth : 0; 726d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textBackground = drawableProvider.getBubbleDrawable( 727d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd isSelected(), 728d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd incoming, 729d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd shouldShowMessageBubbleArrow(), 730d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.hasIncomingErrorStatus()); 731d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textMinHeight = messageTextMinHeightDefault; 732d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textTopMargin = 0; 733d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textTopPadding = textTopPaddingDefault; 734d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textBottomPadding = textBottomPaddingDefault; 735d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (showArrow && incoming) { 736d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textLeftPadding = messageTextLeftRightPadding + arrowWidth; 737d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 738d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textLeftPadding = messageTextLeftRightPadding; 739d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 740d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (showArrow && outgoing) { 741d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textRightPadding = messageTextLeftRightPadding + arrowWidth; 742d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 743d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textRightPadding = messageTextLeftRightPadding; 744d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 745d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 746d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 747d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // These values do not depend on whether the message includes attachments 748d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int gravity = incoming ? (Gravity.START | Gravity.CENTER_VERTICAL) : 749d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (Gravity.END | Gravity.CENTER_VERTICAL); 750d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int messageTopPadding = shouldShowSimplifiedVisualStyle() ? 751d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageTopPaddingClustered : messageTopPaddingDefault; 752d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int metadataTopPadding = res.getDimensionPixelOffset( 753d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.dimen.message_metadata_top_padding); 754d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 755d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update the message text/info views 756d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ImageUtils.setBackgroundDrawableOnView(mMessageTextAndInfoView, textBackground); 757d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextAndInfoView.setMinimumHeight(textMinHeight); 758d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final LinearLayout.LayoutParams textAndInfoLayoutParams = 759d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd (LinearLayout.LayoutParams) mMessageTextAndInfoView.getLayoutParams(); 760d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textAndInfoLayoutParams.topMargin = textTopMargin; 761d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 762d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (UiUtils.isRtlMode()) { 763d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Need to switch right and left padding in RtL mode 764d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextAndInfoView.setPadding(textRightPadding, textTopPadding, textLeftPadding, 765d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textBottomPadding); 766d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageBubble.setPadding(contentRightPadding, 0, contentLeftPadding, 0); 767d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 768d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextAndInfoView.setPadding(textLeftPadding, textTopPadding, textRightPadding, 769d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textBottomPadding); 770d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageBubble.setPadding(contentLeftPadding, 0, contentRightPadding, 0); 771d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 772d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 773d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Update the message row and message bubble views 774d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setPadding(getPaddingLeft(), messageTopPadding, getPaddingRight(), 0); 775d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageBubble.setGravity(gravity); 776d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateMessageAttachmentsAppearance(gravity); 777d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 778d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageMetadataView.setPadding(0, metadataTopPadding, 0, 0); 779d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 780d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd updateTextAppearance(); 781d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 782d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd requestLayout(); 783d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 784d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 785d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateContentDescription() { 786d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd StringBuilder description = new StringBuilder(); 787d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 788d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Resources res = getResources(); 789d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd String separator = res.getString(R.string.enumeration_comma); 790d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 791d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Sender information 792d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean hasPlainTextMessage = !(TextUtils.isEmpty(mData.getText()) || 793d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextHasLinks); 794d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mData.getIsIncoming()) { 795d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int senderResId = hasPlainTextMessage 796d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ? R.string.incoming_text_sender_content_description 797d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd : R.string.incoming_sender_content_description; 798d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(res.getString(senderResId, mData.getSenderDisplayName())); 799d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 800d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int senderResId = hasPlainTextMessage 801d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ? R.string.outgoing_text_sender_content_description 802d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd : R.string.outgoing_sender_content_description; 803d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(res.getString(senderResId)); 804d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 805d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 806d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mSubjectView.getVisibility() == View.VISIBLE) { 807d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(separator); 808d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(mSubjectText.getText()); 809d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 810d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 811d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mMessageTextView.getVisibility() == View.VISIBLE) { 812d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If the message has hyperlinks, we will let the user navigate to the text message so 813d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // that the hyperlink can be clicked. Otherwise, the text message does not need to 814d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // be reachable. 815d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mMessageTextHasLinks) { 816d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES); 817d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 818d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_NO); 819d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(separator); 820d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(mMessageTextView.getText()); 821d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 822d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 823d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 824d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mMessageTitleLayout.getVisibility() == View.VISIBLE) { 825d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(separator); 826d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(mTitleTextView.getText()); 827d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 828d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(separator); 829d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(mMmsInfoTextView.getText()); 830d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 831d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 832d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mStatusTextView.getVisibility() == View.VISIBLE) { 833d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(separator); 834d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(mStatusTextView.getText()); 835d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 836d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 837d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mSimNameView.getVisibility() == View.VISIBLE) { 838d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(separator); 839d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(mSimNameView.getText()); 840d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 841d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 842d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mDeliveredBadge.getVisibility() == View.VISIBLE) { 843d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(separator); 844d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd description.append(res.getString(R.string.delivered_status_content_description)); 845d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 846d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 847d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd setContentDescription(description); 848d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 849d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 850d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateMessageAttachmentsAppearance(final int gravity) { 851d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageAttachmentsView.setGravity(gravity); 852d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 853d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Tint image/video attachments when selected 854d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int selectedImageTint = getResources().getColor(R.color.message_image_selected_tint); 855d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mMessageImageView.getVisibility() == View.VISIBLE) { 856d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isSelected()) { 857d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setColorFilter(selectedImageTint); 858d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 859d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.clearColorFilter(); 860d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 861d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 862d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mMultiAttachmentView.getVisibility() == View.VISIBLE) { 863d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isSelected()) { 864d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMultiAttachmentView.setColorFilter(selectedImageTint); 865d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 866d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMultiAttachmentView.clearColorFilter(); 867d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 868d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 869d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0, size = mMessageAttachmentsView.getChildCount(); i < size; i++) { 870d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final View attachmentView = mMessageAttachmentsView.getChildAt(i); 871d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (attachmentView instanceof VideoThumbnailView 872d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd && attachmentView.getVisibility() == View.VISIBLE) { 873d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final VideoThumbnailView videoView = (VideoThumbnailView) attachmentView; 874d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isSelected()) { 875d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd videoView.setColorFilter(selectedImageTint); 876d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 877d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd videoView.clearColorFilter(); 878d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 879d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 880d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 881d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 882d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If there are multiple attachment bubbles in a single message, add some separation. 883d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int multipleAttachmentPadding = 884d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd getResources().getDimensionPixelSize(R.dimen.message_padding_same_author); 885d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 886d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd boolean previousVisibleView = false; 887d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd for (int i = 0, size = mMessageAttachmentsView.getChildCount(); i < size; i++) { 888d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final View attachmentView = mMessageAttachmentsView.getChildAt(i); 889d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (attachmentView.getVisibility() == View.VISIBLE) { 890d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int margin = previousVisibleView ? multipleAttachmentPadding : 0; 891d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ((LinearLayout.LayoutParams) attachmentView.getLayoutParams()).topMargin = margin; 892d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // updateViewAppearance calls requestLayout() at the end, so we don't need to here 893d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd previousVisibleView = true; 894d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 895d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 896d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 897d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 898d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void updateTextAppearance() { 899d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int messageColorResId; 900d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int statusColorResId = -1; 901d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int infoColorResId = -1; 902d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int timestampColorResId; 903d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd int subjectLabelColorResId; 904d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isSelected()) { 905d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageColorResId = R.color.message_text_color_incoming; 906d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusColorResId = R.color.message_action_status_text; 907d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd infoColorResId = R.color.message_action_info_text; 908d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (shouldShowMessageTextBubble()) { 909d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd timestampColorResId = R.color.message_action_timestamp_text; 910d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subjectLabelColorResId = R.color.message_action_timestamp_text; 911d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 912d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // If there's no text, the timestamp will be shown below the attachments, 913d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // against the conversation view background. 914d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd timestampColorResId = R.color.timestamp_text_outgoing; 915d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subjectLabelColorResId = R.color.timestamp_text_outgoing; 916d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 917d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 918d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageColorResId = (mData.getIsIncoming() ? 919d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd R.color.message_text_color_incoming : R.color.message_text_color_outgoing); 920d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusColorResId = messageColorResId; 921d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd infoColorResId = R.color.timestamp_text_incoming; 922d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd switch(mData.getStatus()) { 923d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 924d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_FAILED: 925d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_FAILED_EMERGENCY_NUMBER: 926d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd timestampColorResId = R.color.message_failed_timestamp_text; 927d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subjectLabelColorResId = R.color.timestamp_text_outgoing; 928d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 929d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 930d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_YET_TO_SEND: 931d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_SENDING: 932d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_RESENDING: 933d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_AWAITING_RETRY: 934d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_COMPLETE: 935d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_OUTGOING_DELIVERED: 936d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd timestampColorResId = R.color.timestamp_text_outgoing; 937d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subjectLabelColorResId = R.color.timestamp_text_outgoing; 938d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 939d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 940d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_EXPIRED_OR_NOT_AVAILABLE: 941d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_DOWNLOAD_FAILED: 942d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd messageColorResId = R.color.message_text_color_incoming_download_failed; 943d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd timestampColorResId = R.color.message_download_failed_timestamp_text; 944d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subjectLabelColorResId = R.color.message_text_color_incoming_download_failed; 945d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd statusColorResId = R.color.message_download_failed_status_text; 946d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd infoColorResId = R.color.message_info_text_incoming_download_failed; 947d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 948d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 949d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_AUTO_DOWNLOADING: 950d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_MANUAL_DOWNLOADING: 951d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_RETRYING_AUTO_DOWNLOAD: 952d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_RETRYING_MANUAL_DOWNLOAD: 953d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_YET_TO_MANUAL_DOWNLOAD: 954d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd timestampColorResId = R.color.message_text_color_incoming; 955d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subjectLabelColorResId = R.color.message_text_color_incoming; 956d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd infoColorResId = R.color.timestamp_text_incoming; 957d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 958d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 959d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd case MessageData.BUGLE_STATUS_INCOMING_COMPLETE: 960d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd default: 961d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd timestampColorResId = R.color.timestamp_text_incoming; 962d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd subjectLabelColorResId = R.color.timestamp_text_incoming; 963d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd infoColorResId = -1; // Not used 964d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd break; 965d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 966d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 967d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int messageColor = getResources().getColor(messageColorResId); 968d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView.setTextColor(messageColor); 969d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageTextView.setLinkTextColor(messageColor); 970d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSubjectText.setTextColor(messageColor); 971d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (statusColorResId >= 0) { 972d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mTitleTextView.setTextColor(getResources().getColor(statusColorResId)); 973d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 974d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (infoColorResId >= 0) { 975d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMmsInfoTextView.setTextColor(getResources().getColor(infoColorResId)); 976d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 977d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (timestampColorResId == R.color.timestamp_text_incoming && 978d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.hasAttachments() && !shouldShowMessageTextBubble()) { 979d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd timestampColorResId = R.color.timestamp_text_outgoing; 980d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 981d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mStatusTextView.setTextColor(getResources().getColor(timestampColorResId)); 982d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 983d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSubjectLabel.setTextColor(getResources().getColor(subjectLabelColorResId)); 984d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mSenderNameTextView.setTextColor(getResources().getColor(timestampColorResId)); 985d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 986d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 987d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 988d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * If we don't know the size of the image, we want to show it in a fixed-sized frame to 989d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * avoid janks when the image is loaded and resized. Otherwise, we can set the imageview to 990d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * take on normal layout params. 991d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 992d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private void adjustImageViewBounds(final MessagePartData imageAttachment) { 993d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd Assert.isTrue(ContentType.isImageType(imageAttachment.getContentType())); 994d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final ViewGroup.LayoutParams layoutParams = mMessageImageView.getLayoutParams(); 995d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (imageAttachment.getWidth() == MessagePartData.UNSPECIFIED_SIZE || 996d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd imageAttachment.getHeight() == MessagePartData.UNSPECIFIED_SIZE) { 997d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // We don't know the size of the image attachment, enable letterboxing on the image 998d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // and show a fixed sized attachment. This should happen at most once per image since 999d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // after the image is loaded we then save the image dimensions to the db so that the 1000d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // next time we can display the full size. 1001d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd layoutParams.width = getResources() 1002d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getDimensionPixelSize(R.dimen.image_attachment_fallback_width); 1003d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd layoutParams.height = getResources() 1004d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd .getDimensionPixelSize(R.dimen.image_attachment_fallback_height); 1005d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setScaleType(ScaleType.CENTER_CROP); 1006d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1007d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd layoutParams.width = ViewGroup.LayoutParams.MATCH_PARENT; 1008d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd layoutParams.height = ViewGroup.LayoutParams.WRAP_CONTENT; 1009d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // ScaleType.CENTER_INSIDE and FIT_CENTER behave similarly for most images. However, 1010d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // FIT_CENTER works better for small images as it enlarges the image such that the 1011d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // minimum size ("android:minWidth" etc) is honored. 1012d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mMessageImageView.setScaleType(ScaleType.FIT_CENTER); 1013d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1014d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1015d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1016d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1017d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void onClick(final View view) { 1018d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Object tag = view.getTag(); 1019d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (tag instanceof MessagePartData) { 1020d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view); 1021d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd onAttachmentClick((MessagePartData) tag, bounds, false /* longPress */); 1022d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else if (tag instanceof String) { 1023d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Currently the only object that would make a tag of a string is a youtube preview 1024d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // image 1025d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd UIIntents.get().launchBrowserForUrl(getContext(), (String) tag); 1026d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1027d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1028d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1029d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1030d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean onLongClick(final View view) { 1031d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (view == mMessageTextView) { 1032d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Preemptively handle the long click event on message text so it's not handled by 1033d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the link spans. 1034d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return performLongClick(); 1035d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1036d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1037d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Object tag = view.getTag(); 1038d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (tag instanceof MessagePartData) { 1039d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Rect bounds = UiUtils.getMeasuredBoundsOnScreen(view); 1040d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return onAttachmentClick((MessagePartData) tag, bounds, true /* longPress */); 1041d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1042d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1043d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 1044d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1045d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1046d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1047d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean onAttachmentClick(final MessagePartData attachment, 1048d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final Rect viewBoundsOnScreen, final boolean longPress) { 1049d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return mHost.onAttachmentClick(this, attachment, viewBoundsOnScreen, longPress); 1050d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1051d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1052d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public ContactIconView getContactIconView() { 1053d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return mContactIconView; 1054d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1055d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1056d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Sort photos in MultiAttachLayout in the same order as the ConversationImagePartsView 1057d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static final Comparator<MessagePartData> sImageComparator = new Comparator<MessagePartData>(){ 1058d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1059d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public int compare(final MessagePartData x, final MessagePartData y) { 1060d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return x.getPartId().compareTo(y.getPartId()); 1061d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1062d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1063d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1064d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static final Predicate<MessagePartData> sVideoFilter = new Predicate<MessagePartData>() { 1065d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1066d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean apply(final MessagePartData part) { 1067d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return part.isVideo(); 1068d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1069d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1070d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1071d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static final Predicate<MessagePartData> sAudioFilter = new Predicate<MessagePartData>() { 1072d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1073d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean apply(final MessagePartData part) { 1074d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return part.isAudio(); 1075d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1076d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1077d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1078d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static final Predicate<MessagePartData> sVCardFilter = new Predicate<MessagePartData>() { 1079d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1080d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean apply(final MessagePartData part) { 1081d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return part.isVCard(); 1082d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1083d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1084d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1085d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd static final Predicate<MessagePartData> sImageFilter = new Predicate<MessagePartData>() { 1086d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1087d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean apply(final MessagePartData part) { 1088d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return part.isImage(); 1089d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1090d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1091d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1092d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd interface AttachmentViewBinder { 1093d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd void bindView(View view, MessagePartData attachment); 1094d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd void unbind(View view); 1095d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1096d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1097d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final AttachmentViewBinder mVideoViewBinder = new AttachmentViewBinder() { 1098d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1099d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void bindView(final View view, final MessagePartData attachment) { 1100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ((VideoThumbnailView) view).setSource(attachment, mData.getIsIncoming()); 1101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void unbind(final View view) { 1105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ((VideoThumbnailView) view).setSource((Uri) null, mData.getIsIncoming()); 1106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final AttachmentViewBinder mAudioViewBinder = new AttachmentViewBinder() { 1110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void bindView(final View view, final MessagePartData attachment) { 1112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final AudioAttachmentView audioView = (AudioAttachmentView) view; 1113eba0949bc60e9002adf0c96044677b4c281b2819Shri Borde audioView.bindMessagePartData(attachment, mData.getIsIncoming(), isSelected()); 1114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd audioView.setBackground(ConversationDrawables.get().getBubbleDrawable( 1115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd isSelected(), mData.getIsIncoming(), false /* needArrow */, 1116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.hasIncomingErrorStatus())); 1117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void unbind(final View view) { 1121eba0949bc60e9002adf0c96044677b4c281b2819Shri Borde ((AudioAttachmentView) view).bindMessagePartData(null, mData.getIsIncoming(), false); 1122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final AttachmentViewBinder mVCardViewBinder = new AttachmentViewBinder() { 1126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void bindView(final View view, final MessagePartData attachment) { 1128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final PersonItemView personView = (PersonItemView) view; 1129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd personView.bind(DataModel.get().createVCardContactItemData(getContext(), 1130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd attachment)); 1131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd personView.setBackground(ConversationDrawables.get().getBubbleDrawable( 1132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd isSelected(), mData.getIsIncoming(), false /* needArrow */, 1133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mData.hasIncomingErrorStatus())); 1134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int nameTextColorRes; 1135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final int detailsTextColorRes; 1136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (isSelected()) { 1137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd nameTextColorRes = R.color.message_text_color_incoming; 1138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd detailsTextColorRes = R.color.message_text_color_incoming; 1139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } else { 1140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd nameTextColorRes = mData.getIsIncoming() ? R.color.message_text_color_incoming 1141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd : R.color.message_text_color_outgoing; 1142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd detailsTextColorRes = mData.getIsIncoming() ? R.color.timestamp_text_incoming 1143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd : R.color.timestamp_text_outgoing; 1144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd personView.setNameTextColor(getResources().getColor(nameTextColorRes)); 1146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd personView.setDetailsTextColor(getResources().getColor(detailsTextColorRes)); 1147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public void unbind(final View view) { 1151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd ((PersonItemView) view).bind(null); 1152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd }; 1154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * A helper class that allows us to handle long clicks on linkified message text view (i.e. to 1157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * select the message) so it's not handled by the link spans to launch apps for the links. 1158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private static class IgnoreLinkLongClickHelper implements OnLongClickListener, OnTouchListener { 1160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private boolean mIsLongClick; 1161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private final OnLongClickListener mDelegateLongClickListener; 1162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd /** 1164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * Ignore long clicks on linkified texts for a given text view. 1165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param textView the TextView to ignore long clicks on 1166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * @param longClickListener a delegate OnLongClickListener to be called when the view is 1167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * long clicked. 1168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */ 1169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public static void ignoreLinkLongClick(final TextView textView, 1170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Nullable final OnLongClickListener longClickListener) { 1171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd final IgnoreLinkLongClickHelper helper = 1172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd new IgnoreLinkLongClickHelper(longClickListener); 1173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textView.setOnLongClickListener(helper); 1174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd textView.setOnTouchListener(helper); 1175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd private IgnoreLinkLongClickHelper(@Nullable final OnLongClickListener longClickListener) { 1178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mDelegateLongClickListener = longClickListener; 1179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean onLongClick(final View v) { 1183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // Record that this click is a long click. 1184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mIsLongClick = true; 1185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (mDelegateLongClickListener != null) { 1186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return mDelegateLongClickListener.onLongClick(v); 1187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 1189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd @Override 1192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd public boolean onTouch(final View v, final MotionEvent event) { 1193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (event.getActionMasked() == MotionEvent.ACTION_UP && mIsLongClick) { 1194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // This touch event is a long click, preemptively handle this touch event so that 1195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd // the link span won't get a onClicked() callback. 1196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mIsLongClick = false; 1197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return true; 1198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd 1200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd if (event.getActionMasked() == MotionEvent.ACTION_DOWN) { 1201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd mIsLongClick = false; 1202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd return false; 1204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd } 1206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd} 1207