ViewStub for ThumbnailView in ConversationItem

// FREEBIE
This commit is contained in:
Moxie Marlinspike 2017-01-20 09:30:08 -08:00
parent e270e8d429
commit 183f8742a7
6 changed files with 78 additions and 46 deletions

View File

@ -49,16 +49,11 @@
android:orientation="vertical" android:orientation="vertical"
tools:backgroundTint="@color/blue_900"> tools:backgroundTint="@color/blue_900">
<org.thoughtcrime.securesms.components.ThumbnailView <ViewStub
android:id="@+id/image_view" android:id="@+id/image_view_stub"
android:layout="@layout/conversation_item_received_thumbnail"
android:layout_width="@dimen/media_bubble_height" android:layout_width="@dimen/media_bubble_height"
android:layout_height="@dimen/media_bubble_height" android:layout_height="@dimen/media_bubble_height"/>
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
android:visibility="gone"
tools:src="@drawable/ic_video_light"
tools:visibility="gone" />
<ViewStub <ViewStub
android:id="@+id/audio_view_stub" android:id="@+id/audio_view_stub"

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.ThumbnailView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/image_view"
android:layout_width="@dimen/media_bubble_height"
android:layout_height="@dimen/media_bubble_height"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
android:visibility="gone"
tools:src="@drawable/ic_video_light"
tools:visibility="gone" />

View File

@ -38,18 +38,11 @@
android:background="@drawable/sent_bubble" android:background="@drawable/sent_bubble"
android:orientation="vertical"> android:orientation="vertical">
<org.thoughtcrime.securesms.components.ThumbnailView <ViewStub
android:id="@+id/image_view" android:id="@+id/image_view_stub"
android:layout_width="@dimen/media_bubble_height" android:layout_width="@dimen/media_bubble_height"
android:layout_height="@dimen/media_bubble_height" android:layout_height="@dimen/media_bubble_height"
android:layout_marginBottom="5dp" android:layout="@layout/conversation_item_sent_thumbnail"/>
android:layout_gravity="center"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
android:visibility="gone"
tools:src="@drawable/ic_video_light"
tools:visibility="visible" />
<ViewStub <ViewStub
android:id="@+id/audio_view_stub" android:id="@+id/audio_view_stub"

View File

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.ThumbnailView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/image_view"
android:layout_width="@dimen/media_bubble_height"
android:layout_height="@dimen/media_bubble_height"
android:layout_marginBottom="5dp"
android:layout_gravity="center"
android:scaleType="centerCrop"
android:adjustViewBounds="true"
android:contentDescription="@string/conversation_item__mms_image_description"
android:visibility="gone"
tools:src="@drawable/ic_video_light"
tools:visibility="visible" />

View File

@ -64,11 +64,13 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
private final Map<String,SoftReference<MessageRecord>> messageRecordCache = private final Map<String,SoftReference<MessageRecord>> messageRecordCache =
Collections.synchronizedMap(new LRUCache<String, SoftReference<MessageRecord>>(MAX_CACHE_SIZE)); Collections.synchronizedMap(new LRUCache<String, SoftReference<MessageRecord>>(MAX_CACHE_SIZE));
private static final int MESSAGE_TYPE_OUTGOING = 0; private static final int MESSAGE_TYPE_OUTGOING = 0;
private static final int MESSAGE_TYPE_INCOMING = 1; private static final int MESSAGE_TYPE_INCOMING = 1;
private static final int MESSAGE_TYPE_UPDATE = 2; private static final int MESSAGE_TYPE_UPDATE = 2;
private static final int MESSAGE_TYPE_AUDIO_OUTGOING = 3; private static final int MESSAGE_TYPE_AUDIO_OUTGOING = 3;
private static final int MESSAGE_TYPE_AUDIO_INCOMING = 4; private static final int MESSAGE_TYPE_AUDIO_INCOMING = 4;
private static final int MESSAGE_TYPE_THUMBNAIL_OUTGOING = 5;
private static final int MESSAGE_TYPE_THUMBNAIL_INCOMING = 6;
private final Set<MessageRecord> batchSelected = Collections.synchronizedSet(new HashSet<MessageRecord>()); private final Set<MessageRecord> batchSelected = Collections.synchronizedSet(new HashSet<MessageRecord>());
@ -172,8 +174,10 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
private @LayoutRes int getLayoutForViewType(int viewType) { private @LayoutRes int getLayoutForViewType(int viewType) {
switch (viewType) { switch (viewType) {
case MESSAGE_TYPE_AUDIO_OUTGOING: case MESSAGE_TYPE_AUDIO_OUTGOING:
case MESSAGE_TYPE_THUMBNAIL_OUTGOING:
case MESSAGE_TYPE_OUTGOING: return R.layout.conversation_item_sent; case MESSAGE_TYPE_OUTGOING: return R.layout.conversation_item_sent;
case MESSAGE_TYPE_AUDIO_INCOMING: case MESSAGE_TYPE_AUDIO_INCOMING:
case MESSAGE_TYPE_THUMBNAIL_INCOMING:
case MESSAGE_TYPE_INCOMING: return R.layout.conversation_item_received; case MESSAGE_TYPE_INCOMING: return R.layout.conversation_item_received;
case MESSAGE_TYPE_UPDATE: return R.layout.conversation_item_update; case MESSAGE_TYPE_UPDATE: return R.layout.conversation_item_update;
default: throw new IllegalArgumentException("unsupported item view type given to ConversationAdapter"); default: throw new IllegalArgumentException("unsupported item view type given to ConversationAdapter");
@ -192,6 +196,9 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
} else if (hasAudio(messageRecord)) { } else if (hasAudio(messageRecord)) {
if (messageRecord.isOutgoing()) return MESSAGE_TYPE_AUDIO_OUTGOING; if (messageRecord.isOutgoing()) return MESSAGE_TYPE_AUDIO_OUTGOING;
else return MESSAGE_TYPE_AUDIO_INCOMING; else return MESSAGE_TYPE_AUDIO_INCOMING;
} else if (hasThumbnail(messageRecord)) {
if (messageRecord.isOutgoing()) return MESSAGE_TYPE_THUMBNAIL_OUTGOING;
else return MESSAGE_TYPE_THUMBNAIL_INCOMING;
} else if (messageRecord.isOutgoing()) { } else if (messageRecord.isOutgoing()) {
return MESSAGE_TYPE_OUTGOING; return MESSAGE_TYPE_OUTGOING;
} else { } else {
@ -240,4 +247,10 @@ public class ConversationAdapter <V extends View & BindableConversationItem>
!messageRecord.isMmsNotification() && !messageRecord.isMmsNotification() &&
((MediaMmsMessageRecord)messageRecord).getSlideDeck().getAudioSlide() != null; ((MediaMmsMessageRecord)messageRecord).getSlideDeck().getAudioSlide() != null;
} }
private boolean hasThumbnail(MessageRecord messageRecord) {
return messageRecord.isMms() &&
!messageRecord.isMmsNotification() &&
((MediaMmsMessageRecord)messageRecord).getSlideDeck().getThumbnailSlide() != null;
}
} }

