org.telegram.ui.Cells.SharedLinkCell.java Source code

Java tutorial

Introduction

Here is the source code for org.telegram.ui.Cells.SharedLinkCell.java

Source

/*
 * This is the source code of Telegram for Android v. 3.x.x.
 * It is licensed under GNU GPL v. 2 or later.
 * You should have received a copy of the license in this archive (see LICENSE).
 *
 * Copyright Nikolai Kudashov, 2013-2016.
 */

package org.telegram.ui.Cells;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.support.v4.content.ContextCompat;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.text.TextUtils;
import android.view.Gravity;
import android.view.MotionEvent;
import android.widget.FrameLayout;

import org.telegram.messenger.AndroidUtilities;
import org.telegram.messenger.ImageReceiver;
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MediaController;
import org.telegram.messenger.MessageObject;
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.R;
import org.telegram.messenger.browser.Browser;
import org.telegram.tgnet.TLRPC;
import org.telegram.ui.Components.CheckBox;
import org.telegram.ui.Components.LayoutHelper;
import org.telegram.ui.Components.LetterDrawable;
import org.telegram.ui.Components.LinkPath;
import org.telegram.ui.ActionBar.Theme;

import java.io.File;
import java.util.ArrayList;
import java.util.Locale;

public class SharedLinkCell extends FrameLayout {

    public interface SharedLinkCellDelegate {
        void needOpenWebView(TLRPC.WebPage webPage);

        boolean canPerformActions();
    }

    private boolean linkPreviewPressed;
    private LinkPath urlPath = new LinkPath();
    private static Paint urlPaint;
    private int pressedLink;

    private ImageReceiver linkImageView;
    private boolean drawLinkImageView;
    private LetterDrawable letterDrawable;
    private CheckBox checkBox;

    private SharedLinkCellDelegate delegate;

    private boolean needDivider;

    ArrayList<String> links = new ArrayList<>();
    private int linkY;
    private ArrayList<StaticLayout> linkLayout = new ArrayList<>();

    private int titleY = AndroidUtilities.dp(7);
    private StaticLayout titleLayout;

    private int descriptionY = AndroidUtilities.dp(27);
    private StaticLayout descriptionLayout;

    private int description2Y = AndroidUtilities.dp(27);
    private StaticLayout descriptionLayout2;

    private MessageObject message;

    private static TextPaint titleTextPaint;
    private static TextPaint descriptionTextPaint;
    private static Paint paint;

    private static int TEXT_COLOR;

    public SharedLinkCell(Context context) {
        super(context);

        if (titleTextPaint == null) {
            titleTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
            titleTextPaint.setTypeface(AndroidUtilities.getTypeface("fonts/rmedium.ttf"));

            TEXT_COLOR = ContextCompat.getColor(context, R.color.primary_text);
            titleTextPaint.setColor(TEXT_COLOR);

            descriptionTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);

            paint = new Paint();
            paint.setColor(ContextCompat.getColor(context, R.color.divider));
            paint.setStrokeWidth(1);

            urlPaint = new Paint();
            urlPaint.setColor(Theme.MSG_LINK_SELECT_BACKGROUND_COLOR);
        }

        titleTextPaint.setTextSize(AndroidUtilities.dp(16));
        descriptionTextPaint.setTextSize(AndroidUtilities.dp(16));

        setWillNotDraw(false);
        linkImageView = new ImageReceiver(this);
        letterDrawable = new LetterDrawable();

