Search in sources :

Example 1 with ConversationItemFooter

use of org.thoughtcrime.securesms.components.ConversationItemFooter in project Signal-Android by WhisperSystems.

the class ConversationItem method getColorizerProjections.

@Override
@NonNull
public ProjectionList getColorizerProjections(@NonNull ViewGroup coordinateRoot) {
    colorizerProjections.clear();
    if (messageRecord.isOutgoing() && !hasNoBubble(messageRecord) && !messageRecord.isRemoteDelete() && bodyBubbleCorners != null && bodyBubble.getVisibility() == VISIBLE) {
        Projection bodyBubbleToRoot = Projection.relativeToParent(coordinateRoot, bodyBubble, bodyBubbleCorners).translateX(bodyBubble.getTranslationX());
        Projection videoToBubble = bodyBubble.getVideoPlayerProjection();
        float translationX = Util.halfOffsetFromScale(bodyBubble.getWidth(), bodyBubble.getScaleX());
        float translationY = Util.halfOffsetFromScale(bodyBubble.getHeight(), bodyBubble.getScaleY());
        if (videoToBubble != null) {
            Projection videoToRoot = Projection.translateFromDescendantToParentCoords(videoToBubble, bodyBubble, coordinateRoot);
            List<Projection> projections = Projection.getCapAndTail(bodyBubbleToRoot, videoToRoot);
            if (!projections.isEmpty()) {
                projections.get(0).scale(bodyBubble.getScaleX()).translateX(translationX).translateY(translationY);
                projections.get(1).scale(bodyBubble.getScaleX()).translateX(translationX).translateY(-translationY);
            }
            colorizerProjections.addAll(projections);
        } else {
            colorizerProjections.add(bodyBubbleToRoot.scale(bodyBubble.getScaleX()).translateX(translationX).translateY(translationY));
        }
    }
    if (messageRecord.isOutgoing() && hasNoBubble(messageRecord) && hasWallpaper && bodyBubble.getVisibility() == VISIBLE) {
        ConversationItemFooter footer = getActiveFooter(messageRecord);
        Projection footerProjection = footer.getProjection(coordinateRoot);
        if (footerProjection != null) {
            colorizerProjections.add(footerProjection.translateX(bodyBubble.getTranslationX()).scale(bodyBubble.getScaleX()).translateX(Util.halfOffsetFromScale(footer.getWidth(), bodyBubble.getScaleX())).translateY(-Util.halfOffsetFromScale(footer.getHeight(), bodyBubble.getScaleY())));
        }
    }
    if (!messageRecord.isOutgoing() && hasQuote(messageRecord) && quoteView != null && bodyBubble.getVisibility() == VISIBLE) {
        bodyBubble.setQuoteViewProjection(quoteView.getProjection(bodyBubble));
        float bubbleOffsetFromScale = Util.halfOffsetFromScale(bodyBubble.getHeight(), bodyBubble.getScaleY());
        Projection cProj = quoteView.getProjection(coordinateRoot).translateX(bodyBubble.getTranslationX() + this.getTranslationX() + Util.halfOffsetFromScale(quoteView.getWidth(), bodyBubble.getScaleX())).translateY(bubbleOffsetFromScale - quoteView.getY() + (quoteView.getY() * bodyBubble.getScaleY())).scale(bodyBubble.getScaleX());
        colorizerProjections.add(cProj);
    }
    for (int i = 0; i < colorizerProjections.size(); i++) {
        colorizerProjections.get(i).translateY(getTranslationY());
    }
    return colorizerProjections;
}
Also used : ConversationItemFooter(org.thoughtcrime.securesms.components.ConversationItemFooter) Projection(org.thoughtcrime.securesms.util.Projection) TextPaint(android.text.TextPaint) SuppressLint(android.annotation.SuppressLint) NonNull(androidx.annotation.NonNull)

Example 2 with ConversationItemFooter

use of org.thoughtcrime.securesms.components.ConversationItemFooter in project Signal-Android by WhisperSystems.

