Search in sources :

Example 6 with LinkPath

use of org.telegram.ui.Components.LinkPath in project Telegram-FOSS by Telegram-FOSS-Team.

the class ChatMessageCell method setHighlightedText.

public void setHighlightedText(String text) {
    MessageObject messageObject = messageObjectToSet != null ? messageObjectToSet : currentMessageObject;
    if (messageObject == null || messageObject.messageOwner.message == null || TextUtils.isEmpty(text)) {
        if (!urlPathSelection.isEmpty()) {
            linkSelectionBlockNum = -1;
            resetUrlPaths(true);
            invalidate();
        }
        return;
    }
    text = text.toLowerCase();
    String message = messageObject.messageOwner.message.toLowerCase();
    int start = -1;
    int length = -1;
    String punctuationsChars = " !\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\n";
    for (int a = 0, N1 = message.length(); a < N1; a++) {
        int currentLen = 0;
        for (int b = 0, N2 = Math.min(text.length(), N1 - a); b < N2; b++) {
            boolean match = message.charAt(a + b) == text.charAt(b);
            if (match) {
                if (currentLen != 0 || a == 0 || punctuationsChars.indexOf(message.charAt(a - 1)) >= 0) {
                    currentLen++;
                } else {
                    match = false;
                }
            }
            if (!match || b == N2 - 1) {
                if (currentLen > 0 && currentLen > length) {
                    length = currentLen;
                    start = a;
                }
                break;
            }
        }
    }
    if (start == -1) {
        if (!urlPathSelection.isEmpty()) {
            linkSelectionBlockNum = -1;
            resetUrlPaths(true);
            invalidate();
        }
        return;
    }
    for (int a = start + length, N = message.length(); a < N; a++) {
        if (punctuationsChars.indexOf(message.charAt(a)) < 0) {
            length++;
        } else {
            break;
        }
    }
    int end = start + length;
    if (captionLayout != null && !TextUtils.isEmpty(messageObject.caption)) {
        resetUrlPaths(true);
        try {
            LinkPath path = obtainNewUrlPath(true);
            path.setCurrentLayout(captionLayout, start, 0);
            captionLayout.getSelectionPath(start, end, path);
        } catch (Exception e) {
            FileLog.e(e);
        }
        invalidate();
    } else if (messageObject.textLayoutBlocks != null) {
        for (int c = 0; c < messageObject.textLayoutBlocks.size(); c++) {
            MessageObject.TextLayoutBlock block = messageObject.textLayoutBlocks.get(c);
            if (start >= block.charactersOffset && start < block.charactersEnd) {
                linkSelectionBlockNum = c;
                resetUrlPaths(true);
                try {
                    LinkPath path = obtainNewUrlPath(true);
                    path.setCurrentLayout(block.textLayout, start, 0);
                    block.textLayout.getSelectionPath(start, end, path);
                    if (end >= block.charactersOffset + length) {
                        for (int a = c + 1; a < messageObject.textLayoutBlocks.size(); a++) {
                            MessageObject.TextLayoutBlock nextBlock = messageObject.textLayoutBlocks.get(a);
                            length = nextBlock.charactersEnd - nextBlock.charactersOffset;
                            path = obtainNewUrlPath(true);
                            path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.height);
                            nextBlock.textLayout.getSelectionPath(0, end - nextBlock.charactersOffset, path);
                            if (end < block.charactersOffset + length - 1) {
                                break;
                            }
                        }
                    }
                } catch (Exception e) {
                    FileLog.e(e);
                }
                invalidate();
                break;
            }
        }
    }
}
Also used : LinkPath(org.telegram.ui.Components.LinkPath) MessageObject(org.telegram.messenger.MessageObject) TextPaint(android.text.TextPaint) Paint(android.graphics.Paint) SuppressLint(android.annotation.SuppressLint) Point(org.telegram.ui.Components.Point)

Example 7 with LinkPath

use of org.telegram.ui.Components.LinkPath in project Telegram-FOSS by Telegram-FOSS-Team.

the class ChatMessageCell method checkLinkPreviewMotionEvent.

