From 740977164bcb00ab82e497bf407c8360b562033c Mon Sep 17 00:00:00 2001 From: Alex Hart Date: Fri, 23 Jul 2021 13:47:43 -0300 Subject: [PATCH] Apply several fixes for beta feedback. * Remove overscroll from avatar picker recyclers. * Center crop wallpaper previews. * If no media thumb exists, return bubble projection instead. --- .../conversation/ConversationAdapter.java | 4 +- .../conversation/ConversationItem.java | 173 +++++++++--------- .../ConversationItemMaskTarget.java | 3 +- .../conversation/ConversationUpdateItem.java | 2 +- .../securesms/giph/mp4/GiphyMp4Playable.java | 2 +- .../giph/mp4/GiphyMp4ProjectionRecycler.java | 3 +- .../giph/mp4/GiphyMp4ViewHolder.java | 2 +- .../MessageHeaderViewHolder.java | 6 +- .../securesms/util/views/NullableStub.java | 40 ++++ .../res/layout/avatar_picker_fragment.xml | 1 + ...lpaper_selection_fragment_adapter_item.xml | 2 +- .../text_avatar_creation_fragment_content.xml | 1 + ...ation_fragment_content_hidden_recycler.xml | 1 + .../vector_avatar_creation_fragment.xml | 1 + 14 files changed, 138 insertions(+), 103 deletions(-) create mode 100644 app/src/main/java/org/thoughtcrime/securesms/util/views/NullableStub.java diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationAdapter.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationAdapter.java index 3de00d869d..6b08f5bf96 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationAdapter.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationAdapter.java @@ -700,8 +700,8 @@ public class ConversationAdapter } @NonNull - public @Override Projection getProjection(@NonNull ViewGroup recyclerView) { - return getBindable().getProjection(recyclerView); + public @Override Projection getGiphyMp4PlayableProjection(@NonNull ViewGroup recyclerView) { + return getBindable().getGiphyMp4PlayableProjection(recyclerView); } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java index b84045a0eb..d38c2868b1 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -128,6 +128,7 @@ import org.thoughtcrime.securesms.util.UrlClickHandler; import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.VibrateUtil; import org.thoughtcrime.securesms.util.ViewUtil; +import org.thoughtcrime.securesms.util.views.NullableStub; import org.thoughtcrime.securesms.util.views.Stub; import org.thoughtcrime.securesms.video.exo.AttachmentMediaSourceFactory; import org.whispersystems.libsignal.util.guava.Optional; @@ -184,19 +185,19 @@ public final class ConversationItem extends RelativeLayout implements BindableCo private AlertView alertView; protected ReactionsConversationView reactionsView; - private @NonNull Set batchSelected = new HashSet<>(); - private @NonNull Outliner outliner = new Outliner(); - private @NonNull Outliner pulseOutliner = new Outliner(); - private @NonNull List outliners = new ArrayList<>(2); - private LiveRecipient conversationRecipient; - private Stub mediaThumbnailStub; - private Stub audioViewStub; - private Stub documentViewStub; - private Stub sharedContactStub; - private Stub linkPreviewStub; - private Stub stickerStub; - private Stub revealableStub; - private @Nullable EventListener eventListener; + private @NonNull Set batchSelected = new HashSet<>(); + private @NonNull Outliner outliner = new Outliner(); + private @NonNull Outliner pulseOutliner = new Outliner(); + private @NonNull List outliners = new ArrayList<>(2); + private LiveRecipient conversationRecipient; + private NullableStub mediaThumbnailStub; + private Stub audioViewStub; + private Stub documentViewStub; + private Stub sharedContactStub; + private Stub linkPreviewStub; + private Stub stickerStub; + private Stub revealableStub; + private @Nullable EventListener eventListener; private int defaultBubbleColor; private int defaultBubbleColorForWallpaper; @@ -243,26 +244,26 @@ public final class ConversationItem extends RelativeLayout implements BindableCo this.backgroundDrawable = new ClipProjectionDrawable(Objects.requireNonNull(ContextCompat.getDrawable(getContext(), R.drawable.conversation_item_background))); - this.bodyText = findViewById(R.id.conversation_item_body); - this.footer = findViewById(R.id.conversation_item_footer); - this.stickerFooter = findViewById(R.id.conversation_item_sticker_footer); - this.groupSender = findViewById(R.id.group_message_sender); - this.alertView = findViewById(R.id.indicators_parent); - this.contactPhoto = findViewById(R.id.contact_photo); - this.contactPhotoHolder = findViewById(R.id.contact_photo_container); - this.bodyBubble = findViewById(R.id.body_bubble); - this.mediaThumbnailStub = new Stub<>(findViewById(R.id.image_view_stub)); - this.audioViewStub = new Stub<>(findViewById(R.id.audio_view_stub)); - this.documentViewStub = new Stub<>(findViewById(R.id.document_view_stub)); - this.sharedContactStub = new Stub<>(findViewById(R.id.shared_contact_view_stub)); - this.linkPreviewStub = new Stub<>(findViewById(R.id.link_preview_stub)); - this.stickerStub = new Stub<>(findViewById(R.id.sticker_view_stub)); - this.revealableStub = new Stub<>(findViewById(R.id.revealable_view_stub)); - this.groupSenderHolder = findViewById(R.id.group_sender_holder); - this.quoteView = findViewById(R.id.quote_view); - this.reply = findViewById(R.id.reply_icon_wrapper); - this.replyIcon = findViewById(R.id.reply_icon); - this.reactionsView = findViewById(R.id.reactions_view); + this.bodyText = findViewById(R.id.conversation_item_body); + this.footer = findViewById(R.id.conversation_item_footer); + this.stickerFooter = findViewById(R.id.conversation_item_sticker_footer); + this.groupSender = findViewById(R.id.group_message_sender); + this.alertView = findViewById(R.id.indicators_parent); + this.contactPhoto = findViewById(R.id.contact_photo); + this.contactPhotoHolder = findViewById(R.id.contact_photo_container); + this.bodyBubble = findViewById(R.id.body_bubble); + this.mediaThumbnailStub = new NullableStub<>(findViewById(R.id.image_view_stub)); + this.audioViewStub = new Stub<>(findViewById(R.id.audio_view_stub)); + this.documentViewStub = new Stub<>(findViewById(R.id.document_view_stub)); + this.sharedContactStub = new Stub<>(findViewById(R.id.shared_contact_view_stub)); + this.linkPreviewStub = new Stub<>(findViewById(R.id.link_preview_stub)); + this.stickerStub = new Stub<>(findViewById(R.id.sticker_view_stub)); + this.revealableStub = new Stub<>(findViewById(R.id.revealable_view_stub)); + this.groupSenderHolder = findViewById(R.id.group_sender_holder); + this.quoteView = findViewById(R.id.quote_view); + this.reply = findViewById(R.id.reply_icon_wrapper); + this.replyIcon = findViewById(R.id.reply_icon); + this.reactionsView = findViewById(R.id.reactions_view); setOnClickListener(new ClickListener(null)); @@ -425,7 +426,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo if (hasAudio(messageRecord)) { availableWidth = audioViewStub.get().getMeasuredWidth() + ViewUtil.getLeftMargin(audioViewStub.get()) + ViewUtil.getRightMargin(audioViewStub.get()); } else if (!isViewOnceMessage(messageRecord) && (hasThumbnail(messageRecord) || hasBigImageLinkPreview(messageRecord))) { - availableWidth = mediaThumbnailStub.get().getMeasuredWidth(); + availableWidth = mediaThumbnailStub.require().getMeasuredWidth(); } else { availableWidth = bodyBubble.getMeasuredWidth() - bodyBubble.getPaddingLeft() - bodyBubble.getPaddingRight(); } @@ -507,7 +508,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo bodyBubble.setOutliners(outliners); if (mediaThumbnailStub.resolved()) { - mediaThumbnailStub.get().setPulseOutliner(pulseOutliner); + mediaThumbnailStub.require().setPulseOutliner(pulseOutliner); } if (audioViewStub.resolved()) { @@ -550,9 +551,9 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } if (mediaThumbnailStub.resolved()) { - mediaThumbnailStub.get().setFocusable(!shouldInterceptClicks(conversationMessage.getMessageRecord()) && batchSelected.isEmpty()); - mediaThumbnailStub.get().setClickable(!shouldInterceptClicks(conversationMessage.getMessageRecord()) && batchSelected.isEmpty()); - mediaThumbnailStub.get().setLongClickable(batchSelected.isEmpty()); + mediaThumbnailStub.require().setFocusable(!shouldInterceptClicks(conversationMessage.getMessageRecord()) && batchSelected.isEmpty()); + mediaThumbnailStub.require().setClickable(!shouldInterceptClicks(conversationMessage.getMessageRecord()) && batchSelected.isEmpty()); + mediaThumbnailStub.require().setLongClickable(batchSelected.isEmpty()); } if (audioViewStub.resolved()) { @@ -574,7 +575,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo bodyBubble.invalidate(); if (mediaThumbnailStub.resolved()) { - mediaThumbnailStub.get().invalidate(); + mediaThumbnailStub.require().invalidate(); } }); pulseOutlinerAlphaAnimator.start(); @@ -752,7 +753,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo if (isViewOnceMessage(messageRecord) && !messageRecord.isRemoteDelete()) { revealableStub.get().setVisibility(VISIBLE); - if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); + if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE); @@ -767,7 +768,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } else if (hasSharedContact(messageRecord)) { sharedContactStub.get().setVisibility(VISIBLE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); - if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); + if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE); if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); @@ -786,7 +787,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } else if (hasLinkPreview(messageRecord) && messageRequestAccepted) { linkPreviewStub.get().setVisibility(View.VISIBLE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); - if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); + if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE); if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); @@ -796,12 +797,12 @@ public final class ConversationItem extends RelativeLayout implements BindableCo LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0); if (hasBigImageLinkPreview(messageRecord)) { - mediaThumbnailStub.get().setVisibility(VISIBLE); - mediaThumbnailStub.get().setMinimumThumbnailWidth(readDimen(R.dimen.media_bubble_min_width_with_content)); - mediaThumbnailStub.get().setImageResource(glideRequests, Collections.singletonList(new ImageSlide(context, linkPreview.getThumbnail().get())), showControls, false); - mediaThumbnailStub.get().setThumbnailClickListener(new LinkPreviewThumbnailClickListener()); - mediaThumbnailStub.get().setDownloadClickListener(downloadClickListener); - mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener); + mediaThumbnailStub.require().setVisibility(VISIBLE); + mediaThumbnailStub.require().setMinimumThumbnailWidth(readDimen(R.dimen.media_bubble_min_width_with_content)); + mediaThumbnailStub.require().setImageResource(glideRequests, Collections.singletonList(new ImageSlide(context, linkPreview.getThumbnail().get())), showControls, false); + mediaThumbnailStub.require().setThumbnailClickListener(new LinkPreviewThumbnailClickListener()); + mediaThumbnailStub.require().setDownloadClickListener(downloadClickListener); + mediaThumbnailStub.require().setOnLongClickListener(passthroughClickListener); linkPreviewStub.get().setLinkPreview(glideRequests, linkPreview, false); @@ -825,7 +826,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo footer.setVisibility(VISIBLE); } else if (hasAudio(messageRecord)) { audioViewStub.get().setVisibility(View.VISIBLE); - if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); + if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE); if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE); @@ -850,7 +851,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo footer.setVisibility(VISIBLE); } else if (hasDocument(messageRecord)) { documentViewStub.get().setVisibility(View.VISIBLE); - if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); + if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE); if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE); @@ -871,7 +872,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo bodyBubble.setBackgroundColor(Color.TRANSPARENT); stickerStub.get().setVisibility(View.VISIBLE); - if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); + if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE); @@ -897,7 +898,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo footer.setVisibility(VISIBLE); } else if (hasThumbnail(messageRecord)) { - mediaThumbnailStub.get().setVisibility(View.VISIBLE); + mediaThumbnailStub.require().setVisibility(View.VISIBLE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE); @@ -906,25 +907,25 @@ public final class ConversationItem extends RelativeLayout implements BindableCo if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE); List thumbnailSlides = ((MmsMessageRecord) messageRecord).getSlideDeck().getThumbnailSlides(); - mediaThumbnailStub.get().setMinimumThumbnailWidth(readDimen(isCaptionlessMms(messageRecord) ? R.dimen.media_bubble_min_width_solo + mediaThumbnailStub.require().setMinimumThumbnailWidth(readDimen(isCaptionlessMms(messageRecord) ? R.dimen.media_bubble_min_width_solo : R.dimen.media_bubble_min_width_with_content)); - mediaThumbnailStub.get().setImageResource(glideRequests, + mediaThumbnailStub.require().setImageResource(glideRequests, thumbnailSlides, showControls, false); - mediaThumbnailStub.get().setThumbnailClickListener(new ThumbnailClickListener()); - mediaThumbnailStub.get().setDownloadClickListener(downloadClickListener); - mediaThumbnailStub.get().setOnLongClickListener(passthroughClickListener); - mediaThumbnailStub.get().setOnClickListener(passthroughClickListener); - mediaThumbnailStub.get().showShade(TextUtils.isEmpty(messageRecord.getDisplayBody(getContext())) && !hasExtraText(messageRecord)); + mediaThumbnailStub.require().setThumbnailClickListener(new ThumbnailClickListener()); + mediaThumbnailStub.require().setDownloadClickListener(downloadClickListener); + mediaThumbnailStub.require().setOnLongClickListener(passthroughClickListener); + mediaThumbnailStub.require().setOnClickListener(passthroughClickListener); + mediaThumbnailStub.require().showShade(TextUtils.isEmpty(messageRecord.getDisplayBody(getContext())) && !hasExtraText(messageRecord)); if (!messageRecord.isOutgoing()) { - mediaThumbnailStub.get().setConversationColor(getDefaultBubbleColor(hasWallpaper)); + mediaThumbnailStub.require().setConversationColor(getDefaultBubbleColor(hasWallpaper)); } else { - mediaThumbnailStub.get().setConversationColor(Color.TRANSPARENT); + mediaThumbnailStub.require().setConversationColor(Color.TRANSPARENT); } - mediaThumbnailStub.get().setBorderless(false); + mediaThumbnailStub.require().setBorderless(false); setThumbnailCorners(messageRecord, previousRecord, nextRecord, isGroupThread); @@ -949,7 +950,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } } else { - if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().setVisibility(View.GONE); + if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().setVisibility(View.GONE); if (audioViewStub.resolved()) audioViewStub.get().setVisibility(View.GONE); if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE); @@ -1025,9 +1026,9 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } if (ViewUtil.isRtl(this)) { - mediaThumbnailStub.get().setCorners(topEnd, topStart, bottomStart, bottomEnd); + mediaThumbnailStub.require().setCorners(topEnd, topStart, bottomStart, bottomEnd); } else { - mediaThumbnailStub.get().setCorners(topStart, topEnd, bottomEnd, bottomStart); + mediaThumbnailStub.require().setCorners(topStart, topEnd, bottomEnd, bottomStart); } } @@ -1161,7 +1162,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } if (mediaThumbnailStub.resolved()) { - ViewUtil.setTopMargin(mediaThumbnailStub.get(), readDimen(R.dimen.message_bubble_top_padding)); + ViewUtil.setTopMargin(mediaThumbnailStub.require(), readDimen(R.dimen.message_bubble_top_padding)); } else if (startOfCluster && !current.isOutgoing() && groupThread) { ViewUtil.setTopMargin(quoteView, readDimen(R.dimen.message_bubble_quote_negative_margin)); } else { @@ -1177,7 +1178,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } if (mediaThumbnailStub.resolved()) { - ViewUtil.setTopMargin(mediaThumbnailStub.get(), 0); + ViewUtil.setTopMargin(mediaThumbnailStub.require(), 0); } } } @@ -1219,7 +1220,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo footer.setVisibility(GONE); stickerFooter.setVisibility(GONE); if (sharedContactStub.resolved()) sharedContactStub.get().getFooter().setVisibility(GONE); - if (mediaThumbnailStub.resolved()) mediaThumbnailStub.get().getFooter().setVisibility(GONE); + if (mediaThumbnailStub.resolved()) mediaThumbnailStub.require().getFooter().setVisibility(GONE); boolean differentTimestamps = next.isPresent() && !DateUtils.isSameExtendedRelativeTimestamp(context, locale, next.get().getTimestamp(), current.getTimestamp()); @@ -1260,7 +1261,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } else if (hasSharedContact(messageRecord) && TextUtils.isEmpty(messageRecord.getDisplayBody(getContext()))) { return sharedContactStub.get().getFooter(); } else if (hasOnlyThumbnail(messageRecord) && TextUtils.isEmpty(messageRecord.getDisplayBody(getContext()))) { - return mediaThumbnailStub.get().getFooter(); + return mediaThumbnailStub.require().getFooter(); } else { return footer; } @@ -1494,7 +1495,7 @@ public final class ConversationItem extends RelativeLayout implements BindableCo @Override public void showProjectionArea() { if (mediaThumbnailStub != null && mediaThumbnailStub.resolved()) { - mediaThumbnailStub.get().showThumbnailView(); + mediaThumbnailStub.require().showThumbnailView(); bodyBubble.setVideoPlayerProjection(null); updateSelectedBackgroundDrawableProjections(); } @@ -1503,9 +1504,9 @@ public final class ConversationItem extends RelativeLayout implements BindableCo @Override public void hideProjectionArea() { if (mediaThumbnailStub != null && mediaThumbnailStub.resolved()) { - mediaThumbnailStub.get().hideThumbnailView(); - mediaThumbnailStub.get().getDrawingRect(thumbnailMaskingRect); - bodyBubble.setVideoPlayerProjection(Projection.relativeToViewWithCommonRoot(mediaThumbnailStub.get(), bodyBubble, null)); + mediaThumbnailStub.require().hideThumbnailView(); + mediaThumbnailStub.require().getDrawingRect(thumbnailMaskingRect); + bodyBubble.setVideoPlayerProjection(Projection.relativeToViewWithCommonRoot(mediaThumbnailStub.require(), bodyBubble, null)); updateSelectedBackgroundDrawableProjections(); } } @@ -1532,27 +1533,19 @@ public final class ConversationItem extends RelativeLayout implements BindableCo } @Override - public @NonNull Projection getProjection(@NonNull ViewGroup recyclerView) { - return Projection.relativeToParent(recyclerView, mediaThumbnailStub.get(), mediaThumbnailStub.get().getCorners()) - .translateX(bodyBubble.getTranslationX()); + public @NonNull Projection getGiphyMp4PlayableProjection(@NonNull ViewGroup recyclerView) { + if (mediaThumbnailStub != null && mediaThumbnailStub.isResolvable()) { + return Projection.relativeToParent(recyclerView, mediaThumbnailStub.require(), mediaThumbnailStub.require().getCorners()) + .translateX(bodyBubble.getTranslationX()); + } else { + return Projection.relativeToParent(recyclerView, bodyBubble, bodyBubbleCorners) + .translateX(bodyBubble.getTranslationX()); + } } @Override public boolean canPlayContent() { - return mediaThumbnailStub != null && canPlayContent; - } - - public @NonNull Rect getThumbnailMaskingRect(@NonNull ViewGroup parent) { - Rect rect = new Rect(); - rect.set(thumbnailMaskingRect); - - parent.offsetDescendantRectToMyCoords(mediaThumbnailStub.get(), rect); - - return rect; - } - - public @NonNull Projection.Corners getThumbnailCorners() { - return mediaThumbnailStub.get().getCorners(); + return mediaThumbnailStub != null && mediaThumbnailStub.isResolvable() && canPlayContent; } @Override diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemMaskTarget.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemMaskTarget.java index 3c4fa1f164..fa69e41f68 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemMaskTarget.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItemMaskTarget.java @@ -3,7 +3,6 @@ package org.thoughtcrime.securesms.conversation; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; -import android.graphics.Path; import android.view.View; import androidx.annotation.NonNull; @@ -57,7 +56,7 @@ public final class ConversationItemMaskTarget extends MaskView.MaskTarget { ).toList(); if (videoContainer != null) { - projections.add(conversationItem.getProjection((RecyclerView) conversationItem.getParent())); + projections.add(conversationItem.getGiphyMp4PlayableProjection((RecyclerView) conversationItem.getParent())); } for (Projection projection : projections) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java index f21c4d499f..d6fd72ade8 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationUpdateItem.java @@ -209,7 +209,7 @@ public final class ConversationUpdateItem extends FrameLayout } @Override - public @NonNull Projection getProjection(@NonNull ViewGroup recyclerView) { + public @NonNull Projection getGiphyMp4PlayableProjection(@NonNull ViewGroup recyclerView) { throw new UnsupportedOperationException("ConversationUpdateItems cannot be projected into."); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4Playable.java b/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4Playable.java index 237f897424..e651fa43bc 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4Playable.java +++ b/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4Playable.java @@ -45,7 +45,7 @@ public interface GiphyMp4Playable { * Width, height, and (x,y) of view which video player will "project" into * @param viewGroup */ - @NonNull Projection getProjection(@NonNull ViewGroup viewGroup); + @NonNull Projection getGiphyMp4PlayableProjection(@NonNull ViewGroup viewGroup); /** * Specifies whether the content can start playing. diff --git a/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4ProjectionRecycler.java b/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4ProjectionRecycler.java index 3fa726d5c1..72b6141c09 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4ProjectionRecycler.java +++ b/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4ProjectionRecycler.java @@ -8,7 +8,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import androidx.recyclerview.widget.RecyclerView; -import org.thoughtcrime.securesms.conversation.ConversationItemSwipeCallback; import org.thoughtcrime.securesms.util.Projection; import java.util.ArrayList; @@ -86,7 +85,7 @@ public final class GiphyMp4ProjectionRecycler implements GiphyMp4PlaybackControl } private void updateDisplay(@NonNull RecyclerView recyclerView, @NonNull GiphyMp4ProjectionPlayerHolder holder, @NonNull GiphyMp4Playable giphyMp4Playable) { - Projection projection = giphyMp4Playable.getProjection(recyclerView); + Projection projection = giphyMp4Playable.getGiphyMp4PlayableProjection(recyclerView); holder.getContainer().setX(projection.getX()); holder.getContainer().setY(projection.getY()); diff --git a/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4ViewHolder.java b/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4ViewHolder.java index c2935f8a1e..79bb4470c7 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4ViewHolder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/giph/mp4/GiphyMp4ViewHolder.java @@ -82,7 +82,7 @@ final class GiphyMp4ViewHolder extends RecyclerView.ViewHolder implements GiphyM } @Override - public @NonNull Projection getProjection(@NonNull ViewGroup recyclerView) { + public @NonNull Projection getGiphyMp4PlayableProjection(@NonNull ViewGroup recyclerView) { return Projection.relativeToParent(recyclerView, container, CORNERS); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageHeaderViewHolder.java b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageHeaderViewHolder.java index 1bad3ea0d6..854a123aa9 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageHeaderViewHolder.java +++ b/app/src/main/java/org/thoughtcrime/securesms/messagedetails/MessageHeaderViewHolder.java @@ -238,8 +238,8 @@ final class MessageHeaderViewHolder extends RecyclerView.ViewHolder implements G } @Override - public @NonNull Projection getProjection(@NonNull ViewGroup recyclerview) { - return conversationItem.getProjection(recyclerview); + public @NonNull Projection getGiphyMp4PlayableProjection(@NonNull ViewGroup recyclerview) { + return conversationItem.getGiphyMp4PlayableProjection(recyclerview); } @Override public @@ -257,7 +257,7 @@ final class MessageHeaderViewHolder extends RecyclerView.ViewHolder implements G Set projections = new HashSet<>(); if (canPlayContent()) { - projections.add(conversationItem.getProjection((ViewGroup) itemView)); + projections.add(conversationItem.getGiphyMp4PlayableProjection((ViewGroup) itemView)); } projections.addAll(Stream.of(conversationItem.getColorizerProjections()) diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/views/NullableStub.java b/app/src/main/java/org/thoughtcrime/securesms/util/views/NullableStub.java new file mode 100644 index 0000000000..95bbbd24fc --- /dev/null +++ b/app/src/main/java/org/thoughtcrime/securesms/util/views/NullableStub.java @@ -0,0 +1,40 @@ +package org.thoughtcrime.securesms.util.views; + + +import android.view.ViewStub; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.Objects; + +public class NullableStub { + + private ViewStub viewStub; + private T view; + + public NullableStub(@Nullable ViewStub viewStub) { + this.viewStub = viewStub; + } + + private @Nullable T get() { + if (viewStub != null && view == null) { + view = (T) viewStub.inflate(); + viewStub = null; + } + + return view; + } + + public @NonNull T require() { + return Objects.requireNonNull(get()); + } + + public boolean isResolvable() { + return viewStub != null || resolved(); + } + + public boolean resolved() { + return view != null; + } +} diff --git a/app/src/main/res/layout/avatar_picker_fragment.xml b/app/src/main/res/layout/avatar_picker_fragment.xml index 2dc4005a8e..14a631aeb3 100644 --- a/app/src/main/res/layout/avatar_picker_fragment.xml +++ b/app/src/main/res/layout/avatar_picker_fragment.xml @@ -112,6 +112,7 @@ android:clipChildren="false" android:clipToPadding="false" android:paddingBottom="80dp" + android:overScrollMode="never" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" diff --git a/app/src/main/res/layout/chat_wallpaper_selection_fragment_adapter_item.xml b/app/src/main/res/layout/chat_wallpaper_selection_fragment_adapter_item.xml index 025852593f..79928af081 100644 --- a/app/src/main/res/layout/chat_wallpaper_selection_fragment_adapter_item.xml +++ b/app/src/main/res/layout/chat_wallpaper_selection_fragment_adapter_item.xml @@ -14,7 +14,7 @@ android:id="@+id/chat_wallpaper_preview" android:layout_width="match_parent" android:layout_height="match_parent" - android:scaleType="fitXY" + android:scaleType="centerCrop" app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.Signal.WallpaperPreview" tools:src="@drawable/test_gradient" /> diff --git a/app/src/main/res/layout/text_avatar_creation_fragment_content.xml b/app/src/main/res/layout/text_avatar_creation_fragment_content.xml index 11ecf2e572..8469abc953 100644 --- a/app/src/main/res/layout/text_avatar_creation_fragment_content.xml +++ b/app/src/main/res/layout/text_avatar_creation_fragment_content.xml @@ -53,6 +53,7 @@ android:layout_marginEnd="@dimen/dsl_settings_gutter" android:clipChildren="false" android:clipToPadding="false" + android:overScrollMode="never" android:paddingBottom="80dp" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layout_constraintBottom_toBottomOf="parent" diff --git a/app/src/main/res/layout/text_avatar_creation_fragment_content_hidden_recycler.xml b/app/src/main/res/layout/text_avatar_creation_fragment_content_hidden_recycler.xml index c592549fa8..2cfef427ac 100644 --- a/app/src/main/res/layout/text_avatar_creation_fragment_content_hidden_recycler.xml +++ b/app/src/main/res/layout/text_avatar_creation_fragment_content_hidden_recycler.xml @@ -52,6 +52,7 @@ android:layout_marginEnd="@dimen/dsl_settings_gutter" android:clipChildren="false" android:clipToPadding="false" + android:overScrollMode="never" android:paddingBottom="80dp" android:visibility="gone" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" diff --git a/app/src/main/res/layout/vector_avatar_creation_fragment.xml b/app/src/main/res/layout/vector_avatar_creation_fragment.xml index 55816e7fa0..8fd0826e72 100644 --- a/app/src/main/res/layout/vector_avatar_creation_fragment.xml +++ b/app/src/main/res/layout/vector_avatar_creation_fragment.xml @@ -87,6 +87,7 @@ android:layout_marginEnd="@dimen/dsl_settings_gutter" android:clipChildren="false" android:clipToPadding="false" + android:overScrollMode="never" android:paddingBottom="80dp" app:layoutManager="androidx.recyclerview.widget.GridLayoutManager" app:layout_constraintBottom_toBottomOf="parent"