the class ConversationItem method onMeasure.

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    if (isInEditMode()) {
        return;
    }
    boolean needsMeasure = false;
    if (hasQuote(messageRecord)) {
        if (quoteView == null) {
            throw new AssertionError();
        }
        int quoteWidth = quoteView.getMeasuredWidth();
        int availableWidth = getAvailableMessageBubbleWidth(quoteView);
        if (quoteWidth != availableWidth) {
            quoteView.getLayoutParams().width = availableWidth;
            needsMeasure = true;
        }
    }
    int defaultTopMargin = readDimen(R.dimen.message_bubble_default_footer_bottom_margin);
    int defaultBottomMargin = readDimen(R.dimen.message_bubble_bottom_padding);
    int collapsedBottomMargin = readDimen(R.dimen.message_bubble_collapsed_bottom_padding);
    if (!updatingFooter && getActiveFooter(messageRecord) == footer && !hasAudio(messageRecord) && isFooterVisible(messageRecord, nextMessageRecord, groupThread) && !bodyText.isJumbomoji() && conversationMessage.getBottomButton() == null && !StringUtil.hasMixedTextDirection(bodyText.getText()) && bodyText.getLastLineWidth() > 0) {
        TextView dateView = footer.getDateView();
        int footerWidth = footer.getMeasuredWidth();
        int availableWidth = getAvailableMessageBubbleWidth(bodyText);
        int collapsedTopMargin = -1 * (dateView.getMeasuredHeight() + ViewUtil.dpToPx(4));
        if (bodyText.isSingleLine() && !messageRecord.isFailed()) {
            int maxBubbleWidth = hasBigImageLinkPreview(messageRecord) || hasThumbnail(messageRecord) ? readDimen(R.dimen.media_bubble_max_width) : getMaxBubbleWidth();
            int bodyMargins = ViewUtil.getLeftMargin(bodyText) + ViewUtil.getRightMargin(bodyText);
            int sizeWithMargins = bodyText.getMeasuredWidth() + ViewUtil.dpToPx(6) + footerWidth + bodyMargins;
            int minSize = Math.min(maxBubbleWidth, Math.max(bodyText.getMeasuredWidth() + ViewUtil.dpToPx(6) + footerWidth + bodyMargins, bodyBubble.getMeasuredWidth()));
            if (hasQuote(messageRecord) && sizeWithMargins < availableWidth) {
                ViewUtil.setTopMargin(footer, collapsedTopMargin);
                ViewUtil.setBottomMargin(footer, collapsedBottomMargin);
                needsMeasure = true;
                updatingFooter = true;
            } else if (sizeWithMargins != bodyText.getMeasuredWidth() && sizeWithMargins <= minSize) {
                bodyBubble.getLayoutParams().width = minSize;
                ViewUtil.setTopMargin(footer, collapsedTopMargin);
                ViewUtil.setBottomMargin(footer, collapsedBottomMargin);
                needsMeasure = true;
                updatingFooter = true;
            }
        }
        if (!updatingFooter && !messageRecord.isFailed() && bodyText.getLastLineWidth() + ViewUtil.dpToPx(6) + footerWidth <= bodyText.getMeasuredWidth()) {
            ViewUtil.setTopMargin(footer, collapsedTopMargin);
            ViewUtil.setBottomMargin(footer, collapsedBottomMargin);
            updatingFooter = true;
            needsMeasure = true;
        }
    }
    if (!updatingFooter && ViewUtil.getTopMargin(footer) != defaultTopMargin) {
        ViewUtil.setTopMargin(footer, defaultTopMargin);
        ViewUtil.setBottomMargin(footer, defaultBottomMargin);
        needsMeasure = true;
    }
    if (hasSharedContact(messageRecord)) {
        int contactWidth = sharedContactStub.get().getMeasuredWidth();
        int availableWidth = getAvailableMessageBubbleWidth(sharedContactStub.get());
        if (contactWidth != availableWidth) {
            sharedContactStub.get().getLayoutParams().width = availableWidth;
            needsMeasure = true;
        }
    }
    if (hasAudio(messageRecord)) {
        ConversationItemFooter activeFooter = getActiveFooter(messageRecord);
        int availableWidth = getAvailableMessageBubbleWidth(footer);
        if (activeFooter.getVisibility() != GONE && activeFooter.getMeasuredWidth() != availableWidth) {
            activeFooter.getLayoutParams().width = availableWidth;
            needsMeasure = true;
        }
        int desiredWidth = audioViewStub.get().getMeasuredWidth() + ViewUtil.getLeftMargin(audioViewStub.get()) + ViewUtil.getRightMargin(audioViewStub.get());
        if (bodyBubble.getMeasuredWidth() != desiredWidth) {
            bodyBubble.getLayoutParams().width = desiredWidth;
            needsMeasure = true;
        }
    }
    if (needsMeasure) {
        if (measureCalls < MAX_MEASURE_CALLS) {
            measureCalls++;
            measure(widthMeasureSpec, heightMeasureSpec);
        } else {
            Log.w(TAG, "Hit measure() cap of " + MAX_MEASURE_CALLS);
        }
    } else {
        measureCalls = 0;
        updatingFooter = false;
    }
}
Also used : ConversationItemFooter(org.thoughtcrime.securesms.components.ConversationItemFooter) PlaybackSpeedToggleTextView(org.thoughtcrime.securesms.components.PlaybackSpeedToggleTextView) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) TextView(android.widget.TextView) TextPaint(android.text.TextPaint) SuppressLint(android.annotation.SuppressLint)