private boolean checkLinkPreviewMotionEvent(MotionEvent event) {
    if (currentMessageObject.type != 0 || !hasLinkPreview) {
        return false;
    }
    int x = (int) event.getX();
    int y = (int) event.getY();
    if (x >= unmovedTextX && x <= unmovedTextX + backgroundWidth && y >= textY + currentMessageObject.textHeight && y <= textY + currentMessageObject.textHeight + linkPreviewHeight + AndroidUtilities.dp(8 + (drawInstantView ? 46 : 0))) {
        if (event.getAction() == MotionEvent.ACTION_DOWN) {
            if (descriptionLayout != null && y >= descriptionY) {
                try {
                    int checkX = x - (unmovedTextX + AndroidUtilities.dp(10) + descriptionX);
                    int checkY = y - descriptionY;
                    if (checkY <= descriptionLayout.getHeight()) {
                        final int line = descriptionLayout.getLineForVertical(checkY);
                        final int off = descriptionLayout.getOffsetForHorizontal(line, checkX);
                        final float left = descriptionLayout.getLineLeft(line);
                        if (left <= checkX && left + descriptionLayout.getLineWidth(line) >= checkX) {
                            Spannable buffer = (Spannable) currentMessageObject.linkDescription;
                            ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
                            boolean ignore = false;
                            if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) {
                                ignore = true;
                            }
                            if (!ignore) {
                                pressedLink = link[0];
                                linkBlockNum = -10;
                                pressedLinkType = 2;
                                resetUrlPaths(false);
                                startCheckLongPress();
                                try {
                                    LinkPath path = obtainNewUrlPath(false);
                                    int[] pos = getRealSpanStartAndEnd(buffer, pressedLink);
                                    path.setCurrentLayout(descriptionLayout, pos[0], 0);
                                    descriptionLayout.getSelectionPath(pos[0], pos[1], path);
                                } catch (Exception e) {
                                    FileLog.e(e);
                                }
                                invalidate();
                                return true;
                            }
                        }
                    }
                } catch (Exception e) {
                    FileLog.e(e);
                }
            }
            if (pressedLink == null) {
                int side = AndroidUtilities.dp(48);
                boolean area2 = false;
                if (miniButtonState >= 0) {
                    int offset = AndroidUtilities.dp(27);
                    area2 = x >= buttonX + offset && x <= buttonX + offset + side && y >= buttonY + offset && y <= buttonY + offset + side;
                }
                if (area2) {
                    miniButtonPressed = 1;
                    invalidate();
                    return true;
                } else if (drawVideoImageButton && buttonState != -1 && x >= videoButtonX && x <= videoButtonX + AndroidUtilities.dp(26 + 8) + Math.max(infoWidth, docTitleWidth) && y >= videoButtonY && y <= videoButtonY + AndroidUtilities.dp(30)) {
                    videoButtonPressed = 1;
                    invalidate();
                    return true;
                } else if (drawPhotoImage && drawImageButton && buttonState != -1 && (!checkOnlyButtonPressed && photoImage.isInsideImage(x, y) || x >= buttonX && x <= buttonX + AndroidUtilities.dp(48) && y >= buttonY && y <= buttonY + AndroidUtilities.dp(48) && radialProgress.getIcon() != MediaActionDrawable.ICON_NONE)) {
                    buttonPressed = 1;
                    invalidate();
                    return true;
                } else if (drawInstantView) {
                    instantPressed = true;
                    selectorDrawableMaskType[0] = 0;
                    if (Build.VERSION.SDK_INT >= 21 && selectorDrawable[0] != null) {
                        if (selectorDrawable[0].getBounds().contains(x, y)) {
                            selectorDrawable[0].setHotspot(x, y);
                            selectorDrawable[0].setState(pressedState);
                            instantButtonPressed = true;
                        }
                    }
                    invalidate();
                    return true;
                } else if (documentAttachType != DOCUMENT_ATTACH_TYPE_DOCUMENT && drawPhotoImage && photoImage.isInsideImage(x, y)) {
                    linkPreviewPressed = true;
                    TLRPC.WebPage webPage = currentMessageObject.messageOwner.media.webpage;
                    if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && buttonState == -1 && SharedConfig.autoplayGifs && (photoImage.getAnimation() == null || !TextUtils.isEmpty(webPage.embed_url))) {
                        linkPreviewPressed = false;
                        return false;
                    }
                    return true;
                }
            }
        } else if (event.getAction() == MotionEvent.ACTION_UP) {
            if (instantPressed) {
                if (delegate != null) {
                    delegate.didPressInstantButton(this, drawInstantViewType);
                }
                playSoundEffect(SoundEffectConstants.CLICK);
                if (Build.VERSION.SDK_INT >= 21 && selectorDrawable[0] != null) {
                    selectorDrawable[0].setState(StateSet.NOTHING);
                }
                instantPressed = instantButtonPressed = false;
                invalidate();
            } else if (pressedLinkType == 2 || buttonPressed != 0 || miniButtonPressed != 0 || videoButtonPressed != 0 || linkPreviewPressed) {
                if (videoButtonPressed == 1) {
                    videoButtonPressed = 0;
                    playSoundEffect(SoundEffectConstants.CLICK);
                    didPressButton(true, true);
                    invalidate();
                } else if (buttonPressed != 0) {
                    buttonPressed = 0;
                    playSoundEffect(SoundEffectConstants.CLICK);
                    if (drawVideoImageButton) {
                        didClickedImage();
                    } else {
                        didPressButton(true, false);
                    }
                    invalidate();
                } else if (miniButtonPressed != 0) {
                    miniButtonPressed = 0;
                    playSoundEffect(SoundEffectConstants.CLICK);
                    didPressMiniButton(true);
                    invalidate();
                } else if (pressedLink != null) {
                    if (pressedLink instanceof URLSpan) {
                        delegate.didPressUrl(this, pressedLink, false);
                    } else if (pressedLink instanceof ClickableSpan) {
                        ((ClickableSpan) pressedLink).onClick(this);
                    }
                    resetPressedLink(2);
                } else {
                    if (documentAttachType == DOCUMENT_ATTACH_TYPE_ROUND) {
                        if (!MediaController.getInstance().isPlayingMessage(currentMessageObject) || MediaController.getInstance().isMessagePaused()) {
                            delegate.needPlayMessage(currentMessageObject);
                        } else {
                            MediaController.getInstance().pauseMessage(currentMessageObject);
                        }
                    } else if (documentAttachType == DOCUMENT_ATTACH_TYPE_GIF && drawImageButton) {
                        if (buttonState == -1) {
                            if (SharedConfig.autoplayGifs) {
                                delegate.didPressImage(this, lastTouchX, lastTouchY);
                            } else {
                                buttonState = 2;
                                currentMessageObject.gifState = 1;
                                photoImage.setAllowStartAnimation(false);
                                photoImage.stopAnimation();
                                radialProgress.setIcon(getIconForCurrentState(), false, true);
                                invalidate();
                                playSoundEffect(SoundEffectConstants.CLICK);
                            }
                        } else if (buttonState == 2 || buttonState == 0) {
                            didPressButton(true, false);
                            playSoundEffect(SoundEffectConstants.CLICK);
                        }
                    } else {
                        TLRPC.WebPage webPage = currentMessageObject.messageOwner.media.webpage;
                        if (webPage != null && !TextUtils.isEmpty(webPage.embed_url)) {
                            delegate.needOpenWebView(currentMessageObject, webPage.embed_url, webPage.site_name, webPage.title, webPage.url, webPage.embed_width, webPage.embed_height);
                        } else if (buttonState == -1 || buttonState == 3) {
                            delegate.didPressImage(this, lastTouchX, lastTouchY);
                            playSoundEffect(SoundEffectConstants.CLICK);
                        } else if (webPage != null) {
                            Browser.openUrl(getContext(), webPage.url);
                        }
                    }
                    resetPressedLink(2);
                    return true;
                }
            } else {
                resetPressedLink(2);
            }
        } else if (event.getAction() == MotionEvent.ACTION_MOVE) {
            if (instantButtonPressed && Build.VERSION.SDK_INT >= 21 && selectorDrawable[0] != null) {
                selectorDrawable[0].setHotspot(x, y);
            }
        }
    }
    return false;
}
Also used : URLSpanBotCommand(org.telegram.ui.Components.URLSpanBotCommand) URLSpan(android.text.style.URLSpan) ClickableSpan(android.text.style.ClickableSpan) TextPaint(android.text.TextPaint) Paint(android.graphics.Paint) SuppressLint(android.annotation.SuppressLint) Point(org.telegram.ui.Components.Point) TLRPC(org.telegram.tgnet.TLRPC) LinkPath(org.telegram.ui.Components.LinkPath) Spannable(android.text.Spannable)