        checkBox = new CheckBox(context, R.drawable.round_check2);
        checkBox.setVisibility(INVISIBLE);
        addView(checkBox,
                LayoutHelper.createFrame(22, 22,
                        (LocaleController.isRTL ? Gravity.RIGHT : Gravity.LEFT) | Gravity.TOP,
                        LocaleController.isRTL ? 0 : 44, 44, LocaleController.isRTL ? 44 : 0, 0));
    }

    @SuppressLint("DrawAllocation")
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        drawLinkImageView = false;
        descriptionLayout = null;
        titleLayout = null;
        descriptionLayout2 = null;
        description2Y = descriptionY;
        linkLayout.clear();
        links.clear();

        int maxWidth = MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(AndroidUtilities.leftBaseline)
                - AndroidUtilities.dp(8);

        String title = null;
        String description = null;
        String description2 = null;
        String webPageLink = null;
        boolean hasPhoto = false;

        if (message.messageOwner.media instanceof TLRPC.TL_messageMediaWebPage
                && message.messageOwner.media.webpage instanceof TLRPC.TL_webPage) {
            TLRPC.WebPage webPage = message.messageOwner.media.webpage;
            if (message.photoThumbs == null && webPage.photo != null) {
                message.generateThumbs(true);
            }
            hasPhoto = webPage.photo != null && message.photoThumbs != null;
            title = webPage.title;
            if (title == null) {
                title = webPage.site_name;
            }
            description = webPage.description;
            webPageLink = webPage.url;
        }
        if (message != null && !message.messageOwner.entities.isEmpty()) {
            for (int a = 0; a < message.messageOwner.entities.size(); a++) {
                TLRPC.MessageEntity entity = message.messageOwner.entities.get(a);
                if (entity.length <= 0 || entity.offset < 0
                        || entity.offset >= message.messageOwner.message.length()) {
                    continue;
                } else if (entity.offset + entity.length > message.messageOwner.message.length()) {
                    entity.length = message.messageOwner.message.length() - entity.offset;
                }
                if (a == 0 && webPageLink != null
                        && !(entity.offset == 0 && entity.length == message.messageOwner.message.length())) {
                    if (message.messageOwner.entities.size() == 1) {
                        if (description == null) {
                            description2 = message.messageOwner.message;
                        }
                    } else {
                        description2 = message.messageOwner.message;
                    }
                }
                try {
                    String link = null;
                    if (entity instanceof TLRPC.TL_messageEntityTextUrl
                            || entity instanceof TLRPC.TL_messageEntityUrl) {
                        if (entity instanceof TLRPC.TL_messageEntityUrl) {
                            link = message.messageOwner.message.substring(entity.offset,
                                    entity.offset + entity.length);
                        } else {
                            link = entity.url;
                        }
                        if (title == null || title.length() == 0) {
                            title = link;
                            Uri uri = Uri.parse(title);
                            title = uri.getHost();
                            if (title == null) {
                                title = link;
                            }
                            int index;
                            if (title != null && (index = title.lastIndexOf('.')) >= 0) {
                                title = title.substring(0, index);
                                if ((index = title.lastIndexOf('.')) >= 0) {
                                    title = title.substring(index + 1);
                                }
                                title = title.substring(0, 1).toUpperCase() + title.substring(1);
                            }
                            if (entity.offset != 0 || entity.length != message.messageOwner.message.length()) {
                                description = message.messageOwner.message;
                            }
                        }
                    } else if (entity instanceof TLRPC.TL_messageEntityEmail) {
                        if (title == null || title.length() == 0) {
                            link = "mailto:" + message.messageOwner.message.substring(entity.offset,
                                    entity.offset + entity.length);
                            title = message.messageOwner.message.substring(entity.offset,
                                    entity.offset + entity.length);
                            if (entity.offset != 0 || entity.length != message.messageOwner.message.length()) {
                                description = message.messageOwner.message;
                            }
                        }
                    }
                    if (link != null) {
                        if (link.toLowerCase().indexOf("http") != 0 && link.toLowerCase().indexOf("mailto") != 0) {
                            links.add("http://" + link);
                        } else {
                            links.add(link);
                        }
                    }
                } catch (Exception e) {
                    FileLog.e("tmessages", e);
                }
            }
        }
        if (webPageLink != null && links.isEmpty()) {
            links.add(webPageLink);
        }

        if (title != null) {
            try {
                int width = (int) Math.ceil(titleTextPaint.measureText(title));
                CharSequence titleFinal = TextUtils.ellipsize(title.replace('\n', ' '), titleTextPaint,
                        Math.min(width, maxWidth), TextUtils.TruncateAt.END);
                titleLayout = new StaticLayout(titleFinal, titleTextPaint, maxWidth, Layout.Alignment.ALIGN_NORMAL,
                        1.0f, 0.0f, false);
            } catch (Exception e) {
                FileLog.e("tmessages", e);
            }
            letterDrawable.setTitle(title);
        }

        if (description != null) {
            try {
                descriptionLayout = ChatMessageCell.generateStaticLayout(description, descriptionTextPaint,
                        maxWidth, maxWidth, 0, 3);
                if (descriptionLayout.getLineCount() > 0) {
                    description2Y = descriptionY
                            + descriptionLayout.getLineBottom(descriptionLayout.getLineCount() - 1)
                            + AndroidUtilities.dp(1);
                }
            } catch (Exception e) {
                FileLog.e("tmessages", e);
            }
        }

        if (description2 != null) {
            try {
                descriptionLayout2 = ChatMessageCell.generateStaticLayout(description2, descriptionTextPaint,
                        maxWidth, maxWidth, 0, 3);
                int height = descriptionLayout2.getLineBottom(descriptionLayout2.getLineCount() - 1);
                if (descriptionLayout != null) {
                    description2Y += AndroidUtilities.dp(10);
                }
            } catch (Exception e) {
                FileLog.e("tmessages", e);
            }
        }

        if (!links.isEmpty()) {
            for (int a = 0; a < links.size(); a++) {
                try {
                    String link = links.get(a);
                    int width = (int) Math.ceil(descriptionTextPaint.measureText(link));
                    CharSequence linkFinal = TextUtils.ellipsize(link.replace('\n', ' '), descriptionTextPaint,
                            Math.min(width, maxWidth), TextUtils.TruncateAt.MIDDLE);
                    StaticLayout layout = new StaticLayout(linkFinal, descriptionTextPaint, maxWidth,
                            Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
                    linkY = description2Y;
                    if (descriptionLayout2 != null && descriptionLayout2.getLineCount() != 0) {
                        linkY += descriptionLayout2.getLineBottom(descriptionLayout2.getLineCount() - 1)
                                + AndroidUtilities.dp(1);
                    }
                    linkLayout.add(layout);
                } catch (Exception e) {
                    FileLog.e("tmessages", e);
                }
            }
        }

        int maxPhotoWidth = AndroidUtilities.dp(52);
        int x = LocaleController.isRTL
                ? MeasureSpec.getSize(widthMeasureSpec) - AndroidUtilities.dp(10) - maxPhotoWidth
                : AndroidUtilities.dp(10);
        letterDrawable.setBounds(x, AndroidUtilities.dp(10), x + maxPhotoWidth, AndroidUtilities.dp(62));

        if (hasPhoto) {
            TLRPC.PhotoSize currentPhotoObject = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs,
                    maxPhotoWidth, true);
            TLRPC.PhotoSize currentPhotoObjectThumb = FileLoader.getClosestPhotoSizeWithSize(message.photoThumbs,
                    80);
            if (currentPhotoObjectThumb == currentPhotoObject) {
                currentPhotoObjectThumb = null;
            }
            currentPhotoObject.size = -1;
            if (currentPhotoObjectThumb != null) {
                currentPhotoObjectThumb.size = -1;
            }
            linkImageView.setImageCoords(x, AndroidUtilities.dp(10), maxPhotoWidth, maxPhotoWidth);
            String fileName = FileLoader.getAttachFileName(currentPhotoObject);
            boolean photoExist = true;
            File cacheFile = FileLoader.getPathToAttach(currentPhotoObject, true);
            if (!cacheFile.exists()) {
                photoExist = false;
            }
            String filter = String.format(Locale.US, "%d_%d", maxPhotoWidth, maxPhotoWidth);
            if (photoExist
                    || MediaController.getInstance().canDownloadMedia(MediaController.AUTODOWNLOAD_MASK_PHOTO)
                    || FileLoader.getInstance().isLoadingFile(fileName)) {
                linkImageView.setImage(currentPhotoObject.location, filter,
                        currentPhotoObjectThumb != null ? currentPhotoObjectThumb.location : null,
                        String.format(Locale.US, "%d_%d_b", maxPhotoWidth, maxPhotoWidth), 0, null, false);
            } else {
                if (currentPhotoObjectThumb != null) {
                    linkImageView.setImage(null, null, currentPhotoObjectThumb.location,
                            String.format(Locale.US, "%d_%d_b", maxPhotoWidth, maxPhotoWidth), 0, null, false);
                } else {
                    linkImageView.setImageBitmap((Drawable) null);
                }
            }
            drawLinkImageView = true;
        }

        int height = 0;
        if (titleLayout != null && titleLayout.getLineCount() != 0) {
            height += titleLayout.getLineBottom(titleLayout.getLineCount() - 1);
        }
        if (descriptionLayout != null && descriptionLayout.getLineCount() != 0) {
            height += descriptionLayout.getLineBottom(descriptionLayout.getLineCount() - 1);
        }
        if (descriptionLayout2 != null && descriptionLayout2.getLineCount() != 0) {
            height += descriptionLayout2.getLineBottom(descriptionLayout2.getLineCount() - 1);
            if (descriptionLayout != null) {
                height += AndroidUtilities.dp(10);
            }
        }
        for (int a = 0; a < linkLayout.size(); a++) {
            StaticLayout layout = linkLayout.get(a);
            if (layout.getLineCount() > 0) {
                height += layout.getLineBottom(layout.getLineCount() - 1);
            }
        }
        if (hasPhoto) {
            height = Math.max(AndroidUtilities.dp(48), height);
        }
        checkBox.measure(MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(22), MeasureSpec.EXACTLY),
                MeasureSpec.makeMeasureSpec(AndroidUtilities.dp(22), MeasureSpec.EXACTLY));
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
                Math.max(AndroidUtilities.dp(72), height + AndroidUtilities.dp(16)) + (needDivider ? 1 : 0));
    }

    public void setLink(MessageObject messageObject, boolean divider) {
        needDivider = divider;
        resetPressedLink();
        message = messageObject;

        requestLayout();
    }

    public void setDelegate(SharedLinkCellDelegate sharedLinkCellDelegate) {
        delegate = sharedLinkCellDelegate;
    }

    public MessageObject getMessage() {
        return message;
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (drawLinkImageView) {
            linkImageView.onDetachedFromWindow();
        }
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
        if (drawLinkImageView) {
            linkImageView.onAttachedToWindow();
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        boolean result = false;
        if (message != null && !linkLayout.isEmpty() && delegate != null && delegate.canPerformActions()) {
            if (event.getAction() == MotionEvent.ACTION_DOWN
                    || linkPreviewPressed && event.getAction() == MotionEvent.ACTION_UP) {
                int x = (int) event.getX();
                int y = (int) event.getY();
                int offset = 0;
                boolean ok = false;
                for (int a = 0; a < linkLayout.size(); a++) {
                    StaticLayout layout = linkLayout.get(a);
                    if (layout.getLineCount() > 0) {
                        int height = layout.getLineBottom(layout.getLineCount() - 1);
                        int linkPosX = AndroidUtilities
                                .dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline);
                        if (x >= linkPosX + layout.getLineLeft(0) && x <= linkPosX + layout.getLineWidth(0)
                                && y >= linkY + offset && y <= linkY + offset + height) {
                            ok = true;
                            if (event.getAction() == MotionEvent.ACTION_DOWN) {
                                resetPressedLink();
                                pressedLink = a;
                                linkPreviewPressed = true;
                                try {
                                    urlPath.setCurrentLayout(layout, 0, 0);
                                    layout.getSelectionPath(0, layout.getText().length(), urlPath);
                                } catch (Exception e) {
                                    FileLog.e("tmessages", e);
                                }
                                result = true;
                            } else if (linkPreviewPressed) {
                                try {
                                    TLRPC.WebPage webPage = pressedLink == 0 && message.messageOwner.media != null
                                            ? message.messageOwner.media.webpage
                                            : null;
                                    if (webPage != null && Build.VERSION.SDK_INT >= 16 && webPage.embed_url != null
                                            && webPage.embed_url.length() != 0) {
                                        delegate.needOpenWebView(webPage);
                                    } else {
                                        Browser.openUrl(getContext(), links.get(pressedLink));
                                    }
                                } catch (Exception e) {
                                    FileLog.e("tmessages", e);
                                }
                                resetPressedLink();
                                result = true;
                            }
                            break;
                        }
                        offset += height;
                    }
                }
                if (!ok) {
                    resetPressedLink();
                }
            } else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
                resetPressedLink();
            }
        } else {
            resetPressedLink();
        }
        return result || super.onTouchEvent(event);
    }

    public String getLink(int num) {
        if (num < 0 || num >= links.size()) {
            return null;
        }
        return links.get(num);
    }

    protected void resetPressedLink() {
        pressedLink = -1;
        linkPreviewPressed = false;
        invalidate();
    }

    public void setChecked(boolean checked, boolean animated) {
        if (checkBox.getVisibility() != VISIBLE) {
            checkBox.setVisibility(VISIBLE);
        }
        checkBox.setChecked(checked, animated);
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (titleLayout != null) {
            canvas.save();
            canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline),
                    titleY);
            titleLayout.draw(canvas);
            canvas.restore();
        }

        if (descriptionLayout != null) {
            descriptionTextPaint.setColor(TEXT_COLOR);
            canvas.save();
            canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline),
                    descriptionY);
            descriptionLayout.draw(canvas);
            canvas.restore();
        }

        if (descriptionLayout2 != null) {
            descriptionTextPaint.setColor(TEXT_COLOR);
            canvas.save();
            canvas.translate(AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline),
                    description2Y);
            descriptionLayout2.draw(canvas);
            canvas.restore();
        }

        if (!linkLayout.isEmpty()) {
            descriptionTextPaint.setColor(Theme.MSG_LINK_TEXT_COLOR);
            int offset = 0;
            for (int a = 0; a < linkLayout.size(); a++) {
                StaticLayout layout = linkLayout.get(a);
                if (layout.getLineCount() > 0) {
                    canvas.save();
                    canvas.translate(
                            AndroidUtilities.dp(LocaleController.isRTL ? 8 : AndroidUtilities.leftBaseline),
                            linkY + offset);
                    if (pressedLink == a) {
                        canvas.drawPath(urlPath, urlPaint);
                    }
                    layout.draw(canvas);
                    canvas.restore();
                    offset += layout.getLineBottom(layout.getLineCount() - 1);
                }
            }
        }

        letterDrawable.draw(canvas);
        if (drawLinkImageView) {
            linkImageView.draw(canvas);
        }

        if (needDivider) {
            if (LocaleController.isRTL) {
                canvas.drawLine(0, getMeasuredHeight() - 1,
                        getMeasuredWidth() - AndroidUtilities.dp(AndroidUtilities.leftBaseline),
                        getMeasuredHeight() - 1, paint);
            } else {
                canvas.drawLine(AndroidUtilities.dp(AndroidUtilities.leftBaseline), getMeasuredHeight() - 1,
                        getMeasuredWidth(), getMeasuredHeight() - 1, paint);
            }
        }
    }

    public static void resetDivider() {
        titleTextPaint = null;
    }
}