Example 3 with ConversationItemFooter

use of org.thoughtcrime.securesms.components.ConversationItemFooter in project Signal-Android by WhisperSystems.

the class ConversationItem method setFooter.

private void setFooter(@NonNull MessageRecord current, @NonNull Optional<MessageRecord> next, @NonNull Locale locale, boolean isGroupThread, boolean hasWallpaper) {
    ViewUtil.updateLayoutParams(footer, LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
    ViewUtil.setTopMargin(footer, readDimen(R.dimen.message_bubble_default_footer_bottom_margin));
    footer.setVisibility(GONE);
    ViewUtil.setVisibilityIfNonNull(stickerFooter, GONE);
    if (sharedContactStub.resolved())
        sharedContactStub.get().getFooter().setVisibility(GONE);
    if (mediaThumbnailStub.resolved())
        mediaThumbnailStub.require().getFooter().setVisibility(GONE);
    if (isFooterVisible(current, next, isGroupThread)) {
        ConversationItemFooter activeFooter = getActiveFooter(current);
        activeFooter.setVisibility(VISIBLE);
        activeFooter.setMessageRecord(current, locale);
        if (hasWallpaper && hasNoBubble((messageRecord))) {
            if (messageRecord.isOutgoing()) {
                activeFooter.disableBubbleBackground();
                activeFooter.setTextColor(ContextCompat.getColor(context, R.color.conversation_item_sent_text_secondary_color));
                activeFooter.setIconColor(ContextCompat.getColor(context, R.color.conversation_item_sent_text_secondary_color));
                activeFooter.setRevealDotColor(ContextCompat.getColor(context, R.color.conversation_item_sent_text_secondary_color));
            } else {
                activeFooter.enableBubbleBackground(R.drawable.wallpaper_bubble_background_tintable_11, getDefaultBubbleColor(hasWallpaper));
            }
        } else if (hasNoBubble(messageRecord)) {
            activeFooter.disableBubbleBackground();
            activeFooter.setTextColor(ContextCompat.getColor(context, R.color.signal_text_secondary));
            activeFooter.setIconColor(ContextCompat.getColor(context, R.color.signal_icon_tint_secondary));
            activeFooter.setRevealDotColor(ContextCompat.getColor(context, R.color.signal_icon_tint_secondary));
        } else {
            activeFooter.disableBubbleBackground();
        }
    }
}
Also used : ConversationItemFooter(org.thoughtcrime.securesms.components.ConversationItemFooter)

Example 4 with ConversationItemFooter

use of org.thoughtcrime.securesms.components.ConversationItemFooter in project Signal-Android by WhisperSystems.

the class LongMessageFragment method initViewModel.

private void initViewModel(long messageId, boolean isMms) {
    viewModel = new ViewModelProvider(this, new LongMessageViewModel.Factory(requireActivity().getApplication(), new LongMessageRepository(), messageId, isMms)).get(LongMessageViewModel.class);
    viewModel.getMessage().observe(this, message -> {
        if (message == null)
            return;
        if (!message.isPresent()) {
            Toast.makeText(requireContext(), R.string.LongMessageActivity_unable_to_find_message, Toast.LENGTH_SHORT).show();
            dismissAllowingStateLoss();
            return;
        }
        if (message.get().getMessageRecord().isOutgoing()) {
            toolbar.setTitle(getString(R.string.LongMessageActivity_your_message));
        } else {
            Recipient recipient = message.get().getMessageRecord().getRecipient();
            String name = recipient.getDisplayName(requireContext());
            toolbar.setTitle(getString(R.string.LongMessageActivity_message_from_s, name));
        }
        ViewGroup bubble;
        if (message.get().getMessageRecord().isOutgoing()) {
            bubble = sentBubble.get();
            colorizerView.setVisibility(View.VISIBLE);
            colorizerView.setBackground(message.get().getMessageRecord().getRecipient().getChatColors().getChatBubbleMask());
            bubble.getBackground().setColorFilter(message.get().getMessageRecord().getRecipient().getChatColors().getChatBubbleColorFilter());
            bubble.addOnLayoutChangeListener(bubbleLayoutListener);
            bubbleLayoutListener.onLayoutChange(bubble, 0, 0, 0, 0, 0, 0, 0, 0);
        } else {
            bubble = receivedBubble.get();
            bubble.getBackground().setColorFilter(ContextCompat.getColor(requireContext(), R.color.signal_background_secondary), PorterDuff.Mode.MULTIPLY);
        }
        EmojiTextView text = bubble.findViewById(R.id.longmessage_text);
        ConversationItemFooter footer = bubble.findViewById(R.id.longmessage_footer);
        CharSequence trimmedBody = getTrimmedBody(message.get().getFullBody(requireContext()));
        SpannableString styledBody = linkifyMessageBody(new SpannableString(trimmedBody));
        bubble.setVisibility(View.VISIBLE);
        text.setText(styledBody);
        text.setMovementMethod(LinkMovementMethod.getInstance());
        text.setTextSize(TypedValue.COMPLEX_UNIT_SP, SignalStore.settings().getMessageFontSize());
        if (!message.get().getMessageRecord().isOutgoing()) {
            text.setMentionBackgroundTint(ContextCompat.getColor(requireContext(), ThemeUtil.isDarkTheme(requireActivity()) ? R.color.core_grey_60 : R.color.core_grey_20));
        } else {
            text.setMentionBackgroundTint(ContextCompat.getColor(requireContext(), R.color.transparent_black_40));
        }
        footer.setMessageRecord(message.get().getMessageRecord(), Locale.getDefault());
    });
}
Also used : SpannableString(android.text.SpannableString) ConversationItemFooter(org.thoughtcrime.securesms.components.ConversationItemFooter) ViewGroup(android.view.ViewGroup) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) Recipient(org.thoughtcrime.securesms.recipients.Recipient) SpannableString(android.text.SpannableString) ViewModelProvider(androidx.lifecycle.ViewModelProvider)

Aggregations

ConversationItemFooter (org.thoughtcrime.securesms.components.ConversationItemFooter)4 SuppressLint (android.annotation.SuppressLint)2 TextPaint (android.text.TextPaint)2 EmojiTextView (org.thoughtcrime.securesms.components.emoji.EmojiTextView)2 SpannableString (android.text.SpannableString)1 ViewGroup (android.view.ViewGroup)1 TextView (android.widget.TextView)1 NonNull (androidx.annotation.NonNull)1 ViewModelProvider (androidx.lifecycle.ViewModelProvider)1 PlaybackSpeedToggleTextView (org.thoughtcrime.securesms.components.PlaybackSpeedToggleTextView)1 Recipient (org.thoughtcrime.securesms.recipients.Recipient)1 Projection (org.thoughtcrime.securesms.util.Projection)1