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;
}
}
}
}
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;
}
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;
}
Aggregations