From c78e098cb4260fab2aa8a26f33117e32b565b04c Mon Sep 17 00:00:00 2001 From: Greyson Parrelli Date: Tue, 25 Aug 2020 16:05:39 -0400 Subject: [PATCH] Add support for link preview descriptions. --- .../components/ConversationItemThumbnail.java | 4 ++ .../securesms/components/LinkPreviewView.java | 38 +++++++++++++++---- .../securesms/components/ThumbnailView.java | 5 +++ .../conversation/ConversationItem.java | 19 ++++++++-- .../securesms/database/MmsDatabase.java | 4 +- .../securesms/jobs/PushProcessMessageJob.java | 9 +++-- .../securesms/jobs/PushSendJob.java | 2 +- .../securesms/linkpreview/LinkPreview.java | 25 ++++++++---- .../linkpreview/LinkPreviewRepository.java | 35 ++++++++++------- .../linkpreview/LinkPreviewUtil.java | 9 ++++- .../conversation_item_received_thumbnail.xml | 2 +- .../conversation_item_sent_thumbnail.xml | 2 +- app/src/main/res/layout/link_preview.xml | 23 +++++++++-- app/src/main/res/layout/sticker_view.xml | 2 +- app/src/main/res/values/dimens.xml | 3 +- .../api/SignalServiceMessageSender.java | 1 + .../api/messages/SignalServiceContent.java | 5 ++- .../messages/SignalServiceDataMessage.java | 14 +++++-- .../src/main/proto/SignalService.proto | 7 ++-- 19 files changed, 151 insertions(+), 58 deletions(-) diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemThumbnail.java b/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemThumbnail.java index 563ad6d6e..95c8fe6ba 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemThumbnail.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ConversationItemThumbnail.java @@ -119,6 +119,10 @@ public class ConversationItemThumbnail extends FrameLayout { outliner.setRadii(topLeft, topRight, bottomRight, bottomLeft); } + public void setMinimumThumbnailWidth(int width) { + thumbnail.setMinimumThumbnailWidth(width); + } + public void setBorderless(boolean borderless) { this.borderless = borderless; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/LinkPreviewView.java b/app/src/main/java/org/thoughtcrime/securesms/components/LinkPreviewView.java index 8537ea44e..4d17513af 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/LinkPreviewView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/LinkPreviewView.java @@ -21,11 +21,12 @@ import org.thoughtcrime.securesms.mms.GlideRequests; import org.thoughtcrime.securesms.mms.ImageSlide; import org.thoughtcrime.securesms.mms.SlidesClickedListener; import org.thoughtcrime.securesms.util.ThemeUtil; +import org.thoughtcrime.securesms.util.Util; import okhttp3.HttpUrl; /** - * The view shown in the compose box that represents the state of the link preview. + * The view shown in the compose box or conversation that represents the state of the link preview. */ public class LinkPreviewView extends FrameLayout { @@ -35,6 +36,7 @@ public class LinkPreviewView extends FrameLayout { private ViewGroup container; private OutlinedThumbnailView thumbnail; private TextView title; + private TextView description; private TextView site; private View divider; private View closeButton; @@ -63,6 +65,7 @@ public class LinkPreviewView extends FrameLayout { container = findViewById(R.id.linkpreview_container); thumbnail = findViewById(R.id.linkpreview_thumbnail); title = findViewById(R.id.linkpreview_title); + description = findViewById(R.id.linkpreview_description); site = findViewById(R.id.linkpreview_site); divider = findViewById(R.id.linkpreview_divider); spinner = findViewById(R.id.linkpreview_progress_wheel); @@ -85,6 +88,8 @@ public class LinkPreviewView extends FrameLayout { container.setPadding(0, 0, 0, 0); divider.setVisibility(VISIBLE); closeButton.setVisibility(VISIBLE); + title.setMaxLines(2); + description.setMaxLines(2); closeButton.setOnClickListener(v -> { if (closeClickedListener != null) { @@ -108,6 +113,7 @@ public class LinkPreviewView extends FrameLayout { public void setLoading() { title.setVisibility(GONE); site.setVisibility(GONE); + description.setVisibility(GONE); thumbnail.setVisibility(GONE); spinner.setVisibility(VISIBLE); noPreview.setVisibility(INVISIBLE); @@ -123,17 +129,33 @@ public class LinkPreviewView extends FrameLayout { } public void setLinkPreview(@NonNull GlideRequests glideRequests, @NonNull LinkPreview linkPreview, boolean showThumbnail) { - title.setVisibility(VISIBLE); - site.setVisibility(VISIBLE); - thumbnail.setVisibility(VISIBLE); spinner.setVisibility(GONE); noPreview.setVisibility(GONE); - title.setText(linkPreview.getTitle()); + if (!Util.isEmpty(linkPreview.getTitle())) { + title.setText(linkPreview.getTitle()); + title.setVisibility(VISIBLE); + } else { + title.setVisibility(GONE); + } - HttpUrl url = HttpUrl.parse(linkPreview.getUrl()); - if (url != null) { - site.setText(url.topPrivateDomain()); + if (!Util.isEmpty(linkPreview.getDescription())) { + description.setText(linkPreview.getDescription()); + description.setVisibility(VISIBLE); + } else { + description.setVisibility(GONE); + } + + if (!Util.isEmpty(linkPreview.getUrl())) { + HttpUrl url = HttpUrl.parse(linkPreview.getUrl()); + if (url != null) { + site.setText(url.topPrivateDomain()); + site.setVisibility(VISIBLE); + } else { + site.setVisibility(GONE); + } + } else { + site.setVisibility(GONE); } if (showThumbnail && linkPreview.getThumbnail().isPresent()) { diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ThumbnailView.java b/app/src/main/java/org/thoughtcrime/securesms/components/ThumbnailView.java index 4227f3c7b..b83793425 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/components/ThumbnailView.java +++ b/app/src/main/java/org/thoughtcrime/securesms/components/ThumbnailView.java @@ -141,6 +141,11 @@ public class ThumbnailView extends FrameLayout { captionIcon.setScaleY(captionIconScale); } + public void setMinimumThumbnailWidth(int width) { + bounds[MIN_WIDTH] = width; + invalidate(); + } + @SuppressWarnings("SuspiciousNameCombination") private void fillTargetDimensions(int[] targetDimens, int[] dimens, int[] bounds) { int dimensFilledCount = getNonZeroCount(dimens); 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 345684424..66d90f6d2 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java +++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/ConversationItem.java @@ -116,6 +116,7 @@ import org.thoughtcrime.securesms.util.LongClickMovementMethod; import org.thoughtcrime.securesms.util.SearchUtil; import org.thoughtcrime.securesms.util.TextSecurePreferences; import org.thoughtcrime.securesms.util.ThemeUtil; +import org.thoughtcrime.securesms.util.Util; import org.thoughtcrime.securesms.util.VibrateUtil; import org.thoughtcrime.securesms.util.UrlClickHandler; import org.thoughtcrime.securesms.util.ViewUtil; @@ -569,10 +570,17 @@ public class ConversationItem extends LinearLayout implements BindableConversati } private boolean hasBigImageLinkPreview(MessageRecord messageRecord) { - if (!hasLinkPreview(messageRecord)) return false; + if (!hasLinkPreview(messageRecord)) { + return false; + } LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0); - int minWidth = getResources().getDimensionPixelSize(R.dimen.media_bubble_min_width); + + if (linkPreview.getThumbnail().isPresent() && !Util.isEmpty(linkPreview.getDescription())) { + return true; + } + + int minWidth = getResources().getDimensionPixelSize(R.dimen.media_bubble_min_width_solo); return linkPreview.getThumbnail().isPresent() && linkPreview.getThumbnail().get().getWidth() >= minWidth && @@ -681,6 +689,7 @@ public class ConversationItem extends LinearLayout implements BindableConversati 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); @@ -778,10 +787,12 @@ public class ConversationItem extends LinearLayout implements BindableConversati if (documentViewStub.resolved()) documentViewStub.get().setVisibility(View.GONE); if (sharedContactStub.resolved()) sharedContactStub.get().setVisibility(GONE); if (linkPreviewStub.resolved()) linkPreviewStub.get().setVisibility(GONE); - if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); - if (revealableStub.resolved()) revealableStub.get().setVisibility(View.GONE); + if (stickerStub.resolved()) stickerStub.get().setVisibility(View.GONE); + 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 + : R.dimen.media_bubble_min_width_with_content)); mediaThumbnailStub.get().setImageResource(glideRequests, thumbnailSlides, showControls, diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java index 9d47687f2..fe9f2c000 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java +++ b/app/src/main/java/org/thoughtcrime/securesms/database/MmsDatabase.java @@ -1118,7 +1118,7 @@ public class MmsDatabase extends MessageDatabase { if (preview.getAttachmentId() != null) { DatabaseAttachment attachment = attachmentIdMap.get(preview.getAttachmentId()); if (attachment != null) { - previews.add(new LinkPreview(preview.getUrl(), preview.getTitle(), attachment)); + previews.add(new LinkPreview(preview.getUrl(), preview.getTitle(), preview.getDescription(), attachment)); } } else { previews.add(preview); @@ -1526,7 +1526,7 @@ public class MmsDatabase extends MessageDatabase { attachmentId = insertedAttachmentIds.get(preview.getThumbnail().get()); } - LinkPreview updatedPreview = new LinkPreview(preview.getUrl(), preview.getTitle(), attachmentId); + LinkPreview updatedPreview = new LinkPreview(preview.getUrl(), preview.getTitle(), preview.getDescription(), attachmentId); linkPreviewJson.put(new JSONObject(updatedPreview.serialize())); } catch (JSONException | IOException e) { Log.w(TAG, "Failed to serialize shared contact. Skipping it.", e); diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java index b0ae64729..36d834514 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushProcessMessageJob.java @@ -1693,15 +1693,16 @@ public final class PushProcessMessageJob extends BaseJob { Optional thumbnail = PointerAttachment.forPointer(preview.getImage()); Optional url = Optional.fromNullable(preview.getUrl()); Optional title = Optional.fromNullable(preview.getTitle()); - boolean hasContent = !TextUtils.isEmpty(title.or("")) || thumbnail.isPresent(); + Optional description = Optional.fromNullable(preview.getDescription()); + boolean hasTitle = !TextUtils.isEmpty(title.or("")); boolean presentInBody = url.isPresent() && Stream.of(LinkPreviewUtil.findValidPreviewUrls(message)).map(Link::getUrl).collect(Collectors.toSet()).contains(url.get()); boolean validDomain = url.isPresent() && LinkPreviewUtil.isValidPreviewUrl(url.get()); - if (hasContent && presentInBody && validDomain) { - LinkPreview linkPreview = new LinkPreview(url.get(), title.or(""), thumbnail); + if (hasTitle && presentInBody && validDomain) { + LinkPreview linkPreview = new LinkPreview(url.get(), title.or(""), description.or(""), thumbnail); linkPreviews.add(linkPreview); } else { - Log.w(TAG, String.format("Discarding an invalid link preview. hasContent: %b presentInBody: %b validDomain: %b", hasContent, presentInBody, validDomain)); + Log.w(TAG, String.format("Discarding an invalid link preview. hasTitle: %b presentInBody: %b validDomain: %b", hasTitle, presentInBody, validDomain)); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java index 32bbd2343..bec17f983 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/app/src/main/java/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -315,7 +315,7 @@ public abstract class PushSendJob extends SendJob { List getPreviewsFor(OutgoingMediaMessage mediaMessage) { return Stream.of(mediaMessage.getLinkPreviews()).map(lp -> { SignalServiceAttachment attachment = lp.getThumbnail().isPresent() ? getAttachmentPointerFor(lp.getThumbnail().get()) : null; - return new Preview(lp.getUrl(), lp.getTitle(), Optional.fromNullable(attachment)); + return new Preview(lp.getUrl(), lp.getTitle(), lp.getDescription(), Optional.fromNullable(attachment)); }).toList(); } diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreview.java b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreview.java index 792004696..7d1e5c735 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreview.java +++ b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreview.java @@ -22,45 +22,56 @@ public class LinkPreview { @JsonProperty private final String title; + @JsonProperty + private final String description; + @JsonProperty private final AttachmentId attachmentId; @JsonIgnore private final Optional thumbnail; - public LinkPreview(@NonNull String url, @NonNull String title, @NonNull DatabaseAttachment thumbnail) { + public LinkPreview(@NonNull String url, @NonNull String title, @NonNull String description, @NonNull DatabaseAttachment thumbnail) { this.url = url; this.title = title; + this.description = description; this.thumbnail = Optional.of(thumbnail); this.attachmentId = thumbnail.getAttachmentId(); } - public LinkPreview(@NonNull String url, @NonNull String title, @NonNull Optional thumbnail) { + public LinkPreview(@NonNull String url, @NonNull String title, @NonNull String description, @NonNull Optional thumbnail) { this.url = url; this.title = title; + this.description = description; this.thumbnail = thumbnail; this.attachmentId = null; } public LinkPreview(@JsonProperty("url") @NonNull String url, @JsonProperty("title") @NonNull String title, + @JsonProperty("description") @Nullable String description, @JsonProperty("attachmentId") @Nullable AttachmentId attachmentId) { this.url = url; this.title = title; + this.description = Optional.fromNullable(description).or(""); this.attachmentId = attachmentId; this.thumbnail = Optional.absent(); } - public String getUrl() { + public @NonNull String getUrl() { return url; } - public String getTitle() { + public @NonNull String getTitle() { return title; } - public Optional getThumbnail() { + public @NonNull String getDescription() { + return description; + } + + public @NonNull Optional getThumbnail() { return thumbnail; } @@ -68,11 +79,11 @@ public class LinkPreview { return attachmentId; } - public String serialize() throws IOException { + public @NonNull String serialize() throws IOException { return JsonUtils.toJson(this); } - public static LinkPreview deserialize(@NonNull String serialized) throws IOException { + public static @NonNull LinkPreview deserialize(@NonNull String serialized) throws IOException { return JsonUtils.fromJson(serialized, LinkPreview.class); } } diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewRepository.java b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewRepository.java index 2a871f2fc..cf5a264ce 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewRepository.java +++ b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewRepository.java @@ -105,7 +105,7 @@ public class LinkPreviewRepository { } if (!metadata.getImageUrl().isPresent()) { - callback.onSuccess(new LinkPreview(url, metadata.getTitle().get(), Optional.absent())); + callback.onSuccess(new LinkPreview(url, metadata.getTitle().or(""), metadata.getDescription().or(""), Optional.absent())); return; } @@ -113,7 +113,7 @@ public class LinkPreviewRepository { if (!metadata.getTitle().isPresent() && !attachment.isPresent()) { callback.onError(Error.PREVIEW_NOT_AVAILABLE); } else { - callback.onSuccess(new LinkPreview(url, metadata.getTitle().or(""), attachment)); + callback.onSuccess(new LinkPreview(url, metadata.getTitle().or(""), metadata.getDescription().or(""), attachment)); } }); @@ -147,17 +147,18 @@ public class LinkPreviewRepository { return; } - String body = OkHttpUtil.readAsString(response.body(), FAILSAFE_MAX_TEXT_SIZE); - OpenGraph openGraph = LinkPreviewUtil.parseOpenGraphFields(body); - Optional title = openGraph.getTitle(); - Optional imageUrl = openGraph.getImageUrl(); + String body = OkHttpUtil.readAsString(response.body(), FAILSAFE_MAX_TEXT_SIZE); + OpenGraph openGraph = LinkPreviewUtil.parseOpenGraphFields(body); + Optional title = openGraph.getTitle(); + Optional description = openGraph.getDescription(); + Optional imageUrl = openGraph.getImageUrl(); if (imageUrl.isPresent() && !LinkPreviewUtil.isValidPreviewUrl(imageUrl.get())) { Log.i(TAG, "Image URL was invalid or for a non-whitelisted domain. Skipping."); imageUrl = Optional.absent(); } - callback.accept(new Metadata(title, imageUrl)); + callback.accept(new Metadata(title, description, imageUrl)); } }); @@ -225,7 +226,7 @@ public class LinkPreviewRepository { Optional thumbnail = bitmapToAttachment(bitmap, Bitmap.CompressFormat.WEBP, MediaUtil.IMAGE_WEBP); - callback.onSuccess(new LinkPreview(packUrl, title, thumbnail)); + callback.onSuccess(new LinkPreview(packUrl, title, "", thumbnail)); } else { callback.onError(Error.PREVIEW_NOT_AVAILABLE); } @@ -268,7 +269,7 @@ public class LinkPreviewRepository { thumbnail = bitmapToAttachment(bitmap, Bitmap.CompressFormat.WEBP, MediaUtil.IMAGE_WEBP); } - callback.onSuccess(new LinkPreview(groupUrl, title, thumbnail)); + callback.onSuccess(new LinkPreview(groupUrl, title, "", thumbnail)); } else { Log.i(TAG, "Group is not locally available for preview generation, fetching from server"); @@ -284,7 +285,7 @@ public class LinkPreviewRepository { if (bitmap != null) bitmap.recycle(); } - callback.onSuccess(new LinkPreview(groupUrl, joinInfo.getTitle(), thumbnail)); + callback.onSuccess(new LinkPreview(groupUrl, joinInfo.getTitle(), "", thumbnail)); } } catch (ExecutionException | InterruptedException | IOException | VerificationFailedException e) { Log.w(TAG, "Failed to fetch group link preview.", e); @@ -337,21 +338,27 @@ public class LinkPreviewRepository { private static class Metadata { private final Optional title; + private final Optional description; private final Optional imageUrl; - Metadata(Optional title, Optional imageUrl) { - this.title = title; - this.imageUrl = imageUrl; + Metadata(Optional title, Optional description, Optional imageUrl) { + this.title = title; + this.description = description; + this.imageUrl = imageUrl; } static Metadata empty() { - return new Metadata(Optional.absent(), Optional.absent()); + return new Metadata(Optional.absent(), Optional.absent(), Optional.absent()); } Optional getTitle() { return title; } + Optional getDescription() { + return description; + } + Optional getImageUrl() { return imageUrl; } diff --git a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java index be20b0c7c..caf615545 100644 --- a/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java +++ b/app/src/main/java/org/thoughtcrime/securesms/linkpreview/LinkPreviewUtil.java @@ -154,8 +154,9 @@ public final class LinkPreviewUtil { private final @Nullable String htmlTitle; private final @Nullable String faviconUrl; - private static final String KEY_TITLE = "title"; - private static final String KEY_IMAGE_URL = "image"; + private static final String KEY_TITLE = "title"; + private static final String KEY_DESCRIPTION_URL = "description"; + private static final String KEY_IMAGE_URL = "image"; public OpenGraph(@NonNull Map values, @Nullable String htmlTitle, @Nullable String faviconUrl) { this.values = values; @@ -170,6 +171,10 @@ public final class LinkPreviewUtil { public @NonNull Optional getImageUrl() { return OptionalUtil.absentIfEmpty(Util.getFirstNonEmpty(values.get(KEY_IMAGE_URL), faviconUrl)); } + + public @NonNull Optional getDescription() { + return OptionalUtil.absentIfEmpty(values.get(KEY_DESCRIPTION_URL)); + } } public interface HtmlDecoder { diff --git a/app/src/main/res/layout/conversation_item_received_thumbnail.xml b/app/src/main/res/layout/conversation_item_received_thumbnail.xml index 3d93f459a..bead0b6f6 100644 --- a/app/src/main/res/layout/conversation_item_received_thumbnail.xml +++ b/app/src/main/res/layout/conversation_item_received_thumbnail.xml @@ -11,7 +11,7 @@ android:contentDescription="@string/conversation_item__mms_image_description" android:visibility="gone" android:elevation="8dp" - app:conversationThumbnail_minWidth="@dimen/media_bubble_min_width" + app:conversationThumbnail_minWidth="@dimen/media_bubble_min_width_solo" app:conversationThumbnail_maxWidth="@dimen/media_bubble_max_width" app:conversationThumbnail_minHeight="@dimen/media_bubble_min_height" app:conversationThumbnail_maxHeight="@dimen/media_bubble_max_height" diff --git a/app/src/main/res/layout/conversation_item_sent_thumbnail.xml b/app/src/main/res/layout/conversation_item_sent_thumbnail.xml index fc7af1b51..4d5d0ada9 100644 --- a/app/src/main/res/layout/conversation_item_sent_thumbnail.xml +++ b/app/src/main/res/layout/conversation_item_sent_thumbnail.xml @@ -13,7 +13,7 @@ android:contentDescription="@string/conversation_item__mms_image_description" android:visibility="gone" android:elevation="8dp" - app:conversationThumbnail_minWidth="@dimen/media_bubble_min_width" + app:conversationThumbnail_minWidth="@dimen/media_bubble_min_width_solo" app:conversationThumbnail_maxWidth="@dimen/media_bubble_max_width" app:conversationThumbnail_minHeight="@dimen/media_bubble_min_height" app:conversationThumbnail_maxHeight="@dimen/media_bubble_max_height" diff --git a/app/src/main/res/layout/link_preview.xml b/app/src/main/res/layout/link_preview.xml index 303ff627f..da8e9868e 100644 --- a/app/src/main/res/layout/link_preview.xml +++ b/app/src/main/res/layout/link_preview.xml @@ -15,6 +15,7 @@ android:id="@+id/linkpreview_thumbnail" android:layout_width="72dp" android:layout_height="0dp" + android:maxHeight="72dp" android:scaleType="centerCrop" android:visibility="gone" app:layout_constraintBottom_toTopOf="@+id/linkpreview_divider" @@ -26,11 +27,11 @@ + tools:text="J. Jonah Jameson on Twitter" /> + + diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 6ba6768e3..d3fd2b50f 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -41,7 +41,8 @@ 24dp 24dp 210dp - 150dp + 150dp + 240dp 240dp 100dp 320dp diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java index f47a603b7..369ba6cb8 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/SignalServiceMessageSender.java @@ -628,6 +628,7 @@ public class SignalServiceMessageSender { for (SignalServiceDataMessage.Preview preview : message.getPreviews().get()) { DataMessage.Preview.Builder previewBuilder = DataMessage.Preview.newBuilder(); previewBuilder.setTitle(preview.getTitle()); + previewBuilder.setDescription(preview.getDescription()); previewBuilder.setUrl(preview.getUrl()); if (preview.getImage().isPresent()) { diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java index 9dc0faf59..1148364bb 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceContent.java @@ -685,8 +685,9 @@ public final class SignalServiceContent { } results.add(new SignalServiceDataMessage.Preview(preview.getUrl(), - preview.getTitle(), - Optional.fromNullable(attachment))); + preview.getTitle(), + preview.getDescription(), + Optional.fromNullable(attachment))); } return results; diff --git a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java index 28f3a3dac..b883b630d 100644 --- a/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java +++ b/libsignal/service/src/main/java/org/whispersystems/signalservice/api/messages/SignalServiceDataMessage.java @@ -412,12 +412,14 @@ public class SignalServiceDataMessage { public static class Preview { private final String url; private final String title; + private final String description; private final Optional image; - public Preview(String url, String title, Optional image) { - this.url = url; - this.title = title; - this.image = image; + public Preview(String url, String title, String description, Optional image) { + this.url = url; + this.title = title; + this.description = description; + this.image = image; } public String getUrl() { @@ -428,6 +430,10 @@ public class SignalServiceDataMessage { return title; } + public String getDescription() { + return description; + } + public Optional getImage() { return image; } diff --git a/libsignal/service/src/main/proto/SignalService.proto b/libsignal/service/src/main/proto/SignalService.proto index f50b7e49b..282e7ebd4 100644 --- a/libsignal/service/src/main/proto/SignalService.proto +++ b/libsignal/service/src/main/proto/SignalService.proto @@ -203,9 +203,10 @@ message DataMessage { } message Preview { - optional string url = 1; - optional string title = 2; - optional AttachmentPointer image = 3; + optional string url = 1; + optional string title = 2; + optional AttachmentPointer image = 3; + optional string description = 4; } message Sticker {