Example 8 with LinkPath

use of org.telegram.ui.Components.LinkPath in project Telegram-FOSS by Telegram-FOSS-Team.

the class ChatMessageCell method checkTextBlockMotionEvent.

private boolean checkTextBlockMotionEvent(MotionEvent event) {
    if (currentMessageObject.type != 0 || currentMessageObject.textLayoutBlocks == null || currentMessageObject.textLayoutBlocks.isEmpty() || !(currentMessageObject.messageText instanceof Spannable)) {
        return false;
    }
    if (event.getAction() == MotionEvent.ACTION_DOWN || event.getAction() == MotionEvent.ACTION_UP && pressedLinkType == 1) {
        int x = (int) event.getX();
        int y = (int) event.getY();
        if (x >= textX && y >= textY && x <= textX + currentMessageObject.textWidth && y <= textY + currentMessageObject.textHeight) {
            y -= textY;
            int blockNum = 0;
            for (int a = 0; a < currentMessageObject.textLayoutBlocks.size(); a++) {
                if (currentMessageObject.textLayoutBlocks.get(a).textYOffset > y) {
                    break;
                }
                blockNum = a;
            }
            try {
                MessageObject.TextLayoutBlock block = currentMessageObject.textLayoutBlocks.get(blockNum);
                x -= textX - (block.isRtl() ? currentMessageObject.textXOffset : 0);
                y -= block.textYOffset;
                final int line = block.textLayout.getLineForVertical(y);
                final int off = block.charactersOffset + block.textLayout.getOffsetForHorizontal(line, x);
                final float left = block.textLayout.getLineLeft(line);
                if (left <= x && left + block.textLayout.getLineWidth(line) >= x) {
                    Spannable buffer = (Spannable) currentMessageObject.messageText;
                    CharacterStyle[] link = buffer.getSpans(off, off, ClickableSpan.class);
                    boolean isMono = false;
                    if (link == null || link.length == 0) {
                        link = buffer.getSpans(off, off, URLSpanMono.class);
                        isMono = true;
                    }
                    boolean ignore = false;
                    if (link.length == 0 || link[0] instanceof URLSpanBotCommand && !URLSpanBotCommand.enabled) {
                        ignore = true;
                    }
                    if (!ignore) {
                        if (event.getAction() == MotionEvent.ACTION_DOWN) {
                            pressedLink = link[0];
                            linkBlockNum = blockNum;
                            pressedLinkType = 1;
                            resetUrlPaths(false);
                            try {
                                LinkPath path = obtainNewUrlPath(false);
                                int[] pos = getRealSpanStartAndEnd(buffer, pressedLink);
                                pos[0] -= block.charactersOffset;
                                pos[1] -= block.charactersOffset;
                                path.setCurrentLayout(block.textLayout, pos[0], 0);
                                block.textLayout.getSelectionPath(pos[0], pos[1], path);
                                if (pos[1] >= block.charactersEnd) {
                                    for (int a = blockNum + 1; a < currentMessageObject.textLayoutBlocks.size(); a++) {
                                        MessageObject.TextLayoutBlock nextBlock = currentMessageObject.textLayoutBlocks.get(a);
                                        CharacterStyle[] nextLink;
                                        if (isMono) {
                                            nextLink = buffer.getSpans(nextBlock.charactersOffset, nextBlock.charactersOffset, URLSpanMono.class);
                                        } else {
                                            nextLink = buffer.getSpans(nextBlock.charactersOffset, nextBlock.charactersOffset, ClickableSpan.class);
                                        }
                                        if (nextLink == null || nextLink.length == 0 || nextLink[0] != pressedLink) {
                                            break;
                                        }
                                        path = obtainNewUrlPath(false);
                                        path.setCurrentLayout(nextBlock.textLayout, 0, nextBlock.textYOffset - block.textYOffset);
                                        int p1 = pos[1] + block.charactersOffset - nextBlock.charactersOffset;
                                        nextBlock.textLayout.getSelectionPath(0, p1, path);
                                        if (p1 < nextBlock.charactersEnd - 1) {
                                            break;
                                        }
                                    }
                                }
                                if (pos[0] <= block.charactersOffset) {
                                    int offsetY = 0;
                                    for (int a = blockNum - 1; a >= 0; a--) {
                                        MessageObject.TextLayoutBlock nextBlock = currentMessageObject.textLayoutBlocks.get(a);
                                        CharacterStyle[] nextLink;
                                        if (isMono) {
                                            nextLink = buffer.getSpans(nextBlock.charactersEnd - 1, nextBlock.charactersEnd - 1, URLSpanMono.class);
                                        } else {
                                            nextLink = buffer.getSpans(nextBlock.charactersEnd - 1, nextBlock.charactersEnd - 1, ClickableSpan.class);
                                        }
                                        if (nextLink == null || nextLink.length == 0 || nextLink[0] != pressedLink) {
                                            break;
                                        }
                                        path = obtainNewUrlPath(false);
                                        offsetY -= nextBlock.height;
                                        int p0 = pos[0] + block.charactersOffset - nextBlock.charactersOffset;
                                        int p1 = pos[1] + block.charactersOffset - nextBlock.charactersOffset;
                                        path.setCurrentLayout(nextBlock.textLayout, p0, offsetY);
                                        nextBlock.textLayout.getSelectionPath(p0, p1, path);
                                        if (p0 > nextBlock.charactersOffset) {
                                            break;
                                        }
                                    }
                                }
                            } catch (Exception e) {
                                FileLog.e(e);
                            }
                            invalidate();
                            return true;
                        } else {
                            if (link[0] == pressedLink) {
                                delegate.didPressUrl(this, pressedLink, false);
                                resetPressedLink(1);
                                return true;
                            }
                        }
                    }
                }
            } catch (Exception e) {
                FileLog.e(e);
            }
        } else {
            resetPressedLink(1);
        }
    }
    return false;
}
Also used : URLSpanMono(org.telegram.ui.Components.URLSpanMono) URLSpanBotCommand(org.telegram.ui.Components.URLSpanBotCommand) ClickableSpan(android.text.style.ClickableSpan) TextPaint(android.text.TextPaint) Paint(android.graphics.Paint) SuppressLint(android.annotation.SuppressLint) Point(org.telegram.ui.Components.Point) CharacterStyle(android.text.style.CharacterStyle) LinkPath(org.telegram.ui.Components.LinkPath) MessageObject(org.telegram.messenger.MessageObject) Spannable(android.text.Spannable)

Aggregations

LinkPath (org.telegram.ui.Components.LinkPath)8 Paint (android.graphics.Paint)7 SuppressLint (android.annotation.SuppressLint)6 TextPaint (android.text.TextPaint)6 Point (org.telegram.ui.Components.Point)5 Spannable (android.text.Spannable)4 URLSpanBotCommand (org.telegram.ui.Components.URLSpanBotCommand)4 ClickableSpan (android.text.style.ClickableSpan)3 Spanned (android.text.Spanned)2 CharacterStyle (android.text.style.CharacterStyle)2 URLSpan (android.text.style.URLSpan)2 MessageObject (org.telegram.messenger.MessageObject)2 TLRPC (org.telegram.tgnet.TLRPC)2 URLSpanMono (org.telegram.ui.Components.URLSpanMono)2 Animator (android.animation.Animator)1 AnimatorListenerAdapter (android.animation.AnimatorListenerAdapter)1 AnimatorSet (android.animation.AnimatorSet)1 ObjectAnimator (android.animation.ObjectAnimator)1 Intent (android.content.Intent)1 Bitmap (android.graphics.Bitmap)1