Search in sources :

Example 1 with EmojiTextView

use of org.thoughtcrime.securesms.components.emoji.EmojiTextView 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)

Example 2 with EmojiTextView

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

the class AvatarPreviewActivity method onCreate.

@Override
protected void onCreate(Bundle savedInstanceState, boolean ready) {
    super.onCreate(savedInstanceState, ready);
    setTheme(R.style.TextSecure_MediaPreview);
    setContentView(R.layout.contact_photo_preview_activity);
    if (Build.VERSION.SDK_INT >= 21) {
        postponeEnterTransition();
        TransitionInflater inflater = TransitionInflater.from(this);
        getWindow().setSharedElementEnterTransition(inflater.inflateTransition(R.transition.full_screen_avatar_image_enter_transition_set));
        getWindow().setSharedElementReturnTransition(inflater.inflateTransition(R.transition.full_screen_avatar_image_return_transition_set));
    }
    Toolbar toolbar = findViewById(R.id.toolbar);
    EmojiTextView title = findViewById(R.id.title);
    ImageView avatar = findViewById(R.id.avatar);
    setSupportActionBar(toolbar);
    requireSupportActionBar().setDisplayHomeAsUpEnabled(true);
    requireSupportActionBar().setDisplayShowTitleEnabled(false);
    Context context = getApplicationContext();
    RecipientId recipientId = RecipientId.from(getIntent().getStringExtra(RECIPIENT_ID_EXTRA));
    Recipient.live(recipientId).observe(this, recipient -> {
        ContactPhoto contactPhoto = recipient.isSelf() ? new ProfileContactPhoto(recipient, recipient.getProfileAvatar()) : recipient.getContactPhoto();
        FallbackContactPhoto fallbackPhoto = recipient.isSelf() ? new ResourceContactPhoto(R.drawable.ic_profile_outline_40, R.drawable.ic_profile_outline_20, R.drawable.ic_person_large) : recipient.getFallbackContactPhoto();
        Resources resources = this.getResources();
        GlideApp.with(this).asBitmap().load(contactPhoto).fallback(fallbackPhoto.asCallCard(this)).error(fallbackPhoto.asCallCard(this)).diskCacheStrategy(DiskCacheStrategy.ALL).addListener(new RequestListener<Bitmap>() {

            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                Log.w(TAG, "Unable to load avatar, or avatar removed, closing");
                finish();
                return false;
            }

            @Override
            public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                return false;
            }
        }).into(new CustomTarget<Bitmap>() {

            @Override
            public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                avatar.setImageDrawable(RoundedBitmapDrawableFactory.create(resources, resource));
                if (Build.VERSION.SDK_INT >= 21) {
                    startPostponedEnterTransition();
                }
            }

            @Override
            public void onLoadCleared(@Nullable Drawable placeholder) {
            }
        });
        title.setText(recipient.getDisplayName(context));
    });
    FullscreenHelper fullscreenHelper = new FullscreenHelper(this);
    findViewById(android.R.id.content).setOnClickListener(v -> fullscreenHelper.toggleUiVisibility());
    fullscreenHelper.configureToolbarSpacer(findViewById(R.id.toolbar_cutout_spacer));
    fullscreenHelper.showAndHideWithSystemUI(getWindow(), findViewById(R.id.toolbar_layout));
}
Also used : Context(android.content.Context) ProfileContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) RequestListener(com.bumptech.glide.request.RequestListener) Drawable(android.graphics.drawable.Drawable) TransitionInflater(android.transition.TransitionInflater) ContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ContactPhoto) ProfileContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto) FallbackContactPhoto(org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto) ResourceContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto) DataSource(com.bumptech.glide.load.DataSource) FallbackContactPhoto(org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto) CustomTarget(com.bumptech.glide.request.target.CustomTarget) Target(com.bumptech.glide.request.target.Target) Bitmap(android.graphics.Bitmap) ResourceContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) ImageView(android.widget.ImageView) Resources(android.content.res.Resources) GlideException(com.bumptech.glide.load.engine.GlideException) Nullable(androidx.annotation.Nullable) FullscreenHelper(org.thoughtcrime.securesms.util.FullscreenHelper) Toolbar(androidx.appcompat.widget.Toolbar)

Example 3 with EmojiTextView

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

the class GroupDescriptionUtil method setText.

