尝试修复链接显示

This commit is contained in:
世界 2020-05-06 22:56:00 +08:00
parent 8b51f06383
commit dc7a59a352
No known key found for this signature in database
GPG Key ID: CD109927C34A63C4
3 changed files with 315 additions and 246 deletions

View File

@ -295,21 +295,17 @@ public class AndroidUtilities {
return true;
};
public static boolean addLinks(Spannable text, int mask) {
if (text != null && containsUnsupportedCharacters(text.toString()) || mask == 0) {
return false;
}
public static boolean addProxyLinks(Spannable text) {
if (text == null) return false;
final URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
for (int i = old.length - 1; i >= 0; i--) {
text.removeSpan(old[i]);
String url = old[i].getURL();
if (url.startsWith("vmess") || url.startsWith("ss")) {
text.removeSpan(old[i]);
}
}
final ArrayList<LinkSpec> links = new ArrayList<>();
if ((mask & Linkify.PHONE_NUMBERS) != 0) {
Linkify.addLinks(text, Linkify.PHONE_NUMBERS);
}
//if ((mask & Linkify.WEB_URLS) != 0) {
gatherLinks(links, text, LinkifyPort.WEB_URL, new String[]{"http://", "https://", "ton://", "tg://", VMESS_PROTOCOL, VMESS1_PROTOCOL, SS_PROTOCOL, SSR_PROTOCOL}, sUrlMatchFilter);
//}
gatherLinks(links, text, LinkifyPort.PROXY_PATTERN, new String[]{VMESS_PROTOCOL, VMESS1_PROTOCOL, SS_PROTOCOL, SSR_PROTOCOL}, sUrlMatchFilter);
pruneOverlaps(links);
if (links.size() == 0) {
return false;
@ -327,6 +323,38 @@ public class AndroidUtilities {
return true;
}
public static boolean addLinks(Spannable text, int mask) {
if (text == null || containsUnsupportedCharacters(text.toString()) || mask == 0) {
return false;
}
final URLSpan[] old = text.getSpans(0, text.length(), URLSpan.class);
for (int i = old.length - 1; i >= 0; i--) {
text.removeSpan(old[i]);
}
final ArrayList<LinkSpec> links = new ArrayList<>();
if ((mask & Linkify.PHONE_NUMBERS) != 0) {
Linkify.addLinks(text, Linkify.PHONE_NUMBERS);
}
if ((mask & Linkify.WEB_URLS) != 0) {
gatherLinks(links, text, LinkifyPort.WEB_URL, new String[]{"http://", "https://", "ton://", "tg://"}, sUrlMatchFilter);
}
pruneOverlaps(links);
if (links.size() == 0) {
return false;
}
for (int a = 0, N = links.size(); a < N; a++) {
LinkSpec link = links.get(a);
URLSpan[] oldSpans = text.getSpans(link.start, link.end, URLSpan.class);
if (oldSpans != null && oldSpans.length > 0) {
for (URLSpan oldSpan : oldSpans) {
text.removeSpan(oldSpan);
}
}
text.setSpan(new URLSpan(link.url), link.start, link.end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return true;
}
private static void pruneOverlaps(ArrayList<LinkSpec> links) {
Comparator<LinkSpec> c = (a, b) -> {
if (a.start < b.start) {
@ -699,218 +727,218 @@ public class AndroidUtilities {
}
}
private static class VcardData {
String name;
ArrayList<String> phones = new ArrayList<>();
StringBuilder vcard = new StringBuilder();
private static class VcardData {
String name;
ArrayList<String> phones = new ArrayList<>();
StringBuilder vcard = new StringBuilder();
}
public static class VcardItem {
public ArrayList<String> vcardData = new ArrayList<>();
public String fullData = "";
public int type;
public boolean checked = true;
public String[] getRawValue() {
int idx = fullData.indexOf(':');
if (idx < 0) {
return new String[0];
}
String valueType = fullData.substring(0, idx);
String value = fullData.substring(idx + 1);
String nameEncoding = null;
String nameCharset = "UTF-8";
String[] params = valueType.split(";");
for (int a = 0; a < params.length; a++) {
String[] args2 = params[a].split("=");
if (args2.length != 2) {
continue;
}
if (args2[0].equals("CHARSET")) {
nameCharset = args2[1];
} else if (args2[0].equals("ENCODING")) {
nameEncoding = args2[1];
}
}
String[] args = value.split(";");
boolean added = false;
for (int a = 0; a < args.length; a++) {
if (TextUtils.isEmpty(args[a])) {
continue;
}
if (nameEncoding != null && nameEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
byte[] bytes = decodeQuotedPrintable(getStringBytes(args[a]));
if (bytes != null && bytes.length != 0) {
try {
args[a] = new String(bytes, nameCharset);
} catch (Exception ignore) {
}
}
}
}
return args;
}
public static class VcardItem {
public ArrayList<String> vcardData = new ArrayList<>();
public String fullData = "";
public int type;
public boolean checked = true;
public String getValue(boolean format) {
StringBuilder result = new StringBuilder();
public String[] getRawValue() {
int idx = fullData.indexOf(':');
if (idx < 0) {
return new String[0];
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
if (result.length() > 0) {
result.append(", ");
}
String valueType = fullData.substring(0, idx);
String value = fullData.substring(idx + 1);
String nameEncoding = null;
String nameCharset = "UTF-8";
String[] params = valueType.split(";");
for (int a = 0; a < params.length; a++) {
String[] args2 = params[a].split("=");
if (args2.length != 2) {
continue;
}
if (args2[0].equals("CHARSET")) {
nameCharset = args2[1];
} else if (args2[0].equals("ENCODING")) {
nameEncoding = args2[1];
}
}
String[] args = value.split(";");
boolean added = false;
for (int a = 0; a < args.length; a++) {
if (TextUtils.isEmpty(args[a])) {
continue;
}
if (nameEncoding != null && nameEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
byte[] bytes = decodeQuotedPrintable(getStringBytes(args[a]));
if (bytes != null && bytes.length != 0) {
try {
args[a] = new String(bytes, nameCharset);
} catch (Exception ignore) {
String valueType = fullData.substring(0, idx);
String value = fullData.substring(idx + 1);
String nameEncoding = null;
String nameCharset = "UTF-8";
String[] params = valueType.split(";");
for (int a = 0; a < params.length; a++) {
String[] args2 = params[a].split("=");
if (args2.length != 2) {
continue;
}
if (args2[0].equals("CHARSET")) {
nameCharset = args2[1];
} else if (args2[0].equals("ENCODING")) {
nameEncoding = args2[1];
}
}
}
if (added && result.length() > 0) {
result.append(" ");
}
result.append(args[a]);
if (!added) {
added = args[a].length() > 0;
}
}
if (format) {
if (type == 0) {
return PhoneFormat.getInstance().format(result.toString());
} else if (type == 5) {
String[] date = result.toString().split("T");
if (date.length > 0) {
date = date[0].split("-");
if (date.length == 3) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Utilities.parseInt(date[0]));
calendar.set(Calendar.MONTH, Utilities.parseInt(date[1]) - 1);
calendar.set(Calendar.DAY_OF_MONTH, Utilities.parseInt(date[2]));
return LocaleController.getInstance().formatterYearMax.format(calendar.getTime());
}
}
}
}
return result.toString();
}
public String getRawType(boolean first) {
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
String value = fullData.substring(0, idx);
if (type == 20) {
value = value.substring(2);
String[] args = value.split(";");
boolean added = false;
for (int a = 0; a < args.length; a++) {
if (TextUtils.isEmpty(args[a])) {
continue;
}
if (nameEncoding != null && nameEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
byte[] bytes = decodeQuotedPrintable(getStringBytes(args[a]));
if (bytes != null && bytes.length != 0) {
try {
args[a] = new String(bytes, nameCharset);
} catch (Exception ignore) {
}
}
}
}
return args;
}
public String getValue(boolean format) {
StringBuilder result = new StringBuilder();
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
if (result.length() > 0) {
result.append(", ");
}
String valueType = fullData.substring(0, idx);
String value = fullData.substring(idx + 1);
String nameEncoding = null;
String nameCharset = "UTF-8";
String[] params = valueType.split(";");
for (int a = 0; a < params.length; a++) {
String[] args2 = params[a].split("=");
if (args2.length != 2) {
continue;
}
if (args2[0].equals("CHARSET")) {
nameCharset = args2[1];
} else if (args2[0].equals("ENCODING")) {
nameEncoding = args2[1];
}
}
String[] args = value.split(";");
boolean added = false;
for (int a = 0; a < args.length; a++) {
if (TextUtils.isEmpty(args[a])) {
continue;
}
if (nameEncoding != null && nameEncoding.equalsIgnoreCase("QUOTED-PRINTABLE")) {
byte[] bytes = decodeQuotedPrintable(getStringBytes(args[a]));
if (bytes != null && bytes.length != 0) {
try {
args[a] = new String(bytes, nameCharset);
} catch (Exception ignore) {
}
}
}
if (added && result.length() > 0) {
result.append(" ");
}
result.append(args[a]);
if (!added) {
added = args[a].length() > 0;
}
}
if (format) {
if (type == 0) {
return PhoneFormat.getInstance().format(result.toString());
} else if (type == 5) {
String[] date = result.toString().split("T");
if (date.length > 0) {
date = date[0].split("-");
if (date.length == 3) {
Calendar calendar = Calendar.getInstance();
calendar.set(Calendar.YEAR, Utilities.parseInt(date[0]));
calendar.set(Calendar.MONTH, Utilities.parseInt(date[1]) - 1);
calendar.set(Calendar.DAY_OF_MONTH, Utilities.parseInt(date[2]));
return LocaleController.getInstance().formatterYearMax.format(calendar.getTime());
}
}
}
}
return result.toString();
}
public String getRawType(boolean first) {
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
String value = fullData.substring(0, idx);
if (type == 20) {
value = value.substring(2);
String[] args = value.split(";");
if (first) {
value = args[0];
} else if (args.length > 1) {
value = args[args.length - 1];
} else {
value = "";
}
} else {
String[] args = value.split(";");
for (int a = 0; a < args.length; a++) {
if (args[a].indexOf('=') >= 0) {
continue;
}
value = args[a];
}
return value;
}
return value;
}
public String getType() {
if (type == 5) {
return LocaleController.getString("ContactBirthday", R.string.ContactBirthday);
} else if (type == 6) {
if ("ORG".equalsIgnoreCase(getRawType(true))) {
return LocaleController.getString("ContactJob", R.string.ContactJob);
} else {
return LocaleController.getString("ContactJobTitle", R.string.ContactJobTitle);
}
}
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
String value = fullData.substring(0, idx);
if (type == 20) {
value = value.substring(2);
String[] args = value.split(";");
if (first) {
value = args[0];
} else if (args.length > 1) {
value = args[args.length - 1];
} else {
String[] args = value.split(";");
for (int a = 0; a < args.length; a++) {
if (args[a].indexOf('=') >= 0) {
continue;
}
value = args[a];
}
if (value.startsWith("X-")) {
value = value.substring(2);
}
switch (value) {
case "PREF":
value = LocaleController.getString("PhoneMain", R.string.PhoneMain);
break;
case "HOME":
value = LocaleController.getString("PhoneHome", R.string.PhoneHome);
break;
case "MOBILE":
case "CELL":
value = LocaleController.getString("PhoneMobile", R.string.PhoneMobile);
break;
case "OTHER":
value = LocaleController.getString("PhoneOther", R.string.PhoneOther);
break;
case "WORK":
value = LocaleController.getString("PhoneWork", R.string.PhoneWork);
break;
}
value = "";
}
} else {
String[] args = value.split(";");
for (int a = 0; a < args.length; a++) {
if (args[a].indexOf('=') >= 0) {
continue;
}
value = args[a];
}
value = value.substring(0, 1).toUpperCase() + value.substring(1).toLowerCase();
return value;
}
return value;
}
public String getType() {
if (type == 5) {
return LocaleController.getString("ContactBirthday", R.string.ContactBirthday);
} else if (type == 6) {
if ("ORG".equalsIgnoreCase(getRawType(true))) {
return LocaleController.getString("ContactJob", R.string.ContactJob);
} else {
return LocaleController.getString("ContactJobTitle", R.string.ContactJobTitle);
}
}
int idx = fullData.indexOf(':');
if (idx < 0) {
return "";
}
String value = fullData.substring(0, idx);
if (type == 20) {
value = value.substring(2);
String[] args = value.split(";");
value = args[0];
} else {
String[] args = value.split(";");
for (int a = 0; a < args.length; a++) {
if (args[a].indexOf('=') >= 0) {
continue;
}
value = args[a];
}
if (value.startsWith("X-")) {
value = value.substring(2);
}
switch (value) {
case "PREF":
value = LocaleController.getString("PhoneMain", R.string.PhoneMain);
break;
case "HOME":
value = LocaleController.getString("PhoneHome", R.string.PhoneHome);
break;
case "MOBILE":
case "CELL":
value = LocaleController.getString("PhoneMobile", R.string.PhoneMobile);
break;
case "OTHER":
value = LocaleController.getString("PhoneOther", R.string.PhoneOther);
break;
case "WORK":
value = LocaleController.getString("PhoneWork", R.string.PhoneWork);
break;
}
}
value = value.substring(0, 1).toUpperCase() + value.substring(1).toLowerCase();
return value;
}
}
public static byte[] getStringBytes(String src) {
try {
return src.getBytes("UTF-8");
@ -1826,22 +1854,23 @@ public class AndroidUtilities {
return new SpannableStringBuilder(str);
}
public static class LinkMovementMethodMy extends LinkMovementMethod {
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
try {
boolean result = super.onTouchEvent(widget, buffer, event);
if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
Selection.removeSelection(buffer);
}
return result;
} catch (Exception e) {
FileLog.e(e);
public static class LinkMovementMethodMy extends LinkMovementMethod {
@Override
public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
try {
boolean result = super.onTouchEvent(widget, buffer, event);
if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
Selection.removeSelection(buffer);
}
return false;
return result;
} catch (Exception e) {
FileLog.e(e);
}
return false;
}
}
public static boolean needShowPasscode() {
return needShowPasscode(false);
}

View File

@ -201,10 +201,11 @@ public class LinkifyPort {
+ ")";
public static Pattern WEB_URL = null;
public static Pattern PROXY_PATTERN = Pattern.compile(PROXY_URL);
static {
try {
WEB_URL = Pattern.compile("(" + WEB_URL_WITH_PROTOCOL + "|" + WEB_URL_WITHOUT_PROTOCOL+ "|" + PROXY_URL + ")");
WEB_URL = Pattern.compile("(" + WEB_URL_WITH_PROTOCOL + "|" + WEB_URL_WITHOUT_PROTOCOL + ")");
} catch (Exception e) {
FileLog.e(e);
}

View File

@ -159,7 +159,7 @@ public class MessageObject {
public CharSequence vCardData;
static final String[] excludeWords = new String[] {
static final String[] excludeWords = new String[]{
" vs. ",
" vs ",
" versus ",
@ -1440,10 +1440,18 @@ public class MessageObject {
if (newMessage.media != null && !(newMessage.media instanceof TLRPC.TL_messageMediaEmpty) && !(newMessage.media instanceof TLRPC.TL_messageMediaWebPage)/* && TextUtils.isEmpty(newMessage.message)*/) {
boolean changedCaption;
boolean changedMedia;
changedCaption = !TextUtils.equals(newMessage.message, oldMessage.message);
changedMedia = newMessage.media.getClass() != oldMessage.media.getClass() ||
if (!TextUtils.equals(newMessage.message, oldMessage.message)) {
changedCaption = true;
} else {
changedCaption = false;
}
if (newMessage.media.getClass() != oldMessage.media.getClass() ||
newMessage.media.photo != null && oldMessage.media.photo != null && newMessage.media.photo.id != oldMessage.media.photo.id ||
newMessage.media.document != null && oldMessage.media.document != null && newMessage.media.document.id != oldMessage.media.document.id;
newMessage.media.document != null && oldMessage.media.document != null && newMessage.media.document.id != oldMessage.media.document.id) {
changedMedia = true;
} else {
changedMedia = false;
}
if (changedMedia && changedCaption) {
messageText = replaceWithLink(LocaleController.getString("EventLogEditedMediaCaption", R.string.EventLogEditedMediaCaption), "un1", fromUser);
} else if (changedCaption) {
@ -2482,7 +2490,7 @@ public class MessageObject {
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaInvoice) {
messageText = messageOwner.media.description;
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported) {
messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia).replace("https://telegram.org/update","https://github.com/NekoX-Dev/NekoX/blob/master/Update.md");
messageText = LocaleController.getString("UnsupportedMedia", R.string.UnsupportedMedia).replace("https://telegram.org/update", "https://github.com/NekoX-Dev/NekoX/blob/master/Update.md");
} else if (messageOwner.media instanceof TLRPC.TL_messageMediaDocument) {
if (isSticker() || isAnimatedSticker()) {
String sch = getStrickerChar();
@ -2748,8 +2756,9 @@ public class MessageObject {
height = attribute.h;
}
}
/*animated && */
return width <= 1280 && height <= 1280;
if (/*animated && */width <= 1280 && height <= 1280) {
return true;
}
}
return false;
}
@ -3153,20 +3162,24 @@ public class MessageObject {
isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT ||
messageOwner.id < 0);
if (containsUrls(caption)) {
try {
if (useManualParse) {
if (useManualParse) {
if (containsUrls(caption)) {
try {
AndroidUtilities.addLinks((Spannable) caption, Linkify.WEB_URLS | Linkify.PHONE_NUMBERS);
} else {
AndroidUtilities.addLinks((Spannable) caption, Linkify.WEB_URLS);
} catch (Exception e) {
FileLog.e(e);
}
} catch (Exception e) {
FileLog.e(e);
}
addUrlsByPattern(isOutOwner(), caption, true, 0, 0, true);
}
addUrlsByPattern(isOutOwner(), caption, true, 0, 0, true);
addEntitiesToText(caption, true);
try {
AndroidUtilities.addProxyLinks((Spannable) caption);
} catch (Exception e) {
FileLog.e(e);
}
addEntitiesToText(caption, useManualParse);
if (isVideo()) {
addUrlsByPattern(isOutOwner(), caption, true, 3, getDuration(), false);
} else if (isMusic() || isVoice()) {
@ -3629,7 +3642,9 @@ public class MessageObject {
}
}
} else if (messageOwner.from_id < 0 || messageOwner.post) {
return messageOwner.to_id.channel_id != 0 && (messageOwner.via_bot_id == 0 && messageOwner.reply_to_msg_id == 0 || type != TYPE_STICKER && type != TYPE_ANIMATED_STICKER);
if (messageOwner.to_id.channel_id != 0 && (messageOwner.via_bot_id == 0 && messageOwner.reply_to_msg_id == 0 || type != TYPE_STICKER && type != TYPE_ANIMATED_STICKER)) {
return true;
}
}
return false;
}
@ -3708,8 +3723,22 @@ public class MessageObject {
isOut() && messageOwner.send_state != MESSAGE_SEND_STATE_SENT ||
messageOwner.id < 0 || messageOwner.media instanceof TLRPC.TL_messageMediaUnsupported);
addLinks(isOutOwner(), messageText, true, true);
if (useManualParse) {
addLinks(isOutOwner(), messageText, true, true);
} else {
if (messageText instanceof Spannable && messageText.length() < 1000) {
try {
AndroidUtilities.addLinks((Spannable) messageText, Linkify.PHONE_NUMBERS);
} catch (Throwable e) {
FileLog.e(e);
}
}
}
try {
AndroidUtilities.addProxyLinks((Spannable) messageText);
} catch (Throwable e) {
FileLog.e(e);
}
if (isYouTubeVideo() || replyMessageObject != null && replyMessageObject.isYouTubeVideo()) {
addUrlsByPattern(isOutOwner(), messageText, false, 3, Integer.MAX_VALUE, false);
} else if (replyMessageObject != null) {
@ -3720,7 +3749,7 @@ public class MessageObject {
}
}
boolean hasUrls = addEntitiesToText(messageText, true);
boolean hasUrls = addEntitiesToText(messageText, useManualParse);
int maxWidth = getMaxMessageTextWidth();
@ -4159,7 +4188,10 @@ public class MessageObject {
return attribute.supports_streaming;
}
}
return SharedConfig.streamMkv && "video/x-matroska".equals(document.mime_type);
if (SharedConfig.streamMkv && "video/x-matroska".equals(document.mime_type)) {
return true;
}
return false;
}
public static long getDialogId(TLRPC.Message message) {
@ -4310,7 +4342,9 @@ public class MessageObject {
String mime = document.mime_type.toLowerCase();
if (mime.equals("audio/flac") || mime.equals("audio/ogg") || mime.equals("audio/opus") || mime.equals("audio/x-opus+ogg")) {
return true;
} else return mime.equals("application/octet-stream") && FileLoader.getDocumentFileName(document).endsWith(".opus");
} else if (mime.equals("application/octet-stream") && FileLoader.getDocumentFileName(document).endsWith(".opus")) {
return true;
}
}
}
return false;
@ -4979,7 +5013,10 @@ public class MessageObject {
if (!ChatObject.isChannel(chat) || chat.megagroup || chat.creator) {
return true;
}
return chat.admin_rights != null && (chat.admin_rights.edit_messages || message.out);
if (chat.admin_rights != null && (chat.admin_rights.edit_messages || message.out)) {
return true;
}
return false;
}
public static boolean canEditMessage(int currentAccount, TLRPC.Message message, TLRPC.Chat chat, boolean scheduled) {
@ -5021,11 +5058,13 @@ public class MessageObject {
message.media == null);
}
if (chat.megagroup && message.out || !chat.megagroup && (chat.creator || chat.admin_rights != null && (chat.admin_rights.edit_messages || message.out && chat.admin_rights.post_messages)) && message.post) {
return message.media instanceof TLRPC.TL_messageMediaPhoto ||
if (message.media instanceof TLRPC.TL_messageMediaPhoto ||
message.media instanceof TLRPC.TL_messageMediaDocument && !isStickerMessage(message) && !isAnimatedStickerMessage(message) ||
message.media instanceof TLRPC.TL_messageMediaEmpty ||
message.media instanceof TLRPC.TL_messageMediaWebPage ||
message.media == null;
message.media == null) {
return true;
}
}
return false;
}