View File

@ -111,7 +111,7 @@ public class ConversationItem extends LinearLayout
private @NonNull Set<MessageRecord> batchSelected = new HashSet<>(); private @NonNull Set<MessageRecord> batchSelected = new HashSet<>();
private @Nullable Recipients conversationRecipients; private @Nullable Recipients conversationRecipients;
private @NonNull ThumbnailView mediaThumbnail; private @NonNull Stub<ThumbnailView> mediaThumbnailStub;
private @NonNull Stub<AudioView> audioViewStub; private @NonNull Stub<AudioView> audioViewStub;
private @NonNull Button mmsDownloadButton; private @NonNull Button mmsDownloadButton;
private @NonNull TextView mmsDownloadingLabel; private @NonNull TextView mmsDownloadingLabel;
@ -158,18 +158,13 @@ public class ConversationItem extends LinearLayout
this.mmsDownloadingLabel = (TextView) findViewById(R.id.mms_label_downloading); this.mmsDownloadingLabel = (TextView) findViewById(R.id.mms_label_downloading);
this.contactPhoto = (AvatarImageView) findViewById(R.id.contact_photo); this.contactPhoto = (AvatarImageView) findViewById(R.id.contact_photo);
this.bodyBubble = findViewById(R.id.body_bubble); this.bodyBubble = findViewById(R.id.body_bubble);
this.mediaThumbnail = (ThumbnailView) findViewById(R.id.image_view); this.mediaThumbnailStub = new Stub<>((ViewStub) findViewById(R.id.image_view_stub));
this.audioViewStub = new Stub<>((ViewStub) findViewById(R.id.audio_view_stub)); this.audioViewStub = new Stub<>((ViewStub) findViewById(R.id.audio_view_stub));
this.expirationTimer = (ExpirationTimerView) findViewById(R.id.expiration_indicator); this.expirationTimer = (ExpirationTimerView) findViewById(R.id.expiration_indicator);
setOnClickListener(new ClickListener(null)); setOnClickListener(new ClickListener(null));
mmsDownloadButton.setOnClickListener(mmsDownloadClickListener); mmsDownloadButton.setOnClickListener(mmsDownloadClickListener);
mediaThumbnail.setThumbnailClickListener(new ThumbnailClickListener());
mediaThumbnail.setDownloadClickListener(downloadClickListener);
mediaThumbnail.setOnLongClickListener(passthroughClickListener);
mediaThumbnail.setOnClickListener(passthroughClickListener);
bodyText.setOnLongClickListener(passthroughClickListener); bodyText.setOnLongClickListener(passthroughClickListener);
bodyText.setOnClickListener(passthroughClickListener); bodyText.setOnClickListener(passthroughClickListener);
} }
@ -192,9 +187,9 @@ public class ConversationItem extends LinearLayout
this.recipient.addListener(this); this.recipient.addListener(this);
this.conversationRecipients.addListener(this); this.conversationRecipients.addListener(this);
setInteractionState(messageRecord);
setBodyText(messageRecord); setBodyText(messageRecord);
setMediaAttributes(messageRecord); setMediaAttributes(messageRecord);
setInteractionState(messageRecord);
setBubbleState(messageRecord, recipient); setBubbleState(messageRecord, recipient);
setStatusIcons(messageRecord); setStatusIcons(messageRecord);
setContactPhoto(recipient); setContactPhoto(recipient);
@ -232,11 +227,11 @@ public class ConversationItem extends LinearLayout
private void setBubbleState(MessageRecord messageRecord, Recipient recipient) { private void setBubbleState(MessageRecord messageRecord, Recipient recipient) {
if (messageRecord.isOutgoing()) { if (messageRecord.isOutgoing()) {
bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY); bodyBubble.getBackground().setColorFilter(defaultBubbleColor, PorterDuff.Mode.MULTIPLY);
mediaThumbnail.setBackgroundColorHint(defaultBubbleColor); if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setBackgroundColorHint(defaultBubbleColor);
} else { } else {
int color = recipient.getColor().toConversationColor(context); int color = recipient.getColor().toConversationColor(context);
bodyBubble.getBackground().setColorFilter(color, PorterDuff.Mode.MULTIPLY); bodyBubble.getBackground().setColorFilter(color, PorterDuff.Mode.MULTIPLY);
mediaThumbnail.setBackgroundColorHint(color); if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setBackgroundColorHint(color);
} }
if (audioViewStub.resolved()) { if (audioViewStub.resolved()) {
@ -258,10 +253,13 @@ public class ConversationItem extends LinearLayout
private void setInteractionState(MessageRecord messageRecord) { private void setInteractionState(MessageRecord messageRecord) {
setSelected(batchSelected.contains(messageRecord)); setSelected(batchSelected.contains(messageRecord));
mediaThumbnail.setFocusable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty());
mediaThumbnail.setClickable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty());
mediaThumbnail.setLongClickable(batchSelected.isEmpty());
bodyText.setAutoLinkMask(batchSelected.isEmpty() ? Linkify.ALL : 0); bodyText.setAutoLinkMask(batchSelected.isEmpty() ? Linkify.ALL : 0);
if (mediaThumbnailStub.resolved()) {
mediaThumbnailStub.get().setFocusable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty());
mediaThumbnailStub.get().setClickable(!shouldInterceptClicks(messageRecord) && batchSelected.isEmpty());
mediaThumbnailStub.get().setLongClickable(batchSelected.isEmpty());
}
} }
private boolean isCaptionlessMms(MessageRecord messageRecord) { private boolean isCaptionlessMms(MessageRecord messageRecord) {
@ -296,14 +294,14 @@ public class ConversationItem extends LinearLayout
boolean showControls = !messageRecord.isFailed() && (!messageRecord.isOutgoing() || messageRecord.isPending()); boolean showControls = !messageRecord.isFailed() && (!messageRecord.isOutgoing() || messageRecord.isPending());
if (messageRecord.isMmsNotification()) { if (messageRecord.isMmsNotification()) {
mediaThumbnail.setVisibility(View.GONE); if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
setNotificationMmsAttributes((NotificationMmsMessageRecord) messageRecord); setNotificationMmsAttributes((NotificationMmsMessageRecord) messageRecord);
} else if (hasAudio(messageRecord)) { } else if (hasAudio(messageRecord)) {
audioViewStub.get().setVisibility(View.VISIBLE); audioViewStub.get().setVisibility(View.VISIBLE);
mediaThumbnail.setVisibility(View.GONE); if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
//noinspection ConstantConditions //noinspection ConstantConditions
audioViewStub.get().setAudio(masterSecret, ((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide(), showControls); audioViewStub.get().setAudio(masterSecret, ((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide(), showControls);
@ -312,17 +310,22 @@ public class ConversationItem extends LinearLayout
bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
} else if (hasThumbnail(messageRecord)) { } else if (hasThumbnail(messageRecord)) {
mediaThumbnail.setVisibility(View.VISIBLE); mediaThumbnailStub.get().setVisibility(View.VISIBLE);
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
//noinspection ConstantConditions //noinspection ConstantConditions
mediaThumbnail.setImageResource(masterSecret, mediaThumbnailStub.get().setImageResource(masterSecret,
((MediaMmsMessageRecord)messageRecord).getSlideDeck().getThumbnailSlide(), ((MediaMmsMessageRecord)messageRecord).getSlideDeck().getThumbnailSlide(),
showControls); showControls);
mediaThumbnailStub.get().setThumbnailClickListener(new ThumbnailClickListener());
mediaThumbnailStub.get().setDownloadClickListener(downloadClickListener);
mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener);
mediaThumbnailStub.get().setOnClickListener(passthroughClickListener);
bodyText.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); bodyText.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT));
} else { } else {
mediaThumbnail.setVisibility(View.GONE); if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE);
if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE);
bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT));
} }
} }