/**
 * Set a group description.
 *
 * @param description   full description
 * @param emojiTextView Text view to update with description
 * @param linkify       flag indicating if web urls should be linkified
 * @param moreClick     Callback for when truncating and need to show more via another means. Required to enable truncating.
 */
public static void setText(@NonNull Context context, @NonNull EmojiTextView emojiTextView, @NonNull String description, boolean linkify, @Nullable Runnable moreClick) {
    boolean shouldEllipsize = moreClick != null;
    String scrubbedDescription = shouldEllipsize ? description.replaceAll("\\n", " ") : description;
    SpannableString descriptionSpannable = new SpannableString(scrubbedDescription);
    if (linkify) {
        int linkPattern = Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS;
        boolean hasLinks = LinkifyCompat.addLinks(descriptionSpannable, linkPattern);
        if (hasLinks) {
            Stream.of(descriptionSpannable.getSpans(0, descriptionSpannable.length(), URLSpan.class)).filterNot(url -> LinkPreviewUtil.isLegalUrl(url.getURL())).forEach(descriptionSpannable::removeSpan);
            URLSpan[] urlSpans = descriptionSpannable.getSpans(0, descriptionSpannable.length(), URLSpan.class);
            for (URLSpan urlSpan : urlSpans) {
                int start = descriptionSpannable.getSpanStart(urlSpan);
                int end = descriptionSpannable.getSpanEnd(urlSpan);
                URLSpan span = new LongClickCopySpan(urlSpan.getURL());
                descriptionSpannable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    }
    if (shouldEllipsize) {
        ClickableSpan style = new ClickableSpan() {

            @Override
            public void onClick(@NonNull View widget) {
                moreClick.run();
            }

            @Override
            public void updateDrawState(@NonNull TextPaint ds) {
                ds.setTypeface(Typeface.DEFAULT_BOLD);
            }
        };
        emojiTextView.setEllipsize(TextUtils.TruncateAt.END);
        emojiTextView.setMaxLines(2);
        SpannableString overflowText = new SpannableString(context.getString(R.string.ManageGroupActivity_more));
        overflowText.setSpan(style, 0, overflowText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        emojiTextView.setOverflowText(overflowText);
    }
    emojiTextView.setText(descriptionSpannable);
}
Also used : Typeface(android.graphics.Typeface) Context(android.content.Context) Spanned(android.text.Spanned) URLSpan(android.text.style.URLSpan) Stream(com.annimon.stream.Stream) SpannableString(android.text.SpannableString) NonNull(androidx.annotation.NonNull) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) TextUtils(android.text.TextUtils) ClickableSpan(android.text.style.ClickableSpan) Linkify(android.text.util.Linkify) R(org.thoughtcrime.securesms.R) LinkPreviewUtil(org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil) LongClickCopySpan(org.thoughtcrime.securesms.util.LongClickCopySpan) Nullable(androidx.annotation.Nullable) TextPaint(android.text.TextPaint) LinkifyCompat(androidx.core.text.util.LinkifyCompat) View(android.view.View) LongClickCopySpan(org.thoughtcrime.securesms.util.LongClickCopySpan) SpannableString(android.text.SpannableString) URLSpan(android.text.style.URLSpan) ClickableSpan(android.text.style.ClickableSpan) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) View(android.view.View) TextPaint(android.text.TextPaint) TextPaint(android.text.TextPaint) SpannableString(android.text.SpannableString) NonNull(androidx.annotation.NonNull)

Example 4 with EmojiTextView

use of org.thoughtcrime.securesms.components.emoji.EmojiTextView in project Signal-Android by signalapp.

the class AvatarPreviewActivity method onCreate.

@Override
protected void onCreate(Bundle savedInstanceState, boolean ready) {
    super.onCreate(savedInstanceState, ready);
    setTheme(R.style.TextSecure_MediaPreview);
    setContentView(R.layout.contact_photo_preview_activity);
    if (Build.VERSION.SDK_INT >= 21) {
        postponeEnterTransition();
        TransitionInflater inflater = TransitionInflater.from(this);
        getWindow().setSharedElementEnterTransition(inflater.inflateTransition(R.transition.full_screen_avatar_image_enter_transition_set));
        getWindow().setSharedElementReturnTransition(inflater.inflateTransition(R.transition.full_screen_avatar_image_return_transition_set));
    }
    Toolbar toolbar = findViewById(R.id.toolbar);
    EmojiTextView title = findViewById(R.id.title);
    ImageView avatar = findViewById(R.id.avatar);
    setSupportActionBar(toolbar);
    requireSupportActionBar().setDisplayHomeAsUpEnabled(true);
    requireSupportActionBar().setDisplayShowTitleEnabled(false);
    Context context = getApplicationContext();
    RecipientId recipientId = RecipientId.from(getIntent().getStringExtra(RECIPIENT_ID_EXTRA));
    Recipient.live(recipientId).observe(this, recipient -> {
        ContactPhoto contactPhoto = recipient.isSelf() ? new ProfileContactPhoto(recipient, recipient.getProfileAvatar()) : recipient.getContactPhoto();
        FallbackContactPhoto fallbackPhoto = recipient.isSelf() ? new ResourceContactPhoto(R.drawable.ic_profile_outline_40, R.drawable.ic_profile_outline_20, R.drawable.ic_person_large) : recipient.getFallbackContactPhoto();
        Resources resources = this.getResources();
        GlideApp.with(this).asBitmap().load(contactPhoto).fallback(fallbackPhoto.asCallCard(this)).error(fallbackPhoto.asCallCard(this)).diskCacheStrategy(DiskCacheStrategy.ALL).addListener(new RequestListener<Bitmap>() {

            @Override
            public boolean onLoadFailed(@Nullable GlideException e, Object model, Target<Bitmap> target, boolean isFirstResource) {
                Log.w(TAG, "Unable to load avatar, or avatar removed, closing");
                finish();
                return false;
            }

            @Override
            public boolean onResourceReady(Bitmap resource, Object model, Target<Bitmap> target, DataSource dataSource, boolean isFirstResource) {
                return false;
            }
        }).into(new CustomTarget<Bitmap>() {

            @Override
            public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
                avatar.setImageDrawable(RoundedBitmapDrawableFactory.create(resources, resource));
                if (Build.VERSION.SDK_INT >= 21) {
                    startPostponedEnterTransition();
                }
            }

            @Override
            public void onLoadCleared(@Nullable Drawable placeholder) {
            }
        });
        title.setText(recipient.getDisplayName(context));
    });
    FullscreenHelper fullscreenHelper = new FullscreenHelper(this);
    findViewById(android.R.id.content).setOnClickListener(v -> fullscreenHelper.toggleUiVisibility());
    fullscreenHelper.configureToolbarSpacer(findViewById(R.id.toolbar_cutout_spacer));
    fullscreenHelper.showAndHideWithSystemUI(getWindow(), findViewById(R.id.toolbar_layout));
}
Also used : Context(android.content.Context) ProfileContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto) RecipientId(org.thoughtcrime.securesms.recipients.RecipientId) RequestListener(com.bumptech.glide.request.RequestListener) Drawable(android.graphics.drawable.Drawable) TransitionInflater(android.transition.TransitionInflater) ContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ContactPhoto) ProfileContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ProfileContactPhoto) FallbackContactPhoto(org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto) ResourceContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto) DataSource(com.bumptech.glide.load.DataSource) FallbackContactPhoto(org.thoughtcrime.securesms.contacts.avatars.FallbackContactPhoto) CustomTarget(com.bumptech.glide.request.target.CustomTarget) Target(com.bumptech.glide.request.target.Target) Bitmap(android.graphics.Bitmap) ResourceContactPhoto(org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) ImageView(android.widget.ImageView) Resources(android.content.res.Resources) GlideException(com.bumptech.glide.load.engine.GlideException) Nullable(androidx.annotation.Nullable) FullscreenHelper(org.thoughtcrime.securesms.util.FullscreenHelper) Toolbar(androidx.appcompat.widget.Toolbar)

