Search in sources :

Example 11 with LinkPreview

use of org.thoughtcrime.securesms.linkpreview.LinkPreview in project Signal-Android by signalapp.

the class MessageContentProcessor method getLinkPreviews.

private Optional<List<LinkPreview>> getLinkPreviews(Optional<List<SignalServiceDataMessage.Preview>> previews, @NonNull String message) {
    if (!previews.isPresent() || previews.get().isEmpty())
        return Optional.absent();
    List<LinkPreview> linkPreviews = new ArrayList<>(previews.get().size());
    LinkPreviewUtil.Links urlsInMessage = LinkPreviewUtil.findValidPreviewUrls(message);
    for (SignalServiceDataMessage.Preview preview : previews.get()) {
        Optional<Attachment> thumbnail = PointerAttachment.forPointer(preview.getImage());
        Optional<String> url = Optional.fromNullable(preview.getUrl());
        Optional<String> title = Optional.fromNullable(preview.getTitle());
        Optional<String> description = Optional.fromNullable(preview.getDescription());
        boolean hasTitle = !TextUtils.isEmpty(title.or(""));
        boolean presentInBody = url.isPresent() && urlsInMessage.containsUrl(url.get());
        boolean validDomain = url.isPresent() && LinkPreviewUtil.isValidPreviewUrl(url.get());
        if (hasTitle && presentInBody && validDomain) {
            LinkPreview linkPreview = new LinkPreview(url.get(), title.or(""), description.or(""), preview.getDate(), thumbnail);
            linkPreviews.add(linkPreview);
        } else {
            warn(String.format("Discarding an invalid link preview. hasTitle: %b presentInBody: %b validDomain: %b", hasTitle, presentInBody, validDomain));
        }
    }
    return Optional.of(linkPreviews);
}
Also used : SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) ArrayList(java.util.ArrayList) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) PointerAttachment(org.thoughtcrime.securesms.attachments.PointerAttachment) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) UriAttachment(org.thoughtcrime.securesms.attachments.UriAttachment) TombstoneAttachment(org.thoughtcrime.securesms.attachments.TombstoneAttachment) LinkPreviewUtil(org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil)

Example 12 with LinkPreview

use of org.thoughtcrime.securesms.linkpreview.LinkPreview in project Signal-Android by WhisperSystems.

the class ConversationItem method setMediaAttributes.

