NekoX/TMessagesProj/src/main/java/org/telegram/ui/Cells/BotHelpCell.java

404 lines
17 KiB
Java
Raw Normal View History

2015-06-29 19:12:11 +02:00
/*
2019-01-23 18:03:33 +01:00
* This is the source code of Telegram for Android v. 5.x.x.
2015-06-29 19:12:11 +02:00
* It is licensed under GNU GPL v. 2 or later.
* You should have received a copy of the license in this archive (see LICENSE).
*
2019-01-23 18:03:33 +01:00
* Copyright Nikolai Kudashov, 2013-2018.
2015-06-29 19:12:11 +02:00
*/
package org.telegram.ui.Cells;
import android.content.Context;
import android.graphics.Canvas;
2022-06-21 04:51:00 +02:00
import android.graphics.drawable.BitmapDrawable;
2020-01-23 07:15:40 +01:00
import android.graphics.drawable.Drawable;
2023-02-03 20:11:36 +01:00
import android.os.Build;
2015-06-29 19:12:11 +02:00
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.StaticLayout;
2022-06-21 04:51:00 +02:00
import android.text.TextUtils;
2015-06-29 19:12:11 +02:00
import android.text.style.ClickableSpan;
2016-03-06 02:49:31 +01:00
import android.text.style.URLSpan;
2015-06-29 19:12:11 +02:00
import android.view.MotionEvent;
import android.view.View;
2019-05-14 14:08:05 +02:00
import android.view.accessibility.AccessibilityNodeInfo;
2015-06-29 19:12:11 +02:00
2023-02-03 20:11:36 +01:00
import androidx.annotation.NonNull;
2015-09-24 22:52:02 +02:00
import org.telegram.messenger.AndroidUtilities;
2015-11-26 22:04:02 +01:00
import org.telegram.messenger.Emoji;
2022-06-21 04:51:00 +02:00
import org.telegram.messenger.FileLoader;
import org.telegram.messenger.FileLog;
import org.telegram.messenger.FileRefController;
import org.telegram.messenger.ImageLoader;
import org.telegram.messenger.ImageLocation;
import org.telegram.messenger.ImageReceiver;
2015-09-24 22:52:02 +02:00
import org.telegram.messenger.LocaleController;
import org.telegram.messenger.MessageObject;
2015-06-29 19:12:11 +02:00
import org.telegram.messenger.R;
2022-06-21 04:51:00 +02:00
import org.telegram.messenger.SharedConfig;
import org.telegram.tgnet.TLObject;
import org.telegram.tgnet.TLRPC;
2016-04-22 15:49:00 +02:00
import org.telegram.ui.ActionBar.Theme;
2022-06-21 04:51:00 +02:00
import org.telegram.ui.Components.LinkPath;
2023-02-03 20:11:36 +01:00
import org.telegram.ui.Components.LinkSpanDrawable;
2015-06-29 19:12:11 +02:00
import org.telegram.ui.Components.TypefaceSpan;
import org.telegram.ui.Components.URLSpanNoUnderline;
2022-06-21 04:51:00 +02:00
import java.util.Objects;
2015-06-29 19:12:11 +02:00
public class BotHelpCell extends View {
private StaticLayout textLayout;
private String oldText;
2022-06-21 04:51:00 +02:00
private String currentPhotoKey;
2015-06-29 19:12:11 +02:00
private int width;
private int height;
private int textX;
private int textY;
public boolean wasDraw;
2015-06-29 19:12:11 +02:00
2023-02-03 20:11:36 +01:00
private LinkSpanDrawable<ClickableSpan> pressedLink;
private LinkSpanDrawable.LinkCollector links = new LinkSpanDrawable.LinkCollector(this);
2015-06-29 19:12:11 +02:00
private BotHelpCellDelegate delegate;
2022-06-21 04:51:00 +02:00
private Theme.ResourcesProvider resourcesProvider;
private int photoHeight;
private ImageReceiver imageReceiver;
private boolean isPhotoVisible;
private boolean isTextVisible;
private int imagePadding = AndroidUtilities.dp(4);
2015-06-29 19:12:11 +02:00
private boolean animating;
2015-06-29 19:12:11 +02:00
public interface BotHelpCellDelegate {
void didPressUrl(String url);
}
2021-09-20 07:54:41 +02:00
public BotHelpCell(Context context, Theme.ResourcesProvider resourcesProvider) {
2015-06-29 19:12:11 +02:00
super(context);
2021-09-20 07:54:41 +02:00
this.resourcesProvider = resourcesProvider;
2022-06-21 04:51:00 +02:00
imageReceiver = new ImageReceiver(this);
imageReceiver.setInvalidateAll(true);
imageReceiver.setCrossfadeWithOldImage(true);
imageReceiver.setCrossfadeDuration(300);
2023-02-03 20:11:36 +01:00
selectorDrawable = Theme.createRadSelectorDrawable(Theme.getColor(Theme.key_listSelector, resourcesProvider), selectorDrawableRadius = SharedConfig.bubbleRadius, SharedConfig.bubbleRadius);
selectorDrawable.setCallback(this);
2015-06-29 19:12:11 +02:00
}
public void setDelegate(BotHelpCellDelegate botHelpCellDelegate) {
delegate = botHelpCellDelegate;
}
private void resetPressedLink() {
if (pressedLink != null) {
pressedLink = null;
}
2023-02-03 20:11:36 +01:00
links.clear();
2015-06-29 19:12:11 +02:00
invalidate();
}
2020-09-30 15:48:47 +02:00
public void setText(boolean bot, String text) {
2022-06-21 04:51:00 +02:00
setText(bot, text, null, null);
}
public void setText(boolean bot, String text, TLObject imageOrAnimation, TLRPC.BotInfo botInfo) {
boolean photoVisible = imageOrAnimation != null;
boolean textVisible = !TextUtils.isEmpty(text);
if ((text == null || text.length() == 0) && !photoVisible) {
2015-06-29 19:12:11 +02:00
setVisibility(GONE);
return;
}
2022-06-21 04:51:00 +02:00
if (text == null) {
text = "";
}
if (text != null && text.equals(oldText) && isPhotoVisible == photoVisible) {
2015-06-29 19:12:11 +02:00
return;
}
2022-06-21 04:51:00 +02:00
isPhotoVisible = photoVisible;
isTextVisible = textVisible;
if (isPhotoVisible) {
String photoKey = FileRefController.getKeyForParentObject(botInfo);
if (!Objects.equals(currentPhotoKey, photoKey)) {
currentPhotoKey = photoKey;
if (imageOrAnimation instanceof TLRPC.TL_photo) {
TLRPC.Photo photo = (TLRPC.Photo) imageOrAnimation;
imageReceiver.setImage(ImageLocation.getForPhoto(FileLoader.getClosestPhotoSizeWithSize(photo.sizes, 400), photo), "400_400", null, "jpg", botInfo, 0);
} else if (imageOrAnimation instanceof TLRPC.Document) {
TLRPC.Document doc = (TLRPC.Document) imageOrAnimation;
TLRPC.PhotoSize photoThumb = FileLoader.getClosestPhotoSizeWithSize(doc.thumbs, 400);
BitmapDrawable strippedThumb = null;
if (SharedConfig.getDevicePerformanceClass() != SharedConfig.PERFORMANCE_CLASS_LOW) {
for (TLRPC.PhotoSize photoSize : doc.thumbs) {
if (photoSize instanceof TLRPC.TL_photoStrippedSize) {
strippedThumb = new BitmapDrawable(getResources(), ImageLoader.getStrippedPhotoBitmap(photoSize.bytes, "b"));
}
}
}
imageReceiver.setImage(ImageLocation.getForDocument(doc), ImageLoader.AUTOPLAY_FILTER, ImageLocation.getForDocument(MessageObject.getDocumentVideoThumb(doc), doc), null, ImageLocation.getForDocument(photoThumb, doc), "86_86_b", strippedThumb, doc.size, "mp4", botInfo, 0);
}
int topRadius = AndroidUtilities.dp(SharedConfig.bubbleRadius) - AndroidUtilities.dp(2), bottomRadius = AndroidUtilities.dp(4);
if (!isTextVisible) {
bottomRadius = topRadius;
}
imageReceiver.setRoundRadius(topRadius, topRadius, bottomRadius, bottomRadius);
}
}
2021-07-30 16:49:55 +02:00
oldText = AndroidUtilities.getSafeString(text);
2015-06-29 19:12:11 +02:00
setVisibility(VISIBLE);
2017-03-31 01:58:05 +02:00
int maxWidth;
2015-06-29 19:12:11 +02:00
if (AndroidUtilities.isTablet()) {
2017-03-31 01:58:05 +02:00
maxWidth = (int) (AndroidUtilities.getMinTabletSide() * 0.7f);
2015-06-29 19:12:11 +02:00
} else {
2017-03-31 01:58:05 +02:00
maxWidth = (int) (Math.min(AndroidUtilities.displaySize.x, AndroidUtilities.displaySize.y) * 0.7f);
2015-06-29 19:12:11 +02:00
}
2022-06-21 04:51:00 +02:00
if (isTextVisible) {
String[] lines = text.split("\n");
SpannableStringBuilder stringBuilder = new SpannableStringBuilder();
String help = LocaleController.getString(R.string.BotInfoTitle);
if (bot) {
stringBuilder.append(help);
stringBuilder.append("\n\n");
2017-03-31 01:58:05 +02:00
}
2022-06-21 04:51:00 +02:00
for (int a = 0; a < lines.length; a++) {
stringBuilder.append(lines[a].trim());
if (a != lines.length - 1) {
stringBuilder.append("\n");
}
}
MessageObject.addLinks(false, stringBuilder);
if (bot) {
stringBuilder.setSpan(new TypefaceSpan(AndroidUtilities.getTypeface("fonts/rmedium.ttf")), 0, help.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
2016-03-16 13:26:32 +01:00
}
2022-06-21 04:51:00 +02:00
Emoji.replaceEmoji(stringBuilder, Theme.chat_msgTextPaint.getFontMetricsInt(), AndroidUtilities.dp(20), false);
try {
textLayout = new StaticLayout(stringBuilder, Theme.chat_msgTextPaint, maxWidth - (isPhotoVisible ? AndroidUtilities.dp(5) : 0), Layout.Alignment.ALIGN_NORMAL, 1.0f, 0.0f, false);
width = 0;
height = textLayout.getHeight() + AndroidUtilities.dp(4 + 18);
int count = textLayout.getLineCount();
for (int a = 0; a < count; a++) {
width = (int) Math.ceil(Math.max(width, textLayout.getLineWidth(a) + textLayout.getLineLeft(a)));
}
if (width > maxWidth || isPhotoVisible) {
width = maxWidth;
}
} catch (Exception e) {
FileLog.e(e);
2017-03-31 01:58:05 +02:00
}
2022-06-21 04:51:00 +02:00
} else if (isPhotoVisible) {
width = maxWidth;
2015-06-29 19:12:11 +02:00
}
width += AndroidUtilities.dp(4 + 18);
2022-06-21 04:51:00 +02:00
if (isPhotoVisible) {
height += (photoHeight = (int) (width * 0.5625)) + AndroidUtilities.dp(4); // 16:9
}
2015-06-29 19:12:11 +02:00
}
2023-02-03 20:11:36 +01:00
public CharSequence getText() {
if (textLayout == null) {
return null;
}
return textLayout.getText();
}
2015-06-29 19:12:11 +02:00
@Override
public boolean onTouchEvent(MotionEvent event) {
float x = event.getX();
float y = event.getY();
boolean result = false;
if (textLayout != null) {
if (event.getAction() == MotionEvent.ACTION_DOWN || pressedLink != null && event.getAction() == MotionEvent.ACTION_UP) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
resetPressedLink();
try {
int x2 = (int) (x - textX);
int y2 = (int) (y - textY);
2022-06-21 04:51:00 +02:00
int line = textLayout.getLineForVertical(y2);
int off = textLayout.getOffsetForHorizontal(line, x2);
2015-06-29 19:12:11 +02:00
2022-06-21 04:51:00 +02:00
float left = textLayout.getLineLeft(line);
2015-06-29 19:12:11 +02:00
if (left <= x2 && left + textLayout.getLineWidth(line) >= x2) {
Spannable buffer = (Spannable) textLayout.getText();
ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
if (link.length != 0) {
resetPressedLink();
2023-02-03 20:11:36 +01:00
pressedLink = new LinkSpanDrawable<ClickableSpan>(link[0], resourcesProvider, x2, y2);
2015-06-29 19:12:11 +02:00
result = true;
try {
2023-02-03 20:11:36 +01:00
int start = buffer.getSpanStart(link[0]);
LinkPath path = pressedLink.obtainNewPath();
path.setCurrentLayout(textLayout, start, 0);
textLayout.getSelectionPath(start, buffer.getSpanEnd(link[0]), path);
2015-06-29 19:12:11 +02:00
} catch (Exception e) {
2017-03-31 01:58:05 +02:00
FileLog.e(e);
2015-06-29 19:12:11 +02:00
}
2023-02-03 20:11:36 +01:00
links.addLink(pressedLink);
invalidate();
2015-06-29 19:12:11 +02:00
} else {
resetPressedLink();
}
} else {
resetPressedLink();
}
} catch (Exception e) {
resetPressedLink();
2017-03-31 01:58:05 +02:00
FileLog.e(e);
2015-06-29 19:12:11 +02:00
}
} else if (pressedLink != null) {
try {
2023-02-03 20:11:36 +01:00
ClickableSpan span = pressedLink.getSpan();
if (span instanceof URLSpanNoUnderline) {
String url = ((URLSpanNoUnderline) span).getURL();
2015-06-29 19:12:11 +02:00
if (url.startsWith("@") || url.startsWith("#") || url.startsWith("/")) {
if (delegate != null) {
delegate.didPressUrl(url);
}
}
2023-02-03 20:11:36 +01:00
} else if (span instanceof URLSpan) {
if (delegate != null) {
delegate.didPressUrl(((URLSpan) span).getURL());
2016-03-06 02:49:31 +01:00
}
2023-02-03 20:11:36 +01:00
} else if (span != null) {
span.onClick(this);
2015-06-29 19:12:11 +02:00
}
} catch (Exception e) {
2017-03-31 01:58:05 +02:00
FileLog.e(e);
2015-06-29 19:12:11 +02:00
}
resetPressedLink();
result = true;
}
} else if (event.getAction() == MotionEvent.ACTION_CANCEL) {
resetPressedLink();
}
}
2023-02-03 20:11:36 +01:00
if (selectorDrawable != null) {
if (!result && y > 0 && event.getAction() == MotionEvent.ACTION_DOWN && isClickable()) {
selectorDrawable.setState(new int[]{android.R.attr.state_pressed, android.R.attr.state_enabled});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
selectorDrawable.setHotspot(event.getX(), event.getY());
}
invalidate();
result = true;
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
selectorDrawable.setState(new int[]{});
invalidate();
if (!result && event.getAction() == MotionEvent.ACTION_UP) {
performClick();
}
result = true;
}
}
2015-06-29 19:12:11 +02:00
return result || super.onTouchEvent(event);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
setMeasuredDimension(MeasureSpec.makeMeasureSpec(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.EXACTLY), height + AndroidUtilities.dp(8));
}
2023-02-03 20:11:36 +01:00
private Drawable selectorDrawable;
private int selectorDrawableRadius;
2015-06-29 19:12:11 +02:00
@Override
protected void onDraw(Canvas canvas) {
2019-06-04 12:14:50 +02:00
int x = (getWidth() - width) / 2;
2022-06-21 04:51:00 +02:00
int y = photoHeight;
y += AndroidUtilities.dp(2);
2020-01-23 07:15:40 +01:00
Drawable shadowDrawable = Theme.chat_msgInMediaDrawable.getShadowDrawable();
if (shadowDrawable != null) {
shadowDrawable.setBounds(x, y, width + x, height + y);
shadowDrawable.draw(canvas);
}
2021-08-31 21:06:39 +02:00
int w = AndroidUtilities.displaySize.x;
2020-01-23 07:15:40 +01:00
int h = AndroidUtilities.displaySize.y;
if (getParent() instanceof View) {
View view = (View) getParent();
2021-08-31 21:06:39 +02:00
w = view.getMeasuredWidth();
2020-01-23 07:15:40 +01:00
h = view.getMeasuredHeight();
}
2021-09-20 07:54:41 +02:00
Theme.MessageDrawable drawable = (Theme.MessageDrawable) getThemedDrawable(Theme.key_drawable_msgInMedia);
drawable.setTop((int) getY(), w, h, false, false);
2022-06-21 04:51:00 +02:00
drawable.setBounds(x, 0, width + x, height);
2021-09-20 07:54:41 +02:00
drawable.draw(canvas);
2022-06-21 04:51:00 +02:00
2023-02-03 20:11:36 +01:00
if (selectorDrawable != null) {
if (selectorDrawableRadius != SharedConfig.bubbleRadius) {
selectorDrawableRadius = SharedConfig.bubbleRadius;
Theme.setMaskDrawableRad(selectorDrawable, selectorDrawableRadius, selectorDrawableRadius);
}
selectorDrawable.setBounds(x + AndroidUtilities.dp(2), AndroidUtilities.dp(2), width + x - AndroidUtilities.dp(2), height - AndroidUtilities.dp(2));
selectorDrawable.draw(canvas);
}
2022-06-21 04:51:00 +02:00
imageReceiver.setImageCoords(x + imagePadding, imagePadding, width - imagePadding * 2, photoHeight - imagePadding);
imageReceiver.draw(canvas);
2021-09-20 07:54:41 +02:00
Theme.chat_msgTextPaint.setColor(getThemedColor(Theme.key_chat_messageTextIn));
Theme.chat_msgTextPaint.linkColor = getThemedColor(Theme.key_chat_messageLinkIn);
2015-06-29 19:12:11 +02:00
canvas.save();
2022-06-21 04:51:00 +02:00
canvas.translate(textX = AndroidUtilities.dp(isPhotoVisible ? 14 : 11) + x, textY = AndroidUtilities.dp(11) + y);
2023-02-03 20:11:36 +01:00
if (links.draw(canvas)) {
invalidate();
2015-06-29 19:12:11 +02:00
}
2016-04-22 15:49:00 +02:00
if (textLayout != null) {
textLayout.draw(canvas);
}
2015-06-29 19:12:11 +02:00
canvas.restore();
wasDraw = true;
}
2022-06-21 04:51:00 +02:00
@Override
protected void onAttachedToWindow() {
super.onAttachedToWindow();
imageReceiver.onAttachedToWindow();
}
@Override
protected void onDetachedFromWindow() {
super.onDetachedFromWindow();
2022-06-21 04:51:00 +02:00
imageReceiver.onDetachedFromWindow();
wasDraw = false;
2015-06-29 19:12:11 +02:00
}
2019-05-14 14:08:05 +02:00
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
2022-09-21 16:20:30 +02:00
if (textLayout != null) {
info.setText(textLayout.getText());
}
2019-05-14 14:08:05 +02:00
}
public boolean animating() {
return animating;
}
public void setAnimating(boolean animating) {
this.animating = animating;
}
2021-09-20 07:54:41 +02:00
private int getThemedColor(String key) {
Integer color = resourcesProvider != null ? resourcesProvider.getColor(key) : null;
return color != null ? color : Theme.getColor(key);
}
private Drawable getThemedDrawable(String drawableKey) {
Drawable drawable = resourcesProvider != null ? resourcesProvider.getDrawable(drawableKey) : null;
return drawable != null ? drawable : Theme.getThemeDrawable(drawableKey);
}
2023-02-03 20:11:36 +01:00
@Override
protected boolean verifyDrawable(@NonNull Drawable who) {
return who == selectorDrawable || super.verifyDrawable(who);
}
2015-06-29 19:12:11 +02:00
}