From e270e8d429acd3e84fc3e74f79b3a56f731645c6 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Fri, 20 Jan 2017 09:11:40 -0800 Subject: [PATCH] ViewStub for AudioView in ConversationItems // FREEBIE --- res/layout/conversation_item_received.xml | 11 ++--- .../conversation_item_received_audio.xml | 12 +++++ res/layout/conversation_item_sent.xml | 10 ++-- res/layout/conversation_item_sent_audio.xml | 10 ++++ .../securesms/ConversationAdapter.java | 31 ++++++++---- .../securesms/ConversationItem.java | 47 +++++++++++-------- .../securesms/util/views/Stub.java | 6 ++- 7 files changed, 83 insertions(+), 44 deletions(-) create mode 100644 res/layout/conversation_item_received_audio.xml create mode 100644 res/layout/conversation_item_sent_audio.xml diff --git a/res/layout/conversation_item_received.xml b/res/layout/conversation_item_received.xml index 6d45ef9fd6..f2fc4196fb 100644 --- a/res/layout/conversation_item_received.xml +++ b/res/layout/conversation_item_received.xml @@ -60,14 +60,11 @@ tools:src="@drawable/ic_video_light" tools:visibility="gone" /> - + android:layout_height="wrap_content"/> + diff --git a/res/layout/conversation_item_sent.xml b/res/layout/conversation_item_sent.xml index 3e89b7a9ab..b0ef521bad 100644 --- a/res/layout/conversation_item_sent.xml +++ b/res/layout/conversation_item_sent.xml @@ -51,13 +51,11 @@ tools:src="@drawable/ic_video_light" tools:visibility="visible" /> - + android:layout_height="wrap_content"/> + diff --git a/src/org/thoughtcrime/securesms/ConversationAdapter.java b/src/org/thoughtcrime/securesms/ConversationAdapter.java index e98bbb2849..7cc3fd6f71 100644 --- a/src/org/thoughtcrime/securesms/ConversationAdapter.java +++ b/src/org/thoughtcrime/securesms/ConversationAdapter.java @@ -35,6 +35,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.MmsSmsColumns; import org.thoughtcrime.securesms.database.MmsSmsDatabase; import org.thoughtcrime.securesms.database.SmsDatabase; +import org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord; import org.thoughtcrime.securesms.database.model.MessageRecord; import org.thoughtcrime.securesms.recipients.Recipients; import org.thoughtcrime.securesms.util.LRUCache; @@ -63,9 +64,11 @@ public class ConversationAdapter private final Map> messageRecordCache = Collections.synchronizedMap(new LRUCache>(MAX_CACHE_SIZE)); - public static final int MESSAGE_TYPE_OUTGOING = 0; - public static final int MESSAGE_TYPE_INCOMING = 1; - public static final int MESSAGE_TYPE_UPDATE = 2; + private static final int MESSAGE_TYPE_OUTGOING = 0; + private static final int MESSAGE_TYPE_INCOMING = 1; + private static final int MESSAGE_TYPE_UPDATE = 2; + private static final int MESSAGE_TYPE_AUDIO_OUTGOING = 3; + private static final int MESSAGE_TYPE_AUDIO_INCOMING = 4; private final Set batchSelected = Collections.synchronizedSet(new HashSet()); @@ -168,10 +171,12 @@ public class ConversationAdapter private @LayoutRes int getLayoutForViewType(int viewType) { switch (viewType) { - case ConversationAdapter.MESSAGE_TYPE_OUTGOING: return R.layout.conversation_item_sent; - case ConversationAdapter.MESSAGE_TYPE_INCOMING: return R.layout.conversation_item_received; - case ConversationAdapter.MESSAGE_TYPE_UPDATE: return R.layout.conversation_item_update; - default: throw new IllegalArgumentException("unsupported item view type given to ConversationAdapter"); + case MESSAGE_TYPE_AUDIO_OUTGOING: + case MESSAGE_TYPE_OUTGOING: return R.layout.conversation_item_sent; + case MESSAGE_TYPE_AUDIO_INCOMING: + case MESSAGE_TYPE_INCOMING: return R.layout.conversation_item_received; + case MESSAGE_TYPE_UPDATE: return R.layout.conversation_item_update; + default: throw new IllegalArgumentException("unsupported item view type given to ConversationAdapter"); } } @@ -182,9 +187,11 @@ public class ConversationAdapter MessageRecord messageRecord = getMessageRecord(id, cursor, type); if (messageRecord.isGroupAction() || messageRecord.isCallLog() || messageRecord.isJoined() || - messageRecord.isExpirationTimerUpdate() || messageRecord.isEndSession() || messageRecord.isIdentityUpdate()) - { + messageRecord.isExpirationTimerUpdate() || messageRecord.isEndSession() || messageRecord.isIdentityUpdate()) { return MESSAGE_TYPE_UPDATE; + } else if (hasAudio(messageRecord)) { + if (messageRecord.isOutgoing()) return MESSAGE_TYPE_AUDIO_OUTGOING; + else return MESSAGE_TYPE_AUDIO_INCOMING; } else if (messageRecord.isOutgoing()) { return MESSAGE_TYPE_OUTGOING; } else { @@ -227,4 +234,10 @@ public class ConversationAdapter public Set getSelectedItems() { return Collections.unmodifiableSet(new HashSet<>(batchSelected)); } + + private boolean hasAudio(MessageRecord messageRecord) { + return messageRecord.isMms() && + !messageRecord.isMmsNotification() && + ((MediaMmsMessageRecord)messageRecord).getSlideDeck().getAudioSlide() != null; + } } diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java index ebf97f2546..7dad93b0da 100644 --- a/src/org/thoughtcrime/securesms/ConversationItem.java +++ b/src/org/thoughtcrime/securesms/ConversationItem.java @@ -33,6 +33,7 @@ import android.util.AttributeSet; import android.util.Log; import android.view.View; import android.view.ViewGroup; +import android.view.ViewStub; import android.widget.Button; import android.widget.ImageView; import android.widget.LinearLayout; @@ -70,6 +71,7 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.dualsim.SubscriptionInfoCompat; import org.thoughtcrime.securesms.util.dualsim.SubscriptionManagerCompat; +import org.thoughtcrime.securesms.util.views.Stub; import org.whispersystems.libsignal.util.guava.Optional; import java.util.HashSet; @@ -96,7 +98,7 @@ public class ConversationItem extends LinearLayout private boolean groupThread; private Recipient recipient; - private View bodyBubble; + protected View bodyBubble; private TextView bodyText; private TextView dateText; private TextView simInfoText; @@ -110,16 +112,19 @@ public class ConversationItem extends LinearLayout private @NonNull Set batchSelected = new HashSet<>(); private @Nullable Recipients conversationRecipients; private @NonNull ThumbnailView mediaThumbnail; - private @NonNull AudioView audioView; + private @NonNull Stub audioViewStub; private @NonNull Button mmsDownloadButton; private @NonNull TextView mmsDownloadingLabel; private @NonNull ExpirationTimerView expirationTimer; private int defaultBubbleColor; - private final MmsDownloadClickListener mmsDownloadClickListener = new MmsDownloadClickListener(); - private final MmsPreferencesClickListener mmsPreferencesClickListener = new MmsPreferencesClickListener(); - private final Context context; + private final MmsDownloadClickListener mmsDownloadClickListener = new MmsDownloadClickListener(); + private final MmsPreferencesClickListener mmsPreferencesClickListener = new MmsPreferencesClickListener(); + private final PassthroughClickListener passthroughClickListener = new PassthroughClickListener(); + private final AttachmentDownloadClickListener downloadClickListener = new AttachmentDownloadClickListener(); + + private final Context context; public ConversationItem(Context context) { this(context, null); @@ -154,20 +159,17 @@ public class ConversationItem extends LinearLayout this.contactPhoto = (AvatarImageView) findViewById(R.id.contact_photo); this.bodyBubble = findViewById(R.id.body_bubble); this.mediaThumbnail = (ThumbnailView) findViewById(R.id.image_view); - this.audioView = (AudioView) findViewById(R.id.audio_view); + this.audioViewStub = new Stub<>((ViewStub) findViewById(R.id.audio_view_stub)); this.expirationTimer = (ExpirationTimerView) findViewById(R.id.expiration_indicator); + setOnClickListener(new ClickListener(null)); - PassthroughClickListener passthroughClickListener = new PassthroughClickListener(); - AttachmentDownloadClickListener downloadClickListener = new AttachmentDownloadClickListener(); mmsDownloadButton.setOnClickListener(mmsDownloadClickListener); mediaThumbnail.setThumbnailClickListener(new ThumbnailClickListener()); mediaThumbnail.setDownloadClickListener(downloadClickListener); mediaThumbnail.setOnLongClickListener(passthroughClickListener); mediaThumbnail.setOnClickListener(passthroughClickListener); - audioView.setDownloadClickListener(downloadClickListener); - audioView.setOnLongClickListener(passthroughClickListener); bodyText.setOnLongClickListener(passthroughClickListener); bodyText.setOnClickListener(passthroughClickListener); } @@ -192,12 +194,12 @@ public class ConversationItem extends LinearLayout setInteractionState(messageRecord); setBodyText(messageRecord); + setMediaAttributes(messageRecord); setBubbleState(messageRecord, recipient); setStatusIcons(messageRecord); setContactPhoto(recipient); setGroupMessageStatus(messageRecord, recipient); setMinimumWidth(); - setMediaAttributes(messageRecord); setSimInfo(messageRecord); setExpiration(messageRecord); } @@ -237,18 +239,20 @@ public class ConversationItem extends LinearLayout mediaThumbnail.setBackgroundColorHint(color); } - setAudioViewTint(messageRecord, conversationRecipients); + if (audioViewStub.resolved()) { + setAudioViewTint(messageRecord, conversationRecipients); + } } private void setAudioViewTint(MessageRecord messageRecord, Recipients recipients) { if (messageRecord.isOutgoing()) { if (DynamicTheme.LIGHT.equals(TextSecurePreferences.getTheme(context))) { - audioView.setTint(recipients.getColor().toConversationColor(context), defaultBubbleColor); + audioViewStub.get().setTint(recipients.getColor().toConversationColor(context), defaultBubbleColor); } else { - audioView.setTint(Color.WHITE, defaultBubbleColor); + audioViewStub.get().setTint(Color.WHITE, defaultBubbleColor); } } else { - audioView.setTint(Color.WHITE, recipients.getColor().toConversationColor(context)); + audioViewStub.get().setTint(Color.WHITE, recipients.getColor().toConversationColor(context)); } } @@ -293,20 +297,23 @@ public class ConversationItem extends LinearLayout if (messageRecord.isMmsNotification()) { mediaThumbnail.setVisibility(View.GONE); - audioView.setVisibility(View.GONE); + if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); setNotificationMmsAttributes((NotificationMmsMessageRecord) messageRecord); } else if (hasAudio(messageRecord)) { - audioView.setVisibility(View.VISIBLE); + audioViewStub.get().setVisibility(View.VISIBLE); mediaThumbnail.setVisibility(View.GONE); //noinspection ConstantConditions - audioView.setAudio(masterSecret, ((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide(), showControls); + audioViewStub.get().setAudio(masterSecret, ((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide(), showControls); + audioViewStub.get().setDownloadClickListener(downloadClickListener); + audioViewStub.get().setOnLongClickListener(passthroughClickListener); + bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)); } else if (hasThumbnail(messageRecord)) { mediaThumbnail.setVisibility(View.VISIBLE); - audioView.setVisibility(View.GONE); + if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); //noinspection ConstantConditions mediaThumbnail.setImageResource(masterSecret, @@ -315,7 +322,7 @@ public class ConversationItem extends LinearLayout bodyText.setLayoutParams(new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT)); } else { mediaThumbnail.setVisibility(View.GONE); - audioView.setVisibility(View.GONE); + if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); bodyText.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); } } diff --git a/src/org/thoughtcrime/securesms/util/views/Stub.java b/src/org/thoughtcrime/securesms/util/views/Stub.java index 2051df0d0b..b208bdc62d 100644 --- a/src/org/thoughtcrime/securesms/util/views/Stub.java +++ b/src/org/thoughtcrime/securesms/util/views/Stub.java @@ -1,20 +1,22 @@ package org.thoughtcrime.securesms.util.views; +import android.support.annotation.NonNull; import android.view.ViewStub; public class Stub { - private final ViewStub viewStub; + private ViewStub viewStub; private T view; - public Stub(ViewStub viewStub) { + public Stub(@NonNull ViewStub viewStub) { this.viewStub = viewStub; } public T get() { if (view == null) { view = (T)viewStub.inflate(); + viewStub = null; } return view;