Example 5 with EmojiTextView

use of org.thoughtcrime.securesms.components.emoji.EmojiTextView in project Signal-Android by signalapp.

the class GroupDescriptionUtil method setText.

/**
 * Set a group description.
 *
 * @param description   full description
 * @param emojiTextView Text view to update with description
 * @param linkify       flag indicating if web urls should be linkified
 * @param moreClick     Callback for when truncating and need to show more via another means. Required to enable truncating.
 */
public static void setText(@NonNull Context context, @NonNull EmojiTextView emojiTextView, @NonNull String description, boolean linkify, @Nullable Runnable moreClick) {
    boolean shouldEllipsize = moreClick != null;
    String scrubbedDescription = shouldEllipsize ? description.replaceAll("\\n", " ") : description;
    SpannableString descriptionSpannable = new SpannableString(scrubbedDescription);
    if (linkify) {
        int linkPattern = Linkify.WEB_URLS | Linkify.EMAIL_ADDRESSES | Linkify.PHONE_NUMBERS;
        boolean hasLinks = LinkifyCompat.addLinks(descriptionSpannable, linkPattern);
        if (hasLinks) {
            Stream.of(descriptionSpannable.getSpans(0, descriptionSpannable.length(), URLSpan.class)).filterNot(url -> LinkPreviewUtil.isLegalUrl(url.getURL())).forEach(descriptionSpannable::removeSpan);
            URLSpan[] urlSpans = descriptionSpannable.getSpans(0, descriptionSpannable.length(), URLSpan.class);
            for (URLSpan urlSpan : urlSpans) {
                int start = descriptionSpannable.getSpanStart(urlSpan);
                int end = descriptionSpannable.getSpanEnd(urlSpan);
                URLSpan span = new LongClickCopySpan(urlSpan.getURL());
                descriptionSpannable.setSpan(span, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
            }
        }
    }
    if (shouldEllipsize) {
        ClickableSpan style = new ClickableSpan() {

            @Override
            public void onClick(@NonNull View widget) {
                moreClick.run();
            }

            @Override
            public void updateDrawState(@NonNull TextPaint ds) {
                ds.setTypeface(Typeface.DEFAULT_BOLD);
            }
        };
        emojiTextView.setEllipsize(TextUtils.TruncateAt.END);
        emojiTextView.setMaxLines(2);
        SpannableString overflowText = new SpannableString(context.getString(R.string.ManageGroupActivity_more));
        overflowText.setSpan(style, 0, overflowText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        emojiTextView.setOverflowText(overflowText);
    }
    emojiTextView.setText(descriptionSpannable);
}
Also used : Typeface(android.graphics.Typeface) Context(android.content.Context) Spanned(android.text.Spanned) URLSpan(android.text.style.URLSpan) Stream(com.annimon.stream.Stream) SpannableString(android.text.SpannableString) NonNull(androidx.annotation.NonNull) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) TextUtils(android.text.TextUtils) ClickableSpan(android.text.style.ClickableSpan) Linkify(android.text.util.Linkify) R(org.thoughtcrime.securesms.R) LinkPreviewUtil(org.thoughtcrime.securesms.linkpreview.LinkPreviewUtil) LongClickCopySpan(org.thoughtcrime.securesms.util.LongClickCopySpan) Nullable(androidx.annotation.Nullable) TextPaint(android.text.TextPaint) LinkifyCompat(androidx.core.text.util.LinkifyCompat) View(android.view.View) LongClickCopySpan(org.thoughtcrime.securesms.util.LongClickCopySpan) SpannableString(android.text.SpannableString) URLSpan(android.text.style.URLSpan) ClickableSpan(android.text.style.ClickableSpan) EmojiTextView(org.thoughtcrime.securesms.components.emoji.EmojiTextView) View(android.view.View) TextPaint(android.text.TextPaint) TextPaint(android.text.TextPaint) SpannableString(android.text.SpannableString) NonNull(androidx.annotation.NonNull)

Aggregations

EmojiTextView (org.thoughtcrime.securesms.components.emoji.EmojiTextView)6 Context (android.content.Context)4 SpannableString (android.text.SpannableString)4 Nullable (androidx.annotation.Nullable)4 Resources (android.content.res.Resources)2 Bitmap (android.graphics.Bitmap)2 Typeface (android.graphics.Typeface)2 Drawable (android.graphics.drawable.Drawable)2 Spanned (android.text.Spanned)2 TextPaint (android.text.TextPaint)2 TextUtils (android.text.TextUtils)2 ClickableSpan (android.text.style.ClickableSpan)2 URLSpan (android.text.style.URLSpan)2 Linkify (android.text.util.Linkify)2 TransitionInflater (android.transition.TransitionInflater)2 View (android.view.View)2 ViewGroup (android.view.ViewGroup)2 ImageView (android.widget.ImageView)2 NonNull (androidx.annotation.NonNull)2 Toolbar (androidx.appcompat.widget.Toolbar)2