private void setMediaAttributes(@NonNull MessageRecord messageRecord, @NonNull Optional<MessageRecord> previousRecord, @NonNull Optional<MessageRecord> nextRecord, boolean isGroupThread, boolean hasWallpaper, boolean messageRequestAccepted, boolean allowedToPlayInline) {
    boolean showControls = !messageRecord.isFailed();
    ViewUtil.setTopMargin(bodyText, readDimen(R.dimen.message_bubble_top_padding));
    bodyBubble.setQuoteViewProjection(null);
    bodyBubble.setVideoPlayerProjection(null);
    if (eventListener != null && audioViewStub.resolved()) {
        Log.d(TAG, "setMediaAttributes: unregistering voice note callbacks for audio slide " + audioViewStub.get().getAudioSlideUri());
        eventListener.onUnregisterVoiceNoteCallbacks(audioViewStub.get().getPlaybackStateObserver());
    }
    footer.setPlaybackSpeedListener(null);
    if (isViewOnceMessage(messageRecord) && !messageRecord.isRemoteDelete()) {
        revealableStub.get().setVisibility(VISIBLE);
        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);
        if (linkPreviewStub.resolved())
            linkPreviewStub.get().setVisibility(GONE);
        if (stickerStub.resolved())
            stickerStub.get().setVisibility(View.GONE);
        revealableStub.get().setMessage((MmsMessageRecord) messageRecord, hasWallpaper);
        revealableStub.get().setOnClickListener(revealableClickListener);
        revealableStub.get().setOnLongClickListener(passthroughClickListener);
        updateRevealableMargins(messageRecord, previousRecord, nextRecord, isGroupThread);
        footer.setVisibility(VISIBLE);
    } else if (hasSharedContact(messageRecord)) {
        sharedContactStub.get().setVisibility(VISIBLE);
        if (audioViewStub.resolved())
            audioViewStub.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);
        if (revealableStub.resolved())
            revealableStub.get().setVisibility(View.GONE);
        sharedContactStub.get().setContact(((MediaMmsMessageRecord) messageRecord).getSharedContacts().get(0), glideRequests, locale);
        sharedContactStub.get().setEventListener(sharedContactEventListener);
        sharedContactStub.get().setOnClickListener(sharedContactClickListener);
        sharedContactStub.get().setOnLongClickListener(passthroughClickListener);
        setSharedContactCorners(messageRecord, previousRecord, nextRecord, isGroupThread);
        ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        footer.setVisibility(GONE);
    } else if (hasLinkPreview(messageRecord) && messageRequestAccepted) {
        linkPreviewStub.get().setVisibility(View.VISIBLE);
        if (audioViewStub.resolved())
            audioViewStub.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);
        if (revealableStub.resolved())
            revealableStub.get().setVisibility(View.GONE);
        // noinspection ConstantConditions
        LinkPreview linkPreview = ((MmsMessageRecord) messageRecord).getLinkPreviews().get(0);
        if (hasBigImageLinkPreview(messageRecord)) {
            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);
            setThumbnailCorners(messageRecord, previousRecord, nextRecord, isGroupThread);
            setLinkPreviewCorners(messageRecord, previousRecord, nextRecord, isGroupThread, true);
            ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            ViewUtil.setTopMargin(linkPreviewStub.get(), 0);
        } else {
            linkPreviewStub.get().setLinkPreview(glideRequests, linkPreview, true);
            linkPreviewStub.get().setDownloadClickedListener(downloadClickListener);
            setLinkPreviewCorners(messageRecord, previousRecord, nextRecord, isGroupThread, false);
            ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
            // noinspection ConstantConditions
            int topMargin = isGroupThread && isStartOfMessageCluster(messageRecord, previousRecord, isGroupThread) && !messageRecord.isOutgoing() ? readDimen(R.dimen.message_bubble_top_padding) : 0;
            ViewUtil.setTopMargin(linkPreviewStub.get(), topMargin);
        }
        linkPreviewStub.get().setOnClickListener(linkPreviewClickListener);
        linkPreviewStub.get().setOnLongClickListener(passthroughClickListener);
        footer.setVisibility(VISIBLE);
    } else if (hasAudio(messageRecord)) {
        audioViewStub.get().setVisibility(View.VISIBLE);
        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);
        if (stickerStub.resolved())
            stickerStub.get().setVisibility(View.GONE);
        if (revealableStub.resolved())
            revealableStub.get().setVisibility(View.GONE);
        audioViewStub.get().setAudio(Objects.requireNonNull(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getAudioSlide()), new AudioViewCallbacks(), showControls, true);
        audioViewStub.get().setDownloadClickListener(singleDownloadClickListener);
        audioViewStub.get().setOnLongClickListener(passthroughClickListener);
        if (eventListener != null) {
            Log.d(TAG, "setMediaAttributes: registered listener for audio slide " + audioViewStub.get().getAudioSlideUri());
            eventListener.onRegisterVoiceNoteCallbacks(audioViewStub.get().getPlaybackStateObserver());
        } else {
            Log.w(TAG, "setMediaAttributes: could not register listener for audio slide " + audioViewStub.get().getAudioSlideUri());
        }
        ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        footer.setPlaybackSpeedListener(new AudioPlaybackSpeedToggleListener());
        footer.setVisibility(VISIBLE);
    } else if (hasDocument(messageRecord)) {
        documentViewStub.get().setVisibility(View.VISIBLE);
        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);
        if (stickerStub.resolved())
            stickerStub.get().setVisibility(View.GONE);
        if (revealableStub.resolved())
            revealableStub.get().setVisibility(View.GONE);
        // noinspection ConstantConditions
        documentViewStub.get().setDocument(((MediaMmsMessageRecord) messageRecord).getSlideDeck().getDocumentSlide(), showControls);
        documentViewStub.get().setDocumentClickListener(new ThumbnailClickListener());
        documentViewStub.get().setDownloadClickListener(singleDownloadClickListener);
        documentViewStub.get().setOnLongClickListener(passthroughClickListener);
        ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        ViewUtil.setTopMargin(bodyText, 0);
        footer.setVisibility(VISIBLE);
    } else if ((hasSticker(messageRecord) && isCaptionlessMms(messageRecord)) || isBorderless(messageRecord)) {
        bodyBubble.setBackgroundColor(Color.TRANSPARENT);
        stickerStub.get().setVisibility(View.VISIBLE);
        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);
        if (linkPreviewStub.resolved())
            linkPreviewStub.get().setVisibility(GONE);
        if (revealableStub.resolved())
            revealableStub.get().setVisibility(View.GONE);
        if (hasSticker(messageRecord)) {
            // noinspection ConstantConditions
            stickerStub.get().setSlide(glideRequests, ((MmsMessageRecord) messageRecord).getSlideDeck().getStickerSlide());
            stickerStub.get().setThumbnailClickListener(new StickerClickListener());
        } else {
            // noinspection ConstantConditions
            stickerStub.get().setSlide(glideRequests, ((MmsMessageRecord) messageRecord).getSlideDeck().getThumbnailSlide());
            stickerStub.get().setThumbnailClickListener((v, slide) -> performClick());
        }
        stickerStub.get().setDownloadClickListener(downloadClickListener);
        stickerStub.get().setOnLongClickListener(passthroughClickListener);
        stickerStub.get().setOnClickListener(passthroughClickListener);
        ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        footer.setVisibility(VISIBLE);
    } else if (hasNoBubble(messageRecord)) {
        bodyBubble.setBackgroundColor(Color.TRANSPARENT);
    } else if (hasThumbnail(messageRecord)) {
        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);
        if (linkPreviewStub.resolved())
            linkPreviewStub.get().setVisibility(GONE);
        if (stickerStub.resolved())
            stickerStub.get().setVisibility(View.GONE);
        if (revealableStub.resolved())
            revealableStub.get().setVisibility(View.GONE);
        List<Slide> thumbnailSlides = ((MmsMessageRecord) messageRecord).getSlideDeck().getThumbnailSlides();
        mediaThumbnailStub.require().setMinimumThumbnailWidth(readDimen(isCaptionlessMms(messageRecord) ? R.dimen.media_bubble_min_width_solo : R.dimen.media_bubble_min_width_with_content));
        mediaThumbnailStub.require().setImageResource(glideRequests, thumbnailSlides, showControls, false);
        mediaThumbnailStub.require().setThumbnailClickListener(new ThumbnailClickListener());
        mediaThumbnailStub.require().setDownloadClickListener(downloadClickListener);
        mediaThumbnailStub.require().setOnLongClickListener(passthroughClickListener);
        mediaThumbnailStub.require().setOnClickListener(passthroughClickListener);
        mediaThumbnailStub.require().showShade(messageRecord.isDisplayBodyEmpty(getContext()) && !hasExtraText(messageRecord));
        if (!messageRecord.isOutgoing()) {
            mediaThumbnailStub.require().setConversationColor(getDefaultBubbleColor(hasWallpaper));
        } else {
            mediaThumbnailStub.require().setConversationColor(Color.TRANSPARENT);
        }
        mediaThumbnailStub.require().setBorderless(false);
        setThumbnailCorners(messageRecord, previousRecord, nextRecord, isGroupThread);
        ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        footer.setVisibility(VISIBLE);
        if (thumbnailSlides.size() == 1 && thumbnailSlides.get(0).isVideoGif() && thumbnailSlides.get(0) instanceof VideoSlide) {
            Uri uri = thumbnailSlides.get(0).getUri();
            if (uri != null) {
                mediaItem = MediaItem.fromUri(uri);
            } else {
                mediaItem = null;
            }
            canPlayContent = (GiphyMp4PlaybackPolicy.autoplay() || allowedToPlayInline) && mediaItem != null;
        }
    } else {
        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);
        if (linkPreviewStub.resolved())
            linkPreviewStub.get().setVisibility(GONE);
        if (stickerStub.resolved())
            stickerStub.get().setVisibility(View.GONE);
        if (revealableStub.resolved())
            revealableStub.get().setVisibility(View.GONE);
        ViewUtil.updateLayoutParams(bodyText, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        ViewUtil.updateLayoutParamsIfNonNull(groupSenderHolder, ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
        footer.setVisibility(VISIBLE);
        // noinspection ConstantConditions
        int topMargin = !messageRecord.isOutgoing() && isGroupThread && isStartOfMessageCluster(messageRecord, previousRecord, isGroupThread) ? readDimen(R.dimen.message_bubble_text_only_top_margin) : readDimen(R.dimen.message_bubble_top_padding);
        ViewUtil.setTopMargin(bodyText, topMargin);
    }
}
Also used : LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) SlideClickListener(org.thoughtcrime.securesms.mms.SlideClickListener) NonNull(androidx.annotation.NonNull) LongClickMovementMethod(org.thoughtcrime.securesms.util.LongClickMovementMethod) Uri(android.net.Uri) StringUtil(org.thoughtcrime.securesms.util.StringUtil) TouchDelegate(android.view.TouchDelegate) ColorInt(androidx.annotation.ColorInt) LinkPreviewUtil(org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil) ImageSlide(org.thoughtcrime.securesms.mms.ImageSlide) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) TextSlide(org.thoughtcrime.securesms.mms.TextSlide) MmsMessageRecord(org.thoughtcrime.securesms.database.model.MmsMessageRecord) BindableConversationItem(org.thoughtcrime.securesms.BindableConversationItem) PartAuthority(org.thoughtcrime.securesms.mms.PartAuthority) LinkPreviewView(org.thoughtcrime.securesms.components.LinkPreviewView) ForegroundColorSpan(android.text.style.ForegroundColorSpan) ContextCompat(androidx.core.content.ContextCompat) PlaceholderURLSpan(org.thoughtcrime.securesms.util.PlaceholderURLSpan) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Set(java.util.Set) MediaPreviewActivity(org.thoughtcrime.securesms.MediaPreviewActivity) MmsDownloadJob(org.thoughtcrime.securesms.jobs.MmsDownloadJob) MessageRecordUtil(org.thoughtcrime.securesms.util.MessageRecordUtil) Nullable(androidx.annotation.Nullable) TextPaint(android.text.TextPaint) AlertView(org.thoughtcrime.securesms.components.AlertView) LinkifyCompat(androidx.core.text.util.LinkifyCompat) ViewOnceMessageView(org.thoughtcrime.securesms.revealable.ViewOnceMessageView) SignalDatabase(org.thoughtcrime.securesms.database.SignalDatabase) Stream(com.annimon.stream.Stream) Util(org.thoughtcrime.securesms.util.Util) PlaybackSpeedToggleTextView(org.thoughtcrime.securesms.components.PlaybackSpeedToggleTextView) AttachmentDatabase(org.thoughtcrime.securesms.database.AttachmentDatabase) ArrayList(java.util.ArrayList) SpannableStringBuilder(android.text.SpannableStringBuilder) Toast(android.widget.Toast) Annotation(android.text.Annotation) AvatarImageView(org.thoughtcrime.securesms.components.AvatarImageView) MultiselectCollection(org.thoughtcrime.securesms.conversation.mutiselect.MultiselectCollection) MediaMmsMessageRecord(org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord) LiveRecipient(org.thoughtcrime.securesms.recipients.LiveRecipient) URLSpan(android.text.style.URLSpan) Contact(org.thoughtcrime.securesms.contactshare.Contact) SpannableString(android.text.SpannableString) StyleSpan(android.text.style.StyleSpan) NullableStub(org.thoughtcrime.securesms.util.views.NullableStub) Optional(org.whispersystems.libsignal.util.guava.Optional) ThemeUtil(org.thoughtcrime.securesms.util.ThemeUtil) TypedValue(android.util.TypedValue) SmsSendJob(org.thoughtcrime.securesms.jobs.SmsSendJob) DocumentView(org.thoughtcrime.securesms.components.DocumentView) ProjectionList(org.thoughtcrime.securesms.util.ProjectionList) ValueAnimator(android.animation.ValueAnimator) SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) Rect(android.graphics.Rect) UrlClickHandler(org.thoughtcrime.securesms.util.UrlClickHandler) DimenRes(androidx.annotation.DimenRes) ConversationItemThumbnail(org.thoughtcrime.securesms.components.ConversationItemThumbnail) AttachmentDownloadJob(org.thoughtcrime.securesms.jobs.AttachmentDownloadJob) Spannable(android.text.Spannable) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) ClickableSpan(android.text.style.ClickableSpan) ViewUtil(org.thoughtcrime.securesms.util.ViewUtil) ChatColors(org.thoughtcrime.securesms.conversation.colors.ChatColors) R(org.thoughtcrime.securesms.R) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) AttributeSet(android.util.AttributeSet) Locale(java.util.Locale) View(android.view.View) Button(android.widget.Button) Recipient(org.thoughtcrime.securesms.recipients.Recipient) SlidesClickedListener(org.thoughtcrime.securesms.mms.SlidesClickedListener) QuoteView(org.thoughtcrime.securesms.components.QuoteView) MediaItem(com.google.android.exoplayer2.MediaItem) Outliner(org.thoughtcrime.securesms.components.Outliner) RecipientForeverObserver(org.thoughtcrime.securesms.recipients.RecipientForeverObserver) PorterDuff(android.graphics.PorterDuff) SharedContactView(org.thoughtcrime.securesms.components.SharedContactView) ViewGroup(android.view.ViewGroup) Sets(com.google.common.collect.Sets) Objects(java.util.Objects) Log(org.signal.core.util.logging.Log) List(java.util.List) TextView(android.widget.TextView) Slide(org.thoughtcrime.securesms.mms.Slide) MentionAnnotation(org.thoughtcrime.securesms.components.mention.MentionAnnotation) SearchUtil(org.thoughtcrime.securesms.util.SearchUtil) ActivityNotFoundException(android.content.ActivityNotFoundException) DateUtils(org.thoughtcrime.securesms.util.DateUtils) RelativeLayout(android.widget.RelativeLayout) GlideRequests(org.thoughtcrime.securesms.mms.GlideRequests) MessageDatabase(org.thoughtcrime.securesms.database.MessageDatabase) ReactionsConversationView(org.thoughtcrime.securesms.reactions.ReactionsConversationView) GiphyMp4PlaybackPolicy(org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackPolicy) Projection(org.thoughtcrime.securesms.util.Projection) VideoSlide(org.thoughtcrime.securesms.mms.VideoSlide) Typeface(android.graphics.Typeface) Context(android.content.Context) Spanned(android.text.Spanned) AlertDialog(androidx.appcompat.app.AlertDialog) InterceptableLongClickCopyLinkSpan(org.thoughtcrime.securesms.util.InterceptableLongClickCopyLinkSpan) BorderlessImageView(org.thoughtcrime.securesms.components.BorderlessImageView) MultiselectPart(org.thoughtcrime.securesms.conversation.mutiselect.MultiselectPart) GiphyMp4PlaybackPolicyEnforcer(org.thoughtcrime.securesms.giph.mp4.GiphyMp4PlaybackPolicyEnforcer) Intent(android.content.Intent) VibrateUtil(org.thoughtcrime.securesms.util.VibrateUtil) Linkify(android.text.util.Linkify) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) HashSet(java.util.HashSet) MmsSendJob(org.thoughtcrime.securesms.jobs.MmsSendJob) SuppressLint(android.annotation.SuppressLint) LifecycleOwner(androidx.lifecycle.LifecycleOwner) MotionEvent(android.view.MotionEvent) Colorizer(org.thoughtcrime.securesms.conversation.colors.Colorizer) AudioView(org.thoughtcrime.securesms.components.AudioView) Stub(org.thoughtcrime.securesms.util.views.Stub) BackgroundColorSpan(android.text.style.BackgroundColorSpan) Quote(org.thoughtcrime.securesms.database.model.Quote) Color(android.graphics.Color) TimeUnit(java.util.concurrent.TimeUnit) BadgeImageView(org.thoughtcrime.securesms.badges.BadgeImageView) CharacterStyle(android.text.style.CharacterStyle) ConversationItemFooter(org.thoughtcrime.securesms.components.ConversationItemFooter) Collections(java.util.Collections) VideoSlide(org.thoughtcrime.securesms.mms.VideoSlide) MediaMmsMessageRecord(org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) MmsMessageRecord(org.thoughtcrime.securesms.database.model.MmsMessageRecord) MediaMmsMessageRecord(org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord) Uri(android.net.Uri) TextPaint(android.text.TextPaint) SuppressLint(android.annotation.SuppressLint) ImageSlide(org.thoughtcrime.securesms.mms.ImageSlide) ArrayList(java.util.ArrayList) ProjectionList(org.thoughtcrime.securesms.util.ProjectionList) List(java.util.List)

Example 13 with LinkPreview

use of org.thoughtcrime.securesms.linkpreview.LinkPreview in project Signal-Android by WhisperSystems.

the class ShareInterstitialViewModel method send.

void send(@NonNull Consumer<MultiShareSender.MultiShareSendResultCollection> resultsConsumer) {
    LinkPreview linkPreview = this.linkPreview;
    String draftText = this.draftText.getValue();
    MultiShareArgs.Builder builder = args.buildUpon().withDraftText(draftText).withLinkPreview(linkPreview);
    MultiShareSender.send(builder.build(), resultsConsumer);
}
Also used : MultiShareArgs(org.thoughtcrime.securesms.sharing.MultiShareArgs) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview)

Example 14 with LinkPreview

use of org.thoughtcrime.securesms.linkpreview.LinkPreview in project Signal-Android by WhisperSystems.

the class MmsDatabase method insertMediaMessage.

private long insertMediaMessage(long threadId, @Nullable String body, @NonNull List<Attachment> attachments, @NonNull List<Attachment> quoteAttachments, @NonNull List<Contact> sharedContacts, @NonNull List<LinkPreview> linkPreviews, @NonNull List<Mention> mentions, @Nullable BodyRangeList messageRanges, @NonNull ContentValues contentValues, @Nullable InsertListener insertListener, boolean updateThread) throws MmsException {
    SQLiteDatabase db = databaseHelper.getSignalWritableDatabase();
    AttachmentDatabase partsDatabase = SignalDatabase.attachments();
    MentionDatabase mentionDatabase = SignalDatabase.mentions();
    boolean mentionsSelf = Stream.of(mentions).filter(m -> Recipient.resolved(m.getRecipientId()).isSelf()).findFirst().isPresent();
    List<Attachment> allAttachments = new LinkedList<>();
    List<Attachment> contactAttachments = Stream.of(sharedContacts).map(Contact::getAvatarAttachment).filter(a -> a != null).toList();
    List<Attachment> previewAttachments = Stream.of(linkPreviews).filter(lp -> lp.getThumbnail().isPresent()).map(lp -> lp.getThumbnail().get()).toList();
    allAttachments.addAll(attachments);
    allAttachments.addAll(contactAttachments);
    allAttachments.addAll(previewAttachments);
    contentValues.put(BODY, body);
    contentValues.put(PART_COUNT, allAttachments.size());
    contentValues.put(MENTIONS_SELF, mentionsSelf ? 1 : 0);
    if (messageRanges != null) {
        contentValues.put(MESSAGE_RANGES, messageRanges.toByteArray());
    }
    db.beginTransaction();
    try {
        long messageId = db.insert(TABLE_NAME, null, contentValues);
        mentionDatabase.insert(threadId, messageId, mentions);
        Map<Attachment, AttachmentId> insertedAttachments = partsDatabase.insertAttachmentsForMessage(messageId, allAttachments, quoteAttachments);
        String serializedContacts = getSerializedSharedContacts(insertedAttachments, sharedContacts);
        String serializedPreviews = getSerializedLinkPreviews(insertedAttachments, linkPreviews);
        if (!TextUtils.isEmpty(serializedContacts)) {
            ContentValues contactValues = new ContentValues();
            contactValues.put(SHARED_CONTACTS, serializedContacts);
            SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
            int rows = database.update(TABLE_NAME, contactValues, ID + " = ?", new String[] { String.valueOf(messageId) });
            if (rows <= 0) {
                Log.w(TAG, "Failed to update message with shared contact data.");
            }
        }
        if (!TextUtils.isEmpty(serializedPreviews)) {
            ContentValues contactValues = new ContentValues();
            contactValues.put(LINK_PREVIEWS, serializedPreviews);
            SQLiteDatabase database = databaseHelper.getSignalReadableDatabase();
            int rows = database.update(TABLE_NAME, contactValues, ID + " = ?", new String[] { String.valueOf(messageId) });
            if (rows <= 0) {
                Log.w(TAG, "Failed to update message with link preview data.");
            }
        }
        db.setTransactionSuccessful();
        return messageId;
    } finally {
        db.endTransaction();
        if (insertListener != null) {
            insertListener.onComplete();
        }
        long contentValuesThreadId = contentValues.getAsLong(THREAD_ID);
        if (updateThread) {
            SignalDatabase.threads().setLastScrolled(contentValuesThreadId, 0);
            SignalDatabase.threads().update(threadId, true);
        }
    }
}
Also used : SignalStore(org.thoughtcrime.securesms.keyvalue.SignalStore) SlideDeck(org.thoughtcrime.securesms.mms.SlideDeck) GroupMigrationMembershipChange(org.thoughtcrime.securesms.groups.GroupMigrationMembershipChange) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) NonNull(androidx.annotation.NonNull) Avatar(org.thoughtcrime.securesms.contactshare.Contact.Avatar) MessageGroupContext(org.thoughtcrime.securesms.mms.MessageGroupContext) Mention(org.thoughtcrime.securesms.database.model.Mention) MessageRecord(org.thoughtcrime.securesms.database.model.MessageRecord) SecureRandom(java.security.SecureRandom) JSONException(org.json.JSONException) JsonUtils(org.thoughtcrime.securesms.util.JsonUtils) JSONObject(org.json.JSONObject) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) BodyRangeList(org.thoughtcrime.securesms.database.model.databaseprotos.BodyRangeList) SqlUtil(org.thoughtcrime.securesms.util.SqlUtil) IdentityKeyMismatchSet(org.thoughtcrime.securesms.database.documents.IdentityKeyMismatchSet) Map(java.util.Map) ViewOnceUtil(org.thoughtcrime.securesms.revealable.ViewOnceUtil) Recipient(org.thoughtcrime.securesms.recipients.Recipient) OutgoingTextMessage(org.thoughtcrime.securesms.sms.OutgoingTextMessage) OutgoingGroupUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingGroupUpdateMessage) InvalidProtocolBufferException(com.google.protobuf.InvalidProtocolBufferException) NotificationInd(com.google.android.mms.pdu_alt.NotificationInd) ACI(org.whispersystems.signalservice.api.push.ACI) ApplicationDependencies(org.thoughtcrime.securesms.dependencies.ApplicationDependencies) Collection(java.util.Collection) OutgoingSecureMediaMessage(org.thoughtcrime.securesms.mms.OutgoingSecureMediaMessage) Set(java.util.Set) UUID(java.util.UUID) OutgoingExpirationUpdateMessage(org.thoughtcrime.securesms.mms.OutgoingExpirationUpdateMessage) Log(org.signal.core.util.logging.Log) NetworkFailureSet(org.thoughtcrime.securesms.database.documents.NetworkFailureSet) List(java.util.List) Nullable(androidx.annotation.Nullable) ContentValues(android.content.ContentValues) IncomingTextMessage(org.thoughtcrime.securesms.sms.IncomingTextMessage) Attachment(org.thoughtcrime.securesms.attachments.Attachment) OutgoingMediaMessage(org.thoughtcrime.securesms.mms.OutgoingMediaMessage) MediaUtil(org.thoughtcrime.securesms.util.MediaUtil) Context(android.content.Context) Stream(com.annimon.stream.Stream) Util(org.thoughtcrime.securesms.util.Util) HashMap(java.util.HashMap) SQLiteStatement(net.zetetic.database.sqlcipher.SQLiteStatement) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) ArrayList(java.util.ArrayList) TextSecurePreferences(org.thoughtcrime.securesms.util.TextSecurePreferences) HashSet(java.util.HashSet) Pair(org.whispersystems.libsignal.util.Pair) MmsNotificationAttachment(org.thoughtcrime.securesms.attachments.MmsNotificationAttachment) NotificationMmsMessageRecord(org.thoughtcrime.securesms.database.model.NotificationMmsMessageRecord) QuoteModel(org.thoughtcrime.securesms.mms.QuoteModel) MediaMmsMessageRecord(org.thoughtcrime.securesms.database.model.MediaMmsMessageRecord) LinkedList(java.util.LinkedList) PduHeaders(com.google.android.mms.pdu_alt.PduHeaders) Cursor(android.database.Cursor) MessageId(org.thoughtcrime.securesms.database.model.MessageId) Collectors(com.annimon.stream.Collectors) Contact(org.thoughtcrime.securesms.contactshare.Contact) IdentityKeyMismatch(org.thoughtcrime.securesms.database.documents.IdentityKeyMismatch) MmsException(org.thoughtcrime.securesms.mms.MmsException) TextUtils(android.text.TextUtils) IOException(java.io.IOException) Quote(org.thoughtcrime.securesms.database.model.Quote) Optional(org.whispersystems.libsignal.util.guava.Optional) CursorUtil(org.thoughtcrime.securesms.util.CursorUtil) ViewOnceExpirationInfo(org.thoughtcrime.securesms.revealable.ViewOnceExpirationInfo) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId) NetworkFailure(org.thoughtcrime.securesms.database.documents.NetworkFailure) TrimThreadJob(org.thoughtcrime.securesms.jobs.TrimThreadJob) SmsMessageRecord(org.thoughtcrime.securesms.database.model.SmsMessageRecord) Collections(java.util.Collections) JSONArray(org.json.JSONArray) IncomingMediaMessage(org.thoughtcrime.securesms.mms.IncomingMediaMessage) ContentValues(android.content.ContentValues) Attachment(org.thoughtcrime.securesms.attachments.Attachment) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) MmsNotificationAttachment(org.thoughtcrime.securesms.attachments.MmsNotificationAttachment) LinkedList(java.util.LinkedList) AttachmentId(org.thoughtcrime.securesms.attachments.AttachmentId) Contact(org.thoughtcrime.securesms.contactshare.Contact)

Example 15 with LinkPreview

use of org.thoughtcrime.securesms.linkpreview.LinkPreview in project Signal-Android by WhisperSystems.

the class MessageContentProcessor method getLinkPreviews.

private Optional<List<LinkPreview>> getLinkPreviews(Optional<List<SignalServiceDataMessage.Preview>> previews, @NonNull String message) {
    if (!previews.isPresent() || previews.get().isEmpty())
        return Optional.absent();
    List<LinkPreview> linkPreviews = new ArrayList<>(previews.get().size());
    LinkPreviewUtil.Links urlsInMessage = LinkPreviewUtil.findValidPreviewUrls(message);
    for (SignalServiceDataMessage.Preview preview : previews.get()) {
        Optional<Attachment> thumbnail = PointerAttachment.forPointer(preview.getImage());
        Optional<String> url = Optional.fromNullable(preview.getUrl());
        Optional<String> title = Optional.fromNullable(preview.getTitle());
        Optional<String> description = Optional.fromNullable(preview.getDescription());
        boolean hasTitle = !TextUtils.isEmpty(title.or(""));
        boolean presentInBody = url.isPresent() && urlsInMessage.containsUrl(url.get());
        boolean validDomain = url.isPresent() && LinkPreviewUtil.isValidPreviewUrl(url.get());
        if (hasTitle && presentInBody && validDomain) {
            LinkPreview linkPreview = new LinkPreview(url.get(), title.or(""), description.or(""), preview.getDate(), thumbnail);
            linkPreviews.add(linkPreview);
        } else {
            warn(String.format("Discarding an invalid link preview. hasTitle: %b presentInBody: %b validDomain: %b", hasTitle, presentInBody, validDomain));
        }
    }
    return Optional.of(linkPreviews);
}
Also used : SignalServiceDataMessage(org.whispersystems.signalservice.api.messages.SignalServiceDataMessage) LinkPreview(org.thoughtcrime.securesms.linkpreview.LinkPreview) ArrayList(java.util.ArrayList) SignalServiceAttachment(org.whispersystems.signalservice.api.messages.SignalServiceAttachment) Attachment(org.thoughtcrime.securesms.attachments.Attachment) PointerAttachment(org.thoughtcrime.securesms.attachments.PointerAttachment) DatabaseAttachment(org.thoughtcrime.securesms.attachments.DatabaseAttachment) UriAttachment(org.thoughtcrime.securesms.attachments.UriAttachment) TombstoneAttachment(org.thoughtcrime.securesms.attachments.TombstoneAttachment) LinkPreviewUtil(org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil)

Aggregations

LinkPreview (org.thoughtcrime.securesms.linkpreview.LinkPreview)20 DatabaseAttachment (org.thoughtcrime.securesms.attachments.DatabaseAttachment)14 Nullable (androidx.annotation.Nullable)12 Attachment (org.thoughtcrime.securesms.attachments.Attachment)12 AttachmentId (org.thoughtcrime.securesms.attachments.AttachmentId)12 Contact (org.thoughtcrime.securesms.contactshare.Contact)12 Recipient (org.thoughtcrime.securesms.recipients.Recipient)12 Context (android.content.Context)10 NonNull (androidx.annotation.NonNull)10 IOException (java.io.IOException)10 ArrayList (java.util.ArrayList)10 List (java.util.List)10 Log (org.signal.core.util.logging.Log)10 MessageRecord (org.thoughtcrime.securesms.database.model.MessageRecord)10 Optional (org.whispersystems.libsignal.util.guava.Optional)10 Stream (com.annimon.stream.Stream)8 Collections (java.util.Collections)8 HashMap (java.util.HashMap)8 LinkedList (java.util.LinkedList)8 Set (java.util.Set)8